summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy
diff options
context:
space:
mode:
authormike bayer <mike_mp@zzzcomputing.com>2023-04-30 21:17:37 +0000
committerGerrit Code Review <gerrit@bbpush.zzzcomputing.com>2023-04-30 21:17:37 +0000
commitc04c8a169152f4065c8159e3c3ab676b2a0cc848 (patch)
tree7b333369b0b142a7ba51eae6c4c352fb926f69f4 /lib/sqlalchemy
parent83726b35def10253757fde2957a33b4ebecddcab (diff)
parent56443acb89e531b3695de669c76297e4a5568fc1 (diff)
downloadsqlalchemy-c04c8a169152f4065c8159e3c3ab676b2a0cc848.tar.gz
Merge "do not allow non-cache-key entity objects in annotations" into main
Diffstat (limited to 'lib/sqlalchemy')
-rw-r--r--lib/sqlalchemy/orm/attributes.py26
1 files changed, 20 insertions, 6 deletions
diff --git a/lib/sqlalchemy/orm/attributes.py b/lib/sqlalchemy/orm/attributes.py
index 69ddd3388..6a979219c 100644
--- a/lib/sqlalchemy/orm/attributes.py
+++ b/lib/sqlalchemy/orm/attributes.py
@@ -84,6 +84,9 @@ from ..sql import cache_key
from ..sql import coercions
from ..sql import roles
from ..sql import visitors
+from ..sql.cache_key import HasCacheKey
+from ..sql.visitors import _TraverseInternalsType
+from ..sql.visitors import InternalTraversal
from ..util.typing import Literal
from ..util.typing import Self
from ..util.typing import TypeGuard
@@ -326,13 +329,16 @@ class QueryableAttribute(
# non-string keys.
# ideally Proxy() would have a separate set of methods to deal
# with this case.
+ entity_namespace = self._entity_namespace
+ assert isinstance(entity_namespace, HasCacheKey)
+
if self.key is _UNKNOWN_ATTR_KEY: # type: ignore[comparison-overlap]
- annotations = {"entity_namespace": self._entity_namespace}
+ annotations = {"entity_namespace": entity_namespace}
else:
annotations = {
"proxy_key": self.key,
"proxy_owner": self._parententity,
- "entity_namespace": self._entity_namespace,
+ "entity_namespace": entity_namespace,
}
ce = self.comparator.__clause_element__()
@@ -558,13 +564,21 @@ class InstrumentedAttribute(QueryableAttribute[_T]):
@dataclasses.dataclass(frozen=True)
-class AdHocHasEntityNamespace:
+class AdHocHasEntityNamespace(HasCacheKey):
+ _traverse_internals: ClassVar[_TraverseInternalsType] = [
+ ("_entity_namespace", InternalTraversal.dp_has_cache_key),
+ ]
+
# py37 compat, no slots=True on dataclass
- __slots__ = ("entity_namespace",)
- entity_namespace: _ExternalEntityType[Any]
+ __slots__ = ("_entity_namespace",)
+ _entity_namespace: _InternalEntityType[Any]
is_mapper: ClassVar[bool] = False
is_aliased_class: ClassVar[bool] = False
+ @property
+ def entity_namespace(self):
+ return self._entity_namespace.entity_namespace
+
def create_proxied_attribute(
descriptor: Any,
@@ -638,7 +652,7 @@ def create_proxied_attribute(
else:
# used by hybrid attributes which try to remain
# agnostic of any ORM concepts like mappers
- return AdHocHasEntityNamespace(self.class_)
+ return AdHocHasEntityNamespace(self._parententity)
@property
def property(self):