diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2019-07-16 13:02:16 -0400 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2019-07-17 10:42:05 -0400 |
commit | 234723fa296c9fa7ac63f1c4d877edc7ba120edd (patch) | |
tree | 103309417ca72507e5e951a81e7cc083a75395b6 /lib/sqlalchemy/orm/attributes.py | |
parent | 1a9f5754e088ff521bf41bddc42b32ec989a8877 (diff) | |
download | sqlalchemy-234723fa296c9fa7ac63f1c4d877edc7ba120edd.tar.gz |
Intercept unresolveable comparator attrbute error for attr access
Fixed bug where a synonym created against a mapped attribute that does not
exist yet, as is the case when it refers to backref before mappers are
configured, would raise recursion errors when trying to test for attributes
on it which ultimately don't exist (as occurs when the classes are run
through Sphinx autodoc), as the unconfigured state of the synonym would put
it into an attribute not found loop.
Fixes: #4767
Change-Id: I9aade8628349fbf538181a0049416cec0a17179c
Diffstat (limited to 'lib/sqlalchemy/orm/attributes.py')
-rw-r--r-- | lib/sqlalchemy/orm/attributes.py | 31 |
1 files changed, 21 insertions, 10 deletions
diff --git a/lib/sqlalchemy/orm/attributes.py b/lib/sqlalchemy/orm/attributes.py index e277f6f5b..d47740e3d 100644 --- a/lib/sqlalchemy/orm/attributes.py +++ b/lib/sqlalchemy/orm/attributes.py @@ -361,23 +361,34 @@ def create_proxied_attribute(descriptor): def __getattr__(self, attribute): """Delegate __getattr__ to the original descriptor and/or comparator.""" - try: return getattr(descriptor, attribute) except AttributeError: + if attribute == "comparator": + raise AttributeError("comparator") try: - return getattr(self.comparator, attribute) + # comparator itself might be unreachable + comparator = self.comparator except AttributeError: raise AttributeError( - "Neither %r object nor %r object associated with %s " - "has an attribute %r" - % ( - type(descriptor).__name__, - type(self.comparator).__name__, - self, - attribute, - ) + "Neither %r object nor unconfigured comparator " + "object associated with %s has an attribute %r" + % (type(descriptor).__name__, self, attribute) ) + else: + try: + return getattr(comparator, attribute) + except AttributeError: + raise AttributeError( + "Neither %r object nor %r object " + "associated with %s has an attribute %r" + % ( + type(descriptor).__name__, + type(comparator).__name__, + self, + attribute, + ) + ) Proxy.__name__ = type(descriptor).__name__ + "Proxy" |