diff options
| author | mike bayer <mike_mp@zzzcomputing.com> | 2019-11-04 19:50:17 +0000 |
|---|---|---|
| committer | Gerrit Code Review <gerrit@bbpush.zzzcomputing.com> | 2019-11-04 19:50:17 +0000 |
| commit | 98f7c0c080ebbc8236fc0cc98970cb1b0112c01e (patch) | |
| tree | f119c0003461e0bd7426bb493391a1c563817bb4 /lib/sqlalchemy/orm | |
| parent | bee7c3462d6235b7e108dbdbcd0727cdcbc49eb0 (diff) | |
| parent | 29330ec1596f12462c501a65404ff52005b16b6c (diff) | |
| download | sqlalchemy-98f7c0c080ebbc8236fc0cc98970cb1b0112c01e.tar.gz | |
Merge "Add anonymizing context to cache keys, comparison; convert traversal"
Diffstat (limited to 'lib/sqlalchemy/orm')
| -rw-r--r-- | lib/sqlalchemy/orm/attributes.py | 10 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/base.py | 1 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/interfaces.py | 13 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/mapper.py | 6 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/path_registry.py | 12 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/strategy_options.py | 38 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/util.py | 10 |
7 files changed, 78 insertions, 12 deletions
diff --git a/lib/sqlalchemy/orm/attributes.py b/lib/sqlalchemy/orm/attributes.py index 83069f113..aa2986205 100644 --- a/lib/sqlalchemy/orm/attributes.py +++ b/lib/sqlalchemy/orm/attributes.py @@ -47,6 +47,8 @@ from .base import state_str from .. import event from .. import inspection from .. import util +from ..sql import base as sql_base +from ..sql import visitors @inspection._self_inspects @@ -54,6 +56,7 @@ class QueryableAttribute( interfaces._MappedAttribute, interfaces.InspectionAttr, interfaces.PropComparator, + sql_base.HasCacheKey, ): """Base class for :term:`descriptor` objects that intercept attribute events on behalf of a :class:`.MapperProperty` @@ -102,6 +105,13 @@ class QueryableAttribute( if base[key].dispatch._active_history: self.dispatch._active_history = True + _cache_key_traversal = [ + # ("class_", visitors.ExtendedInternalTraversal.dp_plain_obj), + ("key", visitors.ExtendedInternalTraversal.dp_string), + ("_parententity", visitors.ExtendedInternalTraversal.dp_multi), + ("_of_type", visitors.ExtendedInternalTraversal.dp_multi), + ] + @util.memoized_property def _supports_population(self): return self.impl.supports_population diff --git a/lib/sqlalchemy/orm/base.py b/lib/sqlalchemy/orm/base.py index 6f8d19293..a3dea6b0e 100644 --- a/lib/sqlalchemy/orm/base.py +++ b/lib/sqlalchemy/orm/base.py @@ -216,7 +216,6 @@ def _assertions(*assertions): for assertion in assertions: assertion(self, fn.__name__) fn(self, *args[1:], **kw) - return self return generate diff --git a/lib/sqlalchemy/orm/interfaces.py b/lib/sqlalchemy/orm/interfaces.py index e94a81fed..704ce9df7 100644 --- a/lib/sqlalchemy/orm/interfaces.py +++ b/lib/sqlalchemy/orm/interfaces.py @@ -36,6 +36,8 @@ from .. import inspect from .. import inspection from .. import util from ..sql import operators +from ..sql import visitors +from ..sql.traversals import HasCacheKey __all__ = ( @@ -54,7 +56,9 @@ __all__ = ( ) -class MapperProperty(_MappedAttribute, InspectionAttr, util.MemoizedSlots): +class MapperProperty( + HasCacheKey, _MappedAttribute, InspectionAttr, util.MemoizedSlots +): """Represent a particular class attribute mapped by :class:`.Mapper`. The most common occurrences of :class:`.MapperProperty` are the @@ -74,6 +78,11 @@ class MapperProperty(_MappedAttribute, InspectionAttr, util.MemoizedSlots): "info", ) + _cache_key_traversal = [ + ("parent", visitors.ExtendedInternalTraversal.dp_has_cache_key), + ("key", visitors.ExtendedInternalTraversal.dp_string), + ] + cascade = frozenset() """The set of 'cascade' attribute names. @@ -647,7 +656,7 @@ class MapperOption(object): self.process_query(query) - def _generate_cache_key(self, path): + def _generate_path_cache_key(self, path): """Used by the "baked lazy loader" to see if this option can be cached. The "baked lazy loader" refers to the :class:`.Query` that is diff --git a/lib/sqlalchemy/orm/mapper.py b/lib/sqlalchemy/orm/mapper.py index 376ad1923..548eca58d 100644 --- a/lib/sqlalchemy/orm/mapper.py +++ b/lib/sqlalchemy/orm/mapper.py @@ -71,7 +71,7 @@ _CONFIGURE_MUTEX = util.threading.RLock() @inspection._self_inspects @log.class_logger -class Mapper(InspectionAttr): +class Mapper(sql_base.HasCacheKey, InspectionAttr): """Define the correlation of class attributes to database table columns. @@ -729,6 +729,10 @@ class Mapper(InspectionAttr): """ return self + _cache_key_traversal = [ + ("class_", visitors.ExtendedInternalTraversal.dp_plain_obj) + ] + @property def entity(self): r"""Part of the inspection API. diff --git a/lib/sqlalchemy/orm/path_registry.py b/lib/sqlalchemy/orm/path_registry.py index 2f680a3a1..585cb80bc 100644 --- a/lib/sqlalchemy/orm/path_registry.py +++ b/lib/sqlalchemy/orm/path_registry.py @@ -15,7 +15,8 @@ from .base import class_mapper from .. import exc from .. import inspection from .. import util - +from ..sql import visitors +from ..sql.traversals import HasCacheKey log = logging.getLogger(__name__) @@ -28,7 +29,7 @@ _WILDCARD_TOKEN = "*" _DEFAULT_TOKEN = "_sa_default" -class PathRegistry(object): +class PathRegistry(HasCacheKey): """Represent query load paths and registry functions. Basically represents structures like: @@ -57,6 +58,10 @@ class PathRegistry(object): is_token = False is_root = False + _cache_key_traversal = [ + ("path", visitors.ExtendedInternalTraversal.dp_has_cache_key_list) + ] + def __eq__(self, other): return other is not None and self.path == other.path @@ -78,6 +83,9 @@ class PathRegistry(object): def __len__(self): return len(self.path) + def __hash__(self): + return id(self) + @property def length(self): return len(self.path) diff --git a/lib/sqlalchemy/orm/strategy_options.py b/lib/sqlalchemy/orm/strategy_options.py index 26f47f616..99bbbe37c 100644 --- a/lib/sqlalchemy/orm/strategy_options.py +++ b/lib/sqlalchemy/orm/strategy_options.py @@ -26,11 +26,13 @@ from .. import inspect from .. import util from ..sql import coercions from ..sql import roles +from ..sql import visitors from ..sql.base import _generative from ..sql.base import Generative +from ..sql.traversals import HasCacheKey -class Load(Generative, MapperOption): +class Load(HasCacheKey, Generative, MapperOption): """Represents loader options which modify the state of a :class:`.Query` in order to affect how various mapped attributes are loaded. @@ -70,6 +72,17 @@ class Load(Generative, MapperOption): """ + _cache_key_traversal = [ + ("path", visitors.ExtendedInternalTraversal.dp_has_cache_key), + ("strategy", visitors.ExtendedInternalTraversal.dp_plain_obj), + ("_of_type", visitors.ExtendedInternalTraversal.dp_multi), + ( + "_context_cache_key", + visitors.ExtendedInternalTraversal.dp_has_cache_key_tuples, + ), + ("local_opts", visitors.ExtendedInternalTraversal.dp_plain_dict), + ] + def __init__(self, entity): insp = inspect(entity) self.path = insp._path_registry @@ -89,7 +102,16 @@ class Load(Generative, MapperOption): load._of_type = None return load - def _generate_cache_key(self, path): + @property + def _context_cache_key(self): + serialized = [] + for (key, loader_path), obj in self.context.items(): + if key != "loader": + continue + serialized.append(loader_path + (obj,)) + return serialized + + def _generate_path_cache_key(self, path): if path.path[0].is_aliased_class: return False @@ -522,9 +544,16 @@ class _UnboundLoad(Load): self._to_bind = [] self.local_opts = {} + _cache_key_traversal = [ + ("path", visitors.ExtendedInternalTraversal.dp_multi_list), + ("strategy", visitors.ExtendedInternalTraversal.dp_plain_obj), + ("_to_bind", visitors.ExtendedInternalTraversal.dp_has_cache_key_list), + ("local_opts", visitors.ExtendedInternalTraversal.dp_plain_dict), + ] + _is_chain_link = False - def _generate_cache_key(self, path): + def _generate_path_cache_key(self, path): serialized = () for val in self._to_bind: for local_elem, val_elem in zip(self.path, val.path): @@ -533,7 +562,7 @@ class _UnboundLoad(Load): else: opt = val._bind_loader([path.path[0]], None, None, False) if opt: - c_key = opt._generate_cache_key(path) + c_key = opt._generate_path_cache_key(path) if c_key is False: return False elif c_key: @@ -660,7 +689,6 @@ class _UnboundLoad(Load): opt = meth(opt, all_tokens[-1], **kw) opt._is_chain_link = False - return opt def _chop_path(self, to_chop, path): diff --git a/lib/sqlalchemy/orm/util.py b/lib/sqlalchemy/orm/util.py index 5f0f41e8d..c86993678 100644 --- a/lib/sqlalchemy/orm/util.py +++ b/lib/sqlalchemy/orm/util.py @@ -30,10 +30,12 @@ from .. import exc as sa_exc from .. import inspection from .. import sql from .. import util +from ..sql import base as sql_base from ..sql import coercions from ..sql import expression from ..sql import roles from ..sql import util as sql_util +from ..sql import visitors all_cascades = frozenset( @@ -530,7 +532,7 @@ class AliasedClass(object): return str(self._aliased_insp) -class AliasedInsp(InspectionAttr): +class AliasedInsp(sql_base.HasCacheKey, InspectionAttr): """Provide an inspection interface for an :class:`.AliasedClass` object. @@ -627,6 +629,12 @@ class AliasedInsp(InspectionAttr): def __clause_element__(self): return self.selectable + _cache_key_traversal = [ + ("name", visitors.ExtendedInternalTraversal.dp_string), + ("_adapt_on_names", visitors.ExtendedInternalTraversal.dp_boolean), + ("selectable", visitors.ExtendedInternalTraversal.dp_clauseelement), + ] + @property def class_(self): """Return the mapped class ultimately represented by this |
