- added more careful check for "_should_exclude", guard against possible heisenbug activity
self._instantiable = False
self.events = self.event_registry_factory()
- # TODO: generalize (and document the rationalization for) this traversal.
- # TODO: figure out why getattr(cls, key) for all attributes
- # causes test failures
- for cls in class_.__mro__[0:-1]:
- for key, meth in cls.__dict__.iteritems():
- if isinstance(meth, types.FunctionType) and \
- hasattr(meth, '__sa_reconstitute__') and \
- hasattr(getattr(class_, key), '__sa_reconstitute__'):
- self.events.add_listener('on_load', getattr(class_, key))
- break
+ for key, meth in util.iterate_attributes(class_):
+ if isinstance(meth, types.FunctionType) and hasattr(meth, '__sa_reconstitute__'):
+ self.events.add_listener('on_load', meth)
def instantiable(self, boolean):
# experiment, probably won't stay in this form
"""
+ def is_userland_descriptor(obj):
+ return not isinstance(obj, attributes.InstrumentedAttribute) and hasattr(obj, '__get__')
+
# check for descriptors, either local or from
# an inherited class
if local:
if self.class_.__dict__.get(name, None)\
- and hasattr(self.class_.__dict__[name], '__get__'):
+ and is_userland_descriptor(self.class_.__dict__[name]):
return True
else:
if getattr(self.class_, name, None)\
- and hasattr(getattr(self.class_, name), '__get__'):
+ and is_userland_descriptor(getattr(self.class_, name)):
return True
if (self.include_properties is not None and
hier.add(s)
return list(hier)
+def iterate_attributes(cls):
+ """iterate all the keys and attributes associated with a class, without using getattr().
+
+ Does not use getattr() so that class-sensitive descriptors (i.e. property.__get__())
+ are not called.
+
+ """
+ keys = dir(cls)
+ for key in keys:
+ for c in cls.__mro__:
+ if key in c.__dict__:
+ yield (key, c.__dict__[key])
+ break
+
# from paste.deploy.converters
def asbool(obj):
if isinstance(obj, (str, unicode)):
assert_table(Point.left_of(p2), table)
assert_table(alias.left_of(p2), alias_table)
-
+
if __name__ == '__main__':
testenv.main()