Skip to content

Commit

Permalink
Merge branch 'main' into pythongh-116380
Browse files Browse the repository at this point in the history
  • Loading branch information
barneygale committed Feb 8, 2025
2 parents d8ec2d4 + 707d066 commit 203b78b
Show file tree
Hide file tree
Showing 9 changed files with 74 additions and 49 deletions.
11 changes: 11 additions & 0 deletions Doc/library/pdb.rst
Original file line number Diff line number Diff line change
Expand Up @@ -697,6 +697,17 @@ can be overridden by the local file.
.. pdbcommand:: q(uit)

Quit from the debugger. The program being executed is aborted.
An end-of-file input is equivalent to :pdbcmd:`quit`.

A confirmation prompt will be shown if the debugger is invoked in
``'inline'`` mode. Either ``y``, ``Y``, ``<Enter>`` or ``EOF``
will confirm the quit.

.. versionchanged:: 3.14
A confirmation prompt will be shown if the debugger is invoked in
``'inline'`` mode. After the confirmation, the debugger will call
:func:`sys.exit` immediately, instead of raising :exc:`bdb.BdbQuit`
in the next trace event.

.. pdbcommand:: debug code

Expand Down
5 changes: 5 additions & 0 deletions Doc/whatsnew/3.14.rst
Original file line number Diff line number Diff line change
Expand Up @@ -641,6 +641,11 @@ pdb
command when :mod:`pdb` is in ``inline`` mode.
(Contributed by Tian Gao in :gh:`123757`.)

* A confirmation prompt will be shown when the user tries to quit :mod:`pdb`
in ``inline`` mode. ``y``, ``Y``, ``<Enter>`` or ``EOF`` will confirm
the quit and call :func:`sys.exit`, instead of raising :exc:`bdb.BdbQuit`.
(Contributed by Tian Gao in :gh:`124704`.)


pickle
------
Expand Down
55 changes: 22 additions & 33 deletions Lib/glob.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ def _relative_glob(select, dirname, dir_fd=None):
prefix is removed from results. If dir_fd is supplied, then dirname is
opened relative to the given file descriptor.
"""
dirname = _StringGlobber.add_slash(dirname)
dirname = os.path.join(dirname, dirname[:0])
slicer = operator.itemgetter(slice(len(dirname), None))
return map(slicer, select(dirname, dir_fd, dirname))

Expand Down Expand Up @@ -239,12 +239,6 @@ def close(fd):
"""
raise NotImplementedError

@staticmethod
def add_slash(path):
"""Returns a path with a trailing slash added.
"""
raise NotImplementedError

@staticmethod
def concat_path(path, text):
"""Implements path concatenation.
Expand Down Expand Up @@ -277,12 +271,14 @@ def selector(self, parts):
def special_selector(self, part, parts):
"""Returns a function that selects special children of the given path.
"""
if parts:
part += self.sep
select_next = self.selector(parts)

def select_special(path, dir_fd=None, rel_path=None, exists=False):
path = self.concat_path(self.add_slash(path), part)
path = self.concat_path(path, part)
if dir_fd is not None:
rel_path = self.concat_path(self.add_slash(rel_path), part)
rel_path = self.concat_path(rel_path, part)
return select_next(path, dir_fd, rel_path, exists)
return select_special

Expand All @@ -292,16 +288,18 @@ def literal_selector(self, part, parts):

# Optimization: consume and join any subsequent literal parts here,
# rather than leaving them for the next selector. This reduces the
# number of string concatenation operations and calls to add_slash().
# number of string concatenation operations.
while parts and magic_check.search(parts[-1]) is None:
part += self.sep + parts.pop()
if parts:
part += self.sep

select_next = self.selector(parts)

def select_literal(path, dir_fd=None, rel_path=None, exists=False):
path = self.concat_path(self.add_slash(path), part)
path = self.concat_path(path, part)
if dir_fd is not None:
rel_path = self.concat_path(self.add_slash(rel_path), part)
rel_path = self.concat_path(rel_path, part)
return select_next(path, dir_fd, rel_path, exists=False)
return select_literal

Expand All @@ -322,7 +320,7 @@ def select_wildcard(path, dir_fd=None, rel_path=None, exists=False):
entries = self.scandir(path)
else:
fd = self.open(rel_path, _dir_open_flags, dir_fd=dir_fd)
entries = self.scandir_fd(fd, self.add_slash(path))
entries = self.scandir_fd(fd, path)
except OSError:
pass
else:
Expand All @@ -335,6 +333,9 @@ def select_wildcard(path, dir_fd=None, rel_path=None, exists=False):
except OSError:
continue
if dir_only:
entry_path = self.concat_path(entry_path, self.sep)
if fd is not None:
entry_name = entry_name + self.sep
yield from select_next(
entry_path, fd, entry_name, exists=True)
else:
Expand Down Expand Up @@ -368,9 +369,6 @@ def recursive_selector(self, part, parts):
select_next = self.selector(parts)

def select_recursive(path, dir_fd=None, rel_path=None, exists=False):
path = self.add_slash(path)
if dir_fd is not None:
rel_path = self.add_slash(rel_path)
match_pos = len(str(path))
if match is None or match(str(path), match_pos):
yield from select_next(path, dir_fd, rel_path, exists)
Expand Down Expand Up @@ -401,7 +399,7 @@ def select_recursive_step(stack, match_pos):
fd = self.open(rel_path, _dir_open_flags, dir_fd=dir_fd)
# Schedule the file descriptor to be closed next step.
stack.append((None, fd, None))
entries = self.scandir_fd(fd, self.add_slash(path))
entries = self.scandir_fd(fd, path)
except OSError:
pass
else:
Expand All @@ -414,7 +412,12 @@ def select_recursive_step(stack, match_pos):
pass

if is_dir or not dir_only:
if match is None or match(str(entry_path), match_pos):
entry_path_str = str(entry_path)
if dir_only:
entry_path = self.concat_path(entry_path, self.sep)
if fd is not None:
entry_name = entry_name + self.sep
if match is None or match(entry_path_str, match_pos):
if dir_only:
yield from select_next(
entry_path, fd, entry_name, exists=True)
Expand Down Expand Up @@ -464,31 +467,17 @@ def scandir(path):

@staticmethod
def scandir_fd(fd, prefix):
prefix = os.path.join(prefix, prefix[:0])
with os.scandir(fd) as scandir_it:
entries = list(scandir_it)
return ((entry, entry.name, prefix + entry.name) for entry in entries)

if os.name == 'nt':
@staticmethod
def add_slash(pathname):
tail = os.path.splitroot(pathname)[2]
if not tail or tail[-1] in '\\/':
return pathname
return f'{pathname}\\'
else:
@staticmethod
def add_slash(pathname):
if not pathname or pathname[-1] == '/':
return pathname
return f'{pathname}/'


class _PathGlobber(_GlobberBase):
"""Provides shell-style pattern matching and globbing for pathlib paths.
"""

lexists = operator.methodcaller('exists', follow_symlinks=False)
add_slash = operator.methodcaller('joinpath', '')

@staticmethod
def scandir(path):
Expand Down
3 changes: 2 additions & 1 deletion Lib/pathlib/_abc.py
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,7 @@ def full_match(self, pattern, *, case_sensitive=None):
return match(str(self)) is not None



class ReadablePath(JoinablePath):
"""Base class for concrete path objects.
Expand Down Expand Up @@ -460,7 +461,7 @@ def glob(self, pattern, *, case_sensitive=None, recurse_symlinks=True):
recursive = True if recurse_symlinks else _no_recurse_symlinks
globber = _PathGlobber(self.parser.sep, case_sensitive, case_pedantic, recursive)
select = globber.selector(parts)
return select(self)
return select(self.joinpath(''))

