[Cython] cython-devel-tests-pyregr regression

Stefan Behnel stefan_ml at behnel.de
Thu Aug 23 13:03:37 CEST 2012


Vitja Makarov, 23.08.2012 07:42:
> 2012/8/23 Vitja Makarov:
>> 2012/8/23 Vitja Makarov:
>>> 2012/8/23 Stefan Behnel:
>>>> Vitja Makarov, 23.08.2012 07:03:
>>>>> 2012/8/23 Stefan Behnel:
>>>>>> Vitja Makarov, 22.08.2012 22:34:
>>>>>>> 2012/8/23 Stefan Behnel:
>>>>>>>> Vitja Makarov, 22.08.2012 22:11:
>>>>>>>>> I've found regression:
>>>>>>>>>
>>>>>>>>> https://sage.math.washington.edu:8091/hudson/job/cython-devel-tests-pyregr/
>>>>>>>>
>>>>>>>> Interesting. It's a Py2 list comprehension in a class body that's failing here:
>>>>>>>>
>>>>>>>> """
>>>>>>>>  class TestHelpSubparsersOrdering(HelpTestCase):
>>>>>>>>      subparsers_signatures = [Sig(name=name)
>>>>>>>>                               for name in ('a', 'b', 'c', 'd', 'e')]
>>>>>>>>  """
>>>>>>>>
>>>>>>>> I wonder why "name" isn't declared as a variable yet at the point where it
>>>>>>>> is being looked up in the function call.
>>>>>>>
>>>>>>>     def lookup_relative(self, name, pos):
>>>>>>>         if name == "name":
>>>>>>>             print name
>>>>>>>             from ipdb import set_trace; set_trace()
>>>>>>>         entry = self.lookup_here(name)
>>>>>>>         if entry is not None and entry.pos[1:] <= pos[1:]: # Lookup fails here
>>>>>>>             return entry
>>>>>>>         if self.outer_scope:
>>>>>>>             return self.outer_scope.lookup_relative(name, pos)
>>>>>>>         return None
>>>>>>>
>>>>>>> What is that comparison for?
>>>>>>
>>>>>> Ah, yes, it is wrong in this context. It was meant to prevent names defined
>>>>>> further down in the class body from being considered assignments to the
>>>>>> name being looked up. Class bodies are not function bodies, assignments in
>>>>>> them do not make a name "local". As long as it's not assigned, it's not
>>>>>> defined and must be looked up in the outer scope.
>>>>>
>>>>> Do you remember this ticket #671
>>>>>
>>>>> If there is assignment in the class body we first lookup in the class
>>>>> dict and then in globals.
>>>>>
>>>>> B = 0
>>>>> def foo():
>>>>>     B = 1
>>>>>     class Foo():
>>>>>         A = B
>>>>>         B = B
>>>>>     class Bar():
>>>>>         A = B
>>>>>     print Foo.A, Foo.B, Bar.A
>>>>> foo()
>>>>>
>>>>> prints "0 0 1"
>>>>
>>>> In the case at hand, it's not an assignment but a method declaration. Maybe
>>>> that makes a difference.
>>>>
>>>> In any case, this needs some more investigation than I did for my change. I
>>>> think it can be rolled back completely.
>>
>> I've reverted your commit and here is my fix:
>> https://github.com/vitek/cython/commit/198f254f62360b61c895ba68be0f4dbe07444449
>>
>> Cause of different class scope lookup rules I think we can't fully
>> trust CF here.
> 
> Another (maybe better) solution is to fix CF. It mustn't set
> cf_maybe_null to False at class scope based on reference success.

I've pushed these changes to the master for now. They are correct, even if
we decide to improve the control flow decisions here (which would only lead
to the same effect anyway).

Stefan



More information about the cython-devel mailing list