Skip to content

Commit

Permalink
Merge branch '3.13' into backport-21c04e1-3.13
Browse files Browse the repository at this point in the history
  • Loading branch information
serhiy-storchaka authored Oct 10, 2024
2 parents ee22212 + c2cb1a8 commit cfe03c7
Show file tree
Hide file tree
Showing 18 changed files with 274 additions and 104 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ jobs:

check_abi:
name: 'Check if the ABI has changed'
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
needs: check_source
if: needs.check_source.outputs.run_tests == 'true'
steps:
Expand Down
4 changes: 1 addition & 3 deletions .github/workflows/reusable-change-detection.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
---

name: Change detection
name: Reusable change detection

on: # yamllint disable-line rule:truthy
workflow_call:
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/reusable-docs.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Docs
name: Reusable Docs

on:
workflow_call:
Expand Down Expand Up @@ -95,7 +95,7 @@ jobs:
# Run "doctest" on HEAD as new syntax doesn't exist in the latest stable release
doctest:
name: 'Doctest'
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
timeout-minutes: 60
steps:
- uses: actions/checkout@v4
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/reusable-macos.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
name: Reusable macOS

on:
workflow_call:
inputs:
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/reusable-tsan.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
name: Reusable Thread Sanitizer

on:
workflow_call:
inputs:
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/reusable-ubuntu.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
name: Reusable Ubuntu

on:
workflow_call:
inputs:
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/reusable-wasi.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
name: Reusable WASI

on:
workflow_call:
inputs:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/reusable-windows-msi.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: TestsMSI
name: Reusable Windows MSI

on:
workflow_call:
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/reusable-windows.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
name: Reusable Windows

on:
workflow_call:
inputs:
Expand Down
1 change: 1 addition & 0 deletions Doc/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

