diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2021-04-07 10:26:31 -0400 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2021-04-07 10:26:31 -0400 |
| commit | 475a1ada5d3ac88f12080ef8672a8fda70c7e76e (patch) | |
| tree | 9279db69a507c329530f0ba227a88a9c0308ff9c /test/ext | |
| parent | d1847bbe268d48d34f4781b317ac8e6bf13d44bd (diff) | |
| download | sqlalchemy-475a1ada5d3ac88f12080ef8672a8fda70c7e76e.tar.gz | |
Check for hybrid's attribute name and support no name
Fixed regression where the ORM compilation scheme would assume the function
name of a hybrid property would be the same as the attribute name in such a
way that an ``AttributeError`` would be raised, when it would attempt to
determine the correct name for each element in a result tuple. A similar
issue exists in 1.3 but only impacts the names of tuple rows. The fix here
adds a check that the hybrid's function name is actually present in the
``__dict__`` of the class or its superclasses before assigning this name;
otherwise, the hybrid is considered to be "unnamed" and ORM result tuples
will use the naming scheme of the underlying expression.
Fixes: #6215
Change-Id: I584c0c05efec957f4dcaccf5df371399a57dffe9
Diffstat (limited to 'test/ext')
| -rw-r--r-- | test/ext/test_hybrid.py | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/test/ext/test_hybrid.py b/test/ext/test_hybrid.py index 3bab7db93..8be802347 100644 --- a/test/ext/test_hybrid.py +++ b/test/ext/test_hybrid.py @@ -5,6 +5,7 @@ from sqlalchemy import func from sqlalchemy import inspect from sqlalchemy import Integer from sqlalchemy import Numeric +from sqlalchemy import select from sqlalchemy import String from sqlalchemy.ext import hybrid from sqlalchemy.ext.declarative import declarative_base @@ -97,6 +98,64 @@ class PropertyComparatorTest(fixtures.TestBase, AssertsCompiledSQL): A = self._fixture() eq_(A.value.__doc__, "This is a docstring") + def test_no_name_one(self): + """test :ticket:`6215`""" + + Base = declarative_base() + + class A(Base): + __tablename__ = "a" + id = Column(Integer, primary_key=True) + name = Column(String(50)) + + @hybrid.hybrid_property + def same_name(self): + return self.id + + def name1(self): + return self.id + + different_name = hybrid.hybrid_property(name1) + + no_name = hybrid.hybrid_property(lambda self: self.name) + + stmt = select(A.same_name, A.different_name, A.no_name) + compiled = stmt.compile() + + eq_( + [ent._label_name for ent in compiled.compile_state._entities], + ["same_name", "id", "name"], + ) + + def test_no_name_two(self): + """test :ticket:`6215`""" + Base = declarative_base() + + class SomeMixin(object): + @hybrid.hybrid_property + def same_name(self): + return self.id + + def name1(self): + return self.id + + different_name = hybrid.hybrid_property(name1) + + no_name = hybrid.hybrid_property(lambda self: self.name) + + class A(SomeMixin, Base): + __tablename__ = "a" + id = Column(Integer, primary_key=True) + name = Column(String(50)) + + stmt = select(A.same_name, A.different_name, A.no_name) + compiled = stmt.compile() + + eq_( + [ent._label_name for ent in compiled.compile_state._entities], + ["same_name", "id", "name"], + ) + class PropertyExpressionTest(fixtures.TestBase, AssertsCompiledSQL): __dialect__ = "default" |
