cython-devel-tests-pyregr regression
I've found regression: https://sage.math.washington.edu:8091/hudson/job/cython-devel-tests-pyregr/ -- vitja.
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. Stefan
2012/8/23 Stefan Behnel <stefan_ml@behnel.de>:
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.
Stefan
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? -- vitja.
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. 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? Actually, I even wonder if it is a good idea to look up the name directly in the class scope - we may want to inject a local comprehension scope here, as for Py3 comprehensions and genexprs, and just switch the fall-through of the declarations on or off based on the code semantics. Stefan
2012/8/23 Stefan Behnel <stefan_ml@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"
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?
Actually, I even wonder if it is a good idea to look up the name directly in the class scope - we may want to inject a local comprehension scope here, as for Py3 comprehensions and genexprs, and just switch the fall-through of the declarations on or off based on the code semantics.
-- vitja.
Vitja Makarov, 23.08.2012 07:03:
2012/8/23 Stefan Behnel <stefan_ml@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
2012/8/23 Stefan Behnel <stefan_ml@behnel.de>:
Vitja Makarov, 23.08.2012 07:03:
2012/8/23 Stefan Behnel <stefan_ml@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.
2012/8/23 Vitja Makarov <vitja.makarov@gmail.com>:
2012/8/23 Stefan Behnel <stefan_ml@behnel.de>:
Vitja Makarov, 23.08.2012 07:03:
2012/8/23 Stefan Behnel <stefan_ml@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/198f254f62360b61c895ba68be0f4dbe07444... Cause of different class scope lookup rules I think we can't fully trust CF here. -- vitja.
2012/8/23 Vitja Makarov <vitja.makarov@gmail.com>:
2012/8/23 Vitja Makarov <vitja.makarov@gmail.com>:
2012/8/23 Stefan Behnel <stefan_ml@behnel.de>:
Vitja Makarov, 23.08.2012 07:03:
2012/8/23 Stefan Behnel <stefan_ml@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/198f254f62360b61c895ba68be0f4dbe07444...
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. -- vitja.
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/198f254f62360b61c895ba68be0f4dbe07444...
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
2012/8/23 Stefan Behnel <stefan_ml@behnel.de>:
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/198f254f62360b61c895ba68be0f4dbe07444...
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).
Ok, I'll take a look later. -- vitja.
2012/8/23 Vitja Makarov <vitja.makarov@gmail.com>:
2012/8/23 Stefan Behnel <stefan_ml@behnel.de>:
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/198f254f62360b61c895ba68be0f4dbe07444...
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).
Ok, I'll take a look later.
Here is fix from CF point of view: https://github.com/vitek/cython/commit/cbd676c598a7ea0ba61262d46c1c733d362c6... Let's wait for jenkins now. -- vitja.
2012/8/24 Vitja Makarov <vitja.makarov@gmail.com>:
2012/8/23 Vitja Makarov <vitja.makarov@gmail.com>:
2012/8/23 Stefan Behnel <stefan_ml@behnel.de>:
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/198f254f62360b61c895ba68be0f4dbe07444...
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).
Ok, I'll take a look later.
Here is fix from CF point of view: https://github.com/vitek/cython/commit/cbd676c598a7ea0ba61262d46c1c733d362c6...
Let's wait for jenkins now.
Jenkins still is not happy about upstream/master. It shows 49.2K instead of previous 50.5K -- vitja.
Vitja Makarov, 24.08.2012 06:31:
Jenkins still is not happy about upstream/master.
It shows 49.2K instead of previous 50.5K
Part of the difference should be that I disabled the ctypes test. It crashes in the pyregr test runs that pyximport the stdlib modules. I don't see anything obvious that I would consider a degradation during the last few runs. Stefan
participants (2)
-
Stefan Behnel -
Vitja Makarov