Python-checkins
Threads by month
- ----- 2025 -----
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
January 2025
- 1 participants
- 106 discussions
[3.12] Docs: mark up json.dump() using parameter list (GH-128482) (#128487)
by erlend-aasland 04 Jan '25
by erlend-aasland 04 Jan '25
04 Jan '25
https://github.com/python/cpython/commit/731fc4052c1ecdaa2eb4a774eb8279b7c7…
commit: 731fc4052c1ecdaa2eb4a774eb8279b7c7e3d4e1
branch: 3.12
author: Miss Islington (bot) <31488909+miss-islington(a)users.noreply.github.com>
committer: erlend-aasland <erlend.aasland(a)protonmail.com>
date: 2025-01-04T15:50:55Z
summary:
[3.12] Docs: mark up json.dump() using parameter list (GH-128482) (#128487)
(cherry picked from commit a0088b40bb212dc132e147d04f9287cabd72d163)
Co-authored-by: Erlend E. Aasland <erlend(a)python.org>
Co-authored-by: Hugo van Kemenade <1324225+hugovk(a)users.noreply.github.com>
files:
M Doc/library/json.rst
diff --git a/Doc/library/json.rst b/Doc/library/json.rst
index 88882aee2b258e..aa33b175659b56 100644
--- a/Doc/library/json.rst
+++ b/Doc/library/json.rst
@@ -140,69 +140,91 @@ Basic Usage
sort_keys=False, **kw)
Serialize *obj* as a JSON formatted stream to *fp* (a ``.write()``-supporting
- :term:`file-like object`) using this :ref:`conversion table
+ :term:`file-like object`) using this :ref:`Python-to-JSON conversion table
<py-to-json-table>`.
- If *skipkeys* is true (default: ``False``), then dict keys that are not
- of a basic type (:class:`str`, :class:`int`, :class:`float`, :class:`bool`,
- ``None``) will be skipped instead of raising a :exc:`TypeError`.
-
- The :mod:`json` module always produces :class:`str` objects, not
- :class:`bytes` objects. Therefore, ``fp.write()`` must support :class:`str`
- input.
-
- If *ensure_ascii* is true (the default), the output is guaranteed to
- have all incoming non-ASCII characters escaped. If *ensure_ascii* is
- false, these characters will be output as-is.
+ To use a custom :class:`JSONEncoder` subclass (for example, one that overrides the
+ :meth:`~JSONEncoder.default` method to serialize additional types), specify it with the
+ *cls* keyword argument; otherwise :class:`JSONEncoder` is used.
- If *check_circular* is false (default: ``True``), then the circular
- reference check for container types will be skipped and a circular reference
- will result in a :exc:`RecursionError` (or worse).
+ .. note::
- If *allow_nan* is false (default: ``True``), then it will be a
- :exc:`ValueError` to serialize out of range :class:`float` values (``nan``,
- ``inf``, ``-inf``) in strict compliance of the JSON specification.
- If *allow_nan* is true, their JavaScript equivalents (``NaN``,
- ``Infinity``, ``-Infinity``) will be used.
+ Unlike :mod:`pickle` and :mod:`marshal`, JSON is not a framed protocol,
+ so trying to serialize multiple objects with repeated calls to
+ :func:`dump` using the same *fp* will result in an invalid JSON file.
- If *indent* is a non-negative integer or string, then JSON array elements and
- object members will be pretty-printed with that indent level. An indent level
- of 0, negative, or ``""`` will only insert newlines. ``None`` (the default)
- selects the most compact representation. Using a positive integer indent
- indents that many spaces per level. If *indent* is a string (such as ``"\t"``),
- that string is used to indent each level.
+ :param object obj:
+ The Python object to be serialized.
+
+ :param fp:
+ The file-like object *obj* will be serialized to.
+ The :mod:`!json` module always produces :class:`str` objects,
+ not :class:`bytes` objects,
+ therefore ``fp.write()`` must support :class:`str` input.
+ :type fp: :term:`file-like object`
+
+ :param bool skipkeys:
+ If ``True``, keys that are not of a basic type
+ (:class:`str`, :class:`int`, :class:`float`, :class:`bool`, ``None``)
+ will be skipped instead of raising a :exc:`TypeError`.
+ Default ``False``.
+
+ :param bool ensure_ascii:
+ If ``True`` (the default), the output is guaranteed to
+ have all incoming non-ASCII characters escaped.
+ If ``False``, these characters will be outputted as-is.
+
+ :param bool check_circular:
+ If ``False``, the circular reference check for container types is skipped
+ and a circular reference will result in a :exc:`RecursionError` (or worse).
+ Default ``True``.
+
+ :param bool allow_nan:
+ If ``False``, serialization of out-of-range :class:`float` values
+ (``nan``, ``inf``, ``-inf``) will result in a :exc:`ValueError`,
+ in strict compliance with the JSON specification.
+ If ``True`` (the default), their JavaScript equivalents
+ (``NaN``, ``Infinity``, ``-Infinity``) are used.
+
+ :param indent:
+ If a positive integer or string, JSON array elements and
+ object members will be pretty-printed with that indent level.
+ A positive integer indents that many spaces per level;
+ a string (such as ``"\t"``) is used to indent each level.
+ If zero, negative, or ``""`` (the empty string),
+ only newlines are inserted.
+ If ``None`` (the default), the most compact representation is used.
+ :type indent: int | str | None
+
+ :param separators:
+ A two-tuple: ``(item_separator, key_separator)``.
+ If ``None`` (the default), *separators* defaults to
+ ``(', ', ': ')`` if *indent* is ``None``,
+ and ``(',', ': ')`` otherwise.
+ For the most compact JSON,
+ specify ``(',', ':')`` to eliminate whitespace.
+ :type separators: tuple | None
+
+ :param default:
+ A function that is called for objects that can't otherwise be serialized.
+ It should return a JSON encodable version of the object
+ or raise a :exc:`TypeError`.
+ If ``None`` (the default), :exc:`!TypeError` is raised.
+ :type default: :term:`callable` | None
+
+ :param sort_keys:
+ If ``True``, dictionaries will be outputted sorted by key.
+ Default ``False``.
.. versionchanged:: 3.2
Allow strings for *indent* in addition to integers.
- If specified, *separators* should be an ``(item_separator, key_separator)``
- tuple. The default is ``(', ', ': ')`` if *indent* is ``None`` and
- ``(',', ': ')`` otherwise. To get the most compact JSON representation,
- you should specify ``(',', ':')`` to eliminate whitespace.
-
.. versionchanged:: 3.4
Use ``(',', ': ')`` as default if *indent* is not ``None``.
- If specified, *default* should be a function that gets called for objects that
- can't otherwise be serialized. It should return a JSON encodable version of
- the object or raise a :exc:`TypeError`. If not specified, :exc:`TypeError`
- is raised.
-
- If *sort_keys* is true (default: ``False``), then the output of
- dictionaries will be sorted by key.
-
- To use a custom :class:`JSONEncoder` subclass (e.g. one that overrides the
- :meth:`~JSONEncoder.default` method to serialize additional types), specify it with the
- *cls* kwarg; otherwise :class:`JSONEncoder` is used.
-
.. versionchanged:: 3.6
All optional parameters are now :ref:`keyword-only <keyword-only_parameter>`.
- .. note::
-
- Unlike :mod:`pickle` and :mod:`marshal`, JSON is not a framed protocol,
- so trying to serialize multiple objects with repeated calls to
- :func:`dump` using the same *fp* will result in an invalid JSON file.
.. function:: dumps(obj, *, skipkeys=False, ensure_ascii=True, \
check_circular=True, allow_nan=True, cls=None, \
1
0
[3.13] Docs: mark up json.dump() using parameter list (GH-128482) (#128486)
by erlend-aasland 04 Jan '25
by erlend-aasland 04 Jan '25
04 Jan '25
https://github.com/python/cpython/commit/ff7ef94e6e31f132570f866338ad1ad8e7…
commit: ff7ef94e6e31f132570f866338ad1ad8e736d654
branch: 3.13
author: Miss Islington (bot) <31488909+miss-islington(a)users.noreply.github.com>
committer: erlend-aasland <erlend.aasland(a)protonmail.com>
date: 2025-01-04T15:49:57Z
summary:
[3.13] Docs: mark up json.dump() using parameter list (GH-128482) (#128486)
(cherry picked from commit a0088b40bb212dc132e147d04f9287cabd72d163)
Co-authored-by: Erlend E. Aasland <erlend(a)python.org>
Co-authored-by: Hugo van Kemenade <1324225+hugovk(a)users.noreply.github.com>
files:
M Doc/library/json.rst
diff --git a/Doc/library/json.rst b/Doc/library/json.rst
index bb7b1852e804a1..ce0e652ee58f7f 100644
--- a/Doc/library/json.rst
+++ b/Doc/library/json.rst
@@ -151,69 +151,91 @@ Basic Usage
sort_keys=False, **kw)
Serialize *obj* as a JSON formatted stream to *fp* (a ``.write()``-supporting
- :term:`file-like object`) using this :ref:`conversion table
+ :term:`file-like object`) using this :ref:`Python-to-JSON conversion table
<py-to-json-table>`.
- If *skipkeys* is true (default: ``False``), then dict keys that are not
- of a basic type (:class:`str`, :class:`int`, :class:`float`, :class:`bool`,
- ``None``) will be skipped instead of raising a :exc:`TypeError`.
-
- The :mod:`json` module always produces :class:`str` objects, not
- :class:`bytes` objects. Therefore, ``fp.write()`` must support :class:`str`
- input.
-
- If *ensure_ascii* is true (the default), the output is guaranteed to
- have all incoming non-ASCII characters escaped. If *ensure_ascii* is
- false, these characters will be output as-is.
+ To use a custom :class:`JSONEncoder` subclass (for example, one that overrides the
+ :meth:`~JSONEncoder.default` method to serialize additional types), specify it with the
+ *cls* keyword argument; otherwise :class:`JSONEncoder` is used.
- If *check_circular* is false (default: ``True``), then the circular
- reference check for container types will be skipped and a circular reference
- will result in a :exc:`RecursionError` (or worse).
+ .. note::
- If *allow_nan* is false (default: ``True``), then it will be a
- :exc:`ValueError` to serialize out of range :class:`float` values (``nan``,
- ``inf``, ``-inf``) in strict compliance of the JSON specification.
- If *allow_nan* is true, their JavaScript equivalents (``NaN``,
- ``Infinity``, ``-Infinity``) will be used.
+ Unlike :mod:`pickle` and :mod:`marshal`, JSON is not a framed protocol,
+ so trying to serialize multiple objects with repeated calls to
+ :func:`dump` using the same *fp* will result in an invalid JSON file.
- If *indent* is a non-negative integer or string, then JSON array elements and
- object members will be pretty-printed with that indent level. An indent level
- of 0, negative, or ``""`` will only insert newlines. ``None`` (the default)
- selects the most compact representation. Using a positive integer indent
- indents that many spaces per level. If *indent* is a string (such as ``"\t"``),
- that string is used to indent each level.
+ :param object obj:
+ The Python object to be serialized.
+
+ :param fp:
+ The file-like object *obj* will be serialized to.
+ The :mod:`!json` module always produces :class:`str` objects,
+ not :class:`bytes` objects,
+ therefore ``fp.write()`` must support :class:`str` input.
+ :type fp: :term:`file-like object`
+
+ :param bool skipkeys:
+ If ``True``, keys that are not of a basic type
+ (:class:`str`, :class:`int`, :class:`float`, :class:`bool`, ``None``)
+ will be skipped instead of raising a :exc:`TypeError`.
+ Default ``False``.
+
+ :param bool ensure_ascii:
+ If ``True`` (the default), the output is guaranteed to
+ have all incoming non-ASCII characters escaped.
+ If ``False``, these characters will be outputted as-is.
+
+ :param bool check_circular:
+ If ``False``, the circular reference check for container types is skipped
+ and a circular reference will result in a :exc:`RecursionError` (or worse).
+ Default ``True``.
+
+ :param bool allow_nan:
+ If ``False``, serialization of out-of-range :class:`float` values
+ (``nan``, ``inf``, ``-inf``) will result in a :exc:`ValueError`,
+ in strict compliance with the JSON specification.
+ If ``True`` (the default), their JavaScript equivalents
+ (``NaN``, ``Infinity``, ``-Infinity``) are used.
+
+ :param indent:
+ If a positive integer or string, JSON array elements and
+ object members will be pretty-printed with that indent level.
+ A positive integer indents that many spaces per level;
+ a string (such as ``"\t"``) is used to indent each level.
+ If zero, negative, or ``""`` (the empty string),
+ only newlines are inserted.
+ If ``None`` (the default), the most compact representation is used.
+ :type indent: int | str | None
+
+ :param separators:
+ A two-tuple: ``(item_separator, key_separator)``.
+ If ``None`` (the default), *separators* defaults to
+ ``(', ', ': ')`` if *indent* is ``None``,
+ and ``(',', ': ')`` otherwise.
+ For the most compact JSON,
+ specify ``(',', ':')`` to eliminate whitespace.
+ :type separators: tuple | None
+
+ :param default:
+ A function that is called for objects that can't otherwise be serialized.
+ It should return a JSON encodable version of the object
+ or raise a :exc:`TypeError`.
+ If ``None`` (the default), :exc:`!TypeError` is raised.
+ :type default: :term:`callable` | None
+
+ :param sort_keys:
+ If ``True``, dictionaries will be outputted sorted by key.
+ Default ``False``.
.. versionchanged:: 3.2
Allow strings for *indent* in addition to integers.
- If specified, *separators* should be an ``(item_separator, key_separator)``
- tuple. The default is ``(', ', ': ')`` if *indent* is ``None`` and
- ``(',', ': ')`` otherwise. To get the most compact JSON representation,
- you should specify ``(',', ':')`` to eliminate whitespace.
-
.. versionchanged:: 3.4
Use ``(',', ': ')`` as default if *indent* is not ``None``.
- If specified, *default* should be a function that gets called for objects that
- can't otherwise be serialized. It should return a JSON encodable version of
- the object or raise a :exc:`TypeError`. If not specified, :exc:`TypeError`
- is raised.
-
- If *sort_keys* is true (default: ``False``), then the output of
- dictionaries will be sorted by key.
-
- To use a custom :class:`JSONEncoder` subclass (e.g. one that overrides the
- :meth:`~JSONEncoder.default` method to serialize additional types), specify it with the
- *cls* kwarg; otherwise :class:`JSONEncoder` is used.
-
.. versionchanged:: 3.6
All optional parameters are now :ref:`keyword-only <keyword-only_parameter>`.
- .. note::
-
- Unlike :mod:`pickle` and :mod:`marshal`, JSON is not a framed protocol,
- so trying to serialize multiple objects with repeated calls to
- :func:`dump` using the same *fp* will result in an invalid JSON file.
.. function:: dumps(obj, *, skipkeys=False, ensure_ascii=True, \
check_circular=True, allow_nan=True, cls=None, \
1
0
pathlib tests: create `walk()` test hierarchy without using class under test (#128338)
by barneygale 04 Jan '25
by barneygale 04 Jan '25
04 Jan '25
https://github.com/python/cpython/commit/fd94c6a8032676d0659aa9e38cdaa7c170…
commit: fd94c6a8032676d0659aa9e38cdaa7c17093119c
branch: main
author: Barney Gale <barney.gale(a)gmail.com>
committer: barneygale <barney.gale(a)gmail.com>
date: 2025-01-04T15:45:24Z
summary:
pathlib tests: create `walk()` test hierarchy without using class under test (#128338)
In the tests for `pathlib.Path.walk()`, avoid using the path class under
test (`self.cls`) in test setup. Instead we use `os` functions in
`test_pathlib`, and direct manipulation of `DummyPath` internal data in
`test_pathlib_abc`.
files:
M Lib/test/test_pathlib/test_pathlib.py
M Lib/test/test_pathlib/test_pathlib_abc.py
diff --git a/Lib/test/test_pathlib/test_pathlib.py b/Lib/test/test_pathlib/test_pathlib.py
index a67a1c531630a1..6548577f4de12c 100644
--- a/Lib/test/test_pathlib/test_pathlib.py
+++ b/Lib/test/test_pathlib/test_pathlib.py
@@ -3029,6 +3029,42 @@ def setUp(self):
if name in _tests_needing_symlinks and not self.can_symlink:
self.skipTest('requires symlinks')
super().setUp()
+
+ def createTestHierarchy(self):
+ # Build:
+ # TESTFN/
+ # TEST1/ a file kid and two directory kids
+ # tmp1
+ # SUB1/ a file kid and a directory kid
+ # tmp2
+ # SUB11/ no kids
+ # SUB2/ a file kid and a dirsymlink kid
+ # tmp3
+ # link/ a symlink to TEST2
+ # broken_link
+ # broken_link2
+ # TEST2/
+ # tmp4 a lone file
+ t2_path = self.cls(self.base, "TEST2")
+ os.makedirs(self.sub11_path)
+ os.makedirs(self.sub2_path)
+ os.makedirs(t2_path)
+
+ tmp1_path = self.walk_path / "tmp1"
+ tmp2_path = self.sub1_path / "tmp2"
+ tmp3_path = self.sub2_path / "tmp3"
+ tmp4_path = self.cls(self.base, "TEST2", "tmp4")
+ for path in tmp1_path, tmp2_path, tmp3_path, tmp4_path:
+ with open(path, "w", encoding='utf-8') as f:
+ f.write(f"I'm {path} and proud of it. Blame test_pathlib.\n")
+
+ if self.can_symlink:
+ broken_link_path = self.sub2_path / "broken_link"
+ broken_link2_path = self.sub2_path / "broken_link2"
+ os.symlink(t2_path, self.link_path, target_is_directory=True)
+ os.symlink('broken', broken_link_path)
+ os.symlink(os.path.join('tmp3', 'broken'), broken_link2_path)
+ self.sub2_tree = (self.sub2_path, [], ["broken_link", "broken_link2", "link", "tmp3"])
sub21_path= self.sub2_path / "SUB21"
tmp5_path = sub21_path / "tmp3"
broken_link3_path = self.sub2_path / "broken_link3"
@@ -3052,7 +3088,7 @@ def setUp(self):
def tearDown(self):
if 'SUB21' in self.sub2_tree[1]:
os.chmod(self.sub2_path / "SUB21", stat.S_IRWXU)
- super().tearDown()
+ os_helper.rmtree(self.base)
def test_walk_bad_dir(self):
errors = []
diff --git a/Lib/test/test_pathlib/test_pathlib_abc.py b/Lib/test/test_pathlib/test_pathlib_abc.py
index 0762f224fc9ac4..87aef0c130cf9e 100644
--- a/Lib/test/test_pathlib/test_pathlib_abc.py
+++ b/Lib/test/test_pathlib/test_pathlib_abc.py
@@ -1580,52 +1580,35 @@ class DummyPathWalkTest(unittest.TestCase):
can_symlink = False
def setUp(self):
- # Build:
- # TESTFN/
- # TEST1/ a file kid and two directory kids
- # tmp1
- # SUB1/ a file kid and a directory kid
- # tmp2
- # SUB11/ no kids
- # SUB2/ a file kid and a dirsymlink kid
- # tmp3
- # link/ a symlink to TEST2
- # broken_link
- # broken_link2
- # TEST2/
- # tmp4 a lone file
self.walk_path = self.cls(self.base, "TEST1")
self.sub1_path = self.walk_path / "SUB1"
self.sub11_path = self.sub1_path / "SUB11"
self.sub2_path = self.walk_path / "SUB2"
- tmp1_path = self.walk_path / "tmp1"
- tmp2_path = self.sub1_path / "tmp2"
- tmp3_path = self.sub2_path / "tmp3"
self.link_path = self.sub2_path / "link"
- t2_path = self.cls(self.base, "TEST2")
- tmp4_path = self.cls(self.base, "TEST2", "tmp4")
- broken_link_path = self.sub2_path / "broken_link"
- broken_link2_path = self.sub2_path / "broken_link2"
-
- self.sub11_path.mkdir(parents=True)
- self.sub2_path.mkdir(parents=True)
- t2_path.mkdir(parents=True)
-
- for path in tmp1_path, tmp2_path, tmp3_path, tmp4_path:
- with path.open("w", encoding='utf-8') as f:
- f.write(f"I'm {path} and proud of it. Blame test_pathlib.\n")
+ self.sub2_tree = (self.sub2_path, [], ["tmp3"])
+ self.createTestHierarchy()
- if self.can_symlink:
- self.link_path.symlink_to(t2_path, target_is_directory=True)
- broken_link_path.symlink_to('broken')
- broken_link2_path.symlink_to(self.cls('tmp3', 'broken'))
- self.sub2_tree = (self.sub2_path, [], ["broken_link", "broken_link2", "link", "tmp3"])
- else:
- self.sub2_tree = (self.sub2_path, [], ["tmp3"])
+ def createTestHierarchy(self):
+ cls = self.cls
+ cls._files = {
+ f'{self.base}/TEST1/tmp1': b'this is tmp1\n',
+ f'{self.base}/TEST1/SUB1/tmp2': b'this is tmp2\n',
+ f'{self.base}/TEST1/SUB2/tmp3': b'this is tmp3\n',
+ f'{self.base}/TEST2/tmp4': b'this is tmp4\n',
+ }
+ cls._directories = {
+ f'{self.base}': {'TEST1', 'TEST2'},
+ f'{self.base}/TEST1': {'SUB1', 'SUB2', 'tmp1'},
+ f'{self.base}/TEST1/SUB1': {'SUB11', 'tmp2'},
+ f'{self.base}/TEST1/SUB1/SUB11': set(),
+ f'{self.base}/TEST1/SUB2': {'tmp3'},
+ f'{self.base}/TEST2': {'tmp4'},
+ }
def tearDown(self):
- base = self.cls(self.base)
- base._delete()
+ cls = self.cls
+ cls._files.clear()
+ cls._directories.clear()
def test_walk_topdown(self):
walker = self.walk_path.walk()
1
0
https://github.com/python/cpython/commit/a0088b40bb212dc132e147d04f9287cabd…
commit: a0088b40bb212dc132e147d04f9287cabd72d163
branch: main
author: Erlend E. Aasland <erlend(a)python.org>
committer: erlend-aasland <erlend.aasland(a)protonmail.com>
date: 2025-01-04T15:44:34Z
summary:
Docs: mark up json.dump() using parameter list (#128482)
Co-authored-by: Hugo van Kemenade <1324225+hugovk(a)users.noreply.github.com>
files:
M Doc/library/json.rst
diff --git a/Doc/library/json.rst b/Doc/library/json.rst
index 758d47462b6e12..f11109fb0ecfed 100644
--- a/Doc/library/json.rst
+++ b/Doc/library/json.rst
@@ -151,69 +151,91 @@ Basic Usage
sort_keys=False, **kw)
Serialize *obj* as a JSON formatted stream to *fp* (a ``.write()``-supporting
- :term:`file-like object`) using this :ref:`conversion table
+ :term:`file-like object`) using this :ref:`Python-to-JSON conversion table
<py-to-json-table>`.
- If *skipkeys* is true (default: ``False``), then dict keys that are not
- of a basic type (:class:`str`, :class:`int`, :class:`float`, :class:`bool`,
- ``None``) will be skipped instead of raising a :exc:`TypeError`.
-
- The :mod:`json` module always produces :class:`str` objects, not
- :class:`bytes` objects. Therefore, ``fp.write()`` must support :class:`str`
- input.
-
- If *ensure_ascii* is true (the default), the output is guaranteed to
- have all incoming non-ASCII characters escaped. If *ensure_ascii* is
- false, these characters will be output as-is.
+ To use a custom :class:`JSONEncoder` subclass (for example, one that overrides the
+ :meth:`~JSONEncoder.default` method to serialize additional types), specify it with the
+ *cls* keyword argument; otherwise :class:`JSONEncoder` is used.
- If *check_circular* is false (default: ``True``), then the circular
- reference check for container types will be skipped and a circular reference
- will result in a :exc:`RecursionError` (or worse).
+ .. note::
- If *allow_nan* is false (default: ``True``), then it will be a
- :exc:`ValueError` to serialize out of range :class:`float` values (``nan``,
- ``inf``, ``-inf``) in strict compliance of the JSON specification.
- If *allow_nan* is true, their JavaScript equivalents (``NaN``,
- ``Infinity``, ``-Infinity``) will be used.
+ Unlike :mod:`pickle` and :mod:`marshal`, JSON is not a framed protocol,
+ so trying to serialize multiple objects with repeated calls to
+ :func:`dump` using the same *fp* will result in an invalid JSON file.
- If *indent* is a non-negative integer or string, then JSON array elements and
- object members will be pretty-printed with that indent level. An indent level
- of 0, negative, or ``""`` will only insert newlines. ``None`` (the default)
- selects the most compact representation. Using a positive integer indent
- indents that many spaces per level. If *indent* is a string (such as ``"\t"``),
- that string is used to indent each level.
+ :param object obj:
+ The Python object to be serialized.
+
+ :param fp:
+ The file-like object *obj* will be serialized to.
+ The :mod:`!json` module always produces :class:`str` objects,
+ not :class:`bytes` objects,
+ therefore ``fp.write()`` must support :class:`str` input.
+ :type fp: :term:`file-like object`
+
+ :param bool skipkeys:
+ If ``True``, keys that are not of a basic type
+ (:class:`str`, :class:`int`, :class:`float`, :class:`bool`, ``None``)
+ will be skipped instead of raising a :exc:`TypeError`.
+ Default ``False``.
+
+ :param bool ensure_ascii:
+ If ``True`` (the default), the output is guaranteed to
+ have all incoming non-ASCII characters escaped.
+ If ``False``, these characters will be outputted as-is.
+
+ :param bool check_circular:
+ If ``False``, the circular reference check for container types is skipped
+ and a circular reference will result in a :exc:`RecursionError` (or worse).
+ Default ``True``.
+
+ :param bool allow_nan:
+ If ``False``, serialization of out-of-range :class:`float` values
+ (``nan``, ``inf``, ``-inf``) will result in a :exc:`ValueError`,
+ in strict compliance with the JSON specification.
+ If ``True`` (the default), their JavaScript equivalents
+ (``NaN``, ``Infinity``, ``-Infinity``) are used.
+
+ :param indent:
+ If a positive integer or string, JSON array elements and
+ object members will be pretty-printed with that indent level.
+ A positive integer indents that many spaces per level;
+ a string (such as ``"\t"``) is used to indent each level.
+ If zero, negative, or ``""`` (the empty string),
+ only newlines are inserted.
+ If ``None`` (the default), the most compact representation is used.
+ :type indent: int | str | None
+
+ :param separators:
+ A two-tuple: ``(item_separator, key_separator)``.
+ If ``None`` (the default), *separators* defaults to
+ ``(', ', ': ')`` if *indent* is ``None``,
+ and ``(',', ': ')`` otherwise.
+ For the most compact JSON,
+ specify ``(',', ':')`` to eliminate whitespace.
+ :type separators: tuple | None
+
+ :param default:
+ A function that is called for objects that can't otherwise be serialized.
+ It should return a JSON encodable version of the object
+ or raise a :exc:`TypeError`.
+ If ``None`` (the default), :exc:`!TypeError` is raised.
+ :type default: :term:`callable` | None
+
+ :param sort_keys:
+ If ``True``, dictionaries will be outputted sorted by key.
+ Default ``False``.
.. versionchanged:: 3.2
Allow strings for *indent* in addition to integers.
- If specified, *separators* should be an ``(item_separator, key_separator)``
- tuple. The default is ``(', ', ': ')`` if *indent* is ``None`` and
- ``(',', ': ')`` otherwise. To get the most compact JSON representation,
- you should specify ``(',', ':')`` to eliminate whitespace.
-
.. versionchanged:: 3.4
Use ``(',', ': ')`` as default if *indent* is not ``None``.
- If specified, *default* should be a function that gets called for objects that
- can't otherwise be serialized. It should return a JSON encodable version of
- the object or raise a :exc:`TypeError`. If not specified, :exc:`TypeError`
- is raised.
-
- If *sort_keys* is true (default: ``False``), then the output of
- dictionaries will be sorted by key.
-
- To use a custom :class:`JSONEncoder` subclass (e.g. one that overrides the
- :meth:`~JSONEncoder.default` method to serialize additional types), specify it with the
- *cls* kwarg; otherwise :class:`JSONEncoder` is used.
-
.. versionchanged:: 3.6
All optional parameters are now :ref:`keyword-only <keyword-only_parameter>`.
- .. note::
-
- Unlike :mod:`pickle` and :mod:`marshal`, JSON is not a framed protocol,
- so trying to serialize multiple objects with repeated calls to
- :func:`dump` using the same *fp* will result in an invalid JSON file.
.. function:: dumps(obj, *, skipkeys=False, ensure_ascii=True, \
check_circular=True, allow_nan=True, cls=None, \
1
0
GH-127381: pathlib ABCs: remove `PathBase.move()` and `move_into()` (#128337)
by barneygale 04 Jan '25
by barneygale 04 Jan '25
04 Jan '25
https://github.com/python/cpython/commit/95352dcb9321423d0606ae0b01524ad61c…
commit: 95352dcb9321423d0606ae0b01524ad61c2c2ec1
branch: main
author: Barney Gale <barney.gale(a)gmail.com>
committer: barneygale <barney.gale(a)gmail.com>
date: 2025-01-04T12:53:51Z
summary:
GH-127381: pathlib ABCs: remove `PathBase.move()` and `move_into()` (#128337)
These methods combine `_delete()` and `copy()`, but `_delete()` isn't part
of the public interface, and it's unlikely to be added until the pathlib
ABCs are made official, or perhaps even later.
files:
M Lib/pathlib/_abc.py
M Lib/pathlib/_local.py
M Lib/test/test_pathlib/test_pathlib.py
M Lib/test/test_pathlib/test_pathlib_abc.py
diff --git a/Lib/pathlib/_abc.py b/Lib/pathlib/_abc.py
index e6ff3fe1187512..7de2bb066f8f99 100644
--- a/Lib/pathlib/_abc.py
+++ b/Lib/pathlib/_abc.py
@@ -573,30 +573,3 @@ def copy_into(self, target_dir, *, follow_symlinks=True,
return self.copy(target, follow_symlinks=follow_symlinks,
dirs_exist_ok=dirs_exist_ok,
preserve_metadata=preserve_metadata)
-
- def _delete(self):
- """
- Delete this file or directory (including all sub-directories).
- """
- raise NotImplementedError
-
- def move(self, target):
- """
- Recursively move this file or directory tree to the given destination.
- """
- target = self.copy(target, follow_symlinks=False, preserve_metadata=True)
- self._delete()
- return target
-
- def move_into(self, target_dir):
- """
- Move this file or directory tree into the given existing directory.
- """
- name = self.name
- if not name:
- raise ValueError(f"{self!r} has an empty name")
- elif isinstance(target_dir, PathBase):
- target = target_dir / name
- else:
- target = self.with_segments(target_dir, name)
- return self.move(target)
diff --git a/Lib/pathlib/_local.py b/Lib/pathlib/_local.py
index c5721a69d00470..1da85ddea24376 100644
--- a/Lib/pathlib/_local.py
+++ b/Lib/pathlib/_local.py
@@ -1128,16 +1128,38 @@ def move(self, target):
"""
Recursively move this file or directory tree to the given destination.
"""
- if not isinstance(target, PathBase):
- target = self.with_segments(target)
- target.copy._ensure_different_file(self)
+ # Use os.replace() if the target is os.PathLike and on the same FS.
try:
- return self.replace(target)
- except OSError as err:
- if err.errno != EXDEV:
- raise
+ target_str = os.fspath(target)
+ except TypeError:
+ pass
+ else:
+ if not isinstance(target, PathBase):
+ target = self.with_segments(target_str)
+ target.copy._ensure_different_file(self)
+ try:
+ os.replace(self, target_str)
+ return target
+ except OSError as err:
+ if err.errno != EXDEV:
+ raise
# Fall back to copy+delete.
- return PathBase.move(self, target)
+ target = self.copy(target, follow_symlinks=False, preserve_metadata=True)
+ self._delete()
+ return target
+
+ def move_into(self, target_dir):
+ """
+ Move this file or directory tree into the given existing directory.
+ """
+ name = self.name
+ if not name:
+ raise ValueError(f"{self!r} has an empty name")
+ elif isinstance(target_dir, PathBase):
+ target = target_dir / name
+ else:
+ target = self.with_segments(target_dir, name)
+ return self.move(target)
if hasattr(os, "symlink"):
def symlink_to(self, target, target_is_directory=False):
diff --git a/Lib/test/test_pathlib/test_pathlib.py b/Lib/test/test_pathlib/test_pathlib.py
index d13daf8ac8cb07..a67a1c531630a1 100644
--- a/Lib/test/test_pathlib/test_pathlib.py
+++ b/Lib/test/test_pathlib/test_pathlib.py
@@ -1423,26 +1423,97 @@ def test_move_dangling_symlink(self):
self.assertTrue(target.is_symlink())
self.assertEqual(source_readlink, target.readlink())
+ def test_move_file(self):
+ base = self.cls(self.base)
+ source = base / 'fileA'
+ source_text = source.read_text()
+ target = base / 'fileA_moved'
+ result = source.move(target)
+ self.assertEqual(result, target)
+ self.assertFalse(source.exists())
+ self.assertTrue(target.exists())
+ self.assertEqual(source_text, target.read_text())
+
@patch_replace
def test_move_file_other_fs(self):
self.test_move_file()
+ def test_move_file_to_file(self):
+ base = self.cls(self.base)
+ source = base / 'fileA'
+ source_text = source.read_text()
+ target = base / 'dirB' / 'fileB'
+ result = source.move(target)
+ self.assertEqual(result, target)
+ self.assertFalse(source.exists())
+ self.assertTrue(target.exists())
+ self.assertEqual(source_text, target.read_text())
+
@patch_replace
def test_move_file_to_file_other_fs(self):
self.test_move_file_to_file()
+ def test_move_file_to_dir(self):
+ base = self.cls(self.base)
+ source = base / 'fileA'
+ target = base / 'dirB'
+ self.assertRaises(OSError, source.move, target)
+
@patch_replace
def test_move_file_to_dir_other_fs(self):
self.test_move_file_to_dir()
+ def test_move_file_to_itself(self):
+ base = self.cls(self.base)
+ source = base / 'fileA'
+ self.assertRaises(OSError, source.move, source)
+
+ def test_move_dir(self):
+ base = self.cls(self.base)
+ source = base / 'dirC'
+ target = base / 'dirC_moved'
+ result = source.move(target)
+ self.assertEqual(result, target)
+ self.assertFalse(source.exists())
+ self.assertTrue(target.is_dir())
+ self.assertTrue(target.joinpath('dirD').is_dir())
+ self.assertTrue(target.joinpath('dirD', 'fileD').is_file())
+ self.assertEqual(target.joinpath('dirD', 'fileD').read_text(),
+ "this is file D\n")
+ self.assertTrue(target.joinpath('fileC').is_file())
+ self.assertTrue(target.joinpath('fileC').read_text(),
+ "this is file C\n")
+
@patch_replace
def test_move_dir_other_fs(self):
self.test_move_dir()
+ def test_move_dir_to_dir(self):
+ base = self.cls(self.base)
+ source = base / 'dirC'
+ target = base / 'dirB'
+ self.assertRaises(OSError, source.move, target)
+ self.assertTrue(source.exists())
+ self.assertTrue(target.exists())
+
@patch_replace
def test_move_dir_to_dir_other_fs(self):
self.test_move_dir_to_dir()
+ def test_move_dir_to_itself(self):
+ base = self.cls(self.base)
+ source = base / 'dirC'
+ self.assertRaises(OSError, source.move, source)
+ self.assertTrue(source.exists())
+
+ def test_move_dir_into_itself(self):
+ base = self.cls(self.base)
+ source = base / 'dirC'
+ target = base / 'dirC' / 'bar'
+ self.assertRaises(OSError, source.move, target)
+ self.assertTrue(source.exists())
+ self.assertFalse(target.exists())
+
@patch_replace
def test_move_dir_into_itself_other_fs(self):
self.test_move_dir_into_itself()
@@ -1472,10 +1543,26 @@ def test_move_dir_symlink_to_itself_other_fs(self):
def test_move_dangling_symlink_other_fs(self):
self.test_move_dangling_symlink()
+ def test_move_into(self):
+ base = self.cls(self.base)
+ source = base / 'fileA'
+ source_text = source.read_text()
+ target_dir = base / 'dirA'
+ result = source.move_into(target_dir)
+ self.assertEqual(result, target_dir / 'fileA')
+ self.assertFalse(source.exists())
+ self.assertTrue(result.exists())
+ self.assertEqual(source_text, result.read_text())
+
@patch_replace
def test_move_into_other_os(self):
self.test_move_into()
+ def test_move_into_empty_name(self):
+ source = self.cls('')
+ target_dir = self.base
+ self.assertRaises(ValueError, source.move_into, target_dir)
+
@patch_replace
def test_move_into_empty_name_other_os(self):
self.test_move_into_empty_name()
@@ -1794,6 +1881,37 @@ def test_rmdir(self):
self.assertFileNotFound(p.stat)
self.assertFileNotFound(p.unlink)
+ def test_delete_file(self):
+ p = self.cls(self.base) / 'fileA'
+ p._delete()
+ self.assertFalse(p.exists())
+ self.assertFileNotFound(p._delete)
+
+ def test_delete_dir(self):
+ base = self.cls(self.base)
+ base.joinpath('dirA')._delete()
+ self.assertFalse(base.joinpath('dirA').exists())
+ self.assertFalse(base.joinpath('dirA', 'linkC').exists(
+ follow_symlinks=False))
+ base.joinpath('dirB')._delete()
+ self.assertFalse(base.joinpath('dirB').exists())
+ self.assertFalse(base.joinpath('dirB', 'fileB').exists())
+ self.assertFalse(base.joinpath('dirB', 'linkD').exists(
+ follow_symlinks=False))
+ base.joinpath('dirC')._delete()
+ self.assertFalse(base.joinpath('dirC').exists())
+ self.assertFalse(base.joinpath('dirC', 'dirD').exists())
+ self.assertFalse(base.joinpath('dirC', 'dirD', 'fileD').exists())
+ self.assertFalse(base.joinpath('dirC', 'fileC').exists())
+ self.assertFalse(base.joinpath('dirC', 'novel.txt').exists())
+
+ def test_delete_missing(self):
+ tmp = self.cls(self.base, 'delete')
+ tmp.mkdir()
+ # filename is guaranteed not to exist
+ filename = tmp / 'foo'
+ self.assertRaises(FileNotFoundError, filename._delete)
+
@needs_symlinks
def test_delete_symlink(self):
tmp = self.cls(self.base, 'delete')
diff --git a/Lib/test/test_pathlib/test_pathlib_abc.py b/Lib/test/test_pathlib/test_pathlib_abc.py
index d588442bd11785..0762f224fc9ac4 100644
--- a/Lib/test/test_pathlib/test_pathlib_abc.py
+++ b/Lib/test/test_pathlib/test_pathlib_abc.py
@@ -1345,93 +1345,6 @@ def test_copy_into_empty_name(self):
target_dir = self.base
self.assertRaises(ValueError, source.copy_into, target_dir)
- def test_move_file(self):
- base = self.cls(self.base)
- source = base / 'fileA'
- source_text = source.read_text()
- target = base / 'fileA_moved'
- result = source.move(target)
- self.assertEqual(result, target)
- self.assertFalse(source.exists())
- self.assertTrue(target.exists())
- self.assertEqual(source_text, target.read_text())
-
- def test_move_file_to_file(self):
- base = self.cls(self.base)
- source = base / 'fileA'
- source_text = source.read_text()
- target = base / 'dirB' / 'fileB'
- result = source.move(target)
- self.assertEqual(result, target)
- self.assertFalse(source.exists())
- self.assertTrue(target.exists())
- self.assertEqual(source_text, target.read_text())
-
- def test_move_file_to_dir(self):
- base = self.cls(self.base)
- source = base / 'fileA'
- target = base / 'dirB'
- self.assertRaises(OSError, source.move, target)
-
- def test_move_file_to_itself(self):
- base = self.cls(self.base)
- source = base / 'fileA'
- self.assertRaises(OSError, source.move, source)
-
- def test_move_dir(self):
- base = self.cls(self.base)
- source = base / 'dirC'
- target = base / 'dirC_moved'
- result = source.move(target)
- self.assertEqual(result, target)
- self.assertFalse(source.exists())
- self.assertTrue(target.is_dir())
- self.assertTrue(target.joinpath('dirD').is_dir())
- self.assertTrue(target.joinpath('dirD', 'fileD').is_file())
- self.assertEqual(target.joinpath('dirD', 'fileD').read_text(),
- "this is file D\n")
- self.assertTrue(target.joinpath('fileC').is_file())
- self.assertTrue(target.joinpath('fileC').read_text(),
- "this is file C\n")
-
- def test_move_dir_to_dir(self):
- base = self.cls(self.base)
- source = base / 'dirC'
- target = base / 'dirB'
- self.assertRaises(OSError, source.move, target)
- self.assertTrue(source.exists())
- self.assertTrue(target.exists())
-
- def test_move_dir_to_itself(self):
- base = self.cls(self.base)
- source = base / 'dirC'
- self.assertRaises(OSError, source.move, source)
- self.assertTrue(source.exists())
-
- def test_move_dir_into_itself(self):
- base = self.cls(self.base)
- source = base / 'dirC'
- target = base / 'dirC' / 'bar'
- self.assertRaises(OSError, source.move, target)
- self.assertTrue(source.exists())
- self.assertFalse(target.exists())
-
- def test_move_into(self):
- base = self.cls(self.base)
- source = base / 'fileA'
- source_text = source.read_text()
- target_dir = base / 'dirA'
- result = source.move_into(target_dir)
- self.assertEqual(result, target_dir / 'fileA')
- self.assertFalse(source.exists())
- self.assertTrue(result.exists())
- self.assertEqual(source_text, result.read_text())
-
- def test_move_into_empty_name(self):
- source = self.cls('')
- target_dir = self.base
- self.assertRaises(ValueError, source.move_into, target_dir)
-
def test_iterdir(self):
P = self.cls
p = P(self.base)
@@ -1660,37 +1573,6 @@ def test_is_symlink(self):
self.assertIs((P / 'linkA\udfff').is_file(), False)
self.assertIs((P / 'linkA\x00').is_file(), False)
- def test_delete_file(self):
- p = self.cls(self.base) / 'fileA'
- p._delete()
- self.assertFalse(p.exists())
- self.assertFileNotFound(p._delete)
-
- def test_delete_dir(self):
- base = self.cls(self.base)
- base.joinpath('dirA')._delete()
- self.assertFalse(base.joinpath('dirA').exists())
- self.assertFalse(base.joinpath('dirA', 'linkC').exists(
- follow_symlinks=False))
- base.joinpath('dirB')._delete()
- self.assertFalse(base.joinpath('dirB').exists())
- self.assertFalse(base.joinpath('dirB', 'fileB').exists())
- self.assertFalse(base.joinpath('dirB', 'linkD').exists(
- follow_symlinks=False))
- base.joinpath('dirC')._delete()
- self.assertFalse(base.joinpath('dirC').exists())
- self.assertFalse(base.joinpath('dirC', 'dirD').exists())
- self.assertFalse(base.joinpath('dirC', 'dirD', 'fileD').exists())
- self.assertFalse(base.joinpath('dirC', 'fileC').exists())
- self.assertFalse(base.joinpath('dirC', 'novel.txt').exists())
-
- def test_delete_missing(self):
- tmp = self.cls(self.base, 'delete')
- tmp.mkdir()
- # filename is guaranteed not to exist
- filename = tmp / 'foo'
- self.assertRaises(FileNotFoundError, filename._delete)
-
class DummyPathWalkTest(unittest.TestCase):
cls = DummyPath
1
0
[3.13] gh-128152: Argument Clinic: ignore pre-processor directives inside C comments (GH-128464) (#128478)
by erlend-aasland 04 Jan '25
by erlend-aasland 04 Jan '25
04 Jan '25
https://github.com/python/cpython/commit/883cb23dd14bcc60921a53cc51c30fda22…
commit: 883cb23dd14bcc60921a53cc51c30fda223b9ca6
branch: 3.13
author: Miss Islington (bot) <31488909+miss-islington(a)users.noreply.github.com>
committer: erlend-aasland <erlend.aasland(a)protonmail.com>
date: 2025-01-04T11:09:25Z
summary:
[3.13] gh-128152: Argument Clinic: ignore pre-processor directives inside C comments (GH-128464) (#128478)
(cherry picked from commit a4e773c540cfd3a9c2bb3b5033d2f79ef50962c8)
Co-authored-by: Erlend E. Aasland <erlend(a)python.org>
files:
A Misc/NEWS.d/next/Tools-Demos/2025-01-03-23-51-07.gh-issue-128152.IhzElS.rst
M Lib/test/test_clinic.py
M Tools/clinic/libclinic/cpp.py
diff --git a/Lib/test/test_clinic.py b/Lib/test/test_clinic.py
index a7ba7f3d99860e..e210103a80f399 100644
--- a/Lib/test/test_clinic.py
+++ b/Lib/test/test_clinic.py
@@ -731,6 +731,16 @@ def test_cloned_forced_text_signature_illegal(self):
err = "Cannot use @text_signature when cloning a function"
self.expect_failure(block, err, lineno=11)
+ def test_ignore_preprocessor_in_comments(self):
+ for dsl in "clinic", "python":
+ raw = dedent(f"""\
+ /*[{dsl} input]
+ # CPP directives, valid or not, should be ignored in C comments.
+ #
+ [{dsl} start generated code]*/
+ """)
+ self.clinic.parse(raw)
+
class ParseFileUnitTest(TestCase):
def expect_parsing_failure(
diff --git a/Misc/NEWS.d/next/Tools-Demos/2025-01-03-23-51-07.gh-issue-128152.IhzElS.rst b/Misc/NEWS.d/next/Tools-Demos/2025-01-03-23-51-07.gh-issue-128152.IhzElS.rst
new file mode 100644
index 00000000000000..9657e138e9911b
--- /dev/null
+++ b/Misc/NEWS.d/next/Tools-Demos/2025-01-03-23-51-07.gh-issue-128152.IhzElS.rst
@@ -0,0 +1,2 @@
+Fix a bug where Argument Clinic's C pre-processor parser tried to parse
+pre-processor directives inside C comments. Patch by Erlend Aasland.
diff --git a/Tools/clinic/libclinic/cpp.py b/Tools/clinic/libclinic/cpp.py
index e115d65a88e1b6..3cfe99b712641d 100644
--- a/Tools/clinic/libclinic/cpp.py
+++ b/Tools/clinic/libclinic/cpp.py
@@ -132,6 +132,9 @@ def pop_stack() -> TokenAndCondition:
if line_comment:
line = before.rstrip()
+ if self.in_comment:
+ return
+
if not line.startswith('#'):
return
1
0
gh-128152: Argument Clinic: ignore pre-processor directives inside C comments (#128464)
by erlend-aasland 04 Jan '25
by erlend-aasland 04 Jan '25
04 Jan '25
https://github.com/python/cpython/commit/a4e773c540cfd3a9c2bb3b5033d2f79ef5…
commit: a4e773c540cfd3a9c2bb3b5033d2f79ef50962c8
branch: main
author: Erlend E. Aasland <erlend(a)python.org>
committer: erlend-aasland <erlend.aasland(a)protonmail.com>
date: 2025-01-04T11:46:04+01:00
summary:
gh-128152: Argument Clinic: ignore pre-processor directives inside C comments (#128464)
files:
A Misc/NEWS.d/next/Tools-Demos/2025-01-03-23-51-07.gh-issue-128152.IhzElS.rst
M Lib/test/test_clinic.py
M Tools/clinic/libclinic/cpp.py
diff --git a/Lib/test/test_clinic.py b/Lib/test/test_clinic.py
index 11054963b6ff03..b45b9ee89ee3de 100644
--- a/Lib/test/test_clinic.py
+++ b/Lib/test/test_clinic.py
@@ -740,6 +740,16 @@ def test_cloned_forced_text_signature_illegal(self):
err = "Cannot use @text_signature when cloning a function"
self.expect_failure(block, err, lineno=11)
+ def test_ignore_preprocessor_in_comments(self):
+ for dsl in "clinic", "python":
+ raw = dedent(f"""\
+ /*[{dsl} input]
+ # CPP directives, valid or not, should be ignored in C comments.
+ #
+ [{dsl} start generated code]*/
+ """)
+ self.clinic.parse(raw)
+
class ParseFileUnitTest(TestCase):
def expect_parsing_failure(
diff --git a/Misc/NEWS.d/next/Tools-Demos/2025-01-03-23-51-07.gh-issue-128152.IhzElS.rst b/Misc/NEWS.d/next/Tools-Demos/2025-01-03-23-51-07.gh-issue-128152.IhzElS.rst
new file mode 100644
index 00000000000000..9657e138e9911b
--- /dev/null
+++ b/Misc/NEWS.d/next/Tools-Demos/2025-01-03-23-51-07.gh-issue-128152.IhzElS.rst
@@ -0,0 +1,2 @@
+Fix a bug where Argument Clinic's C pre-processor parser tried to parse
+pre-processor directives inside C comments. Patch by Erlend Aasland.
diff --git a/Tools/clinic/libclinic/cpp.py b/Tools/clinic/libclinic/cpp.py
index e115d65a88e1b6..3cfe99b712641d 100644
--- a/Tools/clinic/libclinic/cpp.py
+++ b/Tools/clinic/libclinic/cpp.py
@@ -132,6 +132,9 @@ def pop_stack() -> TokenAndCondition:
if line_comment:
line = before.rstrip()
+ if self.in_comment:
+ return
+
if not line.startswith('#'):
return
1
0
https://github.com/python/cpython/commit/03ede5afe2d10c04e05f159fd353ee5869…
commit: 03ede5afe2d10c04e05f159fd353ee5869ae2cdb
branch: main
author: sobolevn <mail(a)sobolevn.me>
committer: sobolevn <mail(a)sobolevn.me>
date: 2025-01-04T13:31:01+03:00
summary:
Add `check-readthedocs` pre-commit hook (#128453)
files:
M .pre-commit-config.yaml
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 107f3b255735f4..af6accd89b5bd4 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -55,6 +55,7 @@ repos:
hooks:
- id: check-dependabot
- id: check-github-workflows
+ - id: check-readthedocs
- repo: https://github.com/rhysd/actionlint
rev: v1.7.4
1
0
04 Jan '25
https://github.com/python/cpython/commit/513a4efa75bf78c9d629ddabc9516fb058…
commit: 513a4efa75bf78c9d629ddabc9516fb058787289
branch: main
author: Kumar Aditya <kumaraditya(a)python.org>
committer: kumaraditya303 <kumaraditya(a)python.org>
date: 2025-01-04T14:18:22+05:30
summary:
gh-128002: fix many thread safety issues in asyncio (#128147)
* Makes `_asyncio.Task` and `_asyncio.Future` thread-safe by adding critical sections
* Add assertions to check for thread safety checking locking of object by critical sections in internal functions
* Make `_asyncio.all_tasks` thread safe when eager tasks are used
* Add a thread safety test
files:
A Lib/test/test_asyncio/test_free_threading.py
M Modules/_asynciomodule.c
M Modules/clinic/_asynciomodule.c.h
diff --git a/Lib/test/test_asyncio/test_free_threading.py b/Lib/test/test_asyncio/test_free_threading.py
new file mode 100644
index 00000000000000..90bddbf3a9dda1
--- /dev/null
+++ b/Lib/test/test_asyncio/test_free_threading.py
@@ -0,0 +1,82 @@
+import asyncio
+import unittest
+from threading import Thread
+from unittest import TestCase
+
+from test.support import threading_helper
+
+threading_helper.requires_working_threading(module=True)
+
+def tearDownModule():
+ asyncio._set_event_loop_policy(None)
+
+
+class TestFreeThreading:
+ def test_all_tasks_race(self) -> None:
+ async def main():
+ loop = asyncio.get_running_loop()
+ future = loop.create_future()
+
+ async def coro():
+ await future
+
+ tasks = set()
+
+ async with asyncio.TaskGroup() as tg:
+ for _ in range(100):
+ tasks.add(tg.create_task(coro()))
+
+ all_tasks = self.all_tasks(loop)
+ self.assertEqual(len(all_tasks), 101)
+
+ for task in all_tasks:
+ self.assertEqual(task.get_loop(), loop)
+ self.assertFalse(task.done())
+
+ current = self.current_task()
+ self.assertEqual(current.get_loop(), loop)
+ self.assertSetEqual(all_tasks, tasks | {current})
+ future.set_result(None)
+
+ def runner():
+ with asyncio.Runner() as runner:
+ loop = runner.get_loop()
+ loop.set_task_factory(self.factory)
+ runner.run(main())
+
+ threads = []
+
+ for _ in range(10):
+ thread = Thread(target=runner)
+ threads.append(thread)
+
+ with threading_helper.start_threads(threads):
+ pass
+
+
+class TestPyFreeThreading(TestFreeThreading, TestCase):
+ all_tasks = staticmethod(asyncio.tasks._py_all_tasks)
+ current_task = staticmethod(asyncio.tasks._py_current_task)
+
+ def factory(self, loop, coro, context=None):
+ return asyncio.tasks._PyTask(coro, loop=loop, context=context)
+
+
+(a)unittest.skipUnless(hasattr(asyncio.tasks, "_c_all_tasks"), "requires _asyncio")
+class TestCFreeThreading(TestFreeThreading, TestCase):
+ all_tasks = staticmethod(getattr(asyncio.tasks, "_c_all_tasks", None))
+ current_task = staticmethod(getattr(asyncio.tasks, "_c_current_task", None))
+
+ def factory(self, loop, coro, context=None):
+ return asyncio.tasks._CTask(coro, loop=loop, context=context)
+
+
+class TestEagerPyFreeThreading(TestPyFreeThreading):
+ def factory(self, loop, coro, context=None):
+ return asyncio.tasks._PyTask(coro, loop=loop, context=context, eager_start=True)
+
+
+(a)unittest.skipUnless(hasattr(asyncio.tasks, "_c_all_tasks"), "requires _asyncio")
+class TestEagerCFreeThreading(TestCFreeThreading, TestCase):
+ def factory(self, loop, coro, context=None):
+ return asyncio.tasks._CTask(coro, loop=loop, context=context, eager_start=True)
diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c
index 74db4c74af905a..b8b184af04a7cb 100644
--- a/Modules/_asynciomodule.c
+++ b/Modules/_asynciomodule.c
@@ -364,6 +364,8 @@ future_ensure_alive(FutureObj *fut)
static int
future_schedule_callbacks(asyncio_state *state, FutureObj *fut)
{
+ _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(fut);
+
if (fut->fut_callback0 != NULL) {
/* There's a 1st callback */
@@ -481,6 +483,8 @@ future_init(FutureObj *fut, PyObject *loop)
static PyObject *
future_set_result(asyncio_state *state, FutureObj *fut, PyObject *res)
{
+ _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(fut);
+
if (future_ensure_alive(fut)) {
return NULL;
}
@@ -503,6 +507,8 @@ future_set_result(asyncio_state *state, FutureObj *fut, PyObject *res)
static PyObject *
future_set_exception(asyncio_state *state, FutureObj *fut, PyObject *exc)
{
+ _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(fut);
+
PyObject *exc_val = NULL;
if (fut->fut_state != STATE_PENDING) {
@@ -569,6 +575,8 @@ future_set_exception(asyncio_state *state, FutureObj *fut, PyObject *exc)
static PyObject *
create_cancelled_error(asyncio_state *state, FutureObj *fut)
{
+ _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(fut);
+
PyObject *exc;
if (fut->fut_cancelled_exc != NULL) {
/* transfer ownership */
@@ -588,6 +596,8 @@ create_cancelled_error(asyncio_state *state, FutureObj *fut)
static void
future_set_cancelled_error(asyncio_state *state, FutureObj *fut)
{
+ _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(fut);
+
PyObject *exc = create_cancelled_error(state, fut);
if (exc == NULL) {
return;
@@ -599,6 +609,8 @@ future_set_cancelled_error(asyncio_state *state, FutureObj *fut)
static int
future_get_result(asyncio_state *state, FutureObj *fut, PyObject **result)
{
+ _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(fut);
+
if (fut->fut_state == STATE_CANCELLED) {
future_set_cancelled_error(state, fut);
return -1;
@@ -632,6 +644,8 @@ static PyObject *
future_add_done_callback(asyncio_state *state, FutureObj *fut, PyObject *arg,
PyObject *ctx)
{
+ _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(fut);
+
if (!future_is_alive(fut)) {
PyErr_SetString(PyExc_RuntimeError, "uninitialized Future object");
return NULL;
@@ -706,6 +720,8 @@ future_add_done_callback(asyncio_state *state, FutureObj *fut, PyObject *arg,
static PyObject *
future_cancel(asyncio_state *state, FutureObj *fut, PyObject *msg)
{
+ _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(fut);
+
fut->fut_log_tb = 0;
if (fut->fut_state != STATE_PENDING) {
@@ -787,6 +803,7 @@ FutureObj_traverse(FutureObj *fut, visitproc visit, void *arg)
}
/*[clinic input]
+@critical_section
_asyncio.Future.result
Return the result this future represents.
@@ -798,7 +815,7 @@ the future is done and has an exception set, this exception is raised.
static PyObject *
_asyncio_Future_result_impl(FutureObj *self)
-/*[clinic end generated code: output=f35f940936a4b1e5 input=49ecf9cf5ec50dc5]*/
+/*[clinic end generated code: output=f35f940936a4b1e5 input=61d89f48e4c8b670]*/
{
asyncio_state *state = get_asyncio_state_by_def((PyObject *)self);
PyObject *result;
@@ -827,6 +844,7 @@ _asyncio_Future_result_impl(FutureObj *self)
}
/*[clinic input]
+@critical_section
_asyncio.Future.exception
cls: defining_class
@@ -842,7 +860,7 @@ InvalidStateError.
static PyObject *
_asyncio_Future_exception_impl(FutureObj *self, PyTypeObject *cls)
-/*[clinic end generated code: output=ce75576b187c905b input=3faf15c22acdb60d]*/
+/*[clinic end generated code: output=ce75576b187c905b input=647d1fd1fc403301]*/
{
if (!future_is_alive(self)) {
asyncio_state *state = get_asyncio_state_by_cls(cls);
@@ -873,6 +891,7 @@ _asyncio_Future_exception_impl(FutureObj *self, PyTypeObject *cls)
}
/*[clinic input]
+@critical_section
_asyncio.Future.set_result
cls: defining_class
@@ -888,7 +907,7 @@ InvalidStateError.
static PyObject *
_asyncio_Future_set_result_impl(FutureObj *self, PyTypeObject *cls,
PyObject *result)
-/*[clinic end generated code: output=99afbbe78f99c32d input=d5a41c1e353acc2e]*/
+/*[clinic end generated code: output=99afbbe78f99c32d input=4069306f03a3b6ee]*/
{
asyncio_state *state = get_asyncio_state_by_cls(cls);
ENSURE_FUTURE_ALIVE(state, self)
@@ -896,6 +915,7 @@ _asyncio_Future_set_result_impl(FutureObj *self, PyTypeObject *cls,
}
/*[clinic input]
+@critical_section
_asyncio.Future.set_exception
cls: defining_class
@@ -911,7 +931,7 @@ InvalidStateError.
static PyObject *
_asyncio_Future_set_exception_impl(FutureObj *self, PyTypeObject *cls,
PyObject *exception)
-/*[clinic end generated code: output=0a5e8b5a52f058d6 input=a245cd49d3df939b]*/
+/*[clinic end generated code: output=0a5e8b5a52f058d6 input=b6eab43a389bc966]*/
{
asyncio_state *state = get_asyncio_state_by_cls(cls);
ENSURE_FUTURE_ALIVE(state, self)
@@ -919,6 +939,7 @@ _asyncio_Future_set_exception_impl(FutureObj *self, PyTypeObject *cls,
}
/*[clinic input]
+@critical_section
_asyncio.Future.add_done_callback
cls: defining_class
@@ -937,7 +958,7 @@ scheduled with call_soon.
static PyObject *
_asyncio_Future_add_done_callback_impl(FutureObj *self, PyTypeObject *cls,
PyObject *fn, PyObject *context)
-/*[clinic end generated code: output=922e9a4cbd601167 input=599261c521458cc2]*/
+/*[clinic end generated code: output=922e9a4cbd601167 input=37d97f941beb7b3e]*/
{
asyncio_state *state = get_asyncio_state_by_cls(cls);
if (context == NULL) {
@@ -953,6 +974,7 @@ _asyncio_Future_add_done_callback_impl(FutureObj *self, PyTypeObject *cls,
}
/*[clinic input]
+@critical_section
_asyncio.Future.remove_done_callback
cls: defining_class
@@ -967,7 +989,7 @@ Returns the number of callbacks removed.
static PyObject *
_asyncio_Future_remove_done_callback_impl(FutureObj *self, PyTypeObject *cls,
PyObject *fn)
-/*[clinic end generated code: output=2da35ccabfe41b98 input=c7518709b86fc747]*/
+/*[clinic end generated code: output=2da35ccabfe41b98 input=3afbc9f6a673091b]*/
{
PyObject *newlist;
Py_ssize_t len, i, j=0;
@@ -1076,6 +1098,7 @@ _asyncio_Future_remove_done_callback_impl(FutureObj *self, PyTypeObject *cls,
}
/*[clinic input]
+@critical_section
_asyncio.Future.cancel
cls: defining_class
@@ -1092,7 +1115,7 @@ return True.
static PyObject *
_asyncio_Future_cancel_impl(FutureObj *self, PyTypeObject *cls,
PyObject *msg)
-/*[clinic end generated code: output=074956f35904b034 input=bba8f8b786941a94]*/
+/*[clinic end generated code: output=074956f35904b034 input=44ab4003da839970]*/
{
asyncio_state *state = get_asyncio_state_by_cls(cls);
ENSURE_FUTURE_ALIVE(state, self)
@@ -1100,6 +1123,7 @@ _asyncio_Future_cancel_impl(FutureObj *self, PyTypeObject *cls,
}
/*[clinic input]
+@critical_section
_asyncio.Future.cancelled
Return True if the future was cancelled.
@@ -1107,7 +1131,7 @@ Return True if the future was cancelled.
static PyObject *
_asyncio_Future_cancelled_impl(FutureObj *self)
-/*[clinic end generated code: output=145197ced586357d input=943ab8b7b7b17e45]*/
+/*[clinic end generated code: output=145197ced586357d input=9b8644819a675416]*/
{
if (future_is_alive(self) && self->fut_state == STATE_CANCELLED) {
Py_RETURN_TRUE;
@@ -1118,6 +1142,7 @@ _asyncio_Future_cancelled_impl(FutureObj *self)
}
/*[clinic input]
+@critical_section
_asyncio.Future.done
Return True if the future is done.
@@ -1128,7 +1153,7 @@ future was cancelled.
static PyObject *
_asyncio_Future_done_impl(FutureObj *self)
-/*[clinic end generated code: output=244c5ac351145096 input=28d7b23fdb65d2ac]*/
+/*[clinic end generated code: output=244c5ac351145096 input=7204d3cc63bef7f3]*/
{
if (!future_is_alive(self) || self->fut_state == STATE_PENDING) {
Py_RETURN_FALSE;
@@ -1139,6 +1164,7 @@ _asyncio_Future_done_impl(FutureObj *self)
}
/*[clinic input]
+@critical_section
_asyncio.Future.get_loop
cls: defining_class
@@ -1149,17 +1175,24 @@ Return the event loop the Future is bound to.
static PyObject *
_asyncio_Future_get_loop_impl(FutureObj *self, PyTypeObject *cls)
-/*[clinic end generated code: output=f50ea6c374d9ee97 input=163c2c498b45a1f0]*/
+/*[clinic end generated code: output=f50ea6c374d9ee97 input=f3ce629bfd9f45c1]*/
{
asyncio_state *state = get_asyncio_state_by_cls(cls);
ENSURE_FUTURE_ALIVE(state, self)
return Py_NewRef(self->fut_loop);
}
+/*[clinic input]
+@critical_section
+@getter
+_asyncio.Future._asyncio_future_blocking
+[clinic start generated code]*/
+
static PyObject *
-FutureObj_get_blocking(FutureObj *fut, void *Py_UNUSED(ignored))
+_asyncio_Future__asyncio_future_blocking_get_impl(FutureObj *self)
+/*[clinic end generated code: output=a558a2c51e38823b input=58da92efc03b617d]*/
{
- if (future_is_alive(fut) && fut->fut_blocking) {
+ if (future_is_alive(self) && self->fut_blocking) {
Py_RETURN_TRUE;
}
else {
@@ -1167,31 +1200,47 @@ FutureObj_get_blocking(FutureObj *fut, void *Py_UNUSED(ignored))
}
}
+/*[clinic input]
+@critical_section
+@setter
+_asyncio.Future._asyncio_future_blocking
+[clinic start generated code]*/
+
static int
-FutureObj_set_blocking(FutureObj *fut, PyObject *val, void *Py_UNUSED(ignored))
+_asyncio_Future__asyncio_future_blocking_set_impl(FutureObj *self,
+ PyObject *value)
+/*[clinic end generated code: output=0686d1cb024a7453 input=3fd4a5f95df788b7]*/
+
{
- if (future_ensure_alive(fut)) {
+ if (future_ensure_alive(self)) {
return -1;
}
- if (val == NULL) {
+ if (value == NULL) {
PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
return -1;
}
- int is_true = PyObject_IsTrue(val);
+ int is_true = PyObject_IsTrue(value);
if (is_true < 0) {
return -1;
}
- fut->fut_blocking = is_true;
+ self->fut_blocking = is_true;
return 0;
}
+/*[clinic input]
+@critical_section
+@getter
+_asyncio.Future._log_traceback
+[clinic start generated code]*/
+
static PyObject *
-FutureObj_get_log_traceback(FutureObj *fut, void *Py_UNUSED(ignored))
+_asyncio_Future__log_traceback_get_impl(FutureObj *self)
+/*[clinic end generated code: output=2724433b238593c7 input=91e5144ea4117d8e]*/
{
- asyncio_state *state = get_asyncio_state_by_def((PyObject *)fut);
- ENSURE_FUTURE_ALIVE(state, fut)
- if (fut->fut_log_tb) {
+ asyncio_state *state = get_asyncio_state_by_def((PyObject *)self);
+ ENSURE_FUTURE_ALIVE(state, self)
+ if (self->fut_log_tb) {
Py_RETURN_TRUE;
}
else {
@@ -1199,14 +1248,21 @@ FutureObj_get_log_traceback(FutureObj *fut, void *Py_UNUSED(ignored))
}
}
+/*[clinic input]
+@critical_section
+@setter
+_asyncio.Future._log_traceback
+[clinic start generated code]*/
+
static int
-FutureObj_set_log_traceback(FutureObj *fut, PyObject *val, void *Py_UNUSED(ignored))
+_asyncio_Future__log_traceback_set_impl(FutureObj *self, PyObject *value)
+/*[clinic end generated code: output=9ce8e19504f42f54 input=30ac8217754b08c2]*/
{
- if (val == NULL) {
+ if (value == NULL) {
PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
return -1;
}
- int is_true = PyObject_IsTrue(val);
+ int is_true = PyObject_IsTrue(value);
if (is_true < 0) {
return -1;
}
@@ -1215,31 +1271,44 @@ FutureObj_set_log_traceback(FutureObj *fut, PyObject *val, void *Py_UNUSED(ignor
"_log_traceback can only be set to False");
return -1;
}
- fut->fut_log_tb = is_true;
+ self->fut_log_tb = is_true;
return 0;
}
+/*[clinic input]
+@critical_section
+@getter
+_asyncio.Future._loop
+[clinic start generated code]*/
static PyObject *
-FutureObj_get_loop(FutureObj *fut, void *Py_UNUSED(ignored))
+_asyncio_Future__loop_get_impl(FutureObj *self)
+/*[clinic end generated code: output=5ba31563eecfeedf input=0337130bc5781670]*/
{
- if (!future_is_alive(fut)) {
+ if (!future_is_alive(self)) {
Py_RETURN_NONE;
}
- return Py_NewRef(fut->fut_loop);
+ return Py_NewRef(self->fut_loop);
}
+/*[clinic input]
+@critical_section
+@getter
+_asyncio.Future._callbacks
+[clinic start generated code]*/
+
static PyObject *
-FutureObj_get_callbacks(FutureObj *fut, void *Py_UNUSED(ignored))
+_asyncio_Future__callbacks_get_impl(FutureObj *self)
+/*[clinic end generated code: output=b40d360505fcc583 input=7a466649530c01bb]*/
{
- asyncio_state *state = get_asyncio_state_by_def((PyObject *)fut);
- ENSURE_FUTURE_ALIVE(state, fut)
+ asyncio_state *state = get_asyncio_state_by_def((PyObject *)self);
+ ENSURE_FUTURE_ALIVE(state, self)
Py_ssize_t len = 0;
- if (fut->fut_callback0 != NULL) {
+ if (self->fut_callback0 != NULL) {
len++;
}
- if (fut->fut_callbacks != NULL) {
- len += PyList_GET_SIZE(fut->fut_callbacks);
+ if (self->fut_callbacks != NULL) {
+ len += PyList_GET_SIZE(self->fut_callbacks);
}
if (len == 0) {
@@ -1252,22 +1321,22 @@ FutureObj_get_callbacks(FutureObj *fut, void *Py_UNUSED(ignored))
}
Py_ssize_t i = 0;
- if (fut->fut_callback0 != NULL) {
+ if (self->fut_callback0 != NULL) {
PyObject *tup0 = PyTuple_New(2);
if (tup0 == NULL) {
Py_DECREF(callbacks);
return NULL;
}
- PyTuple_SET_ITEM(tup0, 0, Py_NewRef(fut->fut_callback0));
- assert(fut->fut_context0 != NULL);
- PyTuple_SET_ITEM(tup0, 1, Py_NewRef(fut->fut_context0));
+ PyTuple_SET_ITEM(tup0, 0, Py_NewRef(self->fut_callback0));
+ assert(self->fut_context0 != NULL);
+ PyTuple_SET_ITEM(tup0, 1, Py_NewRef(self->fut_context0));
PyList_SET_ITEM(callbacks, i, tup0);
i++;
}
- if (fut->fut_callbacks != NULL) {
- for (Py_ssize_t j = 0; j < PyList_GET_SIZE(fut->fut_callbacks); j++) {
- PyObject *cb = PyList_GET_ITEM(fut->fut_callbacks, j);
+ if (self->fut_callbacks != NULL) {
+ for (Py_ssize_t j = 0; j < PyList_GET_SIZE(self->fut_callbacks); j++) {
+ PyObject *cb = PyList_GET_ITEM(self->fut_callbacks, j);
Py_INCREF(cb);
PyList_SET_ITEM(callbacks, i, cb);
i++;
@@ -1277,68 +1346,110 @@ FutureObj_get_callbacks(FutureObj *fut, void *Py_UNUSED(ignored))
return callbacks;
}
+/*[clinic input]
+@critical_section
+@getter
+_asyncio.Future._result
+[clinic start generated code]*/
+
static PyObject *
-FutureObj_get_result(FutureObj *fut, void *Py_UNUSED(ignored))
+_asyncio_Future__result_get_impl(FutureObj *self)
+/*[clinic end generated code: output=6877e8ce97333873 input=624f8e28e67f2636]*/
+
{
- asyncio_state *state = get_asyncio_state_by_def((PyObject *)fut);
- ENSURE_FUTURE_ALIVE(state, fut)
- if (fut->fut_result == NULL) {
+ asyncio_state *state = get_asyncio_state_by_def((PyObject *)self);
+ ENSURE_FUTURE_ALIVE(state, self)
+ if (self->fut_result == NULL) {
Py_RETURN_NONE;
}
- return Py_NewRef(fut->fut_result);
+ return Py_NewRef(self->fut_result);
}
+/*[clinic input]
+@critical_section
+@getter
+_asyncio.Future._exception
+[clinic start generated code]*/
+
static PyObject *
-FutureObj_get_exception(FutureObj *fut, void *Py_UNUSED(ignored))
+_asyncio_Future__exception_get_impl(FutureObj *self)
+/*[clinic end generated code: output=32f2c93b9e021a9b input=1828a1fcac929710]*/
{
- asyncio_state *state = get_asyncio_state_by_def((PyObject *)fut);
- ENSURE_FUTURE_ALIVE(state, fut)
- if (fut->fut_exception == NULL) {
+ asyncio_state *state = get_asyncio_state_by_def((PyObject *)self);
+ ENSURE_FUTURE_ALIVE(state, self)
+ if (self->fut_exception == NULL) {
Py_RETURN_NONE;
}
- return Py_NewRef(fut->fut_exception);
+ return Py_NewRef(self->fut_exception);
}
+/*[clinic input]
+@critical_section
+@getter
+_asyncio.Future._source_traceback
+[clinic start generated code]*/
+
static PyObject *
-FutureObj_get_source_traceback(FutureObj *fut, void *Py_UNUSED(ignored))
+_asyncio_Future__source_traceback_get_impl(FutureObj *self)
+/*[clinic end generated code: output=d4f12b09af22f61b input=3c831fbde5da90d0]*/
{
- if (!future_is_alive(fut) || fut->fut_source_tb == NULL) {
+ if (!future_is_alive(self) || self->fut_source_tb == NULL) {
Py_RETURN_NONE;
}
- return Py_NewRef(fut->fut_source_tb);
+ return Py_NewRef(self->fut_source_tb);
}
+/*[clinic input]
+@critical_section
+@getter
+_asyncio.Future._cancel_message
+[clinic start generated code]*/
+
static PyObject *
-FutureObj_get_cancel_message(FutureObj *fut, void *Py_UNUSED(ignored))
+_asyncio_Future__cancel_message_get_impl(FutureObj *self)
+/*[clinic end generated code: output=52ef6444f92cedac input=54c12c67082e4eea]*/
{
- if (fut->fut_cancel_msg == NULL) {
+ if (self->fut_cancel_msg == NULL) {
Py_RETURN_NONE;
}
- return Py_NewRef(fut->fut_cancel_msg);
+ return Py_NewRef(self->fut_cancel_msg);
}
+/*[clinic input]
+@critical_section
+@setter
+_asyncio.Future._cancel_message
+[clinic start generated code]*/
+
static int
-FutureObj_set_cancel_message(FutureObj *fut, PyObject *msg,
- void *Py_UNUSED(ignored))
+_asyncio_Future__cancel_message_set_impl(FutureObj *self, PyObject *value)
+/*[clinic end generated code: output=0854b2f77bff2209 input=f461d17f2d891fad]*/
{
- if (msg == NULL) {
+ if (value == NULL) {
PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
return -1;
}
- Py_INCREF(msg);
- Py_XSETREF(fut->fut_cancel_msg, msg);
+ Py_INCREF(value);
+ Py_XSETREF(self->fut_cancel_msg, value);
return 0;
}
+/*[clinic input]
+@critical_section
+@getter
+_asyncio.Future._state
+[clinic start generated code]*/
+
static PyObject *
-FutureObj_get_state(FutureObj *fut, void *Py_UNUSED(ignored))
+_asyncio_Future__state_get_impl(FutureObj *self)
+/*[clinic end generated code: output=622f560a3fa69c63 input=7c5ad023a93423ff]*/
{
- asyncio_state *state = get_asyncio_state_by_def((PyObject *)fut);
+ asyncio_state *state = get_asyncio_state_by_def((PyObject *)self);
PyObject *ret = NULL;
- ENSURE_FUTURE_ALIVE(state, fut)
+ ENSURE_FUTURE_ALIVE(state, self)
- switch (fut->fut_state) {
+ switch (self->fut_state) {
case STATE_PENDING:
ret = &_Py_ID(PENDING);
break;
@@ -1364,6 +1475,7 @@ FutureObj_repr(FutureObj *fut)
}
/*[clinic input]
+@critical_section
_asyncio.Future._make_cancelled_error
Create the CancelledError to raise if the Future is cancelled.
@@ -1374,7 +1486,7 @@ it erases the context exception value.
static PyObject *
_asyncio_Future__make_cancelled_error_impl(FutureObj *self)
-/*[clinic end generated code: output=a5df276f6c1213de input=ac6effe4ba795ecc]*/
+/*[clinic end generated code: output=a5df276f6c1213de input=ccb90df8c3c18bcd]*/
{
asyncio_state *state = get_asyncio_state_by_def((PyObject *)self);
return create_cancelled_error(state, self);
@@ -1455,23 +1567,16 @@ static PyMethodDef FutureType_methods[] = {
{NULL, NULL} /* Sentinel */
};
-#define FUTURE_COMMON_GETSETLIST \
- {"_state", (getter)FutureObj_get_state, NULL, NULL}, \
- {"_asyncio_future_blocking", (getter)FutureObj_get_blocking, \
- (setter)FutureObj_set_blocking, NULL}, \
- {"_loop", (getter)FutureObj_get_loop, NULL, NULL}, \
- {"_callbacks", (getter)FutureObj_get_callbacks, NULL, NULL}, \
- {"_result", (getter)FutureObj_get_result, NULL, NULL}, \
- {"_exception", (getter)FutureObj_get_exception, NULL, NULL}, \
- {"_log_traceback", (getter)FutureObj_get_log_traceback, \
- (setter)FutureObj_set_log_traceback, NULL}, \
- {"_source_traceback", (getter)FutureObj_get_source_traceback, \
- NULL, NULL}, \
- {"_cancel_message", (getter)FutureObj_get_cancel_message, \
- (setter)FutureObj_set_cancel_message, NULL},
-
static PyGetSetDef FutureType_getsetlist[] = {
- FUTURE_COMMON_GETSETLIST
+ _ASYNCIO_FUTURE__STATE_GETSETDEF
+ _ASYNCIO_FUTURE__ASYNCIO_FUTURE_BLOCKING_GETSETDEF
+ _ASYNCIO_FUTURE__LOOP_GETSETDEF
+ _ASYNCIO_FUTURE__CALLBACKS_GETSETDEF
+ _ASYNCIO_FUTURE__RESULT_GETSETDEF
+ _ASYNCIO_FUTURE__EXCEPTION_GETSETDEF
+ _ASYNCIO_FUTURE__LOG_TRACEBACK_GETSETDEF
+ _ASYNCIO_FUTURE__SOURCE_TRACEBACK_GETSETDEF
+ _ASYNCIO_FUTURE__CANCEL_MESSAGE_GETSETDEF
{NULL} /* Sentinel */
};
@@ -1550,19 +1655,13 @@ FutureIter_dealloc(futureiterobject *it)
}
static PySendResult
-FutureIter_am_send(futureiterobject *it,
- PyObject *Py_UNUSED(arg),
- PyObject **result)
+FutureIter_am_send_lock_held(futureiterobject *it, PyObject **result)
{
- /* arg is unused, see the comment on FutureIter_send for clarification */
-
PyObject *res;
FutureObj *fut = it->future;
+ _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(fut);
*result = NULL;
- if (fut == NULL) {
- return PYGEN_ERROR;
- }
if (fut->fut_state == STATE_PENDING) {
if (!fut->fut_blocking) {
@@ -1575,18 +1674,29 @@ FutureIter_am_send(futureiterobject *it,
return PYGEN_ERROR;
}
- it->future = NULL;
res = _asyncio_Future_result_impl(fut);
if (res != NULL) {
- Py_DECREF(fut);
*result = res;
return PYGEN_RETURN;
}
- Py_DECREF(fut);
return PYGEN_ERROR;
}
+static PySendResult
+FutureIter_am_send(futureiterobject *it,
+ PyObject *Py_UNUSED(arg),
+ PyObject **result)
+{
+ /* arg is unused, see the comment on FutureIter_send for clarification */
+ PySendResult res;
+ Py_BEGIN_CRITICAL_SECTION(it->future);
+ res = FutureIter_am_send_lock_held(it, result);
+ Py_END_CRITICAL_SECTION();
+ return res;
+}
+
+
static PyObject *
FutureIter_iternext(futureiterobject *it)
{
@@ -1807,7 +1917,11 @@ TaskStepMethWrapper_call(TaskStepMethWrapper *o,
return NULL;
}
asyncio_state *state = get_asyncio_state_by_def((PyObject *)o);
- return task_step(state, o->sw_task, o->sw_arg);
+ PyObject *res;
+ Py_BEGIN_CRITICAL_SECTION(o->sw_task);
+ res = task_step(state, o->sw_task, o->sw_arg);
+ Py_END_CRITICAL_SECTION();
+ return res;
}
static int
@@ -2150,10 +2264,17 @@ TaskObj_traverse(TaskObj *task, visitproc visit, void *arg)
return 0;
}
+/*[clinic input]
+@critical_section
+@getter
+_asyncio.Task._log_destroy_pending
+[clinic start generated code]*/
+
static PyObject *
-TaskObj_get_log_destroy_pending(TaskObj *task, void *Py_UNUSED(ignored))
+_asyncio_Task__log_destroy_pending_get_impl(TaskObj *self)
+/*[clinic end generated code: output=e6c2a47d029ac93b input=17127298cd4c720b]*/
{
- if (task->task_log_destroy_pending) {
+ if (self->task_log_destroy_pending) {
Py_RETURN_TRUE;
}
else {
@@ -2161,25 +2282,40 @@ TaskObj_get_log_destroy_pending(TaskObj *task, void *Py_UNUSED(ignored))
}
}
+/*[clinic input]
+@critical_section
+@setter
+_asyncio.Task._log_destroy_pending
+[clinic start generated code]*/
+
static int
-TaskObj_set_log_destroy_pending(TaskObj *task, PyObject *val, void *Py_UNUSED(ignored))
+_asyncio_Task__log_destroy_pending_set_impl(TaskObj *self, PyObject *value)
+/*[clinic end generated code: output=7ebc030bb92ec5ce input=49b759c97d1216a4]*/
{
- if (val == NULL) {
+ if (value == NULL) {
PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
return -1;
}
- int is_true = PyObject_IsTrue(val);
+ int is_true = PyObject_IsTrue(value);
if (is_true < 0) {
return -1;
}
- task->task_log_destroy_pending = is_true;
+ self->task_log_destroy_pending = is_true;
return 0;
}
+
+/*[clinic input]
+@critical_section
+@getter
+_asyncio.Task._must_cancel
+[clinic start generated code]*/
+
static PyObject *
-TaskObj_get_must_cancel(TaskObj *task, void *Py_UNUSED(ignored))
+_asyncio_Task__must_cancel_get_impl(TaskObj *self)
+/*[clinic end generated code: output=70e79b900996c363 input=2d04529fb23feedf]*/
{
- if (task->task_must_cancel) {
+ if (self->task_must_cancel) {
Py_RETURN_TRUE;
}
else {
@@ -2187,21 +2323,36 @@ TaskObj_get_must_cancel(TaskObj *task, void *Py_UNUSED(ignored))
}
}
+/*[clinic input]
+@critical_section
+@getter
+_asyncio.Task._coro
+[clinic start generated code]*/
+
static PyObject *
-TaskObj_get_coro(TaskObj *task, void *Py_UNUSED(ignored))
+_asyncio_Task__coro_get_impl(TaskObj *self)
+/*[clinic end generated code: output=a2726012ab5fd531 input=323c31a272020624]*/
{
- if (task->task_coro) {
- return Py_NewRef(task->task_coro);
+ if (self->task_coro) {
+ return Py_NewRef(self->task_coro);
}
Py_RETURN_NONE;
}
+
+/*[clinic input]
+@critical_section
+@getter
+_asyncio.Task._fut_waiter
+[clinic start generated code]*/
+
static PyObject *
-TaskObj_get_fut_waiter(TaskObj *task, void *Py_UNUSED(ignored))
+_asyncio_Task__fut_waiter_get_impl(TaskObj *self)
+/*[clinic end generated code: output=c4f966b847fefcdf input=4d1005d725e72db7]*/
{
- if (task->task_fut_waiter) {
- return Py_NewRef(task->task_fut_waiter);
+ if (self->task_fut_waiter) {
+ return Py_NewRef(self->task_fut_waiter);
}
Py_RETURN_NONE;
@@ -2217,6 +2368,7 @@ TaskObj_repr(TaskObj *task)
/*[clinic input]
+@critical_section
_asyncio.Task._make_cancelled_error
Create the CancelledError to raise if the Task is cancelled.
@@ -2227,7 +2379,7 @@ it erases the context exception value.
static PyObject *
_asyncio_Task__make_cancelled_error_impl(TaskObj *self)
-/*[clinic end generated code: output=55a819e8b4276fab input=52c0e32de8e2f840]*/
+/*[clinic end generated code: output=55a819e8b4276fab input=2d3213be0cb02390]*/
{
FutureObj *fut = (FutureObj*)self;
return _asyncio_Future__make_cancelled_error_impl(fut);
@@ -2235,6 +2387,7 @@ _asyncio_Task__make_cancelled_error_impl(TaskObj *self)
/*[clinic input]
+@critical_section
_asyncio.Task.cancel
msg: object = None
@@ -2263,7 +2416,7 @@ This also increases the task's count of cancellation requests.
static PyObject *
_asyncio_Task_cancel_impl(TaskObj *self, PyObject *msg)
-/*[clinic end generated code: output=c66b60d41c74f9f1 input=7bb51bf25974c783]*/
+/*[clinic end generated code: output=c66b60d41c74f9f1 input=6125d45b9a6a5abd]*/
{
self->task_log_tb = 0;
@@ -2308,6 +2461,7 @@ _asyncio_Task_cancel_impl(TaskObj *self, PyObject *msg)
}
/*[clinic input]
+@critical_section
_asyncio.Task.cancelling
Return the count of the task's cancellation requests.
@@ -2318,13 +2472,14 @@ and may be decremented using .uncancel().
static PyObject *
_asyncio_Task_cancelling_impl(TaskObj *self)
-/*[clinic end generated code: output=803b3af96f917d7e input=b625224d310cbb17]*/
+/*[clinic end generated code: output=803b3af96f917d7e input=5ef89b1b38f080ee]*/
/*[clinic end generated code]*/
{
return PyLong_FromLong(self->task_num_cancels_requested);
}
/*[clinic input]
+@critical_section
_asyncio.Task.uncancel
Decrement the task's count of cancellation requests.
@@ -2337,7 +2492,7 @@ Returns the remaining number of cancellation requests.
static PyObject *
_asyncio_Task_uncancel_impl(TaskObj *self)
-/*[clinic end generated code: output=58184d236a817d3c input=68f81a4b90b46be2]*/
+/*[clinic end generated code: output=58184d236a817d3c input=cb3220b0e5afd61d]*/
/*[clinic end generated code]*/
{
if (self->task_num_cancels_requested > 0) {
@@ -2451,12 +2606,13 @@ _asyncio_Task_set_exception(TaskObj *self, PyObject *exception)
}
/*[clinic input]
+@critical_section
_asyncio.Task.get_coro
[clinic start generated code]*/
static PyObject *
_asyncio_Task_get_coro_impl(TaskObj *self)
-/*[clinic end generated code: output=bcac27c8cc6c8073 input=d2e8606c42a7b403]*/
+/*[clinic end generated code: output=bcac27c8cc6c8073 input=a47f81427e39fe0c]*/
{
if (self->task_coro) {
return Py_NewRef(self->task_coro);
@@ -2477,12 +2633,13 @@ _asyncio_Task_get_context_impl(TaskObj *self)
}
/*[clinic input]
+@critical_section
_asyncio.Task.get_name
[clinic start generated code]*/
static PyObject *
_asyncio_Task_get_name_impl(TaskObj *self)
-/*[clinic end generated code: output=0ecf1570c3b37a8f input=a4a6595d12f4f0f8]*/
+/*[clinic end generated code: output=0ecf1570c3b37a8f input=92a8f30c85034249]*/
{
if (self->task_name) {
if (PyLong_CheckExact(self->task_name)) {
@@ -2499,6 +2656,7 @@ _asyncio_Task_get_name_impl(TaskObj *self)
}
/*[clinic input]
+@critical_section
_asyncio.Task.set_name
value: object
@@ -2506,8 +2664,8 @@ _asyncio.Task.set_name
[clinic start generated code]*/
static PyObject *
-_asyncio_Task_set_name(TaskObj *self, PyObject *value)
-/*[clinic end generated code: output=138a8d51e32057d6 input=a8359b6e65f8fd31]*/
+_asyncio_Task_set_name_impl(TaskObj *self, PyObject *value)
+/*[clinic end generated code: output=f88ff4c0d64a9a6f input=e8d400ad64bad799]*/
{
if (!PyUnicode_CheckExact(value)) {
value = PyObject_Str(value);
@@ -2618,12 +2776,10 @@ static PyMethodDef TaskType_methods[] = {
};
static PyGetSetDef TaskType_getsetlist[] = {
- FUTURE_COMMON_GETSETLIST
- {"_log_destroy_pending", (getter)TaskObj_get_log_destroy_pending,
- (setter)TaskObj_set_log_destroy_pending, NULL},
- {"_must_cancel", (getter)TaskObj_get_must_cancel, NULL, NULL},
- {"_coro", (getter)TaskObj_get_coro, NULL, NULL},
- {"_fut_waiter", (getter)TaskObj_get_fut_waiter, NULL, NULL},
+ _ASYNCIO_TASK__LOG_DESTROY_PENDING_GETSETDEF
+ _ASYNCIO_TASK__MUST_CANCEL_GETSETDEF
+ _ASYNCIO_TASK__CORO_GETSETDEF
+ _ASYNCIO_TASK__FUT_WAITER_GETSETDEF
{NULL} /* Sentinel */
};
@@ -2738,6 +2894,8 @@ gen_status_from_result(PyObject **result)
static PyObject *
task_step_impl(asyncio_state *state, TaskObj *task, PyObject *exc)
{
+ _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(task);
+
int clear_exc = 0;
PyObject *result = NULL;
PyObject *coro;
@@ -2867,6 +3025,8 @@ task_step_impl(asyncio_state *state, TaskObj *task, PyObject *exc)
static PyObject *
task_step_handle_result_impl(asyncio_state *state, TaskObj *task, PyObject *result)
{
+ _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(task);
+
int res;
PyObject *o;
@@ -2897,8 +3057,10 @@ task_step_handle_result_impl(asyncio_state *state, TaskObj *task, PyObject *resu
if (wrapper == NULL) {
goto fail;
}
+ Py_BEGIN_CRITICAL_SECTION(result);
tmp = future_add_done_callback(state,
(FutureObj*)result, wrapper, task->task_context);
+ Py_END_CRITICAL_SECTION();
Py_DECREF(wrapper);
if (tmp == NULL) {
goto fail;
@@ -3140,7 +3302,10 @@ task_eager_start(asyncio_state *state, TaskObj *task)
int retval = 0;
- PyObject *stepres = task_step_impl(state, task, NULL);
+ PyObject *stepres;
+ Py_BEGIN_CRITICAL_SECTION(task);
+ stepres = task_step_impl(state, task, NULL);
+ Py_END_CRITICAL_SECTION();
if (stepres == NULL) {
PyObject *exc = PyErr_GetRaisedException();
_PyErr_ChainExceptions1(exc);
@@ -3177,16 +3342,20 @@ task_eager_start(asyncio_state *state, TaskObj *task)
}
static PyObject *
-task_wakeup(TaskObj *task, PyObject *o)
+task_wakeup_lock_held(TaskObj *task, PyObject *o)
{
+ _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(task);
+
PyObject *result;
assert(o);
asyncio_state *state = get_asyncio_state_by_def((PyObject *)task);
if (Future_CheckExact(state, o) || Task_CheckExact(state, o)) {
PyObject *fut_result = NULL;
- int res = future_get_result(state, (FutureObj*)o, &fut_result);
-
+ int res;
+ Py_BEGIN_CRITICAL_SECTION(o);
+ res = future_get_result(state, (FutureObj*)o, &fut_result);
+ Py_END_CRITICAL_SECTION();
switch(res) {
case -1:
assert(fut_result == NULL);
@@ -3220,6 +3389,16 @@ task_wakeup(TaskObj *task, PyObject *o)
return result;
}
+static PyObject *
+task_wakeup(TaskObj *task, PyObject *o)
+{
+ PyObject *res;
+ Py_BEGIN_CRITICAL_SECTION(task);
+ res = task_wakeup_lock_held(task, o);
+ Py_END_CRITICAL_SECTION();
+ return res;
+}
+
/*********************** Functions **************************/
@@ -3564,62 +3743,41 @@ static PyObject *
_asyncio_all_tasks_impl(PyObject *module, PyObject *loop)
/*[clinic end generated code: output=0e107cbb7f72aa7b input=43a1b423c2d95bfa]*/
{
-
asyncio_state *state = get_asyncio_state(module);
- PyObject *tasks = PySet_New(NULL);
- if (tasks == NULL) {
- return NULL;
- }
if (loop == Py_None) {
loop = _asyncio_get_running_loop_impl(module);
if (loop == NULL) {
- Py_DECREF(tasks);
return NULL;
}
} else {
Py_INCREF(loop);
}
- // First add eager tasks to the set so that we don't miss
+ // First add eager tasks to the list so that we don't miss
// any tasks which graduates from eager to non-eager
- PyObject *eager_iter = PyObject_GetIter(state->eager_tasks);
- if (eager_iter == NULL) {
- Py_DECREF(tasks);
+ // We first add all the tasks to `tasks` list and then filter
+ // out the tasks which are done and return it as a set.
+ PyObject *tasks = PyList_New(0);
+ if (tasks == NULL) {
Py_DECREF(loop);
return NULL;
}
- PyObject *item;
- while ((item = PyIter_Next(eager_iter)) != NULL) {
- if (add_one_task(state, tasks, item, loop) < 0) {
- Py_DECREF(tasks);
- Py_DECREF(loop);
- Py_DECREF(item);
- Py_DECREF(eager_iter);
- return NULL;
- }
- Py_DECREF(item);
- }
- Py_DECREF(eager_iter);
-
- if (PyErr_Occurred()) {
+ if (PyList_Extend(tasks, state->eager_tasks) < 0) {
Py_DECREF(tasks);
Py_DECREF(loop);
return NULL;
}
-
int err = 0;
ASYNCIO_STATE_LOCK(state);
struct llist_node *node;
+
llist_for_each_safe(node, &state->asyncio_tasks_head) {
TaskObj *task = llist_data(node, TaskObj, task_node);
- Py_INCREF(task);
- if (add_one_task(state, tasks, (PyObject *)task, loop) < 0) {
- Py_DECREF(task);
+ if (PyList_Append(tasks, (PyObject *)task) < 0) {
Py_DECREF(tasks);
Py_DECREF(loop);
err = 1;
break;
}
- Py_DECREF(task);
}
ASYNCIO_STATE_UNLOCK(state);
if (err) {
@@ -3631,8 +3789,9 @@ _asyncio_all_tasks_impl(PyObject *module, PyObject *loop)
Py_DECREF(loop);
return NULL;
}
+ PyObject *item;
while ((item = PyIter_Next(scheduled_iter)) != NULL) {
- if (add_one_task(state, tasks, item, loop) < 0) {
+ if (PyList_Append(tasks, item) < 0) {
Py_DECREF(tasks);
Py_DECREF(loop);
Py_DECREF(item);
@@ -3642,14 +3801,27 @@ _asyncio_all_tasks_impl(PyObject *module, PyObject *loop)
Py_DECREF(item);
}
Py_DECREF(scheduled_iter);
- Py_DECREF(loop);
-
- if (PyErr_Occurred()) {
+ // All the tasks are now in the list, now filter the tasks which are done
+ PyObject *res = PySet_New(NULL);
+ if (res == NULL) {
Py_DECREF(tasks);
+ Py_DECREF(loop);
return NULL;
}
- return tasks;
+ for (Py_ssize_t i = 0; i < PyList_GET_SIZE(tasks); i++) {
+ PyObject *task = PyList_GET_ITEM(tasks, i);
+ if (add_one_task(state, res, task, loop) < 0) {
+ Py_DECREF(res);
+ Py_DECREF(tasks);
+ Py_DECREF(loop);
+ return NULL;
+ }
+ }
+
+ Py_DECREF(tasks);
+ Py_DECREF(loop);
+ return res;
}
static int
diff --git a/Modules/clinic/_asynciomodule.c.h b/Modules/clinic/_asynciomodule.c.h
index 32045804c35004..3a37cdd9b5fa83 100644
--- a/Modules/clinic/_asynciomodule.c.h
+++ b/Modules/clinic/_asynciomodule.c.h
@@ -6,6 +6,7 @@ preserve
# include "pycore_gc.h" // PyGC_Head
# include "pycore_runtime.h" // _Py_ID()
#endif
+#include "pycore_critical_section.h"// Py_BEGIN_CRITICAL_SECTION()
#include "pycore_modsupport.h" // _PyArg_UnpackKeywords()
PyDoc_STRVAR(_asyncio_Future___init____doc__,
@@ -98,7 +99,13 @@ _asyncio_Future_result_impl(FutureObj *self);
static PyObject *
_asyncio_Future_result(FutureObj *self, PyObject *Py_UNUSED(ignored))
{
- return _asyncio_Future_result_impl(self);
+ PyObject *return_value = NULL;
+
+ Py_BEGIN_CRITICAL_SECTION(self);
+ return_value = _asyncio_Future_result_impl(self);
+ Py_END_CRITICAL_SECTION();
+
+ return return_value;
}
PyDoc_STRVAR(_asyncio_Future_exception__doc__,
@@ -121,11 +128,18 @@ _asyncio_Future_exception_impl(FutureObj *self, PyTypeObject *cls);
static PyObject *
_asyncio_Future_exception(FutureObj *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
+ PyObject *return_value = NULL;
+
if (nargs || (kwnames && PyTuple_GET_SIZE(kwnames))) {
PyErr_SetString(PyExc_TypeError, "exception() takes no arguments");
- return NULL;
+ goto exit;
}
- return _asyncio_Future_exception_impl(self, cls);
+ Py_BEGIN_CRITICAL_SECTION(self);
+ return_value = _asyncio_Future_exception_impl(self, cls);
+ Py_END_CRITICAL_SECTION();
+
+exit:
+ return return_value;
}
PyDoc_STRVAR(_asyncio_Future_set_result__doc__,
@@ -170,7 +184,9 @@ _asyncio_Future_set_result(FutureObj *self, PyTypeObject *cls, PyObject *const *
goto exit;
}
result = args[0];
+ Py_BEGIN_CRITICAL_SECTION(self);
return_value = _asyncio_Future_set_result_impl(self, cls, result);
+ Py_END_CRITICAL_SECTION();
exit:
return return_value;
@@ -218,7 +234,9 @@ _asyncio_Future_set_exception(FutureObj *self, PyTypeObject *cls, PyObject *cons
goto exit;
}
exception = args[0];
+ Py_BEGIN_CRITICAL_SECTION(self);
return_value = _asyncio_Future_set_exception_impl(self, cls, exception);
+ Py_END_CRITICAL_SECTION();
exit:
return return_value;
@@ -286,7 +304,9 @@ _asyncio_Future_add_done_callback(FutureObj *self, PyTypeObject *cls, PyObject *
}
context = args[1];
skip_optional_kwonly:
+ Py_BEGIN_CRITICAL_SECTION(self);
return_value = _asyncio_Future_add_done_callback_impl(self, cls, fn, context);
+ Py_END_CRITICAL_SECTION();
exit:
return return_value;
@@ -333,7 +353,9 @@ _asyncio_Future_remove_done_callback(FutureObj *self, PyTypeObject *cls, PyObjec
goto exit;
}
fn = args[0];
+ Py_BEGIN_CRITICAL_SECTION(self);
return_value = _asyncio_Future_remove_done_callback_impl(self, cls, fn);
+ Py_END_CRITICAL_SECTION();
exit:
return return_value;
@@ -399,7 +421,9 @@ _asyncio_Future_cancel(FutureObj *self, PyTypeObject *cls, PyObject *const *args
}
msg = args[0];
skip_optional_pos:
+ Py_BEGIN_CRITICAL_SECTION(self);
return_value = _asyncio_Future_cancel_impl(self, cls, msg);
+ Py_END_CRITICAL_SECTION();
exit:
return return_value;
@@ -420,7 +444,13 @@ _asyncio_Future_cancelled_impl(FutureObj *self);
static PyObject *
_asyncio_Future_cancelled(FutureObj *self, PyObject *Py_UNUSED(ignored))
{
- return _asyncio_Future_cancelled_impl(self);
+ PyObject *return_value = NULL;
+
+ Py_BEGIN_CRITICAL_SECTION(self);
+ return_value = _asyncio_Future_cancelled_impl(self);
+ Py_END_CRITICAL_SECTION();
+
+ return return_value;
}
PyDoc_STRVAR(_asyncio_Future_done__doc__,
@@ -441,7 +471,13 @@ _asyncio_Future_done_impl(FutureObj *self);
static PyObject *
_asyncio_Future_done(FutureObj *self, PyObject *Py_UNUSED(ignored))
{
- return _asyncio_Future_done_impl(self);
+ PyObject *return_value = NULL;
+
+ Py_BEGIN_CRITICAL_SECTION(self);
+ return_value = _asyncio_Future_done_impl(self);
+ Py_END_CRITICAL_SECTION();
+
+ return return_value;
}
PyDoc_STRVAR(_asyncio_Future_get_loop__doc__,
@@ -459,11 +495,319 @@ _asyncio_Future_get_loop_impl(FutureObj *self, PyTypeObject *cls);
static PyObject *
_asyncio_Future_get_loop(FutureObj *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
+ PyObject *return_value = NULL;
+
if (nargs || (kwnames && PyTuple_GET_SIZE(kwnames))) {
PyErr_SetString(PyExc_TypeError, "get_loop() takes no arguments");
- return NULL;
+ goto exit;
}
- return _asyncio_Future_get_loop_impl(self, cls);
+ Py_BEGIN_CRITICAL_SECTION(self);
+ return_value = _asyncio_Future_get_loop_impl(self, cls);
+ Py_END_CRITICAL_SECTION();
+
+exit:
+ return return_value;
+}
+
+#if !defined(_asyncio_Future__asyncio_future_blocking_DOCSTR)
+# define _asyncio_Future__asyncio_future_blocking_DOCSTR NULL
+#endif
+#if defined(_ASYNCIO_FUTURE__ASYNCIO_FUTURE_BLOCKING_GETSETDEF)
+# undef _ASYNCIO_FUTURE__ASYNCIO_FUTURE_BLOCKING_GETSETDEF
+# define _ASYNCIO_FUTURE__ASYNCIO_FUTURE_BLOCKING_GETSETDEF {"_asyncio_future_blocking", (getter)_asyncio_Future__asyncio_future_blocking_get, (setter)_asyncio_Future__asyncio_future_blocking_set, _asyncio_Future__asyncio_future_blocking_DOCSTR},
+#else
+# define _ASYNCIO_FUTURE__ASYNCIO_FUTURE_BLOCKING_GETSETDEF {"_asyncio_future_blocking", (getter)_asyncio_Future__asyncio_future_blocking_get, NULL, _asyncio_Future__asyncio_future_blocking_DOCSTR},
+#endif
+
+static PyObject *
+_asyncio_Future__asyncio_future_blocking_get_impl(FutureObj *self);
+
+static PyObject *
+_asyncio_Future__asyncio_future_blocking_get(FutureObj *self, void *Py_UNUSED(context))
+{
+ PyObject *return_value = NULL;
+
+ Py_BEGIN_CRITICAL_SECTION(self);
+ return_value = _asyncio_Future__asyncio_future_blocking_get_impl(self);
+ Py_END_CRITICAL_SECTION();
+
+ return return_value;
+}
+
+#if !defined(_asyncio_Future__asyncio_future_blocking_DOCSTR)
+# define _asyncio_Future__asyncio_future_blocking_DOCSTR NULL
+#endif
+#if defined(_ASYNCIO_FUTURE__ASYNCIO_FUTURE_BLOCKING_GETSETDEF)
+# undef _ASYNCIO_FUTURE__ASYNCIO_FUTURE_BLOCKING_GETSETDEF
+# define _ASYNCIO_FUTURE__ASYNCIO_FUTURE_BLOCKING_GETSETDEF {"_asyncio_future_blocking", (getter)_asyncio_Future__asyncio_future_blocking_get, (setter)_asyncio_Future__asyncio_future_blocking_set, _asyncio_Future__asyncio_future_blocking_DOCSTR},
+#else
+# define _ASYNCIO_FUTURE__ASYNCIO_FUTURE_BLOCKING_GETSETDEF {"_asyncio_future_blocking", NULL, (setter)_asyncio_Future__asyncio_future_blocking_set, NULL},
+#endif
+
+static int
+_asyncio_Future__asyncio_future_blocking_set_impl(FutureObj *self,
+ PyObject *value);
+
+static int
+_asyncio_Future__asyncio_future_blocking_set(FutureObj *self, PyObject *value, void *Py_UNUSED(context))
+{
+ int return_value;
+
+ Py_BEGIN_CRITICAL_SECTION(self);
+ return_value = _asyncio_Future__asyncio_future_blocking_set_impl(self, value);
+ Py_END_CRITICAL_SECTION();
+
+ return return_value;
+}
+
+#if !defined(_asyncio_Future__log_traceback_DOCSTR)
+# define _asyncio_Future__log_traceback_DOCSTR NULL
+#endif
+#if defined(_ASYNCIO_FUTURE__LOG_TRACEBACK_GETSETDEF)
+# undef _ASYNCIO_FUTURE__LOG_TRACEBACK_GETSETDEF
+# define _ASYNCIO_FUTURE__LOG_TRACEBACK_GETSETDEF {"_log_traceback", (getter)_asyncio_Future__log_traceback_get, (setter)_asyncio_Future__log_traceback_set, _asyncio_Future__log_traceback_DOCSTR},
+#else
+# define _ASYNCIO_FUTURE__LOG_TRACEBACK_GETSETDEF {"_log_traceback", (getter)_asyncio_Future__log_traceback_get, NULL, _asyncio_Future__log_traceback_DOCSTR},
+#endif
+
+static PyObject *
+_asyncio_Future__log_traceback_get_impl(FutureObj *self);
+
+static PyObject *
+_asyncio_Future__log_traceback_get(FutureObj *self, void *Py_UNUSED(context))
+{
+ PyObject *return_value = NULL;
+
+ Py_BEGIN_CRITICAL_SECTION(self);
+ return_value = _asyncio_Future__log_traceback_get_impl(self);
+ Py_END_CRITICAL_SECTION();
+
+ return return_value;
+}
+
+#if !defined(_asyncio_Future__log_traceback_DOCSTR)
+# define _asyncio_Future__log_traceback_DOCSTR NULL
+#endif
+#if defined(_ASYNCIO_FUTURE__LOG_TRACEBACK_GETSETDEF)
+# undef _ASYNCIO_FUTURE__LOG_TRACEBACK_GETSETDEF
+# define _ASYNCIO_FUTURE__LOG_TRACEBACK_GETSETDEF {"_log_traceback", (getter)_asyncio_Future__log_traceback_get, (setter)_asyncio_Future__log_traceback_set, _asyncio_Future__log_traceback_DOCSTR},
+#else
+# define _ASYNCIO_FUTURE__LOG_TRACEBACK_GETSETDEF {"_log_traceback", NULL, (setter)_asyncio_Future__log_traceback_set, NULL},
+#endif
+
+static int
+_asyncio_Future__log_traceback_set_impl(FutureObj *self, PyObject *value);
+
+static int
+_asyncio_Future__log_traceback_set(FutureObj *self, PyObject *value, void *Py_UNUSED(context))
+{
+ int return_value;
+
+ Py_BEGIN_CRITICAL_SECTION(self);
+ return_value = _asyncio_Future__log_traceback_set_impl(self, value);
+ Py_END_CRITICAL_SECTION();
+
+ return return_value;
+}
+
+#if !defined(_asyncio_Future__loop_DOCSTR)
+# define _asyncio_Future__loop_DOCSTR NULL
+#endif
+#if defined(_ASYNCIO_FUTURE__LOOP_GETSETDEF)
+# undef _ASYNCIO_FUTURE__LOOP_GETSETDEF
+# define _ASYNCIO_FUTURE__LOOP_GETSETDEF {"_loop", (getter)_asyncio_Future__loop_get, (setter)_asyncio_Future__loop_set, _asyncio_Future__loop_DOCSTR},
+#else
+# define _ASYNCIO_FUTURE__LOOP_GETSETDEF {"_loop", (getter)_asyncio_Future__loop_get, NULL, _asyncio_Future__loop_DOCSTR},
+#endif
+
+static PyObject *
+_asyncio_Future__loop_get_impl(FutureObj *self);
+
+static PyObject *
+_asyncio_Future__loop_get(FutureObj *self, void *Py_UNUSED(context))
+{
+ PyObject *return_value = NULL;
+
+ Py_BEGIN_CRITICAL_SECTION(self);
+ return_value = _asyncio_Future__loop_get_impl(self);
+ Py_END_CRITICAL_SECTION();
+
+ return return_value;
+}
+
+#if !defined(_asyncio_Future__callbacks_DOCSTR)
+# define _asyncio_Future__callbacks_DOCSTR NULL
+#endif
+#if defined(_ASYNCIO_FUTURE__CALLBACKS_GETSETDEF)
+# undef _ASYNCIO_FUTURE__CALLBACKS_GETSETDEF
+# define _ASYNCIO_FUTURE__CALLBACKS_GETSETDEF {"_callbacks", (getter)_asyncio_Future__callbacks_get, (setter)_asyncio_Future__callbacks_set, _asyncio_Future__callbacks_DOCSTR},
+#else
+# define _ASYNCIO_FUTURE__CALLBACKS_GETSETDEF {"_callbacks", (getter)_asyncio_Future__callbacks_get, NULL, _asyncio_Future__callbacks_DOCSTR},
+#endif
+
+static PyObject *
+_asyncio_Future__callbacks_get_impl(FutureObj *self);
+
+static PyObject *
+_asyncio_Future__callbacks_get(FutureObj *self, void *Py_UNUSED(context))
+{
+ PyObject *return_value = NULL;
+
+ Py_BEGIN_CRITICAL_SECTION(self);
+ return_value = _asyncio_Future__callbacks_get_impl(self);
+ Py_END_CRITICAL_SECTION();
+
+ return return_value;
+}
+
+#if !defined(_asyncio_Future__result_DOCSTR)
+# define _asyncio_Future__result_DOCSTR NULL
+#endif
+#if defined(_ASYNCIO_FUTURE__RESULT_GETSETDEF)
+# undef _ASYNCIO_FUTURE__RESULT_GETSETDEF
+# define _ASYNCIO_FUTURE__RESULT_GETSETDEF {"_result", (getter)_asyncio_Future__result_get, (setter)_asyncio_Future__result_set, _asyncio_Future__result_DOCSTR},
+#else
+# define _ASYNCIO_FUTURE__RESULT_GETSETDEF {"_result", (getter)_asyncio_Future__result_get, NULL, _asyncio_Future__result_DOCSTR},
+#endif
+
+static PyObject *
+_asyncio_Future__result_get_impl(FutureObj *self);
+
+static PyObject *
+_asyncio_Future__result_get(FutureObj *self, void *Py_UNUSED(context))
+{
+ PyObject *return_value = NULL;
+
+ Py_BEGIN_CRITICAL_SECTION(self);
+ return_value = _asyncio_Future__result_get_impl(self);
+ Py_END_CRITICAL_SECTION();
+
+ return return_value;
+}
+
+#if !defined(_asyncio_Future__exception_DOCSTR)
+# define _asyncio_Future__exception_DOCSTR NULL
+#endif
+#if defined(_ASYNCIO_FUTURE__EXCEPTION_GETSETDEF)
+# undef _ASYNCIO_FUTURE__EXCEPTION_GETSETDEF
+# define _ASYNCIO_FUTURE__EXCEPTION_GETSETDEF {"_exception", (getter)_asyncio_Future__exception_get, (setter)_asyncio_Future__exception_set, _asyncio_Future__exception_DOCSTR},
+#else
+# define _ASYNCIO_FUTURE__EXCEPTION_GETSETDEF {"_exception", (getter)_asyncio_Future__exception_get, NULL, _asyncio_Future__exception_DOCSTR},
+#endif
+
+static PyObject *
+_asyncio_Future__exception_get_impl(FutureObj *self);
+
+static PyObject *
+_asyncio_Future__exception_get(FutureObj *self, void *Py_UNUSED(context))
+{
+ PyObject *return_value = NULL;
+
+ Py_BEGIN_CRITICAL_SECTION(self);
+ return_value = _asyncio_Future__exception_get_impl(self);
+ Py_END_CRITICAL_SECTION();
+
+ return return_value;
+}
+
+#if !defined(_asyncio_Future__source_traceback_DOCSTR)
+# define _asyncio_Future__source_traceback_DOCSTR NULL
+#endif
+#if defined(_ASYNCIO_FUTURE__SOURCE_TRACEBACK_GETSETDEF)
+# undef _ASYNCIO_FUTURE__SOURCE_TRACEBACK_GETSETDEF
+# define _ASYNCIO_FUTURE__SOURCE_TRACEBACK_GETSETDEF {"_source_traceback", (getter)_asyncio_Future__source_traceback_get, (setter)_asyncio_Future__source_traceback_set, _asyncio_Future__source_traceback_DOCSTR},
+#else
+# define _ASYNCIO_FUTURE__SOURCE_TRACEBACK_GETSETDEF {"_source_traceback", (getter)_asyncio_Future__source_traceback_get, NULL, _asyncio_Future__source_traceback_DOCSTR},
+#endif
+
+static PyObject *
+_asyncio_Future__source_traceback_get_impl(FutureObj *self);
+
+static PyObject *
+_asyncio_Future__source_traceback_get(FutureObj *self, void *Py_UNUSED(context))
+{
+ PyObject *return_value = NULL;
+
+ Py_BEGIN_CRITICAL_SECTION(self);
+ return_value = _asyncio_Future__source_traceback_get_impl(self);
+ Py_END_CRITICAL_SECTION();
+
+ return return_value;
+}
+
+#if !defined(_asyncio_Future__cancel_message_DOCSTR)
+# define _asyncio_Future__cancel_message_DOCSTR NULL
+#endif
+#if defined(_ASYNCIO_FUTURE__CANCEL_MESSAGE_GETSETDEF)
+# undef _ASYNCIO_FUTURE__CANCEL_MESSAGE_GETSETDEF
+# define _ASYNCIO_FUTURE__CANCEL_MESSAGE_GETSETDEF {"_cancel_message", (getter)_asyncio_Future__cancel_message_get, (setter)_asyncio_Future__cancel_message_set, _asyncio_Future__cancel_message_DOCSTR},
+#else
+# define _ASYNCIO_FUTURE__CANCEL_MESSAGE_GETSETDEF {"_cancel_message", (getter)_asyncio_Future__cancel_message_get, NULL, _asyncio_Future__cancel_message_DOCSTR},
+#endif
+
+static PyObject *
+_asyncio_Future__cancel_message_get_impl(FutureObj *self);
+
+static PyObject *
+_asyncio_Future__cancel_message_get(FutureObj *self, void *Py_UNUSED(context))
+{
+ PyObject *return_value = NULL;
+
+ Py_BEGIN_CRITICAL_SECTION(self);
+ return_value = _asyncio_Future__cancel_message_get_impl(self);
+ Py_END_CRITICAL_SECTION();
+
+ return return_value;
+}
+
+#if !defined(_asyncio_Future__cancel_message_DOCSTR)
+# define _asyncio_Future__cancel_message_DOCSTR NULL
+#endif
+#if defined(_ASYNCIO_FUTURE__CANCEL_MESSAGE_GETSETDEF)
+# undef _ASYNCIO_FUTURE__CANCEL_MESSAGE_GETSETDEF
+# define _ASYNCIO_FUTURE__CANCEL_MESSAGE_GETSETDEF {"_cancel_message", (getter)_asyncio_Future__cancel_message_get, (setter)_asyncio_Future__cancel_message_set, _asyncio_Future__cancel_message_DOCSTR},
+#else
+# define _ASYNCIO_FUTURE__CANCEL_MESSAGE_GETSETDEF {"_cancel_message", NULL, (setter)_asyncio_Future__cancel_message_set, NULL},
+#endif
+
+static int
+_asyncio_Future__cancel_message_set_impl(FutureObj *self, PyObject *value);
+
+static int
+_asyncio_Future__cancel_message_set(FutureObj *self, PyObject *value, void *Py_UNUSED(context))
+{
+ int return_value;
+
+ Py_BEGIN_CRITICAL_SECTION(self);
+ return_value = _asyncio_Future__cancel_message_set_impl(self, value);
+ Py_END_CRITICAL_SECTION();
+
+ return return_value;
+}
+
+#if !defined(_asyncio_Future__state_DOCSTR)
+# define _asyncio_Future__state_DOCSTR NULL
+#endif
+#if defined(_ASYNCIO_FUTURE__STATE_GETSETDEF)
+# undef _ASYNCIO_FUTURE__STATE_GETSETDEF
+# define _ASYNCIO_FUTURE__STATE_GETSETDEF {"_state", (getter)_asyncio_Future__state_get, (setter)_asyncio_Future__state_set, _asyncio_Future__state_DOCSTR},
+#else
+# define _ASYNCIO_FUTURE__STATE_GETSETDEF {"_state", (getter)_asyncio_Future__state_get, NULL, _asyncio_Future__state_DOCSTR},
+#endif
+
+static PyObject *
+_asyncio_Future__state_get_impl(FutureObj *self);
+
+static PyObject *
+_asyncio_Future__state_get(FutureObj *self, void *Py_UNUSED(context))
+{
+ PyObject *return_value = NULL;
+
+ Py_BEGIN_CRITICAL_SECTION(self);
+ return_value = _asyncio_Future__state_get_impl(self);
+ Py_END_CRITICAL_SECTION();
+
+ return return_value;
}
PyDoc_STRVAR(_asyncio_Future__make_cancelled_error__doc__,
@@ -484,7 +828,13 @@ _asyncio_Future__make_cancelled_error_impl(FutureObj *self);
static PyObject *
_asyncio_Future__make_cancelled_error(FutureObj *self, PyObject *Py_UNUSED(ignored))
{
- return _asyncio_Future__make_cancelled_error_impl(self);
+ PyObject *return_value = NULL;
+
+ Py_BEGIN_CRITICAL_SECTION(self);
+ return_value = _asyncio_Future__make_cancelled_error_impl(self);
+ Py_END_CRITICAL_SECTION();
+
+ return return_value;
}
PyDoc_STRVAR(_asyncio_Task___init____doc__,
@@ -575,6 +925,131 @@ _asyncio_Task___init__(PyObject *self, PyObject *args, PyObject *kwargs)
return return_value;
}
+#if !defined(_asyncio_Task__log_destroy_pending_DOCSTR)
+# define _asyncio_Task__log_destroy_pending_DOCSTR NULL
+#endif
+#if defined(_ASYNCIO_TASK__LOG_DESTROY_PENDING_GETSETDEF)
+# undef _ASYNCIO_TASK__LOG_DESTROY_PENDING_GETSETDEF
+# define _ASYNCIO_TASK__LOG_DESTROY_PENDING_GETSETDEF {"_log_destroy_pending", (getter)_asyncio_Task__log_destroy_pending_get, (setter)_asyncio_Task__log_destroy_pending_set, _asyncio_Task__log_destroy_pending_DOCSTR},
+#else
+# define _ASYNCIO_TASK__LOG_DESTROY_PENDING_GETSETDEF {"_log_destroy_pending", (getter)_asyncio_Task__log_destroy_pending_get, NULL, _asyncio_Task__log_destroy_pending_DOCSTR},
+#endif
+
+static PyObject *
+_asyncio_Task__log_destroy_pending_get_impl(TaskObj *self);
+
+static PyObject *
+_asyncio_Task__log_destroy_pending_get(TaskObj *self, void *Py_UNUSED(context))
+{
+ PyObject *return_value = NULL;
+
+ Py_BEGIN_CRITICAL_SECTION(self);
+ return_value = _asyncio_Task__log_destroy_pending_get_impl(self);
+ Py_END_CRITICAL_SECTION();
+
+ return return_value;
+}
+
+#if !defined(_asyncio_Task__log_destroy_pending_DOCSTR)
+# define _asyncio_Task__log_destroy_pending_DOCSTR NULL
+#endif
+#if defined(_ASYNCIO_TASK__LOG_DESTROY_PENDING_GETSETDEF)
+# undef _ASYNCIO_TASK__LOG_DESTROY_PENDING_GETSETDEF
+# define _ASYNCIO_TASK__LOG_DESTROY_PENDING_GETSETDEF {"_log_destroy_pending", (getter)_asyncio_Task__log_destroy_pending_get, (setter)_asyncio_Task__log_destroy_pending_set, _asyncio_Task__log_destroy_pending_DOCSTR},
+#else
+# define _ASYNCIO_TASK__LOG_DESTROY_PENDING_GETSETDEF {"_log_destroy_pending", NULL, (setter)_asyncio_Task__log_destroy_pending_set, NULL},
+#endif
+
+static int
+_asyncio_Task__log_destroy_pending_set_impl(TaskObj *self, PyObject *value);
+
+static int
+_asyncio_Task__log_destroy_pending_set(TaskObj *self, PyObject *value, void *Py_UNUSED(context))
+{
+ int return_value;
+
+ Py_BEGIN_CRITICAL_SECTION(self);
+ return_value = _asyncio_Task__log_destroy_pending_set_impl(self, value);
+ Py_END_CRITICAL_SECTION();
+
+ return return_value;
+}
+
+#if !defined(_asyncio_Task__must_cancel_DOCSTR)
+# define _asyncio_Task__must_cancel_DOCSTR NULL
+#endif
+#if defined(_ASYNCIO_TASK__MUST_CANCEL_GETSETDEF)
+# undef _ASYNCIO_TASK__MUST_CANCEL_GETSETDEF
+# define _ASYNCIO_TASK__MUST_CANCEL_GETSETDEF {"_must_cancel", (getter)_asyncio_Task__must_cancel_get, (setter)_asyncio_Task__must_cancel_set, _asyncio_Task__must_cancel_DOCSTR},
+#else
+# define _ASYNCIO_TASK__MUST_CANCEL_GETSETDEF {"_must_cancel", (getter)_asyncio_Task__must_cancel_get, NULL, _asyncio_Task__must_cancel_DOCSTR},
+#endif
+
+static PyObject *
+_asyncio_Task__must_cancel_get_impl(TaskObj *self);
+
+static PyObject *
+_asyncio_Task__must_cancel_get(TaskObj *self, void *Py_UNUSED(context))
+{
+ PyObject *return_value = NULL;
+
+ Py_BEGIN_CRITICAL_SECTION(self);
+ return_value = _asyncio_Task__must_cancel_get_impl(self);
+ Py_END_CRITICAL_SECTION();
+
+ return return_value;
+}
+
+#if !defined(_asyncio_Task__coro_DOCSTR)
+# define _asyncio_Task__coro_DOCSTR NULL
+#endif
+#if defined(_ASYNCIO_TASK__CORO_GETSETDEF)
+# undef _ASYNCIO_TASK__CORO_GETSETDEF
+# define _ASYNCIO_TASK__CORO_GETSETDEF {"_coro", (getter)_asyncio_Task__coro_get, (setter)_asyncio_Task__coro_set, _asyncio_Task__coro_DOCSTR},
+#else
+# define _ASYNCIO_TASK__CORO_GETSETDEF {"_coro", (getter)_asyncio_Task__coro_get, NULL, _asyncio_Task__coro_DOCSTR},
+#endif
+
+static PyObject *
+_asyncio_Task__coro_get_impl(TaskObj *self);
+
+static PyObject *
+_asyncio_Task__coro_get(TaskObj *self, void *Py_UNUSED(context))
+{
+ PyObject *return_value = NULL;
+
+ Py_BEGIN_CRITICAL_SECTION(self);
+ return_value = _asyncio_Task__coro_get_impl(self);
+ Py_END_CRITICAL_SECTION();
+
+ return return_value;
+}
+
+#if !defined(_asyncio_Task__fut_waiter_DOCSTR)
+# define _asyncio_Task__fut_waiter_DOCSTR NULL
+#endif
+#if defined(_ASYNCIO_TASK__FUT_WAITER_GETSETDEF)
+# undef _ASYNCIO_TASK__FUT_WAITER_GETSETDEF
+# define _ASYNCIO_TASK__FUT_WAITER_GETSETDEF {"_fut_waiter", (getter)_asyncio_Task__fut_waiter_get, (setter)_asyncio_Task__fut_waiter_set, _asyncio_Task__fut_waiter_DOCSTR},
+#else
+# define _ASYNCIO_TASK__FUT_WAITER_GETSETDEF {"_fut_waiter", (getter)_asyncio_Task__fut_waiter_get, NULL, _asyncio_Task__fut_waiter_DOCSTR},
+#endif
+
+static PyObject *
+_asyncio_Task__fut_waiter_get_impl(TaskObj *self);
+
+static PyObject *
+_asyncio_Task__fut_waiter_get(TaskObj *self, void *Py_UNUSED(context))
+{
+ PyObject *return_value = NULL;
+
+ Py_BEGIN_CRITICAL_SECTION(self);
+ return_value = _asyncio_Task__fut_waiter_get_impl(self);
+ Py_END_CRITICAL_SECTION();
+
+ return return_value;
+}
+
PyDoc_STRVAR(_asyncio_Task__make_cancelled_error__doc__,
"_make_cancelled_error($self, /)\n"
"--\n"
@@ -593,7 +1068,13 @@ _asyncio_Task__make_cancelled_error_impl(TaskObj *self);
static PyObject *
_asyncio_Task__make_cancelled_error(TaskObj *self, PyObject *Py_UNUSED(ignored))
{
- return _asyncio_Task__make_cancelled_error_impl(self);
+ PyObject *return_value = NULL;
+
+ Py_BEGIN_CRITICAL_SECTION(self);
+ return_value = _asyncio_Task__make_cancelled_error_impl(self);
+ Py_END_CRITICAL_SECTION();
+
+ return return_value;
}
PyDoc_STRVAR(_asyncio_Task_cancel__doc__,
@@ -670,7 +1151,9 @@ _asyncio_Task_cancel(TaskObj *self, PyObject *const *args, Py_ssize_t nargs, PyO
}
msg = args[0];
skip_optional_pos:
+ Py_BEGIN_CRITICAL_SECTION(self);
return_value = _asyncio_Task_cancel_impl(self, msg);
+ Py_END_CRITICAL_SECTION();
exit:
return return_value;
@@ -694,7 +1177,13 @@ _asyncio_Task_cancelling_impl(TaskObj *self);
static PyObject *
_asyncio_Task_cancelling(TaskObj *self, PyObject *Py_UNUSED(ignored))
{
- return _asyncio_Task_cancelling_impl(self);
+ PyObject *return_value = NULL;
+
+ Py_BEGIN_CRITICAL_SECTION(self);
+ return_value = _asyncio_Task_cancelling_impl(self);
+ Py_END_CRITICAL_SECTION();
+
+ return return_value;
}
PyDoc_STRVAR(_asyncio_Task_uncancel__doc__,
@@ -717,7 +1206,13 @@ _asyncio_Task_uncancel_impl(TaskObj *self);
static PyObject *
_asyncio_Task_uncancel(TaskObj *self, PyObject *Py_UNUSED(ignored))
{
- return _asyncio_Task_uncancel_impl(self);
+ PyObject *return_value = NULL;
+
+ Py_BEGIN_CRITICAL_SECTION(self);
+ return_value = _asyncio_Task_uncancel_impl(self);
+ Py_END_CRITICAL_SECTION();
+
+ return return_value;
}
PyDoc_STRVAR(_asyncio_Task_get_stack__doc__,
@@ -905,7 +1400,13 @@ _asyncio_Task_get_coro_impl(TaskObj *self);
static PyObject *
_asyncio_Task_get_coro(TaskObj *self, PyObject *Py_UNUSED(ignored))
{
- return _asyncio_Task_get_coro_impl(self);
+ PyObject *return_value = NULL;
+
+ Py_BEGIN_CRITICAL_SECTION(self);
+ return_value = _asyncio_Task_get_coro_impl(self);
+ Py_END_CRITICAL_SECTION();
+
+ return return_value;
}
PyDoc_STRVAR(_asyncio_Task_get_context__doc__,
@@ -939,7 +1440,13 @@ _asyncio_Task_get_name_impl(TaskObj *self);
static PyObject *
_asyncio_Task_get_name(TaskObj *self, PyObject *Py_UNUSED(ignored))
{
- return _asyncio_Task_get_name_impl(self);
+ PyObject *return_value = NULL;
+
+ Py_BEGIN_CRITICAL_SECTION(self);
+ return_value = _asyncio_Task_get_name_impl(self);
+ Py_END_CRITICAL_SECTION();
+
+ return return_value;
}
PyDoc_STRVAR(_asyncio_Task_set_name__doc__,
@@ -950,6 +1457,21 @@ PyDoc_STRVAR(_asyncio_Task_set_name__doc__,
#define _ASYNCIO_TASK_SET_NAME_METHODDEF \
{"set_name", (PyCFunction)_asyncio_Task_set_name, METH_O, _asyncio_Task_set_name__doc__},
+static PyObject *
+_asyncio_Task_set_name_impl(TaskObj *self, PyObject *value);
+
+static PyObject *
+_asyncio_Task_set_name(TaskObj *self, PyObject *value)
+{
+ PyObject *return_value = NULL;
+
+ Py_BEGIN_CRITICAL_SECTION(self);
+ return_value = _asyncio_Task_set_name_impl(self, value);
+ Py_END_CRITICAL_SECTION();
+
+ return return_value;
+}
+
PyDoc_STRVAR(_asyncio__get_running_loop__doc__,
"_get_running_loop($module, /)\n"
"--\n"
@@ -1566,4 +2088,4 @@ _asyncio_all_tasks(PyObject *module, PyObject *const *args, Py_ssize_t nargs, Py
exit:
return return_value;
}
-/*[clinic end generated code: output=e5d95a0ec229ffcd input=a9049054013a1b77]*/
+/*[clinic end generated code: output=408e156476ced07f input=a9049054013a1b77]*/
1
0
[3.13] gh-128354: Consistently use LIBS over LDFLAGS in library build… (#128465)
by erlend-aasland 04 Jan '25
by erlend-aasland 04 Jan '25
04 Jan '25
https://github.com/python/cpython/commit/855af3bbc62e89aeeb6af1e22061cf0635…
commit: 855af3bbc62e89aeeb6af1e22061cf06354ad99a
branch: 3.13
author: Zanie Blue <contact(a)zanie.dev>
committer: erlend-aasland <erlend.aasland(a)protonmail.com>
date: 2025-01-04T00:50:13Z
summary:
[3.13] gh-128354: Consistently use LIBS over LDFLAGS in library build… (#128465)
(cherry picked from commit b75ed951d4de8ba85349d80c8e7f097b3cd6052f)
files:
M configure
M configure.ac
diff --git a/configure b/configure
index b093689aeb1e4b..c66333c721d841 100755
--- a/configure
+++ b/configure
@@ -13467,7 +13467,7 @@ save_LIBS=$LIBS
CPPFLAGS="$CPPFLAGS $LIBUUID_CFLAGS"
- LDFLAGS="$LDFLAGS $LIBUUID_LIBS"
+ LIBS="$LIBS $LIBUUID_LIBS"
for ac_header in uuid/uuid.h
do :
ac_fn_c_check_header_compile "$LINENO" "uuid/uuid.h" "ac_cv_header_uuid_uuid_h" "$ac_includes_default"
@@ -13593,7 +13593,7 @@ save_LIBS=$LIBS
CPPFLAGS="$CPPFLAGS $LIBUUID_CFLAGS"
- LDFLAGS="$LDFLAGS $LIBUUID_LIBS"
+ LIBS="$LIBS $LIBUUID_LIBS"
for ac_header in uuid/uuid.h
do :
ac_fn_c_check_header_compile "$LINENO" "uuid/uuid.h" "ac_cv_header_uuid_uuid_h" "$ac_includes_default"
@@ -14363,7 +14363,7 @@ save_LIBS=$LIBS
CPPFLAGS="$CPPFLAGS $LIBFFI_CFLAGS"
- LDFLAGS="$LDFLAGS $LIBFFI_LIBS"
+ LIBS="$LIBS $LIBFFI_LIBS"
ac_fn_c_check_header_compile "$LINENO" "ffi.h" "ac_cv_header_ffi_h" "$ac_includes_default"
if test "x$ac_cv_header_ffi_h" = xyes
then :
@@ -14436,7 +14436,7 @@ save_LIBS=$LIBS
CPPFLAGS="$CPPFLAGS $LIBFFI_CFLAGS"
- LDFLAGS="$LDFLAGS $LIBFFI_LIBS"
+ LIBS="$LIBS $LIBFFI_LIBS"
ac_fn_c_check_header_compile "$LINENO" "ffi.h" "ac_cv_header_ffi_h" "$ac_includes_default"
if test "x$ac_cv_header_ffi_h" = xyes
then :
@@ -14547,8 +14547,8 @@ save_LDFLAGS=$LDFLAGS
save_LIBS=$LIBS
- CFLAGS="$LIBFFI_CFLAGS $CFLAGS"
- LDFLAGS="$LIBFFI_LIBS $LDFLAGS"
+ CFLAGS="$CFLAGS $LIBFFI_CFLAGS"
+ LIBS="$LIBS $LIBFFI_LIBS"
@@ -14787,8 +14787,8 @@ save_LDFLAGS=$LDFLAGS
save_LIBS=$LIBS
- CPPFLAGS="$LIBMPDEC_CFLAGS $CPPFLAGS"
- LIBS="$LIBMPDEC_LIBS $LIBS"
+ CPPFLAGS="$CPPFLAGS $LIBMPDEC_CFLAGS"
+ LIBS="$LIBS $LIBMPDEC_LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -15055,7 +15055,7 @@ save_LIBS=$LIBS
CPPFLAGS="$CPPFLAGS $LIBSQLITE3_CFLAGS"
- LIBS="$LIBSQLITE3_LIBS $LIBS"
+ LIBS="$LIBS $LIBSQLITE3_LIBS"
ac_fn_c_check_header_compile "$LINENO" "sqlite3.h" "ac_cv_header_sqlite3_h" "$ac_includes_default"
if test "x$ac_cv_header_sqlite3_h" = xyes
@@ -15935,7 +15935,7 @@ save_LIBS=$LIBS
CPPFLAGS="$CPPFLAGS $TCLTK_CFLAGS"
- LIBS="$TCLTK_LIBS $LDFLAGS"
+ LIBS="$LIBS $TCLTK_LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -16001,7 +16001,7 @@ save_LIBS=$LIBS
CPPFLAGS="$CPPFLAGS $GDBM_CFLAGS"
- LDFLAGS="$GDBM_LIBS $LDFLAGS"
+ LIBS="$LIBS $GDBM_LIBS"
for ac_header in gdbm.h
do :
ac_fn_c_check_header_compile "$LINENO" "gdbm.h" "ac_cv_header_gdbm_h" "$ac_includes_default"
@@ -20278,7 +20278,7 @@ save_LIBS=$LIBS
CPPFLAGS="$CPPFLAGS $ZLIB_CFLAGS"
- LDFLAGS="$LDFLAGS $ZLIB_LIBS"
+ LIBS="$LIBS $ZLIB_LIBS"
for ac_header in zlib.h
do :
ac_fn_c_check_header_compile "$LINENO" "zlib.h" "ac_cv_header_zlib_h" "$ac_includes_default"
@@ -20407,7 +20407,7 @@ save_LIBS=$LIBS
CPPFLAGS="$CPPFLAGS $ZLIB_CFLAGS"
- LDFLAGS="$LDFLAGS $ZLIB_LIBS"
+ LIBS="$LIBS $ZLIB_LIBS"
for ac_header in zlib.h
do :
ac_fn_c_check_header_compile "$LINENO" "zlib.h" "ac_cv_header_zlib_h" "$ac_includes_default"
@@ -20626,7 +20626,7 @@ save_LIBS=$LIBS
CPPFLAGS="$CPPFLAGS $BZIP2_CFLAGS"
- LDFLAGS="$LDFLAGS $BZIP2_LIBS"
+ LIBS="$LIBS $BZIP2_LIBS"
for ac_header in bzlib.h
do :
ac_fn_c_check_header_compile "$LINENO" "bzlib.h" "ac_cv_header_bzlib_h" "$ac_includes_default"
@@ -20708,7 +20708,7 @@ save_LIBS=$LIBS
CPPFLAGS="$CPPFLAGS $BZIP2_CFLAGS"
- LDFLAGS="$LDFLAGS $BZIP2_LIBS"
+ LIBS="$LIBS $BZIP2_LIBS"
for ac_header in bzlib.h
do :
ac_fn_c_check_header_compile "$LINENO" "bzlib.h" "ac_cv_header_bzlib_h" "$ac_includes_default"
@@ -20854,7 +20854,7 @@ save_LIBS=$LIBS
CPPFLAGS="$CPPFLAGS $LIBLZMA_CFLAGS"
- LDFLAGS="$LDFLAGS $LIBLZMA_LIBS"
+ LIBS="$LIBS $LIBLZMA_LIBS"
for ac_header in lzma.h
do :
ac_fn_c_check_header_compile "$LINENO" "lzma.h" "ac_cv_header_lzma_h" "$ac_includes_default"
@@ -20936,7 +20936,7 @@ save_LIBS=$LIBS
CPPFLAGS="$CPPFLAGS $LIBLZMA_CFLAGS"
- LDFLAGS="$LDFLAGS $LIBLZMA_LIBS"
+ LIBS="$LIBS $LIBLZMA_LIBS"
for ac_header in lzma.h
do :
ac_fn_c_check_header_compile "$LINENO" "lzma.h" "ac_cv_header_lzma_h" "$ac_includes_default"
@@ -24862,7 +24862,7 @@ save_LIBS=$LIBS
CPPFLAGS="$CPPFLAGS $LIBREADLINE_CFLAGS"
- LDFLAGS="$LDFLAGS $LIBREADLINE_LIBS"
+ LIBS="$LIBS $LIBREADLINE_LIBS"
for ac_header in readline/readline.h
do :
ac_fn_c_check_header_compile "$LINENO" "readline/readline.h" "ac_cv_header_readline_readline_h" "$ac_includes_default"
@@ -24941,7 +24941,7 @@ save_LIBS=$LIBS
CPPFLAGS="$CPPFLAGS $LIBREADLINE_CFLAGS"
- LDFLAGS="$LDFLAGS $LIBREADLINE_LIBS"
+ LIBS="$LIBS $LIBREADLINE_LIBS"
for ac_header in readline/readline.h
do :
ac_fn_c_check_header_compile "$LINENO" "readline/readline.h" "ac_cv_header_readline_readline_h" "$ac_includes_default"
@@ -25093,7 +25093,7 @@ save_LIBS=$LIBS
CPPFLAGS="$CPPFLAGS $LIBEDIT_CFLAGS"
- LDFLAGS="$LDFLAGS $LIBEDIT_LIBS"
+ LIBS="$LIBS $LIBEDIT_LIBS"
for ac_header in editline/readline.h
do :
ac_fn_c_check_header_compile "$LINENO" "editline/readline.h" "ac_cv_header_editline_readline_h" "$ac_includes_default"
@@ -25174,7 +25174,7 @@ save_LIBS=$LIBS
CPPFLAGS="$CPPFLAGS $LIBEDIT_CFLAGS"
- LDFLAGS="$LDFLAGS $LIBEDIT_LIBS"
+ LIBS="$LIBS $LIBEDIT_LIBS"
for ac_header in editline/readline.h
do :
ac_fn_c_check_header_compile "$LINENO" "editline/readline.h" "ac_cv_header_editline_readline_h" "$ac_includes_default"
@@ -25282,7 +25282,7 @@ save_LIBS=$LIBS
CPPFLAGS="$CPPFLAGS $READLINE_CFLAGS"
- LIBS="$READLINE_LIBS $LIBS"
+ LIBS="$LIBS $READLINE_LIBS"
LIBS_SAVE=$LIBS
diff --git a/configure.ac b/configure.ac
index ea557fba25df96..c53e55fbba2a5f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3744,7 +3744,7 @@ AS_VAR_IF([have_uuid], [missing], [
], [
WITH_SAVE_ENV([
CPPFLAGS="$CPPFLAGS $LIBUUID_CFLAGS"
- LDFLAGS="$LDFLAGS $LIBUUID_LIBS"
+ LIBS="$LIBS $LIBUUID_LIBS"
AC_CHECK_HEADERS([uuid/uuid.h], [
PY_CHECK_LIB([uuid], [uuid_generate_time], [have_uuid=yes])
PY_CHECK_LIB([uuid], [uuid_generate_time_safe],
@@ -3978,7 +3978,7 @@ AS_VAR_IF([have_libffi], [missing], [
PKG_CHECK_MODULES([LIBFFI], [libffi], [have_libffi=yes], [
WITH_SAVE_ENV([
CPPFLAGS="$CPPFLAGS $LIBFFI_CFLAGS"
- LDFLAGS="$LDFLAGS $LIBFFI_LIBS"
+ LIBS="$LIBS $LIBFFI_LIBS"
AC_CHECK_HEADER([ffi.h], [
AC_CHECK_LIB([ffi], [ffi_call], [
have_libffi=yes
@@ -4012,8 +4012,8 @@ AS_VAR_IF([have_libffi], [yes], [
AS_VAR_IF([ac_cv_lib_dl_dlopen], [yes], [AS_VAR_APPEND([LIBFFI_LIBS], [" -ldl"])])
WITH_SAVE_ENV([
- CFLAGS="$LIBFFI_CFLAGS $CFLAGS"
- LDFLAGS="$LIBFFI_LIBS $LDFLAGS"
+ CFLAGS="$CFLAGS $LIBFFI_CFLAGS"
+ LIBS="$LIBS $LIBFFI_LIBS"
PY_CHECK_FUNC([ffi_prep_cif_var], [@%:@include <ffi.h>])
PY_CHECK_FUNC([ffi_prep_closure_loc], [@%:@include <ffi.h>])
@@ -4051,8 +4051,8 @@ AS_VAR_IF(
AS_VAR_IF([with_system_libmpdec], [yes],
[WITH_SAVE_ENV([
- CPPFLAGS="$LIBMPDEC_CFLAGS $CPPFLAGS"
- LIBS="$LIBMPDEC_LIBS $LIBS"
+ CPPFLAGS="$CPPFLAGS $LIBMPDEC_CFLAGS"
+ LIBS="$LIBS $LIBMPDEC_LIBS"
AC_LINK_IFELSE([
AC_LANG_PROGRAM([
@@ -4185,7 +4185,7 @@ WITH_SAVE_ENV([
dnl bpo-45774/GH-29507: The CPP check in AC_CHECK_HEADER can fail on FreeBSD,
dnl hence CPPFLAGS instead of CFLAGS.
CPPFLAGS="$CPPFLAGS $LIBSQLITE3_CFLAGS"
- LIBS="$LIBSQLITE3_LIBS $LIBS"
+ LIBS="$LIBS $LIBSQLITE3_LIBS"
AC_CHECK_HEADER([sqlite3.h], [
have_sqlite3=yes
@@ -4288,7 +4288,7 @@ AS_CASE([$ac_sys_system],
WITH_SAVE_ENV([
CPPFLAGS="$CPPFLAGS $TCLTK_CFLAGS"
- LIBS="$TCLTK_LIBS $LDFLAGS"
+ LIBS="$LIBS $TCLTK_LIBS"
AC_LINK_IFELSE([
AC_LANG_PROGRAM([
@@ -4330,7 +4330,7 @@ AC_ARG_VAR([GDBM_CFLAGS], [C compiler flags for gdbm])
AC_ARG_VAR([GDBM_LIBS], [additional linker flags for gdbm])
WITH_SAVE_ENV([
CPPFLAGS="$CPPFLAGS $GDBM_CFLAGS"
- LDFLAGS="$GDBM_LIBS $LDFLAGS"
+ LIBS="$LIBS $GDBM_LIBS"
AC_CHECK_HEADERS([gdbm.h], [
AC_CHECK_LIB([gdbm], [gdbm_open], [
have_gdbm=yes
@@ -5288,7 +5288,7 @@ PKG_CHECK_MODULES([ZLIB], [zlib >= 1.2.0], [
], [
WITH_SAVE_ENV([
CPPFLAGS="$CPPFLAGS $ZLIB_CFLAGS"
- LDFLAGS="$LDFLAGS $ZLIB_LIBS"
+ LIBS="$LIBS $ZLIB_LIBS"
AC_CHECK_HEADERS([zlib.h], [
PY_CHECK_LIB([z], [gzread], [have_zlib=yes], [have_zlib=no])
], [have_zlib=no])
@@ -5312,7 +5312,7 @@ PY_CHECK_EMSCRIPTEN_PORT([BZIP2], [-sUSE_BZIP2])
PKG_CHECK_MODULES([BZIP2], [bzip2], [have_bzip2=yes], [
WITH_SAVE_ENV([
CPPFLAGS="$CPPFLAGS $BZIP2_CFLAGS"
- LDFLAGS="$LDFLAGS $BZIP2_LIBS"
+ LIBS="$LIBS $BZIP2_LIBS"
AC_CHECK_HEADERS([bzlib.h], [
AC_CHECK_LIB([bz2], [BZ2_bzCompress], [have_bzip2=yes], [have_bzip2=no])
], [have_bzip2=no])
@@ -5326,7 +5326,7 @@ PKG_CHECK_MODULES([BZIP2], [bzip2], [have_bzip2=yes], [
PKG_CHECK_MODULES([LIBLZMA], [liblzma], [have_liblzma=yes], [
WITH_SAVE_ENV([
CPPFLAGS="$CPPFLAGS $LIBLZMA_CFLAGS"
- LDFLAGS="$LDFLAGS $LIBLZMA_LIBS"
+ LIBS="$LIBS $LIBLZMA_LIBS"
AC_CHECK_HEADERS([lzma.h], [
AC_CHECK_LIB([lzma], [lzma_easy_encoder], [have_liblzma=yes], [have_liblzma=no])
], [have_liblzma=no])
@@ -6318,7 +6318,7 @@ AS_VAR_IF([with_readline], [readline], [
], [
WITH_SAVE_ENV([
CPPFLAGS="$CPPFLAGS $LIBREADLINE_CFLAGS"
- LDFLAGS="$LDFLAGS $LIBREADLINE_LIBS"
+ LIBS="$LIBS $LIBREADLINE_LIBS"
AC_CHECK_HEADERS([readline/readline.h], [
AC_CHECK_LIB([readline], [readline], [
LIBREADLINE=readline
@@ -6339,7 +6339,7 @@ AS_VAR_IF([with_readline], [edit], [
], [
WITH_SAVE_ENV([
CPPFLAGS="$CPPFLAGS $LIBEDIT_CFLAGS"
- LDFLAGS="$LDFLAGS $LIBEDIT_LIBS"
+ LIBS="$LIBS $LIBEDIT_LIBS"
AC_CHECK_HEADERS([editline/readline.h], [
AC_CHECK_LIB([edit], [readline], [
LIBREADLINE=edit
@@ -6363,7 +6363,7 @@ AS_VAR_IF([with_readline], [no], [
WITH_SAVE_ENV([
CPPFLAGS="$CPPFLAGS $READLINE_CFLAGS"
- LIBS="$READLINE_LIBS $LIBS"
+ LIBS="$LIBS $READLINE_LIBS"
LIBS_SAVE=$LIBS
m4_define([readline_includes], [
1
0