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. -- vitja. _______________________________________________ cython-devel mailing list cython-devel@python.org http://mail.python.org/mailman/listinfo/cython-devel