]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.13] gh-122445: populate only modified fields in __static_attributes__ (#122446...
authorIrit Katriel <1055913+iritkatriel@users.noreply.github.com>
Fri, 2 Aug 2024 18:26:57 +0000 (19:26 +0100)
committerGitHub <noreply@github.com>
Fri, 2 Aug 2024 18:26:57 +0000 (19:26 +0100)
gh-122445: populate only modified fields in __static_attributes__ (#122446)

(cherry picked from commit 498376d7a7d6f704f22a2c963130cc15c17e7a6f)

Doc/reference/datamodel.rst
Doc/whatsnew/3.13.rst
Lib/test/test_compile.py
Misc/NEWS.d/next/Core and Builtins/2024-07-30-11-41-35.gh-issue-122445.Rq0bjS.rst [new file with mode: 0644]
Python/compile.c

index fa5bd93ebf218596b1c243f094d6cd892d61f8fd..440f912190a57b5820215cc039970e157cd735f9 100644 (file)
@@ -996,7 +996,7 @@ Special attributes:
       a :ref:`generic class <generic-classes>`.
 
    :attr:`~class.__static_attributes__`
-      A tuple containing names of attributes of this class which are accessed
+      A tuple containing names of attributes of this class which are assigned
       through ``self.X`` from any function in its body.
 
    :attr:`__firstlineno__`
index b53f419a59f0621b8c845cfd9129cd622ff4cbba..239447f762a4089d1e1d666cf2ee15642acc3e9f 100644 (file)
@@ -247,7 +247,7 @@ Improved Error Messages
     TypeError: split() got an unexpected keyword argument 'max_split'. Did you mean 'maxsplit'?
 
 * Classes have a new :attr:`~class.__static_attributes__` attribute, populated by the compiler,
-  with a tuple of names of attributes of this class which are accessed
+  with a tuple of names of attributes of this class which are assigned
   through ``self.X`` from any function in its body. (Contributed by Irit Katriel
   in :gh:`115775`.)
 
index e29c95e8bf263a312919ead9159bd1a182d648c8..7960089c4cdf947a9cd0b0987748e685804f0696 100644 (file)
@@ -2056,12 +2056,15 @@ class TestSourcePositions(unittest.TestCase):
                         self.assertLessEqual(end_col, code_end)
 
 
-class TestExpectedAttributes(unittest.TestCase):
+class TestStaticAttributes(unittest.TestCase):
 
     def test_basic(self):
         class C:
             def f(self):
                 self.a = self.b = 42
+                # read fields are not included
+                self.f()
+                self.arr[3]
 
         self.assertIsInstance(C.__static_attributes__, tuple)
         self.assertEqual(sorted(C.__static_attributes__), ['a', 'b'])
diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-07-30-11-41-35.gh-issue-122445.Rq0bjS.rst b/Misc/NEWS.d/next/Core and Builtins/2024-07-30-11-41-35.gh-issue-122445.Rq0bjS.rst
new file mode 100644 (file)
index 0000000..f5aa07c
--- /dev/null
@@ -0,0 +1 @@
+Add only fields which are modified via self.* to :attr:`~class.__static_attributes__`.
index 74566683a0400e60312975de6832dffe90ff3825..6c6260c7add6ac533a2b07dc0be80a807f979e4b 100644 (file)
@@ -589,9 +589,17 @@ compiler_unit_free(struct compiler_unit *u)
     PyMem_Free(u);
 }
 
-static struct compiler_unit *
-get_class_compiler_unit(struct compiler *c)
+static int
+compiler_maybe_add_static_attribute_to_class(struct compiler *c, expr_ty e)
 {
+    assert(e->kind == Attribute_kind);
+    expr_ty attr_value = e->v.Attribute.value;
+    if (attr_value->kind != Name_kind ||
+        e->v.Attribute.ctx != Store ||
+        !_PyUnicode_EqualToASCIIString(attr_value->v.Name.id, "self"))
+    {
+        return SUCCESS;
+    }
     Py_ssize_t stack_size = PyList_GET_SIZE(c->c_stack);
     for (Py_ssize_t i = stack_size - 1; i >= 0; i--) {
         PyObject *capsule = PyList_GET_ITEM(c->c_stack, i);
@@ -599,10 +607,12 @@ get_class_compiler_unit(struct compiler *c)
                                                               capsule, CAPSULE_NAME);
         assert(u);
         if (u->u_scope_type == COMPILER_SCOPE_CLASS) {
-            return u;
+            assert(u->u_static_attributes);
+            RETURN_IF_ERROR(PySet_Add(u->u_static_attributes, e->v.Attribute.attr));
+            break;
         }
     }
-    return NULL;
+    return SUCCESS;
 }
 
 static int
@@ -6283,17 +6293,7 @@ compiler_visit_expr1(struct compiler *c, expr_ty e)
             ADDOP(c, loc, NOP);
             return SUCCESS;
         }
-        if (e->v.Attribute.value->kind == Name_kind &&
-            _PyUnicode_EqualToASCIIString(e->v.Attribute.value->v.Name.id, "self"))
-        {
-            struct compiler_unit *class_u = get_class_compiler_unit(c);
-            if (class_u != NULL) {
-                assert(class_u->u_scope_type == COMPILER_SCOPE_CLASS);
-                assert(class_u->u_static_attributes);
-                RETURN_IF_ERROR(
-                    PySet_Add(class_u->u_static_attributes, e->v.Attribute.attr));
-            }
-        }
+        RETURN_IF_ERROR(compiler_maybe_add_static_attribute_to_class(c, e));
         VISIT(c, expr, e->v.Attribute.value);
         loc = LOC(e);
         loc = update_start_location_to_match_attr(c, loc, e);