@@ -758,6 +758,8 @@ inline_comprehension(PySTEntryObject *ste, PySTEntryObject *comp,
758
758
{
759
759
PyObject * k , * v ;
760
760
Py_ssize_t pos = 0 ;
761
+ int remove_dunder_class = 0 ;
762
+
761
763
while (PyDict_Next (comp -> ste_symbols , & pos , & k , & v )) {
762
764
// skip comprehension parameter
763
765
long comp_flags = PyLong_AS_LONG (v );
@@ -779,6 +781,19 @@ inline_comprehension(PySTEntryObject *ste, PySTEntryObject *comp,
779
781
if (!existing ) {
780
782
// name does not exist in scope, copy from comprehension
781
783
assert (scope != FREE || PySet_Contains (comp_free , k ) == 1 );
784
+ if (scope == FREE && ste -> ste_type == ClassBlock &&
785
+ _PyUnicode_EqualToASCIIString (k , "__class__" )) {
786
+ // if __class__ is unbound in the enclosing class scope and free
787
+ // in the comprehension scope, it needs special handling; just
788
+ // letting it be marked as free in class scope will break due to
789
+ // drop_class_free
790
+ scope = GLOBAL_IMPLICIT ;
791
+ only_flags &= ~DEF_FREE ;
792
+ if (PySet_Discard (comp_free , k ) < 0 ) {
793
+ return 0 ;
794
+ }
795
+ remove_dunder_class = 1 ;
796
+ }
782
797
PyObject * v_flags = PyLong_FromLong (only_flags );
783
798
if (v_flags == NULL ) {
784
799
return 0 ;
@@ -803,6 +818,10 @@ inline_comprehension(PySTEntryObject *ste, PySTEntryObject *comp,
803
818
}
804
819
}
805
820
}
821
+ comp -> ste_free = PySet_Size (comp_free ) > 0 ;
822
+ if (remove_dunder_class && PyDict_DelItem (comp -> ste_symbols , k ) < 0 ) {
823
+ return 0 ;
824
+ }
806
825
return 1 ;
807
826
}
808
827
0 commit comments