extensions = [
'audit_events',
'availability',
'c_annotations',
'glossary_search',
'lexers',
Expand Down
133 changes: 118 additions & 15 deletions Doc/library/traceback.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,15 @@

--------------

This module provides a standard interface to extract, format and print stack
traces of Python programs. It exactly mimics the behavior of the Python
interpreter when it prints a stack trace. This is useful when you want to print
stack traces under program control, such as in a "wrapper" around the
interpreter.
This module provides a standard interface to extract, format and print
stack traces of Python programs. It is more flexible than the
interpreter's default traceback display, and therefore makes it
possible to configure certain aspects of the output. Finally,
it contains a utility for capturing enough information about an
exception to print it later, without the need to save a reference
to the actual exception. Since exceptions can be the roots of large
objects graph, this utility can significantly improve
memory management.

.. index:: pair: object; traceback

Expand All @@ -29,7 +33,20 @@ which are assigned to the :attr:`~BaseException.__traceback__` field of
Module :mod:`pdb`
Interactive source code debugger for Python programs.

The module defines the following functions:
The module's API can be divided into two parts:

* Module-level functions offering basic functionality, which are useful for interactive
inspection of exceptions and tracebacks.

* :class:`TracebackException` class and its helper classes
:class:`StackSummary` and :class:`FrameSummary`. These offer both more
flexibility in the output generated and the ability to store the information
necessary for later formatting without holding references to actual exception
and traceback objects.


Module-Level Functions
----------------------

.. function:: print_tb(tb, limit=None, file=None)

Expand Down Expand Up @@ -237,20 +254,24 @@ The module defines the following functions:

.. versionadded:: 3.5

The module also defines the following classes:

:class:`!TracebackException` Objects
------------------------------------

.. versionadded:: 3.5

:class:`!TracebackException` objects are created from actual exceptions to
capture data for later printing in a lightweight fashion.
capture data for later printing. They offer a more lightweight method of
storing this information by avoiding holding references to
:ref:`traceback<traceback-objects>` and :ref:`frame<frame-objects>` objects
In addition, they expose more options to configure the output compared to
the module-level functions described above.

.. class:: TracebackException(exc_type, exc_value, exc_traceback, *, limit=None, lookup_lines=True, capture_locals=False, compact=False, max_group_width=15, max_group_depth=10)

Capture an exception for later rendering. *limit*, *lookup_lines* and
*capture_locals* are as for the :class:`StackSummary` class.
Capture an exception for later rendering. The meaning of *limit*,
*lookup_lines* and *capture_locals* are as for the :class:`StackSummary`
class.

If *compact* is true, only data that is required by
:class:`!TracebackException`'s :meth:`format` method
Expand Down Expand Up @@ -509,8 +530,8 @@ in a :ref:`traceback <traceback-objects>`.

.. _traceback-example:

Traceback Examples
------------------
Examples of Using the Module-Level Functions
--------------------------------------------

This simple example implements a basic read-eval-print loop, similar to (but
less useful than) the standard Python interactive interpreter loop. For a more
Expand Down Expand Up @@ -549,8 +570,7 @@ exception and traceback:

try:
lumberjack()
except IndexError:
exc = sys.exception()
except IndexError as exc:
print("*** print_tb:")
traceback.print_tb(exc.__traceback__, limit=1, file=sys.stdout)
print("*** print_exception:")
Expand Down Expand Up @@ -653,5 +673,88 @@ This last example demonstrates the final few formatting functions:
[' File "spam.py", line 3, in <module>\n spam.eggs()\n',
' File "eggs.py", line 42, in eggs\n return "bacon"\n']
>>> an_error = IndexError('tuple index out of range')
>>> traceback.format_exception_only(type(an_error), an_error)
>>> traceback.format_exception_only(an_error)
['IndexError: tuple index out of range\n']


Examples of Using :class:`TracebackException`
---------------------------------------------

With the helper class, we have more options::

>>> import sys
>>> from traceback import TracebackException
>>>
>>> def lumberjack():
... bright_side_of_life()
...
>>> def bright_side_of_life():
... t = "bright", "side", "of", "life"
... return t[5]
...
>>> try:
... lumberjack()
... except IndexError as e:
... exc = e
...
>>> try:
... try:
... lumberjack()
... except:
... 1/0
... except Exception as e:
... chained_exc = e
...
>>> # limit works as with the module-level functions
>>> TracebackException.from_exception(exc, limit=-2).print()
Traceback (most recent call last):
File "<python-input-1>", line 6, in lumberjack
bright_side_of_life()
~~~~~~~~~~~~~~~~~~~^^
File "<python-input-1>", line 10, in bright_side_of_life
return t[5]
~^^^
IndexError: tuple index out of range

>>> # capture_locals adds local variables in frames
>>> TracebackException.from_exception(exc, limit=-2, capture_locals=True).print()
Traceback (most recent call last):
File "<python-input-1>", line 6, in lumberjack
bright_side_of_life()
~~~~~~~~~~~~~~~~~~~^^
File "<python-input-1>", line 10, in bright_side_of_life
return t[5]
~^^^
t = ("bright", "side", "of", "life")
IndexError: tuple index out of range

>>> # The *chain* kwarg to print() controls whether chained
>>> # exceptions are displayed
>>> TracebackException.from_exception(chained_exc).print()
Traceback (most recent call last):
File "<python-input-19>", line 4, in <module>
lumberjack()
~~~~~~~~~~^^
File "<python-input-8>", line 7, in lumberjack
bright_side_of_life()
~~~~~~~~~~~~~~~~~~~^^
File "<python-input-8>", line 11, in bright_side_of_life
return t[5]
~^^^
IndexError: tuple index out of range

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "<python-input-19>", line 6, in <module>
1/0
~^~
ZeroDivisionError: division by zero

>>> TracebackException.from_exception(chained_exc).print(chain=False)
Traceback (most recent call last):
File "<python-input-19>", line 6, in <module>
1/0
~^~
ZeroDivisionError: division by zero

125 changes: 125 additions & 0 deletions Doc/tools/extensions/availability.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
"""Support for documenting platform availability"""

from __future__ import annotations

from typing import TYPE_CHECKING

from docutils import nodes
from sphinx import addnodes
from sphinx.util import logging
from sphinx.util.docutils import SphinxDirective

if TYPE_CHECKING:
from sphinx.application import Sphinx
from sphinx.util.typing import ExtensionMetadata

logger = logging.getLogger("availability")

# known platform, libc, and threading implementations
_PLATFORMS = frozenset({
"AIX",
"Android",
"BSD",
"DragonFlyBSD",
"Emscripten",
"FreeBSD",
"GNU/kFreeBSD",
"iOS",
"Linux",
"macOS",
"NetBSD",
"OpenBSD",
"POSIX",
"Solaris",
"Unix",
"VxWorks",
"WASI",
"Windows",
})
_LIBC = frozenset({
"BSD libc",
"glibc",
"musl",
})
_THREADING = frozenset({
# POSIX platforms with pthreads
"pthreads",
})
KNOWN_PLATFORMS = _PLATFORMS | _LIBC | _THREADING


class Availability(SphinxDirective):
has_content = True
required_arguments = 1
optional_arguments = 0
final_argument_whitespace = True

def run(self) -> list[nodes.container]:
title = "Availability"
refnode = addnodes.pending_xref(
title,
nodes.inline(title, title, classes=["xref", "std", "std-ref"]),
refdoc=self.env.docname,
refdomain="std",
refexplicit=True,
reftarget="availability",
reftype="ref",
refwarn=True,
)
sep = nodes.Text(": ")
parsed, msgs = self.state.inline_text(self.arguments[0], self.lineno)
pnode = nodes.paragraph(title, "", refnode, sep, *parsed, *msgs)
self.set_source_info(pnode)
cnode = nodes.container("", pnode, classes=["availability"])
self.set_source_info(cnode)
if self.content:
self.state.nested_parse(self.content, self.content_offset, cnode)
self.parse_platforms()

return [cnode]

def parse_platforms(self) -> dict[str, str | bool]:
"""Parse platform information from arguments
Arguments is a comma-separated string of platforms. A platform may
be prefixed with "not " to indicate that a feature is not available.
Example::
.. availability:: Windows, Linux >= 4.2, not WASI
Arguments like "Linux >= 3.17 with glibc >= 2.27" are currently not
parsed into separate tokens.
"""
platforms = {}
for arg in self.arguments[0].rstrip(".").split(","):
arg = arg.strip()
platform, _, version = arg.partition(" >= ")
if platform.startswith("not "):
version = False
platform = platform.removeprefix("not ")
elif not version:
version = True
platforms[platform] = version

if unknown := set(platforms).difference(KNOWN_PLATFORMS):
logger.warning(
"Unknown platform%s or syntax '%s' in '.. availability:: %s', "
"see %s:KNOWN_PLATFORMS for a set of known platforms.",
"s" if len(platforms) != 1 else "",
" ".join(sorted(unknown)),
self.arguments[0],
__file__,
)

return platforms


def setup(app: Sphinx) -> ExtensionMetadata:
app.add_directive("availability", Availability)

return {
"version": "1.0",
"parallel_read_safe": True,
"parallel_write_safe": True,
}
Loading

0 comments on commit cfe03c7

Please sign in to comment.