Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Lib/_android_support.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,13 @@ def write(self, prio, tag, message):
# message.
message = message.replace(b"\x00", b"\xc0\x80")

# On API level 30 and higher, Logcat will strip any number of leading
# newlines. This is visible in all `logcat` modes, even --binary. Work
# around this by adding a leading space, which shouldn't make any
# difference to the log's usability.
if message.startswith(b"\n"):
message = b" " + message

with self._lock:
now = time()
self._bucket_level += (
Expand Down
19 changes: 16 additions & 3 deletions Lib/annotationlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -919,7 +919,7 @@ def get_annotations(
does not exist, the __annotate__ function is called. The
FORWARDREF format uses __annotations__ if it exists and can be
evaluated, and otherwise falls back to calling the __annotate__ function.
The SOURCE format tries __annotate__ first, and falls back to
The STRING format tries __annotate__ first, and falls back to
using __annotations__, stringified using annotations_to_string().

This function handles several details for you:
Expand Down Expand Up @@ -1037,13 +1037,26 @@ def get_annotations(
obj_globals = obj_locals = unwrap = None

if unwrap is not None:
# Use an id-based visited set to detect cycles in the __wrapped__
# and functools.partial.func chain (e.g. f.__wrapped__ = f).
# On cycle detection we stop and use whatever __globals__ we have
# found so far, mirroring the approach of inspect.unwrap().
_seen_ids = {id(unwrap)}
while True:
if hasattr(unwrap, "__wrapped__"):
unwrap = unwrap.__wrapped__
candidate = unwrap.__wrapped__
if id(candidate) in _seen_ids:
break
_seen_ids.add(id(candidate))
unwrap = candidate
continue
if functools := sys.modules.get("functools"):
if isinstance(unwrap, functools.partial):
unwrap = unwrap.func
candidate = unwrap.func
if id(candidate) in _seen_ids:
break
_seen_ids.add(id(candidate))
unwrap = candidate
continue
break
if hasattr(unwrap, "__globals__"):
Expand Down
10 changes: 6 additions & 4 deletions Lib/argparse.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,10 @@ def _copy_items(items):
return copy.copy(items)


def _identity(value):
return value


# ===============
# Formatting Help
# ===============
Expand Down Expand Up @@ -200,7 +204,7 @@ def _set_color(self, color):
self._decolor = decolor
else:
self._theme = get_theme(force_no_color=True).argparse
self._decolor = lambda text: text
self._decolor = _identity

# ===============================
# Section and indentation methods
Expand Down Expand Up @@ -1903,9 +1907,7 @@ def __init__(self,
self._subparsers = None

# register types
def identity(string):
return string
self.register('type', None, identity)
self.register('type', None, _identity)

# add help argument if necessary
# (using explicit default to override global argument_default)
Expand Down
27 changes: 24 additions & 3 deletions Lib/glob.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

def glob(pathname, *, root_dir=None, dir_fd=None, recursive=False,
include_hidden=False):
"""Return a list of paths matching a pathname pattern.
"""Return a list of paths matching a `pathname` pattern.

The pattern may contain simple shell-style wildcards a la
fnmatch. Unlike fnmatch, filenames starting with a
Expand All @@ -25,6 +25,15 @@ def glob(pathname, *, root_dir=None, dir_fd=None, recursive=False,
The order of the returned list is undefined. Sort it if you need a
particular order.

If `root_dir` is not None, it should be a path-like object specifying the
root directory for searching. It has the same effect as changing the
current directory before calling it (without actually
changing it). If pathname is relative, the result will contain
paths relative to `root_dir`.

If `dir_fd` is not None, it should be a file descriptor referring to a
directory, and paths will then be relative to that directory.

If `include_hidden` is true, the patterns '*', '?', '**' will match hidden
directories.

Expand All @@ -36,7 +45,7 @@ def glob(pathname, *, root_dir=None, dir_fd=None, recursive=False,

def iglob(pathname, *, root_dir=None, dir_fd=None, recursive=False,
include_hidden=False):
"""Return an iterator which yields the paths matching a pathname pattern.
"""Return an iterator which yields the paths matching a `pathname` pattern.

The pattern may contain simple shell-style wildcards a la
fnmatch. However, unlike fnmatch, filenames starting with a
Expand All @@ -46,7 +55,19 @@ def iglob(pathname, *, root_dir=None, dir_fd=None, recursive=False,
The order of the returned paths is undefined. Sort them if you need a
particular order.

If recursive is true, the pattern '**' will match any files and
If `root_dir` is not None, it should be a path-like object specifying
the root directory for searching. It has the same effect as changing
the current directory before calling it (without actually
changing it). If pathname is relative, the result will contain
paths relative to `root_dir`.

If `dir_fd` is not None, it should be a file descriptor referring to a
directory, and paths will then be relative to that directory.

If `include_hidden` is true, the patterns '*', '?', '**' will match hidden
directories.

If `recursive` is true, the pattern '**' will match any files and
zero or more directories and subdirectories.
"""
sys.audit("glob.glob", pathname, recursive)
Expand Down
3 changes: 2 additions & 1 deletion Lib/inspect.py
Original file line number Diff line number Diff line change
Expand Up @@ -2660,11 +2660,12 @@ class Parameter:
The annotation for the parameter if specified. If the
parameter has no annotation, this attribute is set to
`Parameter.empty`.
* kind : str
* kind
Describes how argument values are bound to the parameter.
Possible values: `Parameter.POSITIONAL_ONLY`,
`Parameter.POSITIONAL_OR_KEYWORD`, `Parameter.VAR_POSITIONAL`,
`Parameter.KEYWORD_ONLY`, `Parameter.VAR_KEYWORD`.
Every value has a `description` attribute describing meaning.
"""

__slots__ = ('_name', '_kind', '_default', '_annotation')
Expand Down
2 changes: 1 addition & 1 deletion Lib/pydoc_data/module_docs.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Autogenerated by Sphinx on Tue Feb 3 17:32:13 2026
# Autogenerated by Sphinx on Tue Apr 7 16:13:12 2026
# as part of the release process.

module_docs = {
Expand Down
Loading
Loading