Skip to content

Commit 68fbc00

Browse files
gh-118851: Default ctx arguments to AST constructors to Load() (#118854)
Co-authored-by: Alex Waygood <[email protected]>
1 parent 98ff3f6 commit 68fbc00

File tree

6 files changed

+41
-6
lines changed

6 files changed

+41
-6
lines changed

Doc/library/ast.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,8 @@ Node classes
120120

121121
If a field that is optional in the grammar is omitted from the constructor,
122122
it defaults to ``None``. If a list field is omitted, it defaults to the empty
123-
list. If any other field is omitted, a :exc:`DeprecationWarning` is raised
123+
list. If a field of type :class:`!ast.expr_context` is omitted, it defaults to
124+
:class:`Load() <ast.Load>`. If any other field is omitted, a :exc:`DeprecationWarning` is raised
124125
and the AST node will not have this field. In Python 3.15, this condition will
125126
raise an error.
126127

@@ -596,8 +597,7 @@ Expressions
596597
* ``keywords`` holds a list of :class:`.keyword` objects representing
597598
arguments passed by keyword.
598599

599-
When creating a ``Call`` node, ``args`` and ``keywords`` are required, but
600-
they can be empty lists.
600+
The ``args`` and ``keywords`` arguments are optional and default to empty lists.
601601

602602
.. doctest::
603603

Doc/whatsnew/3.13.rst

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -521,8 +521,10 @@ ast
521521

522522
If an optional field on an AST node is not included as an argument when
523523
constructing an instance, the field will now be set to ``None``. Similarly,
524-
if a list field is omitted, that field will now be set to an empty list.
525-
(Previously, in both cases, the attribute would be missing on the newly
524+
if a list field is omitted, that field will now be set to an empty list,
525+
and if a :class:`!ast.expr_context` field is omitted, it defaults to
526+
:class:`Load() <ast.Load>`.
527+
(Previously, in all cases, the attribute would be missing on the newly
526528
constructed AST node instance.)
527529

528530
If other arguments are omitted, a :exc:`DeprecationWarning` is emitted.
@@ -534,7 +536,7 @@ ast
534536
unless the class opts in to the new behavior by setting the attribute
535537
:attr:`ast.AST._field_types`.
536538

537-
(Contributed by Jelle Zijlstra in :gh:`105858` and :gh:`117486`.)
539+
(Contributed by Jelle Zijlstra in :gh:`105858`, :gh:`117486`, and :gh:`118851`.)
538540

539541
* :func:`ast.parse` now accepts an optional argument *optimize*
540542
which is passed on to the :func:`compile` built-in. This makes it

Lib/test/test_ast.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3036,6 +3036,23 @@ def test_FunctionDef(self):
30363036
self.assertEqual(node.name, 'foo')
30373037
self.assertEqual(node.decorator_list, [])
30383038

3039+
def test_expr_context(self):
3040+
name = ast.Name("x")
3041+
self.assertEqual(name.id, "x")
3042+
self.assertIsInstance(name.ctx, ast.Load)
3043+
3044+
name2 = ast.Name("x", ast.Store())
3045+
self.assertEqual(name2.id, "x")
3046+
self.assertIsInstance(name2.ctx, ast.Store)
3047+
3048+
name3 = ast.Name("x", ctx=ast.Del())
3049+
self.assertEqual(name3.id, "x")
3050+
self.assertIsInstance(name3.ctx, ast.Del)
3051+
3052+
with self.assertWarnsRegex(DeprecationWarning,
3053+
r"Name\.__init__ missing 1 required positional argument: 'id'"):
3054+
name3 = ast.Name()
3055+
30393056
def test_custom_subclass_with_no_fields(self):
30403057
class NoInit(ast.AST):
30413058
pass
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
``ctx`` arguments to the constructors of :mod:`ast` node classes now default
2+
to :class:`ast.Load() <ast.Load>`. Patch by Jelle Zijlstra.

Parser/asdl_c.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1022,6 +1022,13 @@ def visitModule(self, mod):
10221022
goto set_remaining_cleanup;
10231023
}
10241024
}
1025+
else if (type == state->expr_context_type) {
1026+
// special case for expr_context: default to Load()
1027+
res = PyObject_SetAttr(self, name, state->Load_singleton);
1028+
if (res < 0) {
1029+
goto set_remaining_cleanup;
1030+
}
1031+
}
10251032
else {
10261033
// simple field (e.g., identifier)
10271034
if (PyErr_WarnFormat(

Python/Python-ast.c

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)