| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -168,6 +168,31 @@ def test_references___class__(self): | |||
| 168 | 168 | """ | |
| 169 | 169 | self._check_in_scopes(code, raises=NameError) | |
| 170 | 170 | ||
| 171 | + def test_references___class___defined(self): | ||
| 172 | + code = """ | ||
| 173 | + __class__ = 2 | ||
| 174 | + res = [__class__ for x in [1]] | ||
| 175 | + """ | ||
| 176 | + self._check_in_scopes( | ||
| 177 | + code, outputs={"res": [2]}, scopes=["module", "function"]) | ||
| 178 | + self._check_in_scopes(code, raises=NameError, scopes=["class"]) | ||
| 179 | + | ||
| 180 | + def test_references___class___enclosing(self): | ||
| 181 | + code = """ | ||
| 182 | + __class__ = 2 | ||
| 183 | + class C: | ||
| 184 | + res = [__class__ for x in [1]] | ||
| 185 | + res = C.res | ||
| 186 | + """ | ||
| 187 | + self._check_in_scopes(code, raises=NameError) | ||
| 188 | + | ||
| 189 | + def test_super_and_class_cell_in_sibling_comps(self): | ||
| 190 | + code = """ | ||
| 191 | + [super for _ in [1]] | ||
| 192 | + [__class__ for _ in [1]] | ||
| 193 | + """ | ||
| 194 | + self._check_in_scopes(code, raises=NameError) | ||
| 195 | + | ||
| 171 | 196 | def test_inner_cell_shadows_outer(self): | |
| 172 | 197 | code = """ | |
| 173 | 198 | items = [(lambda: i) for i in range(5)] | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1 @@ | |||
| 1 | + Fix a compiler crash in the case where two comprehensions in class scope both reference ``__class__``. | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -781,22 +781,19 @@ inline_comprehension(PySTEntryObject *ste, PySTEntryObject *comp, | |||
| 781 | 781 | if (existing == NULL && PyErr_Occurred()) { | |
| 782 | 782 | return 0; | |
| 783 | 783 | } | |
| 784 | + // __class__ is never allowed to be free through a class scope (see | ||
| 785 | + // drop_class_free) | ||
| 786 | + if (scope == FREE && ste->ste_type == ClassBlock && | ||
| 787 | + _PyUnicode_EqualToASCIIString(k, "__class__")) { | ||
| 788 | + scope = GLOBAL_IMPLICIT; | ||
| 789 | + if (PySet_Discard(comp_free, k) < 0) { | ||
| 790 | + return 0; | ||
| 791 | + } | ||
| 792 | + remove_dunder_class = 1; | ||
| 793 | + } | ||
| 784 | 794 | if (!existing) { | |
| 785 | 795 | // name does not exist in scope, copy from comprehension | |
| 786 | 796 | assert(scope != FREE || PySet_Contains(comp_free, k) == 1); | |
| 787 | - if (scope == FREE && ste->ste_type == ClassBlock && | ||
| 788 | - _PyUnicode_EqualToASCIIString(k, "__class__")) { | ||
| 789 | - // if __class__ is unbound in the enclosing class scope and free | ||
| 790 | - // in the comprehension scope, it needs special handling; just | ||
| 791 | - // letting it be marked as free in class scope will break due to | ||
| 792 | - // drop_class_free | ||
| 793 | - scope = GLOBAL_IMPLICIT; | ||
| 794 | - only_flags &= ~DEF_FREE; | ||
| 795 | - if (PySet_Discard(comp_free, k) < 0) { | ||
| 796 | - return 0; | ||
| 797 | - } | ||
| 798 | - remove_dunder_class = 1; | ||
| 799 | - } | ||
| 800 | 797 | PyObject *v_flags = PyLong_FromLong(only_flags); | |
| 801 | 798 | if (v_flags == NULL) { | |
| 802 | 799 | return 0; | |
| Back | FazBrowse Home | New Git URL |
0 commit comments