Skip to content

Commit 498376d

Browse files
authored
gh-122445: populate only modified fields in __static_attributes__ (#122446)
1 parent 9fc1c99 commit 498376d

File tree

5 files changed

+18
-10
lines changed

5 files changed

+18
-10
lines changed

Doc/reference/datamodel.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -999,7 +999,7 @@ Special attributes:
999999
a :ref:`generic class <generic-classes>`.
10001000

10011001
:attr:`~class.__static_attributes__`
1002-
A tuple containing names of attributes of this class which are accessed
1002+
A tuple containing names of attributes of this class which are assigned
10031003
through ``self.X`` from any function in its body.
10041004

10051005
:attr:`__firstlineno__`

Doc/whatsnew/3.13.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ Improved Error Messages
247247
TypeError: split() got an unexpected keyword argument 'max_split'. Did you mean 'maxsplit'?
248248

249249
* Classes have a new :attr:`~class.__static_attributes__` attribute, populated by the compiler,
250-
with a tuple of names of attributes of this class which are accessed
250+
with a tuple of names of attributes of this class which are assigned
251251
through ``self.X`` from any function in its body. (Contributed by Irit Katriel
252252
in :gh:`115775`.)
253253

Lib/test/test_compile.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2089,12 +2089,15 @@ def f():
20892089
self.assertEqual(end_col, 20)
20902090

20912091

2092-
class TestExpectedAttributes(unittest.TestCase):
2092+
class TestStaticAttributes(unittest.TestCase):
20932093

20942094
def test_basic(self):
20952095
class C:
20962096
def f(self):
20972097
self.a = self.b = 42
2098+
# read fields are not included
2099+
self.f()
2100+
self.arr[3]
20982101

20992102
self.assertIsInstance(C.__static_attributes__, tuple)
21002103
self.assertEqual(sorted(C.__static_attributes__), ['a', 'b'])
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add only fields which are modified via self.* to :attr:`~class.__static_attributes__`.

Python/compile.c

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -563,8 +563,16 @@ compiler_unit_free(struct compiler_unit *u)
563563
}
564564

565565
static int
566-
compiler_add_static_attribute_to_class(struct compiler *c, PyObject *attr)
566+
compiler_maybe_add_static_attribute_to_class(struct compiler *c, expr_ty e)
567567
{
568+
assert(e->kind == Attribute_kind);
569+
expr_ty attr_value = e->v.Attribute.value;
570+
if (attr_value->kind != Name_kind ||
571+
e->v.Attribute.ctx != Store ||
572+
!_PyUnicode_EqualToASCIIString(attr_value->v.Name.id, "self"))
573+
{
574+
return SUCCESS;
575+
}
568576
Py_ssize_t stack_size = PyList_GET_SIZE(c->c_stack);
569577
for (Py_ssize_t i = stack_size - 1; i >= 0; i--) {
570578
PyObject *capsule = PyList_GET_ITEM(c->c_stack, i);
@@ -573,7 +581,7 @@ compiler_add_static_attribute_to_class(struct compiler *c, PyObject *attr)
573581
assert(u);
574582
if (u->u_scope_type == COMPILER_SCOPE_CLASS) {
575583
assert(u->u_static_attributes);
576-
RETURN_IF_ERROR(PySet_Add(u->u_static_attributes, attr));
584+
RETURN_IF_ERROR(PySet_Add(u->u_static_attributes, e->v.Attribute.attr));
577585
break;
578586
}
579587
}
@@ -6065,11 +6073,7 @@ compiler_visit_expr(struct compiler *c, expr_ty e)
60656073
ADDOP(c, loc, NOP);
60666074
return SUCCESS;
60676075
}
6068-
if (e->v.Attribute.value->kind == Name_kind &&
6069-
_PyUnicode_EqualToASCIIString(e->v.Attribute.value->v.Name.id, "self"))
6070-
{
6071-
RETURN_IF_ERROR(compiler_add_static_attribute_to_class(c, e->v.Attribute.attr));
6072-
}
6076+
RETURN_IF_ERROR(compiler_maybe_add_static_attribute_to_class(c, e));
60736077
VISIT(c, expr, e->v.Attribute.value);
60746078
loc = LOC(e);
60756079
loc = update_start_location_to_match_attr(c, loc, e);

0 commit comments

Comments
 (0)