From 32cd414122128986ddd789729b76949efadc8f9e Mon Sep 17 00:00:00 2001 From: Kostya Farber Date: Sun, 6 Aug 2023 16:22:22 +0100 Subject: [PATCH 01/10] add docs to ctypes array --- Modules/_ctypes/_ctypes.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 9aee37a9d954ef..3ab0c45bd336fe 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -4793,6 +4793,15 @@ static PyMappingMethods Array_as_mapping = { Array_ass_subscript, }; +PyDoc_STRVAR(array_doc, +"Abstract base class for arrays.\n" +"\n" +"The recommended way to create concrete array types is by multiplying any ctypes data type with\n" +"a non-negative integer. Alternatively, you can subclass this type and define _length_ and _type_\n" +"class variables. Array elements can be read and written using standard subscript and slice accesses;\n" +"for slice reads, the resulting object is not itself an Array." +); + PyTypeObject PyCArray_Type = { PyVarObject_HEAD_INIT(NULL, 0) "_ctypes.Array", @@ -4813,8 +4822,8 @@ PyTypeObject PyCArray_Type = { 0, /* tp_getattro */ 0, /* tp_setattro */ &PyCData_as_buffer, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ - PyDoc_STR("XXX to be provided"), /* tp_doc */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + PyDoc_STR(array_doc), /* tp_doc */ (traverseproc)PyCData_traverse, /* tp_traverse */ (inquiry)PyCData_clear, /* tp_clear */ 0, /* tp_richcompare */ From af53ee81aba5566f671157e34f8720dcc38b618b Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Sun, 6 Aug 2023 15:34:12 +0000 Subject: [PATCH 02/10] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20b?= =?UTF-8?q?lurb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Documentation/2023-08-06-15-34-11.gh-issue-107689.oL193x.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Documentation/2023-08-06-15-34-11.gh-issue-107689.oL193x.rst diff --git a/Misc/NEWS.d/next/Documentation/2023-08-06-15-34-11.gh-issue-107689.oL193x.rst b/Misc/NEWS.d/next/Documentation/2023-08-06-15-34-11.gh-issue-107689.oL193x.rst new file mode 100644 index 00000000000000..c220390663d017 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2023-08-06-15-34-11.gh-issue-107689.oL193x.rst @@ -0,0 +1 @@ +Added a docstring to the ctypes array. From 7cc52a606dba6dc2850e5d6c9630ba4785ab2f75 Mon Sep 17 00:00:00 2001 From: Kostya Farber Date: Sun, 6 Aug 2023 18:52:01 +0100 Subject: [PATCH 03/10] fix linting --- Modules/_ctypes/_ctypes.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 3ab0c45bd336fe..73feef1becfdbe 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -4795,9 +4795,9 @@ static PyMappingMethods Array_as_mapping = { PyDoc_STRVAR(array_doc, "Abstract base class for arrays.\n" -"\n" +"\n" "The recommended way to create concrete array types is by multiplying any ctypes data type with\n" -"a non-negative integer. Alternatively, you can subclass this type and define _length_ and _type_\n" +"a non-negative integer. Alternatively, you can subclass this type and define _length_ and _type_\n" "class variables. Array elements can be read and written using standard subscript and slice accesses;\n" "for slice reads, the resulting object is not itself an Array." ); From 0c14eef4be665a6d8c87589ca016393176629ed9 Mon Sep 17 00:00:00 2001 From: Alex Waygood Date: Sun, 6 Aug 2023 20:40:55 +0100 Subject: [PATCH 04/10] gh-106368: Improve coverage reports for argument clinic (#107693) --- .coveragerc | 5 +++++ Tools/clinic/clinic.py | 11 +++++++---- Tools/clinic/cpp.py | 10 ++++++++-- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/.coveragerc b/.coveragerc index 18bf2f40fe523f..b5d94317e8aa8b 100644 --- a/.coveragerc +++ b/.coveragerc @@ -7,6 +7,11 @@ exclude_lines = # Don't complain if non-runnable code isn't run: if 0: if __name__ == .__main__.: + raise AssertionError\( + + # Empty bodies in protocols or abstract methods + ^\s*def [a-zA-Z0-9_]+\(.*\)(\s*->.*)?:\s*\.\.\.(\s*#.*)?$ + ^\s*\.\.\.(\s*#.*)?$ .*# pragma: no cover .*# pragma: no branch diff --git a/Tools/clinic/clinic.py b/Tools/clinic/clinic.py index 423cdfb939c161..47b5f5ae32f581 100755 --- a/Tools/clinic/clinic.py +++ b/Tools/clinic/clinic.py @@ -469,7 +469,7 @@ class Language(metaclass=abc.ABCMeta): checksum_line = "" def __init__(self, filename: str) -> None: - pass + ... @abc.abstractmethod def render( @@ -477,10 +477,10 @@ def render( clinic: Clinic | None, signatures: Iterable[Module | Class | Function] ) -> str: - pass + ... def parse_line(self, line: str) -> None: - pass + ... def validate(self) -> None: def assert_only_one( @@ -2862,6 +2862,9 @@ def __getattr__(self, attr): f"Note: accessing self.function inside converter_init is disallowed!" ) return super().__getattr__(attr) + # this branch is just here for coverage reporting + else: # pragma: no cover + pass def converter_init(self) -> None: pass @@ -3990,7 +3993,7 @@ def correct_name_for_self( return "void *", "null" if f.kind in (CLASS_METHOD, METHOD_NEW): return "PyTypeObject *", "type" - raise RuntimeError("Unhandled type of function f: " + repr(f.kind)) + raise AssertionError(f"Unhandled type of function f: {f.kind!r}") def required_type_for_self_for_parser( f: Function diff --git a/Tools/clinic/cpp.py b/Tools/clinic/cpp.py index 876105120c97f2..3d9c61ac678965 100644 --- a/Tools/clinic/cpp.py +++ b/Tools/clinic/cpp.py @@ -178,11 +178,17 @@ def pop_stack() -> TokenAndCondition: if self.verbose: print(self.status()) -if __name__ == '__main__': - for filename in sys.argv[1:]: + +def _main(filenames: list[str] | None = None) -> None: + filenames = filenames or sys.argv[1:] + for filename in filenames: with open(filename) as f: cpp = Monitor(filename, verbose=True) print() print(filename) for line_number, line in enumerate(f.read().split('\n'), 1): cpp.writeline(line) + + +if __name__ == '__main__': + _main() From bc3d1ebd2a6ed4b153ad2f9123c3575a5612c300 Mon Sep 17 00:00:00 2001 From: Kamil Turek Date: Sun, 6 Aug 2023 23:11:16 +0200 Subject: [PATCH 05/10] Improve cross-references in `runpy` docs (#107673) - Add links to `__main__` and `sys.path` where appropriate - Ensure each paragraph never has more than one link to the same thing, to avoid visual clutter from too many links --- Doc/library/runpy.rst | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/Doc/library/runpy.rst b/Doc/library/runpy.rst index 42ed8c253b8027..406b080b7be30f 100644 --- a/Doc/library/runpy.rst +++ b/Doc/library/runpy.rst @@ -39,7 +39,7 @@ The :mod:`runpy` module provides two functions: The *mod_name* argument should be an absolute module name. If the module name refers to a package rather than a normal - module, then that package is imported and the ``__main__`` submodule within + module, then that package is imported and the :mod:`__main__` submodule within that package is then executed and the resulting module globals dictionary returned. @@ -74,7 +74,7 @@ The :mod:`runpy` module provides two functions: Note that this manipulation of :mod:`sys` is not thread-safe. Other threads may see the partially initialised module, as well as the altered list of - arguments. It is recommended that the :mod:`sys` module be left alone when + arguments. It is recommended that the ``sys`` module be left alone when invoking this function from threaded code. .. seealso:: @@ -82,7 +82,7 @@ The :mod:`runpy` module provides two functions: command line. .. versionchanged:: 3.1 - Added ability to execute packages by looking for a ``__main__`` submodule. + Added ability to execute packages by looking for a :mod:`__main__` submodule. .. versionchanged:: 3.2 Added ``__cached__`` global variable (see :pep:`3147`). @@ -106,15 +106,16 @@ The :mod:`runpy` module provides two functions: Execute the code at the named filesystem location and return the resulting module globals dictionary. As with a script name supplied to the CPython command line, the supplied path may refer to a Python source file, a - compiled bytecode file or a valid sys.path entry containing a ``__main__`` - module (e.g. a zipfile containing a top-level ``__main__.py`` file). + compiled bytecode file or a valid :data:`sys.path` entry containing a + :mod:`__main__` module + (e.g. a zipfile containing a top-level ``__main__.py`` file). For a simple script, the specified code is simply executed in a fresh - module namespace. For a valid sys.path entry (typically a zipfile or + module namespace. For a valid :data:`sys.path` entry (typically a zipfile or directory), the entry is first added to the beginning of ``sys.path``. The function then looks for and executes a :mod:`__main__` module using the updated path. Note that there is no special protection against invoking - an existing :mod:`__main__` entry located elsewhere on ``sys.path`` if + an existing ``__main__`` entry located elsewhere on ``sys.path`` if there is no such module at the specified location. The optional dictionary argument *init_globals* may be used to pre-populate @@ -137,14 +138,14 @@ The :mod:`runpy` module provides two functions: supplied path, and ``__spec__``, ``__cached__``, ``__loader__`` and ``__package__`` will all be set to :const:`None`. - If the supplied path is a reference to a valid sys.path entry, then - ``__spec__`` will be set appropriately for the imported ``__main__`` + If the supplied path is a reference to a valid :data:`sys.path` entry, then + ``__spec__`` will be set appropriately for the imported :mod:`__main__` module (that is, ``__spec__.name`` will always be ``__main__``). ``__file__``, ``__cached__``, ``__loader__`` and ``__package__`` will be :ref:`set as normal ` based on the module spec. A number of alterations are also made to the :mod:`sys` module. Firstly, - ``sys.path`` may be altered as described above. ``sys.argv[0]`` is updated + :data:`sys.path` may be altered as described above. ``sys.argv[0]`` is updated with the value of ``path_name`` and ``sys.modules[__name__]`` is updated with a temporary module object for the module being executed. All modifications to items in :mod:`sys` are reverted before the function @@ -152,7 +153,7 @@ The :mod:`runpy` module provides two functions: Note that, unlike :func:`run_module`, the alterations made to :mod:`sys` are not optional in this function as these adjustments are essential to - allowing the execution of sys.path entries. As the thread-safety + allowing the execution of :data:`sys.path` entries. As the thread-safety limitations still apply, use of this function in threaded code should be either serialised with the import lock or delegated to a separate process. @@ -165,7 +166,7 @@ The :mod:`runpy` module provides two functions: .. versionchanged:: 3.4 Updated to take advantage of the module spec feature added by :pep:`451`. This allows ``__cached__`` to be set correctly in the - case where ``__main__`` is imported from a valid sys.path entry rather + case where ``__main__`` is imported from a valid :data:`sys.path` entry rather than being executed directly. .. versionchanged:: 3.12 From 11d079b43f5779e1bd481464491d2cb84d3fe4cd Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Mon, 7 Aug 2023 02:08:34 +0200 Subject: [PATCH 06/10] Docs: Argument Clinic: Move the CConverter class to the reference (#107671) --- Doc/howto/clinic.rst | 133 ++++++++++++++++++++++--------------------- 1 file changed, 69 insertions(+), 64 deletions(-) diff --git a/Doc/howto/clinic.rst b/Doc/howto/clinic.rst index dcede13a03b4a5..e8e6aace350e0c 100644 --- a/Doc/howto/clinic.rst +++ b/Doc/howto/clinic.rst @@ -193,6 +193,71 @@ The CLI supports the following options: The list of files to process. +.. _clinic-classes: + +Classes for extending Argument Clinic +------------------------------------- + +.. module:: clinic + +.. class:: CConverter + + The base class for all converters. + See :ref:`clinic-howto-custom-converter` for how to subclass this class. + + .. attribute:: type + + The C type to use for this variable. + :attr:`!type` should be a Python string specifying the type, + e.g. ``'int'``. + If this is a pointer type, the type string should end with ``' *'``. + + .. attribute:: default + + The Python default value for this parameter, as a Python value. + Or the magic value ``unspecified`` if there is no default. + + .. attribute:: py_default + + :attr:`!default` as it should appear in Python code, + as a string. + Or ``None`` if there is no default. + + .. attribute:: c_default + + :attr:`!default` as it should appear in C code, + as a string. + Or ``None`` if there is no default. + + .. attribute:: c_ignored_default + + The default value used to initialize the C variable when + there is no default, but not specifying a default may + result in an "uninitialized variable" warning. This can + easily happen when using option groups—although + properly written code will never actually use this value, + the variable does get passed in to the impl, and the + C compiler will complain about the "use" of the + uninitialized value. This value should always be a + non-empty string. + + .. attribute:: converter + + The name of the C converter function, as a string. + + .. attribute:: impl_by_reference + + A boolean value. If true, + Argument Clinic will add a ``&`` in front of the name of + the variable when passing it into the impl function. + + .. attribute:: parse_by_reference + + A boolean value. If true, + Argument Clinic will add a ``&`` in front of the name of + the variable when passing it into :c:func:`PyArg_ParseTuple`. + + .. _clinic-tutorial: Tutorial @@ -1348,7 +1413,7 @@ See also :pep:`573`. How to write a custom converter ------------------------------- -A converter is a Python class that inherits from :py:class:`!CConverter`. +A converter is a Python class that inherits from :py:class:`CConverter`. The main purpose of a custom converter, is for parameters parsed with the ``O&`` format unit --- parsing such a parameter means calling a :c:func:`PyArg_ParseTuple` "converter function". @@ -1360,73 +1425,13 @@ your converter class with the ``_converter`` suffix stripped off. Instead of subclassing :py:meth:`!CConverter.__init__`, write a :py:meth:`!converter_init` method. -Apart for the *self* parameter, all additional :py:meth:`!converter_init` -parameters **must** be keyword-only. +:py:meth:`!converter_init` always accepts a *self* parameter. +After *self*, all additional parameters **must** be keyword-only. Any arguments passed to the converter in Argument Clinic will be passed along to your :py:meth:`!converter_init` method. -See :py:class:`!CConverter` for a list of members you may wish to specify in +See :py:class:`CConverter` for a list of members you may wish to specify in your subclass. -.. module:: clinic - -.. class:: CConverter - - The base class for all converters. - See :ref:`clinic-howto-custom-converter` for how to subclass this class. - - .. attribute:: type - - The C type to use for this variable. - :attr:`!type` should be a Python string specifying the type, - e.g. ``'int'``. - If this is a pointer type, the type string should end with ``' *'``. - - .. attribute:: default - - The Python default value for this parameter, as a Python value. - Or the magic value ``unspecified`` if there is no default. - - .. attribute:: py_default - - :attr:`!default` as it should appear in Python code, - as a string. - Or ``None`` if there is no default. - - .. attribute:: c_default - - :attr:`!default` as it should appear in C code, - as a string. - Or ``None`` if there is no default. - - .. attribute:: c_ignored_default - - The default value used to initialize the C variable when - there is no default, but not specifying a default may - result in an "uninitialized variable" warning. This can - easily happen when using option groups—although - properly written code will never actually use this value, - the variable does get passed in to the impl, and the - C compiler will complain about the "use" of the - uninitialized value. This value should always be a - non-empty string. - - .. attribute:: converter - - The name of the C converter function, as a string. - - .. attribute:: impl_by_reference - - A boolean value. If true, - Argument Clinic will add a ``&`` in front of the name of - the variable when passing it into the impl function. - - .. attribute:: parse_by_reference - - A boolean value. If true, - Argument Clinic will add a ``&`` in front of the name of - the variable when passing it into :c:func:`PyArg_ParseTuple`. - - Here's the simplest example of a custom converter, from :source:`Modules/zlibmodule.c`:: /*[python input] From 42eac161f1ab01470152a934757e6d5d9e4087cb Mon Sep 17 00:00:00 2001 From: Kostya Farber Date: Mon, 7 Aug 2023 07:13:05 +0100 Subject: [PATCH 07/10] fix line width on docstring --- Modules/_ctypes/_ctypes.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 73feef1becfdbe..6e8d5ecea58ae8 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -4796,10 +4796,11 @@ static PyMappingMethods Array_as_mapping = { PyDoc_STRVAR(array_doc, "Abstract base class for arrays.\n" "\n" -"The recommended way to create concrete array types is by multiplying any ctypes data type with\n" -"a non-negative integer. Alternatively, you can subclass this type and define _length_ and _type_\n" -"class variables. Array elements can be read and written using standard subscript and slice accesses;\n" -"for slice reads, the resulting object is not itself an Array." +"The recommended way to create concrete array types is by multiplying any\n" +"ctypes data type with a non-negative integer. Alternatively, you can subclass\n" +"this type and define _length_ and _type_ class variables. Array elements can\n" +"be read and written using standard subscript and slice accesses for slice\n" +"reads, the resulting object is not itself an Array." ); PyTypeObject PyCArray_Type = { From 1b0f5b14b25adce55fdfd25aa3187a5bbaef1ce5 Mon Sep 17 00:00:00 2001 From: Kostya Farber <73378227+kostyafarber@users.noreply.github.com> Date: Mon, 7 Aug 2023 07:13:54 +0100 Subject: [PATCH 08/10] Update Misc/NEWS.d/next/Documentation/2023-08-06-15-34-11.gh-issue-107689.oL193x.rst Co-authored-by: sunmy2019 <59365878+sunmy2019@users.noreply.github.com> --- .../2023-08-06-15-34-11.gh-issue-107689.oL193x.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Documentation/2023-08-06-15-34-11.gh-issue-107689.oL193x.rst b/Misc/NEWS.d/next/Documentation/2023-08-06-15-34-11.gh-issue-107689.oL193x.rst index c220390663d017..1961cfc3e4b610 100644 --- a/Misc/NEWS.d/next/Documentation/2023-08-06-15-34-11.gh-issue-107689.oL193x.rst +++ b/Misc/NEWS.d/next/Documentation/2023-08-06-15-34-11.gh-issue-107689.oL193x.rst @@ -1 +1 @@ -Added a docstring to the ctypes array. +Add a docstring to :class:`ctypes.Array`. From a1ac1aa304b476b0af80433e4d197ef0ced0516a Mon Sep 17 00:00:00 2001 From: Kostya Farber <73378227+kostyafarber@users.noreply.github.com> Date: Mon, 7 Aug 2023 10:14:12 +0100 Subject: [PATCH 09/10] Update Modules/_ctypes/_ctypes.c Co-authored-by: Charlie Zhao --- Modules/_ctypes/_ctypes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 6e8d5ecea58ae8..dc80291d3b810b 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -4824,7 +4824,7 @@ PyTypeObject PyCArray_Type = { 0, /* tp_setattro */ &PyCData_as_buffer, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ - PyDoc_STR(array_doc), /* tp_doc */ + array_doc, /* tp_doc */ (traverseproc)PyCData_traverse, /* tp_traverse */ (inquiry)PyCData_clear, /* tp_clear */ 0, /* tp_richcompare */ From c117a4252ea89c68d69112dce76e0391017107f9 Mon Sep 17 00:00:00 2001 From: Kumar Aditya Date: Thu, 10 Aug 2023 11:42:09 +0530 Subject: [PATCH 10/10] Delete 2023-08-06-15-34-11.gh-issue-107689.oL193x.rst --- .../Documentation/2023-08-06-15-34-11.gh-issue-107689.oL193x.rst | 1 - 1 file changed, 1 deletion(-) delete mode 100644 Misc/NEWS.d/next/Documentation/2023-08-06-15-34-11.gh-issue-107689.oL193x.rst diff --git a/Misc/NEWS.d/next/Documentation/2023-08-06-15-34-11.gh-issue-107689.oL193x.rst b/Misc/NEWS.d/next/Documentation/2023-08-06-15-34-11.gh-issue-107689.oL193x.rst deleted file mode 100644 index 1961cfc3e4b610..00000000000000 --- a/Misc/NEWS.d/next/Documentation/2023-08-06-15-34-11.gh-issue-107689.oL193x.rst +++ /dev/null @@ -1 +0,0 @@ -Add a docstring to :class:`ctypes.Array`.