From af44efe26e3f703ca1c30e79ee68428eed35abcf Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Sat, 2 Feb 2013 20:06:31 -0500 Subject: [PATCH] Fixed a bug regarding column annotations which in particular could impact some usages of the new :func:`.orm.remote` and :func:`.orm.local` annotation functions, where annotations could be lost when the column were used in a subsequent expression. [ticket:2660] --- doc/build/changelog/changelog_08.rst | 10 +++++++++ lib/sqlalchemy/sql/util.py | 2 +- test/sql/test_selectable.py | 31 ++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/doc/build/changelog/changelog_08.rst b/doc/build/changelog/changelog_08.rst index e35de3b2d5..52414be6d6 100644 --- a/doc/build/changelog/changelog_08.rst +++ b/doc/build/changelog/changelog_08.rst @@ -6,6 +6,16 @@ .. changelog:: :version: 0.8.0 + .. change:: + :tags: bug, sql + :tickets: 2660, 1768 + + Fixed a bug regarding column annotations which in particular + could impact some usages of the new :func:`.orm.remote` and + :func:`.orm.local` annotation functions, where annotations + could be lost when the column were used in a subsequent + expression. + .. change:: :tags: bug, mysql, gae :tickets: 2649 diff --git a/lib/sqlalchemy/sql/util.py b/lib/sqlalchemy/sql/util.py index aab1ae5ba3..fd138cfec6 100644 --- a/lib/sqlalchemy/sql/util.py +++ b/lib/sqlalchemy/sql/util.py @@ -449,7 +449,7 @@ class Annotated(object): def _with_annotations(self, values): clone = self.__class__.__new__(self.__class__) clone.__dict__ = self.__dict__.copy() - expression.ColumnElement.comparator._reset(self) + expression.ColumnElement.comparator._reset(clone) clone._annotations = values return clone diff --git a/test/sql/test_selectable.py b/test/sql/test_selectable.py index 7857681f36..30052a8068 100644 --- a/test/sql/test_selectable.py +++ b/test/sql/test_selectable.py @@ -1556,3 +1556,34 @@ class AnnotationsTest(fixtures.TestBase): # also pass, [ticket:2425] eq_(str(or_(b, b._annotate({"foo": "bar"}))), ":bind_1 OR :bind_1") + + def test_comparators_cleaned_out_construction(self): + c = column('a') + + comp1 = c.comparator + + c1 = c._annotate({"foo": "bar"}) + comp2 = c1.comparator + assert comp1 is not comp2 + + def test_comparators_cleaned_out_reannotate(self): + c = column('a') + + c1 = c._annotate({"foo": "bar"}) + comp1 = c1.comparator + + c2 = c1._annotate({"bat": "hoho"}) + comp2 = c2.comparator + + assert comp1 is not comp2 + + def test_comparator_cleanout_integration(self): + c = column('a') + + c1 = c._annotate({"foo": "bar"}) + comp1 = c1.comparator + + c2 = c1._annotate({"bat": "hoho"}) + comp2 = c2.comparator + + assert (c2 == 5).left._annotations == {"foo": "bar", "bat": "hoho"} -- 2.47.2