From 3cb614009ee87a115ec7230949c031402efb17c1 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Sat, 22 Feb 2020 13:11:20 -0500 Subject: [PATCH] Ensure descendants of mixins don't become cacheable HasPrefix / HasSuffixes / SupportsCloneAnnotations exported a _traverse_internals attribute that does not represent a complete traversal, meaning non-traversible subclasses would seem traversible. rename these attributes so that this does not occur. DML is currently not traversible (will be soon). Change-Id: I2605e61c8c3d49965335e66e09f4aeedc5e73bd3 --- lib/sqlalchemy/sql/annotation.py | 2 +- lib/sqlalchemy/sql/selectable.py | 22 +++++++++++++--------- test/sql/test_compare.py | 6 +++++- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/lib/sqlalchemy/sql/annotation.py b/lib/sqlalchemy/sql/annotation.py index 0f668ebe7f..7984dc7ea3 100644 --- a/lib/sqlalchemy/sql/annotation.py +++ b/lib/sqlalchemy/sql/annotation.py @@ -37,7 +37,7 @@ class SupportsAnnotations(object): class SupportsCloneAnnotations(SupportsAnnotations): _annotations = util.immutabledict() - _traverse_internals = [ + _clone_annotations_traverse_internals = [ ("_annotations_cache_key", InternalTraversal.dp_plain_obj) ] diff --git a/lib/sqlalchemy/sql/selectable.py b/lib/sqlalchemy/sql/selectable.py index 5f22457fa1..b11e315ea5 100644 --- a/lib/sqlalchemy/sql/selectable.py +++ b/lib/sqlalchemy/sql/selectable.py @@ -208,7 +208,9 @@ class Selectable(ReturnsRows): class HasPrefixes(object): _prefixes = () - _traverse_internals = [("_prefixes", InternalTraversal.dp_prefix_sequence)] + _has_prefixes_traverse_internals = [ + ("_prefixes", InternalTraversal.dp_prefix_sequence) + ] @_generative @_document_text_coercion( @@ -261,7 +263,9 @@ class HasPrefixes(object): class HasSuffixes(object): _suffixes = () - _traverse_internals = [("_suffixes", InternalTraversal.dp_prefix_sequence)] + _has_suffixes_traverse_internals = [ + ("_suffixes", InternalTraversal.dp_prefix_sequence) + ] @_generative @_document_text_coercion( @@ -1480,8 +1484,8 @@ class CTE(Generative, HasPrefixes, HasSuffixes, AliasedReturnsRows): ("_restates", InternalTraversal.dp_clauseelement_unordered_set), ("recursive", InternalTraversal.dp_boolean), ] - + HasPrefixes._traverse_internals - + HasSuffixes._traverse_internals + + HasPrefixes._has_prefixes_traverse_internals + + HasSuffixes._has_suffixes_traverse_internals ) @classmethod @@ -2793,7 +2797,7 @@ class CompoundSelect(GenerativeSelect): ("_group_by_clause", InternalTraversal.dp_clauseelement), ("_for_update_arg", InternalTraversal.dp_clauseelement), ("keyword", InternalTraversal.dp_string), - ] + SupportsCloneAnnotations._traverse_internals + ] + SupportsCloneAnnotations._clone_annotations_traverse_internals UNION = util.symbol("UNION") UNION_ALL = util.symbol("UNION ALL") @@ -3173,9 +3177,9 @@ class Select( ("_distinct", InternalTraversal.dp_boolean), ("_distinct_on", InternalTraversal.dp_clauseelement_list), ] - + HasPrefixes._traverse_internals - + HasSuffixes._traverse_internals - + SupportsCloneAnnotations._traverse_internals + + HasPrefixes._has_prefixes_traverse_internals + + HasSuffixes._has_suffixes_traverse_internals + + SupportsCloneAnnotations._clone_annotations_traverse_internals ) @classmethod @@ -4500,7 +4504,7 @@ class TextualSelect(SelectBase): _traverse_internals = [ ("element", InternalTraversal.dp_clauseelement), ("column_args", InternalTraversal.dp_clauseelement_list), - ] + SupportsCloneAnnotations._traverse_internals + ] + SupportsCloneAnnotations._clone_annotations_traverse_internals _is_textual = True diff --git a/test/sql/test_compare.py b/test/sql/test_compare.py index 2d0e393314..7333fb3064 100644 --- a/test/sql/test_compare.py +++ b/test/sql/test_compare.py @@ -19,6 +19,7 @@ from sqlalchemy import select from sqlalchemy import String from sqlalchemy import Table from sqlalchemy import table +from sqlalchemy import testing from sqlalchemy import text from sqlalchemy import tuple_ from sqlalchemy import union @@ -62,7 +63,6 @@ from sqlalchemy.testing import ne_ from sqlalchemy.testing.util import random_choices from sqlalchemy.util import class_hierarchy - meta = MetaData() meta2 = MetaData() @@ -543,6 +543,10 @@ class CacheKeyFixture(object): class CacheKeyTest(CacheKeyFixture, CoreFixtures, fixtures.TestBase): + @testing.combinations(table_a.update(), table_a.insert(), table_a.delete()) + def test_dml_not_cached_yet(self, dml_stmt): + eq_(dml_stmt._generate_cache_key(), None) + def test_cache_key(self): for fixtures_, compare_values in [ (self.fixtures, True), -- 2.47.3