From 22e5d8320a72bbae5b4e99fce14247279fa2d522 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Fri, 4 Aug 2023 21:12:25 +0100 Subject: [PATCH 01/17] Add what's new for PEP 669 --- Doc/whatsnew/3.12.rst | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/Doc/whatsnew/3.12.rst b/Doc/whatsnew/3.12.rst index 6553013552d003..093a287fca57c5 100644 --- a/Doc/whatsnew/3.12.rst +++ b/Doc/whatsnew/3.12.rst @@ -73,6 +73,8 @@ Interpreter improvements: * :ref:`whatsnew312-pep684` +* :ref:`whatsnew312-pep669` + New typing features: * :pep:`688`: Making the buffer protocol accessible in Python @@ -310,6 +312,19 @@ A Python API is anticipated for 3.13. (See :pep:`554`.) (Contributed by Eric Snow in :gh:`104210`, etc.) +.. _whatsnew312-pep684: + +PEP 669: Low impact monitoring for CPython +------------------------------------------ + +CPython 3.12 now supports the ability to monitor calls, +returns, lines, exceptions and other events using instrumentation. +This means that you only pay for what you use, providing support +for near-zero overhead debuggers and coverage tools. + +See :mod:`sys.monitoring` for details. + + New Features Related to Type Hints ================================== From 6e5a4350cbdbcb9b501c3568edb77dd02f6cd928 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Fri, 4 Aug 2023 21:15:31 +0100 Subject: [PATCH 02/17] Document sys.monitoring. First draft. --- Doc/library/sys.monitoring.rst | 267 +++++++++++++++++++++++++++++++++ Doc/library/sys.rst | 6 + 2 files changed, 273 insertions(+) create mode 100644 Doc/library/sys.monitoring.rst diff --git a/Doc/library/sys.monitoring.rst b/Doc/library/sys.monitoring.rst new file mode 100644 index 00000000000000..99ab0ba7cf61b1 --- /dev/null +++ b/Doc/library/sys.monitoring.rst @@ -0,0 +1,267 @@ +:mod:`sys.monitoring` --- Execution event monitoring +==================================================== + +.. module:: sys.monitoring + :synopsis: Access and control event monitoring + + .. note:: + + :mod:`sys.monitoring` is a namespace within the `sys` module, + not an independent module, so ``import sys.monitoring`` will not + work. + +----------------- + +This namespace provides access to the functions and constants necessary to +activate and control event monitoring. + +As programs execute, events occur that might be of interest to tools that +monitor execution. The `mod:`sys.monitoring` namespace provides means to +receive callbacks when events of interest occur. + +The monitoring API consists of three components: + +* Tool identifiers +* Events +* Callbacks + +Tool identifiers +---------------- + +A tool identifier is an integer and associated name. +Tool identifiers are used to discourage tools from interfering with each +other and to allow multiple tools to operate at the same time. +Currently tools are completely independent and cannot be used to +monitor each other. This restriction may be lifted in the future. + +Before registering or activating events, a tool should choose an identifier. +Identifiers are integers in the range 0 to 5. + +To register a tool:: + + sys.monitoring.use_tool_id(id: range(6), name:str) -> None + sys.monitoring.free_tool_id(id: range(6)) -> None + sys.monitoring.get_tool(id: range(6)) -> str | None + + +``sys.monitoring.use_tool_id`` raises a ``ValueError`` if ``id`` is in use. +``sys.monitoring.get_tool`` returns the name of the tool if ``id`` is in use, +otherwise it returns ``None``. + +All IDs are treated the same by the VM with regard to events, but the +following IDs are pre-defined to make co-operation of tools easier:: + + sys.monitoring.DEBUGGER_ID = 0 + sys.monitoring.COVERAGE_ID = 1 + sys.monitoring.PROFILER_ID = 2 + sys.monitoring.OPTIMIZER_ID = 5 + +There is no obligation to set an ID, nor is there anything preventing a tool +from using an ID even it is already in use. +However, tools are encouraged to use a unique ID and respect other tools. + +Events +------ + +The following events are supported: + +* BRANCH: A conditional branch is taken (or not). +* CALL: A call in Python code (event occurs before the call). +* C_RAISE: Exception raised from any callable, except Python functions (event occurs after the exit). +* C_RETURN: Return from any callable, except Python functions (event occurs after the return). +* EXCEPTION_HANDLED: An exception is handled. +* INSTRUCTION: A VM instruction is about to be executed. +* JUMP: An unconditional jump in the control flow graph is made. +* LINE: An instruction is about to be executed that has a different line number from the preceding instruction. +* PY_RESUME: Resumption of a Python function (for generator and coroutine functions), except for throw() calls. +* PY_RETURN: Return from a Python function (occurs immediately before the return, the callee's frame will be on the stack). +* PY_START: Start of a Python function (occurs immediately after the call, the callee's frame will be on the stack) +* PY_THROW: A Python function is resumed by a throw() call. +* PY_UNWIND: Exit from a Python function during exception unwinding. +* PY_YIELD: Yield from a Python function (occurs immediately before the yield, the callee's frame will be on the stack). +* RAISE: An exception is raised, except those that cause a ``STOP_ITERATION`` event. +* RERAISE: An exception is re-raised, for example at the end of a ``finally`` block. +* STOP_ITERATION -- An artificial ``StopIteration`` is raised; + see `the STOP_ITERATION event`_. + +More events may be added in the future. + +These events are attributes of the `:mod:sys.monitoring.events` namespace. +Each event is represented as a power-of-2 integer constant. +To define a set of events, simply bitwise or the individual events together. +For example, to specify both ``PY_RETURN`` and ``PY_START`` events, use the +expression ``PY_RETURN | PY_START``. + +Events are divided into three groups: + +Local events +'''''''''''' + +Local events are associated with normal execution of the program and happen +at clearly defined locations. All local events can be disabled. +The local events are: + +* PY_START +* PY_RESUME +* PY_RETURN +* PY_YIELD +* CALL +* LINE +* INSTRUCTION +* JUMP +* BRANCH +* STOP_ITERATION + +Ancilliary events +''''''''''''''''' + +Ancillary events can be monitored like other events, but are controlled +by another event: + +* C_RAISE +* C_RETURN + +The ``C_RETURN`` and ``C_RAISE`` events are are controlled by the ``CALL`` +event. ``C_RETURN`` and ``C_RAISE`` events will only be seen if the +corresponding ``CALL`` event is being monitored. + +Other events +'''''''''''' + +Other events are not necessarily tied to a specific location in the +program and cannot be individually disabled. + +The other events that can be monitored are: + +* PY_THROW +* PY_UNWIND +* RAISE +* EXCEPTION_HANDLED + + +The STOP_ITERATION event +'''''''''''''''''''''''' + +:pep:`PEP 380 <380#use-of-stopiteration-to-return-values>` +specifies that a ``StopIteration`` exception is raised when returning a value +from a generator or coroutine. However, this is a very inefficient way to +return a value, so some Python implementations, notably CPython 3.12+, do not +raise an exception unless it would be visible to other code. + +To allow tools to monitor for real exceptions without slowing down generators +and coroutines, the ``STOP_ITERATION`` event is provided. +``STOP_ITERATION`` can be locally disabled, unlike ``RAISE``. + + +Turning events on and off +------------------------- + +In order to monitor an event, it must be turned on and a callback registered. +Events can be turned on or off by setting the events either globally or +for a particular code object. + + +Setting events globally +''''''''''''''''''''''' + +Events can be controlled globally by modifying the set of events being monitored: + +* ``sys.monitoring.get_events(tool_id:int)->int`` + Returns the ``int`` representing all the active events. + +* ``sys.monitoring.set_events(tool_id:int, event_set: int)`` + Activates all events which are set in ``event_set``. + Raises a ``ValueError`` if ``tool_id`` is not in use. + +No events are active by default. + +Per code object events +'''''''''''''''''''''' + +Events can also be controlled on a per code object basis: + +* ``sys.monitoring.get_local_events(tool_id:int, code: CodeType)->int`` + Returns all the local events for ``code`` + +* ``sys.monitoring.set_local_events(tool_id:int, code: CodeType, event_set: int)`` + Activates all the local events for ``code`` which are set in ``event_set``. + Raises a ``ValueError`` if ``tool_id`` is not in use. + +Local events add to global events, but do not mask them. +In other words, all global events will trigger for a code object, +regardless of the local events. + + +Disabling events +'''''''''''''''' + +Local events can be disabled for a specific code location by returning +`sys.monitoring.DISABLE` from a callback function. This does not change +which events are set, or any other code locations for the same event. + +Disabling events for specific locations is very important for high +performance monitoring. For example, a program can be run under a +debugger with no overhead if the debugger disables all monitoring +except for a few breakpoints. + + +Registering callback functions +------------------------------ + +To register a callable for events call:: + + sys.monitoring.register_callback(tool_id:int, event: int, func: Callable | None) -> Callable | None + +If another callback was registered for the given ``tool_id`` and ``event``, +it is unregistered and returned. +Otherwise ``register_callback`` returns ``None``. + +Functions can be unregistered by calling +``sys.monitoring.register_callback(tool_id, event, None)``. + +Callback functions can be registered and unregistered at any time. + +Registering or unregistering a callback function will generate a ``sys.audit`` event. + + +Callback function arguments +''''''''''''''''''''''''''' + +When an active event occurs, the registered callback function is called. +Different events will provide the callback function with different arguments, as follows: + +* ``PY_START`` and ``PY_RESUME``:: + + func(code: CodeType, instruction_offset: int) -> DISABLE | Any + +* ``PY_RETURN`` and ``PY_YIELD``: + + ``func(code: CodeType, instruction_offset: int, retval: object) -> DISABLE | Any`` + +* ``CALL``, ``C_RAISE`` and ``C_RETURN``: + + ``func(code: CodeType, instruction_offset: int, callable: object, arg0: object | MISSING) -> DISABLE | Any`` + + If there are no arguments, ``arg0`` is set to ``MISSING``. + +* ``RAISE``, ``RERAISE``, ``EXCEPTION_HANDLED``, ``PY_UNWIND``, ``PY_THROW`` and ``STOP_ITERATION``: + + ``func(code: CodeType, instruction_offset: int, exception: BaseException) -> DISABLE | Any`` + +* ``LINE``: + + ``func(code: CodeType, line_number: int) -> DISABLE | Any`` + +* ``BRANCH`` and ``JUMP``: + + ``func(code: CodeType, instruction_offset: int, destination_offset: int) -> DISABLE | Any`` + + Note that the ``destination_offset`` is where the code will next execute. + For an untaken branch this will be the offset of the instruction following + the branch. + +* ``INSTRUCTION``: + + ``func(code: CodeType, instruction_offset: int) -> DISABLE | Any`` + + diff --git a/Doc/library/sys.rst b/Doc/library/sys.rst index a61737383e3939..2eaa80adf2d28f 100644 --- a/Doc/library/sys.rst +++ b/Doc/library/sys.rst @@ -1880,6 +1880,12 @@ always available. .. availability:: Windows. +.. data:: monitoring + + Namespace containing functions and constants for register callbacks + and controlling monitoring events. + See :mod:`sys.monitoring` for details. + .. data:: _xoptions A dictionary of the various implementation-specific flags passed through From e373cbe678ee16518b9be02859fb1c320508c42d Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Sat, 5 Aug 2023 01:11:47 +0100 Subject: [PATCH 03/17] Fix sphinx errors --- Doc/library/python.rst | 1 + Doc/library/sys.monitoring.rst | 7 ++++--- Doc/library/sys.rst | 1 + Doc/whatsnew/3.12.rst | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Doc/library/python.rst b/Doc/library/python.rst index f39613f572884f..610435999d9f48 100644 --- a/Doc/library/python.rst +++ b/Doc/library/python.rst @@ -12,6 +12,7 @@ overview: .. toctree:: sys.rst + sys.monitoring.rst sysconfig.rst builtins.rst __main__.rst diff --git a/Doc/library/sys.monitoring.rst b/Doc/library/sys.monitoring.rst index 99ab0ba7cf61b1..9828628a1470b7 100644 --- a/Doc/library/sys.monitoring.rst +++ b/Doc/library/sys.monitoring.rst @@ -2,6 +2,7 @@ ==================================================== .. module:: sys.monitoring + :synopsis: Access and control event monitoring .. note:: @@ -16,7 +17,7 @@ This namespace provides access to the functions and constants necessary to activate and control event monitoring. As programs execute, events occur that might be of interest to tools that -monitor execution. The `mod:`sys.monitoring` namespace provides means to +monitor execution. The :mod:`sys.monitoring` namespace provides means to receive callbacks when events of interest occur. The monitoring API consists of three components: @@ -86,7 +87,7 @@ The following events are supported: More events may be added in the future. -These events are attributes of the `:mod:sys.monitoring.events` namespace. +These events are attributes of the :mod:`sys.monitoring.events` namespace. Each event is represented as a power-of-2 integer constant. To define a set of events, simply bitwise or the individual events together. For example, to specify both ``PY_RETURN`` and ``PY_START`` events, use the @@ -196,7 +197,7 @@ Disabling events '''''''''''''''' Local events can be disabled for a specific code location by returning -`sys.monitoring.DISABLE` from a callback function. This does not change +``sys.monitoring.DISABLE`` from a callback function. This does not change which events are set, or any other code locations for the same event. Disabling events for specific locations is very important for high diff --git a/Doc/library/sys.rst b/Doc/library/sys.rst index 2eaa80adf2d28f..64bdffb80ad83e 100644 --- a/Doc/library/sys.rst +++ b/Doc/library/sys.rst @@ -1881,6 +1881,7 @@ always available. .. data:: monitoring + :noindex: Namespace containing functions and constants for register callbacks and controlling monitoring events. diff --git a/Doc/whatsnew/3.12.rst b/Doc/whatsnew/3.12.rst index 093a287fca57c5..7fa7f6170a14d1 100644 --- a/Doc/whatsnew/3.12.rst +++ b/Doc/whatsnew/3.12.rst @@ -312,7 +312,7 @@ A Python API is anticipated for 3.13. (See :pep:`554`.) (Contributed by Eric Snow in :gh:`104210`, etc.) -.. _whatsnew312-pep684: +.. _whatsnew312-pep669: PEP 669: Low impact monitoring for CPython ------------------------------------------ From c648e70969d84679d265993c48e2cc0bec0aa197 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Mon, 28 Aug 2023 01:02:49 +0100 Subject: [PATCH 04/17] Address review comments --- Doc/library/sys.monitoring.rst | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/Doc/library/sys.monitoring.rst b/Doc/library/sys.monitoring.rst index 9828628a1470b7..b8169b08b0c486 100644 --- a/Doc/library/sys.monitoring.rst +++ b/Doc/library/sys.monitoring.rst @@ -7,7 +7,7 @@ .. note:: - :mod:`sys.monitoring` is a namespace within the `sys` module, + :mod:`!sys.monitoring` is a namespace within the `sys` module, not an independent module, so ``import sys.monitoring`` will not work. @@ -17,7 +17,7 @@ This namespace provides access to the functions and constants necessary to activate and control event monitoring. As programs execute, events occur that might be of interest to tools that -monitor execution. The :mod:`sys.monitoring` namespace provides means to +monitor execution. The :mod:`!sys.monitoring` namespace provides means to receive callbacks when events of interest occur. The monitoring API consists of three components: @@ -40,14 +40,15 @@ Identifiers are integers in the range 0 to 5. To register a tool:: - sys.monitoring.use_tool_id(id: range(6), name:str) -> None + sys.monitoring.use_tool_id(id: range(6), name: str) -> None sys.monitoring.free_tool_id(id: range(6)) -> None sys.monitoring.get_tool(id: range(6)) -> str | None -``sys.monitoring.use_tool_id`` raises a ``ValueError`` if ``id`` is in use. -``sys.monitoring.get_tool`` returns the name of the tool if ``id`` is in use, -otherwise it returns ``None``. +:py:func:`sys.monitoring.use_tool_id` raises a ``ValueError`` +if ``id`` is in use. +:py:func:`sys.monitoring.get_tool` returns the name of the tool +if ``id`` is in use, otherwise it returns ``None``. All IDs are treated the same by the VM with regard to events, but the following IDs are pre-defined to make co-operation of tools easier:: @@ -87,7 +88,7 @@ The following events are supported: More events may be added in the future. -These events are attributes of the :mod:`sys.monitoring.events` namespace. +These events are attributes of the :mod:`!sys.monitoring.events` namespace. Each event is represented as a power-of-2 integer constant. To define a set of events, simply bitwise or the individual events together. For example, to specify both ``PY_RETURN`` and ``PY_START`` events, use the @@ -113,8 +114,8 @@ The local events are: * BRANCH * STOP_ITERATION -Ancilliary events -''''''''''''''''' +Ancillary events +'''''''''''''''' Ancillary events can be monitored like other events, but are controlled by another event: @@ -167,10 +168,10 @@ Setting events globally Events can be controlled globally by modifying the set of events being monitored: -* ``sys.monitoring.get_events(tool_id:int)->int`` +* ``sys.monitoring.get_events(tool_id: int) -> int`` Returns the ``int`` representing all the active events. -* ``sys.monitoring.set_events(tool_id:int, event_set: int)`` +* ``sys.monitoring.set_events(tool_id: int, event_set: int)`` Activates all events which are set in ``event_set``. Raises a ``ValueError`` if ``tool_id`` is not in use. @@ -181,10 +182,10 @@ Per code object events Events can also be controlled on a per code object basis: -* ``sys.monitoring.get_local_events(tool_id:int, code: CodeType)->int`` +* ``sys.monitoring.get_local_events(tool_id: int, code: CodeType) -> int`` Returns all the local events for ``code`` -* ``sys.monitoring.set_local_events(tool_id:int, code: CodeType, event_set: int)`` +* ``sys.monitoring.set_local_events(tool_id: int, code: CodeType, event_set: int)`` Activates all the local events for ``code`` which are set in ``event_set``. Raises a ``ValueError`` if ``tool_id`` is not in use. @@ -211,7 +212,7 @@ Registering callback functions To register a callable for events call:: - sys.monitoring.register_callback(tool_id:int, event: int, func: Callable | None) -> Callable | None + sys.monitoring.register_callback(tool_id: int, event: int, func: Callable | None) -> Callable | None If another callback was registered for the given ``tool_id`` and ``event``, it is unregistered and returned. From c15022c03854a9d62048cab79c3edee7991764b0 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Mon, 28 Aug 2023 01:32:30 +0100 Subject: [PATCH 05/17] Use add more cross-references --- Doc/library/sys.monitoring.rst | 62 ++++++++++++++++++++-------------- 1 file changed, 37 insertions(+), 25 deletions(-) diff --git a/Doc/library/sys.monitoring.rst b/Doc/library/sys.monitoring.rst index b8169b08b0c486..7d7c2d5d328dc2 100644 --- a/Doc/library/sys.monitoring.rst +++ b/Doc/library/sys.monitoring.rst @@ -38,17 +38,22 @@ monitor each other. This restriction may be lifted in the future. Before registering or activating events, a tool should choose an identifier. Identifiers are integers in the range 0 to 5. -To register a tool:: +Registering and using tools +''''''''''''''''''''''''''' + +.. function:: use_tool_id(id: range(6), name: str) -> None + + Must be called before ``id`` can be used. + Raises a ``ValueError`` if ``id`` is in use. - sys.monitoring.use_tool_id(id: range(6), name: str) -> None - sys.monitoring.free_tool_id(id: range(6)) -> None - sys.monitoring.get_tool(id: range(6)) -> str | None +.. function:: free_tool_id(id: range(6)) -> None + Should be called once a tool no longer requires ``id``. -:py:func:`sys.monitoring.use_tool_id` raises a ``ValueError`` -if ``id`` is in use. -:py:func:`sys.monitoring.get_tool` returns the name of the tool -if ``id`` is in use, otherwise it returns ``None``. +.. function:: get_tool(id: range(6)) -> str | None + + Returns the name of the tool if ``id`` is in use, + otherwise it returns ``None``. All IDs are treated the same by the VM with regard to events, but the following IDs are pre-defined to make co-operation of tools easier:: @@ -166,28 +171,32 @@ for a particular code object. Setting events globally ''''''''''''''''''''''' -Events can be controlled globally by modifying the set of events being monitored: +Events can be controlled globally by modifying the set of events being monitored. + +.. function:: sys.monitoring.get_events(tool_id: int) -> int -* ``sys.monitoring.get_events(tool_id: int) -> int`` - Returns the ``int`` representing all the active events. + Returns the ``int`` representing all the active events. -* ``sys.monitoring.set_events(tool_id: int, event_set: int)`` - Activates all events which are set in ``event_set``. - Raises a ``ValueError`` if ``tool_id`` is not in use. +.. function:: sys.monitoring.set_events(tool_id: int, event_set: int) + + Activates all events which are set in ``event_set``. + Raises a ``ValueError`` if ``tool_id`` is not in use. No events are active by default. Per code object events '''''''''''''''''''''' -Events can also be controlled on a per code object basis: +Events can also be controlled on a per code object basis. + +.. function:: sys.monitoring.get_local_events(tool_id: int, code: CodeType) -> int + + Returns all the local events for ``code`` -* ``sys.monitoring.get_local_events(tool_id: int, code: CodeType) -> int`` - Returns all the local events for ``code`` +.. function:: sys.monitoring.set_local_events(tool_id: int, code: CodeType, event_set: int) -* ``sys.monitoring.set_local_events(tool_id: int, code: CodeType, event_set: int)`` - Activates all the local events for ``code`` which are set in ``event_set``. - Raises a ``ValueError`` if ``tool_id`` is not in use. + Activates all the local events for ``code`` which are set in ``event_set``. + Raises a ``ValueError`` if ``tool_id`` is not in use. Local events add to global events, but do not mask them. In other words, all global events will trigger for a code object, @@ -210,13 +219,16 @@ except for a few breakpoints. Registering callback functions ------------------------------ -To register a callable for events call:: +To register a callable for events call + +.. function:: sys.monitoring.register_callback(tool_id: int, event: int, func: Callable | None) -> Callable | None + + Registers the callable ``func`` for the ``event`` with the given ``tool_id`` - sys.monitoring.register_callback(tool_id: int, event: int, func: Callable | None) -> Callable | None + If another callback was registered for the given ``tool_id`` and ``event``, + it is unregistered and returned. + Otherwise ``register_callback`` returns ``None``. -If another callback was registered for the given ``tool_id`` and ``event``, -it is unregistered and returned. -Otherwise ``register_callback`` returns ``None``. Functions can be unregistered by calling ``sys.monitoring.register_callback(tool_id, event, None)``. From 5d547040a098cdf5822a71aaf3d993f1095804f4 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Mon, 28 Aug 2023 01:38:42 +0100 Subject: [PATCH 06/17] Fix note --- Doc/library/sys.monitoring.rst | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Doc/library/sys.monitoring.rst b/Doc/library/sys.monitoring.rst index 7d7c2d5d328dc2..835ec2705bd11b 100644 --- a/Doc/library/sys.monitoring.rst +++ b/Doc/library/sys.monitoring.rst @@ -5,11 +5,12 @@ :synopsis: Access and control event monitoring - .. note:: +.. note:: - :mod:`!sys.monitoring` is a namespace within the `sys` module, - not an independent module, so ``import sys.monitoring`` will not - work. + :mod:`!sys.monitoring` is a namespace within the `sys` module, + not an independent module, so there is no need to + ``import sys.monitoring``, simply ``import sys`` and then use + ``sys.monitoring``. ----------------- From 7a500bd1d95deb20a9b8dc1c85f38010063985a2 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Mon, 28 Aug 2023 01:41:52 +0100 Subject: [PATCH 07/17] Fix lint --- Doc/library/sys.monitoring.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/sys.monitoring.rst b/Doc/library/sys.monitoring.rst index 835ec2705bd11b..3199836a5135f4 100644 --- a/Doc/library/sys.monitoring.rst +++ b/Doc/library/sys.monitoring.rst @@ -7,7 +7,7 @@ .. note:: - :mod:`!sys.monitoring` is a namespace within the `sys` module, + ``sys.monitoring`` is a namespace within the `sys` module, not an independent module, so there is no need to ``import sys.monitoring``, simply ``import sys`` and then use ``sys.monitoring``. From bb4100ce00a390ae53fddfa801c323c2e7a46998 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Mon, 28 Aug 2023 01:42:38 +0100 Subject: [PATCH 08/17] Fix lint --- Doc/library/sys.monitoring.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/sys.monitoring.rst b/Doc/library/sys.monitoring.rst index 3199836a5135f4..48f9189a65df40 100644 --- a/Doc/library/sys.monitoring.rst +++ b/Doc/library/sys.monitoring.rst @@ -7,7 +7,7 @@ .. note:: - ``sys.monitoring`` is a namespace within the `sys` module, + ``sys.monitoring`` is a namespace within the ``sys`` module, not an independent module, so there is no need to ``import sys.monitoring``, simply ``import sys`` and then use ``sys.monitoring``. From 181843ef5f0f7af7b50e68de07f2302689a73ca8 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Mon, 28 Aug 2023 01:49:11 +0100 Subject: [PATCH 09/17] Another attempt to fix the syntax --- Doc/library/sys.monitoring.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/sys.monitoring.rst b/Doc/library/sys.monitoring.rst index 48f9189a65df40..5f8ff6edca845f 100644 --- a/Doc/library/sys.monitoring.rst +++ b/Doc/library/sys.monitoring.rst @@ -2,9 +2,10 @@ ==================================================== .. module:: sys.monitoring - :synopsis: Access and control event monitoring +----------------- + .. note:: ``sys.monitoring`` is a namespace within the ``sys`` module, @@ -12,7 +13,6 @@ ``import sys.monitoring``, simply ``import sys`` and then use ``sys.monitoring``. ------------------ This namespace provides access to the functions and constants necessary to activate and control event monitoring. From fb16167855c3af7ae8ce8214801af90203e67bfd Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Tue, 5 Sep 2023 12:00:38 +0100 Subject: [PATCH 10/17] Update Doc/library/sys.monitoring.rst Co-authored-by: Adam Turner <9087854+AA-Turner@users.noreply.github.com> --- Doc/library/sys.monitoring.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/sys.monitoring.rst b/Doc/library/sys.monitoring.rst index 5f8ff6edca845f..2149dc6efbe732 100644 --- a/Doc/library/sys.monitoring.rst +++ b/Doc/library/sys.monitoring.rst @@ -174,7 +174,7 @@ Setting events globally Events can be controlled globally by modifying the set of events being monitored. -.. function:: sys.monitoring.get_events(tool_id: int) -> int +.. function:: get_events(tool_id: int) -> int Returns the ``int`` representing all the active events. From bfb3b1d9c9fd6e110cae1982f39f874449f013ae Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Tue, 5 Sep 2023 12:00:44 +0100 Subject: [PATCH 11/17] Update Doc/library/sys.monitoring.rst Co-authored-by: Adam Turner <9087854+AA-Turner@users.noreply.github.com> --- Doc/library/sys.monitoring.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/sys.monitoring.rst b/Doc/library/sys.monitoring.rst index 2149dc6efbe732..f576a8bf4c367c 100644 --- a/Doc/library/sys.monitoring.rst +++ b/Doc/library/sys.monitoring.rst @@ -178,7 +178,7 @@ Events can be controlled globally by modifying the set of events being monitored Returns the ``int`` representing all the active events. -.. function:: sys.monitoring.set_events(tool_id: int, event_set: int) +.. function:: set_events(tool_id: int, event_set: int) Activates all events which are set in ``event_set``. Raises a ``ValueError`` if ``tool_id`` is not in use. From 0833922f7946f3724d1584f017137c99e8ddfc46 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Tue, 5 Sep 2023 12:00:53 +0100 Subject: [PATCH 12/17] Update Doc/library/sys.monitoring.rst Co-authored-by: Adam Turner <9087854+AA-Turner@users.noreply.github.com> --- Doc/library/sys.monitoring.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/sys.monitoring.rst b/Doc/library/sys.monitoring.rst index f576a8bf4c367c..13e741d51783c5 100644 --- a/Doc/library/sys.monitoring.rst +++ b/Doc/library/sys.monitoring.rst @@ -190,7 +190,7 @@ Per code object events Events can also be controlled on a per code object basis. -.. function:: sys.monitoring.get_local_events(tool_id: int, code: CodeType) -> int +.. function:: get_local_events(tool_id: int, code: CodeType) -> int Returns all the local events for ``code`` From 63643151f868e30bbd3fceda598ca3131fdb0db4 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Tue, 5 Sep 2023 12:01:04 +0100 Subject: [PATCH 13/17] Update Doc/library/sys.monitoring.rst Co-authored-by: Adam Turner <9087854+AA-Turner@users.noreply.github.com> --- Doc/library/sys.monitoring.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/sys.monitoring.rst b/Doc/library/sys.monitoring.rst index 13e741d51783c5..7fa1638cee0b46 100644 --- a/Doc/library/sys.monitoring.rst +++ b/Doc/library/sys.monitoring.rst @@ -194,7 +194,7 @@ Events can also be controlled on a per code object basis. Returns all the local events for ``code`` -.. function:: sys.monitoring.set_local_events(tool_id: int, code: CodeType, event_set: int) +.. function:: set_local_events(tool_id: int, code: CodeType, event_set: int) Activates all the local events for ``code`` which are set in ``event_set``. Raises a ``ValueError`` if ``tool_id`` is not in use. From 48943333776b9a6ab351b4a30b4c5ee4b14c2af2 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Tue, 5 Sep 2023 12:01:11 +0100 Subject: [PATCH 14/17] Update Doc/library/sys.monitoring.rst Co-authored-by: Adam Turner <9087854+AA-Turner@users.noreply.github.com> --- Doc/library/sys.monitoring.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/sys.monitoring.rst b/Doc/library/sys.monitoring.rst index 7fa1638cee0b46..cc3744b53ee682 100644 --- a/Doc/library/sys.monitoring.rst +++ b/Doc/library/sys.monitoring.rst @@ -222,7 +222,7 @@ Registering callback functions To register a callable for events call -.. function:: sys.monitoring.register_callback(tool_id: int, event: int, func: Callable | None) -> Callable | None +.. function:: register_callback(tool_id: int, event: int, func: Callable | None) -> Callable | None Registers the callable ``func`` for the ``event`` with the given ``tool_id`` From a94367985a19706bd23bd70824fea559796b4d7d Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Tue, 5 Sep 2023 12:02:55 +0100 Subject: [PATCH 15/17] Apply suggestions from code review Co-authored-by: Adam Turner <9087854+AA-Turner@users.noreply.github.com> --- Doc/library/sys.monitoring.rst | 54 ++++++++++++++++++++++------------ 1 file changed, 35 insertions(+), 19 deletions(-) diff --git a/Doc/library/sys.monitoring.rst b/Doc/library/sys.monitoring.rst index cc3744b53ee682..5993a445e139e2 100644 --- a/Doc/library/sys.monitoring.rst +++ b/Doc/library/sys.monitoring.rst @@ -73,24 +73,40 @@ Events The following events are supported: -* BRANCH: A conditional branch is taken (or not). -* CALL: A call in Python code (event occurs before the call). -* C_RAISE: Exception raised from any callable, except Python functions (event occurs after the exit). -* C_RETURN: Return from any callable, except Python functions (event occurs after the return). -* EXCEPTION_HANDLED: An exception is handled. -* INSTRUCTION: A VM instruction is about to be executed. -* JUMP: An unconditional jump in the control flow graph is made. -* LINE: An instruction is about to be executed that has a different line number from the preceding instruction. -* PY_RESUME: Resumption of a Python function (for generator and coroutine functions), except for throw() calls. -* PY_RETURN: Return from a Python function (occurs immediately before the return, the callee's frame will be on the stack). -* PY_START: Start of a Python function (occurs immediately after the call, the callee's frame will be on the stack) -* PY_THROW: A Python function is resumed by a throw() call. -* PY_UNWIND: Exit from a Python function during exception unwinding. -* PY_YIELD: Yield from a Python function (occurs immediately before the yield, the callee's frame will be on the stack). -* RAISE: An exception is raised, except those that cause a ``STOP_ITERATION`` event. -* RERAISE: An exception is re-raised, for example at the end of a ``finally`` block. -* STOP_ITERATION -- An artificial ``StopIteration`` is raised; - see `the STOP_ITERATION event`_. +BRANCH + A conditional branch is taken (or not). +CALL + A call in Python code (event occurs before the call). +C_RAISE + Exception raised from any callable, except Python functions (event occurs after the exit). +C_RETURN + Return from any callable, except Python functions (event occurs after the return). +EXCEPTION_HANDLED + An exception is handled. +INSTRUCTION + A VM instruction is about to be executed. +JUMP + An unconditional jump in the control flow graph is made. +LINE + An instruction is about to be executed that has a different line number from the preceding instruction. +PY_RESUME + Resumption of a Python function (for generator and coroutine functions), except for throw() calls. +PY_RETURN + Return from a Python function (occurs immediately before the return, the callee's frame will be on the stack). +PY_START + Start of a Python function (occurs immediately after the call, the callee's frame will be on the stack) +PY_THROW + A Python function is resumed by a throw() call. +PY_UNWIND + Exit from a Python function during exception unwinding. +PY_YIELD + Yield from a Python function (occurs immediately before the yield, the callee's frame will be on the stack). +RAISE + An exception is raised, except those that cause a ``STOP_ITERATION`` event. +RERAISE + An exception is re-raised, for example at the end of a ``finally`` block. +STOP_ITERATION + An artificial ``StopIteration`` is raised; see `the STOP_ITERATION event`_. More events may be added in the future. @@ -196,7 +212,7 @@ Events can also be controlled on a per code object basis. .. function:: set_local_events(tool_id: int, code: CodeType, event_set: int) - Activates all the local events for ``code`` which are set in ``event_set``. + Activates all the local events for ``code`` which are set in ``event_set``. Raises a ``ValueError`` if ``tool_id`` is not in use. Local events add to global events, but do not mask them. From 002e74469280603b90afb9a2d11ba554a1613ecd Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Tue, 5 Sep 2023 02:14:43 +0100 Subject: [PATCH 16/17] Drop use of range(6) to avoid confusing sphinx --- Doc/library/sys.monitoring.rst | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Doc/library/sys.monitoring.rst b/Doc/library/sys.monitoring.rst index 5993a445e139e2..8c2f11a6ee4328 100644 --- a/Doc/library/sys.monitoring.rst +++ b/Doc/library/sys.monitoring.rst @@ -42,19 +42,21 @@ Identifiers are integers in the range 0 to 5. Registering and using tools ''''''''''''''''''''''''''' -.. function:: use_tool_id(id: range(6), name: str) -> None +.. function:: use_tool_id(id: int, name: str) -> None Must be called before ``id`` can be used. + ``id`` must be in the range 0 to 5 inclusive. Raises a ``ValueError`` if ``id`` is in use. -.. function:: free_tool_id(id: range(6)) -> None +.. function:: free_tool_id(id: int) -> None Should be called once a tool no longer requires ``id``. -.. function:: get_tool(id: range(6)) -> str | None +.. function:: get_tool(id: int) -> str | None Returns the name of the tool if ``id`` is in use, otherwise it returns ``None``. + ``id`` must be in the range 0 to 5 inclusive. All IDs are treated the same by the VM with regard to events, but the following IDs are pre-defined to make co-operation of tools easier:: From 200e4a31ccb68280d029be0969411afa900c972a Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Tue, 5 Sep 2023 02:16:07 +0100 Subject: [PATCH 17/17] Remove double space --- Doc/library/sys.monitoring.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/sys.monitoring.rst b/Doc/library/sys.monitoring.rst index 8c2f11a6ee4328..7b02b95fd766a7 100644 --- a/Doc/library/sys.monitoring.rst +++ b/Doc/library/sys.monitoring.rst @@ -52,7 +52,7 @@ Registering and using tools Should be called once a tool no longer requires ``id``. -.. function:: get_tool(id: int) -> str | None +.. function:: get_tool(id: int) -> str | None Returns the name of the tool if ``id`` is in use, otherwise it returns ``None``.