summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/sql/coercions.py
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2022-04-19 21:06:41 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2022-04-27 14:46:36 -0400
commitad11c482e2233f44e8747d4d5a2b17a995fff1fa (patch)
tree57f8ddd30928951519fd6ac0f418e9cbf8e65610 /lib/sqlalchemy/sql/coercions.py
parent033d1a16e7a220555d7611a5b8cacb1bd83822ae (diff)
downloadsqlalchemy-ad11c482e2233f44e8747d4d5a2b17a995fff1fa.tar.gz
pep484 ORM / SQL result support
after some experimentation it seems mypy is more amenable to the generic types being fully integrated rather than having separate spin-off types. so key structures like Result, Row, Select become generic. For DML Insert, Update, Delete, these are spun into type-specific subclasses ReturningInsert, ReturningUpdate, ReturningDelete, which is fine since the "row-ness" of these constructs doesn't happen until returning() is called in any case. a Tuple based model is then integrated so that these objects can carry along information about their return types. Overloads at the .execute() level carry through the Tuple from the invoked object to the result. To suit the issue of AliasedClass generating attributes that are dynamic, experimented with a custom subclass AsAliased, but then just settled on having aliased() lie to the type checker and return `Type[_O]`, essentially. will need some type-related accessors for with_polymorphic() also. Additionally, identified an issue in Update when used "mysql style" against a join(), it basically doesn't work if asked to UPDATE two tables on the same column name. added an error message to the specific condition where it happens with a very non-specific error message that we hit a thing we can't do right now, suggest multi-table update as a possible cause. Change-Id: I5eff7eefe1d6166ee74160b2785c5e6a81fa8b95
Diffstat (limited to 'lib/sqlalchemy/sql/coercions.py')
-rw-r--r--lib/sqlalchemy/sql/coercions.py25
1 files changed, 13 insertions, 12 deletions
diff --git a/lib/sqlalchemy/sql/coercions.py b/lib/sqlalchemy/sql/coercions.py
index 0659709ab..9b7231360 100644
--- a/lib/sqlalchemy/sql/coercions.py
+++ b/lib/sqlalchemy/sql/coercions.py
@@ -29,6 +29,7 @@ from typing import Union
from . import operators
from . import roles
from . import visitors
+from ._typing import is_from_clause
from .base import ExecutableOption
from .base import Options
from .cache_key import HasCacheKey
@@ -38,25 +39,18 @@ from .. import inspection
from .. import util
from ..util.typing import Literal
-if not typing.TYPE_CHECKING:
- elements = None
- lambdas = None
- schema = None
- selectable = None
- traversals = None
-
if typing.TYPE_CHECKING:
from . import elements
from . import lambdas
from . import schema
from . import selectable
- from . import traversals
from ._typing import _ColumnExpressionArgument
from ._typing import _ColumnsClauseArgument
from ._typing import _DDLColumnArgument
from ._typing import _DMLTableArgument
from ._typing import _FromClauseArgument
from .dml import _DMLTableElement
+ from .elements import BindParameter
from .elements import ClauseElement
from .elements import ColumnClause
from .elements import ColumnElement
@@ -64,9 +58,7 @@ if typing.TYPE_CHECKING:
from .elements import SQLCoreOperations
from .schema import Column
from .selectable import _ColumnsClauseElement
- from .selectable import _JoinTargetElement
from .selectable import _JoinTargetProtocol
- from .selectable import _OnClauseElement
from .selectable import FromClause
from .selectable import HasCTE
from .selectable import SelectBase
@@ -170,6 +162,15 @@ def expect(
@overload
def expect(
+ role: Type[roles.LiteralValueRole],
+ element: Any,
+ **kw: Any,
+) -> BindParameter[Any]:
+ ...
+
+
+@overload
+def expect(
role: Type[roles.DDLReferredColumnRole],
element: Any,
**kw: Any,
@@ -272,7 +273,7 @@ def expect(
@overload
def expect(
role: Type[roles.ColumnsClauseRole],
- element: _ColumnsClauseArgument,
+ element: _ColumnsClauseArgument[Any],
**kw: Any,
) -> _ColumnsClauseElement:
...
@@ -933,7 +934,7 @@ class GroupByImpl(ByOfImpl, RoleImpl):
argname: Optional[str] = None,
**kw: Any,
) -> Any:
- if isinstance(resolved, roles.StrictFromClauseRole):
+ if is_from_clause(resolved):
return elements.ClauseList(*resolved.c)
else:
return resolved