diff options
Diffstat (limited to 'lib/sqlalchemy')
| -rw-r--r-- | lib/sqlalchemy/orm/attributes.py | 13 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/mapper.py | 7 | ||||
| -rw-r--r-- | lib/sqlalchemy/util.py | 14 |
3 files changed, 22 insertions, 12 deletions
diff --git a/lib/sqlalchemy/orm/attributes.py b/lib/sqlalchemy/orm/attributes.py index dd470f358..5076775bc 100644 --- a/lib/sqlalchemy/orm/attributes.py +++ b/lib/sqlalchemy/orm/attributes.py @@ -1056,16 +1056,9 @@ class ClassManager(dict): 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 diff --git a/lib/sqlalchemy/orm/mapper.py b/lib/sqlalchemy/orm/mapper.py index 06f4f3dad..52acdcb33 100644 --- a/lib/sqlalchemy/orm/mapper.py +++ b/lib/sqlalchemy/orm/mapper.py @@ -644,15 +644,18 @@ class Mapper(object): """ + 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 diff --git a/lib/sqlalchemy/util.py b/lib/sqlalchemy/util.py index a9e7d2238..76c73ca6a 100644 --- a/lib/sqlalchemy/util.py +++ b/lib/sqlalchemy/util.py @@ -410,6 +410,20 @@ def class_hierarchy(cls): 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)): |
