2012/8/23 Vitja Makarov <vitja.maka...@gmail.com>: > 2012/8/23 Stefan Behnel <stefan...@behnel.de>: >> Vitja Makarov, 23.08.2012 07:03: >>> 2012/8/23 Stefan Behnel <stefan...@behnel.de>: >>>> 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 think comprehensions are actually the only case where a name is used in >>>> the source before its declaration. It should work in all other cases. >>>> >>>> I had considered solving this problem with the flow control analysis >>>> information, but I can't see how that helps me to figure out if an entry is >>>> already assigned (i.e. declared) at a given point in the class body. >>>> >>>> Any idea? >>> >>> What would you do with maybe assigned case? >> >> Hmm, yes - I guess we can't solve the general case at compile time. That's >> unfortunate, though, because it prevents proper compile time optimisation >> of builtins in class bodies when their names are assigned at some point, >> e.g. with a ".type()" method or ".set()", as was the case here. >> >> Stefan >> > > > > This is NameNode related problem > > The following code would fail as well: > XXX = 123 > class Foo(object): > t1 = XXX # XXX cf_is_null = True > t2 = XXX # XXX cf_is_null = False > XXX = 123 > > CF assumes that after first apperence of NULL name it must be then set > otherwise exception must be raised. > NameNode code relays on CF here, so I think it mustn't. We must > allways check result of PyObject_GetItem() and if's NULL look at the > globals then. > > I'll try to fix it soon. > >
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. -- vitja. _______________________________________________ cython-devel mailing list cython-devel@python.org http://mail.python.org/mailman/listinfo/cython-devel