API refactor
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2025-10-07 16:25:52 +09:00
parent 76d0d86211
commit 91c7e04474
1171 changed files with 81940 additions and 44117 deletions

View File

@@ -1,5 +1,5 @@
# orm/interfaces.py
# Copyright (C) 2005-2023 the SQLAlchemy authors and contributors
# Copyright (C) 2005-2025 the SQLAlchemy authors and contributors
# <see AUTHORS file>
#
# This module is part of SQLAlchemy and is released under
@@ -29,6 +29,7 @@ from typing import Dict
from typing import Generic
from typing import Iterator
from typing import List
from typing import Mapping
from typing import NamedTuple
from typing import NoReturn
from typing import Optional
@@ -115,7 +116,7 @@ _TLS = TypeVar("_TLS", bound="Type[LoaderStrategy]")
class ORMStatementRole(roles.StatementRole):
__slots__ = ()
_role_name = (
"Executable SQL or text() construct, including ORM " "aware objects"
"Executable SQL or text() construct, including ORM aware objects"
)
@@ -149,13 +150,17 @@ class ORMColumnDescription(TypedDict):
class _IntrospectsAnnotations:
__slots__ = ()
@classmethod
def _mapper_property_name(cls) -> str:
return cls.__name__
def found_in_pep593_annotated(self) -> Any:
"""return a copy of this object to use in declarative when the
object is found inside of an Annotated object."""
raise NotImplementedError(
f"Use of the {self.__class__} construct inside of an "
f"Annotated object is not yet supported."
f"Use of the {self._mapper_property_name()!r} "
"construct inside of an Annotated object is not yet supported."
)
def declarative_scan(
@@ -181,7 +186,8 @@ class _IntrospectsAnnotations:
raise sa_exc.ArgumentError(
f"Python typing annotation is required for attribute "
f'"{cls.__name__}.{key}" when primary argument(s) for '
f'"{self.__class__.__name__}" construct are None or not present'
f'"{self._mapper_property_name()}" '
"construct are None or not present"
)
@@ -201,6 +207,8 @@ class _AttributeOptions(NamedTuple):
dataclasses_default_factory: Union[_NoArg, Callable[[], Any]]
dataclasses_compare: Union[_NoArg, bool]
dataclasses_kw_only: Union[_NoArg, bool]
dataclasses_hash: Union[_NoArg, bool, None]
dataclasses_dataclass_metadata: Union[_NoArg, Mapping[Any, Any], None]
def _as_dataclass_field(self, key: str) -> Any:
"""Return a ``dataclasses.Field`` object given these arguments."""
@@ -218,6 +226,10 @@ class _AttributeOptions(NamedTuple):
kw["compare"] = self.dataclasses_compare
if self.dataclasses_kw_only is not _NoArg.NO_ARG:
kw["kw_only"] = self.dataclasses_kw_only
if self.dataclasses_hash is not _NoArg.NO_ARG:
kw["hash"] = self.dataclasses_hash
if self.dataclasses_dataclass_metadata is not _NoArg.NO_ARG:
kw["metadata"] = self.dataclasses_dataclass_metadata
if "default" in kw and callable(kw["default"]):
# callable defaults are ambiguous. deprecate them in favour of
@@ -255,7 +267,7 @@ class _AttributeOptions(NamedTuple):
key: str,
annotation: _AnnotationScanType,
mapped_container: Optional[Any],
elem: _T,
elem: Any,
) -> Union[
Tuple[str, _AnnotationScanType],
Tuple[str, _AnnotationScanType, dataclasses.Field[Any]],
@@ -297,6 +309,8 @@ _DEFAULT_ATTRIBUTE_OPTIONS = _AttributeOptions(
_NoArg.NO_ARG,
_NoArg.NO_ARG,
_NoArg.NO_ARG,
_NoArg.NO_ARG,
_NoArg.NO_ARG,
)
_DEFAULT_READONLY_ATTRIBUTE_OPTIONS = _AttributeOptions(
@@ -306,6 +320,8 @@ _DEFAULT_READONLY_ATTRIBUTE_OPTIONS = _AttributeOptions(
_NoArg.NO_ARG,
_NoArg.NO_ARG,
_NoArg.NO_ARG,
_NoArg.NO_ARG,
_NoArg.NO_ARG,
)
@@ -675,27 +691,37 @@ class PropComparator(SQLORMOperations[_T_co], Generic[_T_co], ColumnOperators):
# definition of custom PropComparator subclasses
from sqlalchemy.orm.properties import \
ColumnProperty,\
Composite,\
Relationship
from sqlalchemy.orm.properties import (
ColumnProperty,
Composite,
Relationship,
)
class MyColumnComparator(ColumnProperty.Comparator):
def __eq__(self, other):
return self.__clause_element__() == other
class MyRelationshipComparator(Relationship.Comparator):
def any(self, expression):
"define the 'any' operation"
# ...
class MyCompositeComparator(Composite.Comparator):
def __gt__(self, other):
"redefine the 'greater than' operation"
return sql.and_(*[a>b for a, b in
zip(self.__clause_element__().clauses,
other.__composite_values__())])
return sql.and_(
*[
a > b
for a, b in zip(
self.__clause_element__().clauses,
other.__composite_values__(),
)
]
)
# application of custom PropComparator subclasses
@@ -703,17 +729,22 @@ class PropComparator(SQLORMOperations[_T_co], Generic[_T_co], ColumnOperators):
from sqlalchemy.orm import column_property, relationship, composite
from sqlalchemy import Column, String
class SomeMappedClass(Base):
some_column = column_property(Column("some_column", String),
comparator_factory=MyColumnComparator)
some_relationship = relationship(SomeOtherClass,
comparator_factory=MyRelationshipComparator)
class SomeMappedClass(Base):
some_column = column_property(
Column("some_column", String),
comparator_factory=MyColumnComparator,
)
some_relationship = relationship(
SomeOtherClass, comparator_factory=MyRelationshipComparator
)
some_composite = composite(
Column("a", String), Column("b", String),
comparator_factory=MyCompositeComparator
)
Column("a", String),
Column("b", String),
comparator_factory=MyCompositeComparator,
)
Note that for column-level operator redefinition, it's usually
simpler to define the operators at the Core level, using the
@@ -735,6 +766,7 @@ class PropComparator(SQLORMOperations[_T_co], Generic[_T_co], ColumnOperators):
:attr:`.TypeEngine.comparator_factory`
"""
__slots__ = "prop", "_parententity", "_adapt_to_entity"
__visit_name__ = "orm_prop_comparator"
@@ -754,7 +786,7 @@ class PropComparator(SQLORMOperations[_T_co], Generic[_T_co], ColumnOperators):
self._adapt_to_entity = adapt_to_entity
@util.non_memoized_property
def property(self) -> MapperProperty[_T]:
def property(self) -> MapperProperty[_T_co]:
"""Return the :class:`.MapperProperty` associated with this
:class:`.PropComparator`.
@@ -784,7 +816,7 @@ class PropComparator(SQLORMOperations[_T_co], Generic[_T_co], ColumnOperators):
def adapt_to_entity(
self, adapt_to_entity: AliasedInsp[Any]
) -> PropComparator[_T]:
) -> PropComparator[_T_co]:
"""Return a copy of this PropComparator which will use the given
:class:`.AliasedInsp` to produce corresponding expressions.
"""
@@ -838,15 +870,13 @@ class PropComparator(SQLORMOperations[_T_co], Generic[_T_co], ColumnOperators):
def operate(
self, op: OperatorType, *other: Any, **kwargs: Any
) -> ColumnElement[Any]:
...
) -> ColumnElement[Any]: ...
def reverse_operate(
self, op: OperatorType, other: Any, **kwargs: Any
) -> ColumnElement[Any]:
...
) -> ColumnElement[Any]: ...
def of_type(self, class_: _EntityType[Any]) -> PropComparator[_T]:
def of_type(self, class_: _EntityType[Any]) -> PropComparator[_T_co]:
r"""Redefine this object in terms of a polymorphic subclass,
:func:`_orm.with_polymorphic` construct, or :func:`_orm.aliased`
construct.
@@ -856,8 +886,9 @@ class PropComparator(SQLORMOperations[_T_co], Generic[_T_co], ColumnOperators):
e.g.::
query.join(Company.employees.of_type(Engineer)).\
filter(Engineer.name=='foo')
query.join(Company.employees.of_type(Engineer)).filter(
Engineer.name == "foo"
)
:param \class_: a class or mapper indicating that criterion will be
against this specific subclass.
@@ -883,11 +914,11 @@ class PropComparator(SQLORMOperations[_T_co], Generic[_T_co], ColumnOperators):
stmt = select(User).join(
User.addresses.and_(Address.email_address != 'foo')
User.addresses.and_(Address.email_address != "foo")
)
stmt = select(User).options(
joinedload(User.addresses.and_(Address.email_address != 'foo'))
joinedload(User.addresses.and_(Address.email_address != "foo"))
)
.. versionadded:: 1.4