def rglob(self, pattern, *, case_sensitive=None, recurse_symlinks=True):
"""Recursively yield all existing files (of any kind, including
Expand Down
2 changes: 1 addition & 1 deletion Lib/pathlib/_local.py
Original file line number Diff line number Diff line change
Expand Up @@ -962,7 +962,7 @@ def glob(self, pattern, *, case_sensitive=None, recurse_symlinks=False):
recursive, include_hidden=True)
select = globber.selector(parts[::-1])
root = str(self)
paths = select(root)
paths = select(self.parser.join(root, ''))

# Normalize results
if root == '.':
Expand Down
8 changes: 4 additions & 4 deletions Lib/test/test_glob.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,9 +192,9 @@ def test_glob_directory_with_trailing_slash(self):
eq = self.assertSequencesEqual_noorder
eq(glob.glob(self.norm('aa*') + sep),
[self.norm('aaa') + os.sep, self.norm('aab') + os.sep])
# Stripping the redundant separators is an implementation detail.
# Preserving the redundant separators is an implementation detail.
eq(glob.glob(self.norm('aa*') + sep*2),
[self.norm('aaa') + os.sep, self.norm('aab') + os.sep])
[self.norm('aaa') + os.sep*2, self.norm('aab') + os.sep*2])

def test_glob_bytes_directory_with_trailing_slash(self):
# Same as test_glob_directory_with_trailing_slash, but with a
Expand All @@ -212,8 +212,8 @@ def test_glob_bytes_directory_with_trailing_slash(self):
[os.fsencode(self.norm('aaa') + os.sep),
os.fsencode(self.norm('aab') + os.sep)])
eq(glob.glob(os.fsencode(self.norm('aa*') + sep*2)),
[os.fsencode(self.norm('aaa') + os.sep),
os.fsencode(self.norm('aab') + os.sep)])
[os.fsencode(self.norm('aaa') + os.sep*2),
os.fsencode(self.norm('aab') + os.sep*2)])

@skip_unless_symlink
def test_glob_symlinks(self):
Expand Down
2 changes: 1 addition & 1 deletion Lib/test/test_pathlib/test_pathlib_abc.py
Original file line number Diff line number Diff line change
Expand Up @@ -1125,7 +1125,7 @@ def test_glob_windows(self):
def test_glob_empty_pattern(self):
P = self.cls
p = P(self.base)
self.assertEqual(list(p.glob("")), [p])
self.assertEqual(list(p.glob("")), [p.joinpath("")])

def test_glob_case_sensitive(self):
P = self.cls
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix possible extra reference when using objects returned by :func:`hashlib.sha256` under :term:`free threading`.
36 changes: 27 additions & 9 deletions Modules/_hashopenssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,14 @@
#include <stdbool.h>
#include "Python.h"
#include "pycore_hashtable.h"
#include "pycore_strhex.h" // _Py_strhex()
#include "pycore_strhex.h" // _Py_strhex()
#include "pycore_pyatomic_ft_wrappers.h" // FT_ATOMIC_LOAD_PTR_RELAXED
#include "hashlib.h"

/* EVP is the preferred interface to hashing in OpenSSL */
#include <openssl/evp.h>
#include <openssl/hmac.h>
#include <openssl/crypto.h> // FIPS_mode()
#include <openssl/crypto.h> // FIPS_mode()
/* We use the object interface to discover what hashes OpenSSL supports. */
#include <openssl/objects.h>
#include <openssl/err.h>
Expand Down Expand Up @@ -369,6 +370,7 @@ static PY_EVP_MD*
py_digest_by_name(PyObject *module, const char *name, enum Py_hash_type py_ht)
{
PY_EVP_MD *digest = NULL;
PY_EVP_MD *other_digest = NULL;
_hashlibstate *state = get_hashlib_state(module);
py_hashentry_t *entry = (py_hashentry_t *)_Py_hashtable_get(
state->hashtable, (const void*)name
Expand All @@ -379,20 +381,36 @@ py_digest_by_name(PyObject *module, const char *name, enum Py_hash_type py_ht)
case Py_ht_evp:
case Py_ht_mac:
case Py_ht_pbkdf2:
if (entry->evp == NULL) {
entry->evp = PY_EVP_MD_fetch(entry->ossl_name, NULL);
digest = FT_ATOMIC_LOAD_PTR_RELAXED(entry->evp);
if (digest == NULL) {
digest = PY_EVP_MD_fetch(entry->ossl_name, NULL);
#ifdef Py_GIL_DISABLED
// exchange just in case another thread did same thing at same time
other_digest = _Py_atomic_exchange_ptr(&entry->evp, digest);
#else
entry->evp = digest;
#endif
}
digest = entry->evp;
break;
case Py_ht_evp_nosecurity:
if (entry->evp_nosecurity == NULL) {
entry->evp_nosecurity = PY_EVP_MD_fetch(entry->ossl_name, "-fips");
digest = FT_ATOMIC_LOAD_PTR_RELAXED(entry->evp_nosecurity);
if (digest == NULL) {
digest = PY_EVP_MD_fetch(entry->ossl_name, "-fips");
#ifdef Py_GIL_DISABLED
// exchange just in case another thread did same thing at same time
other_digest = _Py_atomic_exchange_ptr(&entry->evp_nosecurity, digest);
#else
entry->evp_nosecurity = digest;
#endif
}
digest = entry->evp_nosecurity;
break;
}
// if another thread same thing at same time make sure we got same ptr
assert(other_digest == NULL || other_digest == digest);
if (digest != NULL) {
PY_EVP_MD_up_ref(digest);
if (other_digest == NULL) {
PY_EVP_MD_up_ref(digest);
}
}
} else {
// Fall back for looking up an unindexed OpenSSL specific name.
Expand Down

0 comments on commit 203b78b

Please sign in to comment.