Skip to content

Commit 545a328

Browse files
authored
[3.13] gh-122445: populate only modified fields in __static_attributes__ (#122446) (#122621)
gh-122445: populate only modified fields in __static_attributes__ (#122446) (cherry picked from commit 498376d)
1 parent b20893b commit 545a328

File tree

5 files changed

+22
-18
lines changed

5 files changed

+22
-18
lines changed

Doc/reference/datamodel.rst

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

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

10021002
: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
@@ -2056,12 +2056,15 @@ def test_lambda_return_position(self):
20562056
self.assertLessEqual(end_col, code_end)
20572057

20582058

2059-
class TestExpectedAttributes(unittest.TestCase):
2059+
class TestStaticAttributes(unittest.TestCase):
20602060

20612061
def test_basic(self):
20622062
class C:
20632063
def f(self):
20642064
self.a = self.b = 42
2065+
# read fields are not included
2066+
self.f()
2067+
self.arr[3]
20652068

20662069
self.assertIsInstance(C.__static_attributes__, tuple)
20672070
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: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -589,20 +589,30 @@ compiler_unit_free(struct compiler_unit *u)
589589
PyMem_Free(u);
590590
}
591591

592-
static struct compiler_unit *
593-
get_class_compiler_unit(struct compiler *c)
592+
static int
593+
compiler_maybe_add_static_attribute_to_class(struct compiler *c, expr_ty e)
594594
{
595+
assert(e->kind == Attribute_kind);
596+
expr_ty attr_value = e->v.Attribute.value;
597+
if (attr_value->kind != Name_kind ||
598+
e->v.Attribute.ctx != Store ||
599+
!_PyUnicode_EqualToASCIIString(attr_value->v.Name.id, "self"))
600+
{
601+
return SUCCESS;
602+
}
595603
Py_ssize_t stack_size = PyList_GET_SIZE(c->c_stack);
596604
for (Py_ssize_t i = stack_size - 1; i >= 0; i--) {
597605
PyObject *capsule = PyList_GET_ITEM(c->c_stack, i);
598606
struct compiler_unit *u = (struct compiler_unit *)PyCapsule_GetPointer(
599607
capsule, CAPSULE_NAME);
600608
assert(u);
601609
if (u->u_scope_type == COMPILER_SCOPE_CLASS) {
602-
return u;
610+
assert(u->u_static_attributes);
611+
RETURN_IF_ERROR(PySet_Add(u->u_static_attributes, e->v.Attribute.attr));
612+
break;
603613
}
604614
}
605-
return NULL;
615+
return SUCCESS;
606616
}
607617

608618
static int
@@ -6283,17 +6293,7 @@ compiler_visit_expr1(struct compiler *c, expr_ty e)
62836293
ADDOP(c, loc, NOP);
62846294
return SUCCESS;
62856295
}
6286-
if (e->v.Attribute.value->kind == Name_kind &&
6287-
_PyUnicode_EqualToASCIIString(e->v.Attribute.value->v.Name.id, "self"))
6288-
{
6289-
struct compiler_unit *class_u = get_class_compiler_unit(c);
6290-
if (class_u != NULL) {
6291-
assert(class_u->u_scope_type == COMPILER_SCOPE_CLASS);
6292-
assert(class_u->u_static_attributes);
6293-
RETURN_IF_ERROR(
6294-
PySet_Add(class_u->u_static_attributes, e->v.Attribute.attr));
6295-
}
6296-
}
6296+
RETURN_IF_ERROR(compiler_maybe_add_static_attribute_to_class(c, e));
62976297
VISIT(c, expr, e->v.Attribute.value);
62986298
loc = LOC(e);
62996299
loc = update_start_location_to_match_attr(c, loc, e);

0 commit comments

Comments
 (0)