You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.
class C(object):
@property
def p(self):
log.info("p", stack_info=True)
C().p
Look at the log.
You get something like this:
File "<console>", line 4, in p
File "C:\Python27\lib\logging\__init__.py", line 1159, in info
self._log(INFO, msg, args, **kwargs)
File "logHandler.py", line 91, in _log
codepath=getCodePath(f)
File "logHandler.py", line 55, in getCodePath
attr=getattr(arg0,funcName)
File "<console>", line 4, in p
File "C:\Python27\lib\logging\__init__.py", line 1159, in info
self._log(INFO, msg, args, **kwargs)
File "logHandler.py", line 91, in _log
codepath=getCodePath(f)
File "logHandler.py", line 55, in getCodePath
attr=getattr(arg0,funcName)
File "<console>", line 4, in p
File "C:\Python27\lib\logging\__init__.py", line 1159, in info
self._log(INFO, msg, args, **kwargs)
File "logHandler.py", line 91, in _log
codepath=getCodePath(f)
File "logHandler.py", line 55, in getCodePath
attr=getattr(arg0,funcName)
...
And so the recursion continues. The reason is that logHandler.getCodePath retrieves the p attribute from the class, but in this case, the attribute is a property. Retrieving the property runs the logging code again... and thus begins the infinite recursion. I'm pretty sure we exceed maximum recursion depth, but getCodePath catches that exception.
As to why we aren't hitting this all the time, I think this only applies to properties which use decorators. In contrast, most of our properties use the _get_foo magic methods, and in that case, the function name from the code attribute will point at the _get_foo method, not the foo property itself. So, we've just been lucky enough not to log within a decorated property.
We should be able to solve this by trying to retrieve the attribute from the class first. If that attribute has a __get__ attribute, we know it's a descriptor (usually a property). If so, we shouldn't try to retrieve the attribute from the instance.
The text was updated successfully, but these errors were encountered:
… infinite recursion if that attribute is a property. Also choose the actual class the function was defined on, rather than the sub most class of the object.
Fixes#6122
… infinite recursion if that attribute is a property. Also choose the actual class the function was defined on, rather than the sub most class of the object. (#6151)
Fixes#6122
STR:
Open the NVDA Python console.
Type the following:
Look at the log.
You get something like this:
And so the recursion continues. The reason is that
logHandler.getCodePath
retrieves thep
attribute from the class, but in this case, the attribute is a property. Retrieving the property runs the logging code again... and thus begins the infinite recursion. I'm pretty sure we exceed maximum recursion depth, butgetCodePath
catches that exception.As to why we aren't hitting this all the time, I think this only applies to properties which use decorators. In contrast, most of our properties use the
_get_foo
magic methods, and in that case, the function name from the code attribute will point at the_get_foo
method, not thefoo
property itself. So, we've just been lucky enough not to log within a decorated property.We should be able to solve this by trying to retrieve the attribute from the class first. If that attribute has a
__get__
attribute, we know it's a descriptor (usually a property). If so, we shouldn't try to retrieve the attribute from the instance.The text was updated successfully, but these errors were encountered: