matrix:
# emulated wheels on linux take too much time, split wheels into multiple runs
python:
- - "cp39-*"
- "cp310-* cp311-*"
- "cp312-* cp313-*"
wheel_mode:
# create pure python build
- os: ubuntu-22.04
wheel_mode: pure-python
- python: "cp-312*"
+ python: "cp-313*"
exclude:
- os: "windows-2022"
- name: Set up Python for twine and pure-python wheel
uses: actions/setup-python@v5
with:
- python-version: "3.12"
+ python-version: "3.13"
- name: Build pure-python wheel
if: ${{ matrix.wheel_mode == 'pure-python' && runner.os == 'Linux' }}
os:
- "ubuntu-22.04"
python-version:
- - "3.12"
+ - "3.13"
tox-env:
- mypy
- lint
- "macos-latest"
- "macos-13"
python-version:
- - "3.9"
- "3.10"
- "3.11"
- "3.12"
- "3.13"
+ - "3.14.0-alpha - 3.14"
- "pypy-3.10"
build-type:
- "cext"
# windows des not have arm64 python
- os: "windows-latest"
architecture: arm64
- # macos: latests uses arm macs. only 3.10+; no x86/x64
+ # macos: latests uses arm macs. no x86/x64
- os: "macos-latest"
architecture: x86
- os: "macos-latest"
architecture: x64
- - os: "macos-latest"
- python-version: "3.9"
# macos 13: uses intel macs. no arm64, x86
- os: "macos-13"
architecture: arm64
python-version: "pypy-3.10"
- os: "windows-11-arm"
python-version: "3.10"
- - os: "windows-11-arm"
- python-version: "3.9"
- os: "windows-11-arm"
architecture: x86
- os: "windows-11-arm"
- pep484
include:
- # run lint only on 3.12
+ # run lint only on 3.13
- tox-env: lint
- python-version: "3.12"
+ python-version: "3.13"
os: "ubuntu-22.04"
fail-fast: false
+++ /dev/null
-import sys
-
-from packaging import tags
-
-to_check = "--"
-found = False
-if len(sys.argv) > 1:
- to_check = sys.argv[1]
- for t in tags.sys_tags():
- start = "-".join(str(t).split("-")[:2])
- if to_check.lower() == start:
- print(
- "Wheel tag {0} matches installed version {1}.".format(
- to_check, t
- )
- )
- found = True
- break
-if not found:
- print(
- "Wheel tag {0} not found in installed version tags {1}.".format(
- to_check, [str(t) for t in tags.sys_tags()]
- )
- )
- exit(1)
+++ /dev/null
-.. change::
- :tags: change, installation
- :tickets: 10357, 12029
-
- Python 3.9 or above is now required; support for Python 3.8 and 3.7 is
- dropped as these versions are EOL.
--- /dev/null
+.. change::
+ :tags: change, installation
+ :tickets: 10357, 12029, 12819
+
+ Python 3.10 or above is now required; support for Python 3.9, 3.8 and 3.7
+ is dropped as these versions are EOL.
SQLAlchemy 2.1 supports the following platforms:
-* cPython 3.9 and higher
+* cPython 3.10 and higher
* Python-3 compatible versions of `PyPy <http://pypy.org/>`_
.. versionchanged:: 2.1
- SQLAlchemy now targets Python 3.9 and above.
+ SQLAlchemy now targets Python 3.10 and above.
Supported Installation Methods
import datetime
import operator
import re
+from typing import Literal
from typing import overload
from typing import TYPE_CHECKING
from uuid import UUID as _python_UUID
from ...types import TEXT
from ...types import VARCHAR
from ...util import update_wrapper
-from ...util.typing import Literal
if TYPE_CHECKING:
from ...sql.dml import DMLState
import json as _py_json
import re
import time
+from types import NoneType
from typing import Any
from typing import Awaitable
from typing import Callable
def bind_processor(self, dialect):
asyncpg_Range = dialect.dbapi.asyncpg.Range
- NoneType = type(None)
-
def to_range(value):
if isinstance(value, (str, NoneType)):
return value
import collections
import logging
import re
+from types import NoneType
from typing import cast
from typing import TYPE_CHECKING
PGDialect_psycopg, dialect
)._psycopg_Multirange
- NoneType = type(None)
-
def to_range(value):
if isinstance(value, (str, NoneType, psycopg_Multirange)):
return value
from typing import cast
from typing import Generic
from typing import List
+from typing import Literal
from typing import Optional
from typing import overload
from typing import Sequence
from ... import types as sqltypes
from ...sql import operators
from ...sql.type_api import TypeEngine
-from ...util import py310
-from ...util.typing import Literal
if TYPE_CHECKING:
from ...sql.elements import ColumnElement
_BoundsType = Literal["()", "[)", "(]", "[]"]
-if py310:
- dc_slots = {"slots": True}
- dc_kwonly = {"kw_only": True}
-else:
- dc_slots = {}
- dc_kwonly = {}
-
-@dataclasses.dataclass(frozen=True, **dc_slots)
+@dataclasses.dataclass(frozen=True, slots=True)
class Range(Generic[_T]):
"""Represent a PostgreSQL range.
upper: Optional[_T] = None
"""the upper bound"""
- if TYPE_CHECKING:
- bounds: _BoundsType = dataclasses.field(default="[)")
- empty: bool = dataclasses.field(default=False)
- else:
- bounds: _BoundsType = dataclasses.field(default="[)", **dc_kwonly)
- empty: bool = dataclasses.field(default=False, **dc_kwonly)
-
- if not py310:
-
- def __init__(
- self,
- lower: Optional[_T] = None,
- upper: Optional[_T] = None,
- *,
- bounds: _BoundsType = "[)",
- empty: bool = False,
- ):
- # no __slots__ either so we can update dict
- self.__dict__.update(
- {
- "lower": lower,
- "upper": upper,
- "bounds": bounds,
- "empty": empty,
- }
- )
+ bounds: _BoundsType = dataclasses.field(default="[)", kw_only=True)
+ empty: bool = dataclasses.field(default=False, kw_only=True)
def __bool__(self) -> bool:
return not self.empty
from ..util import immutabledict
if typing.TYPE_CHECKING:
+ from typing import Literal
+
from .base import Engine
from .interfaces import _ExecuteOptions
from .interfaces import _ParamStyle
from ..pool import _CreatorWRecFnType
from ..pool import _ResetStyleArgType
from ..pool import Pool
- from ..util.typing import Literal
@overload
from typing import Iterable
from typing import Iterator
from typing import List
+from typing import Literal
from typing import Mapping
from typing import NoReturn
from typing import Optional
from ..sql.compiler import RM_RENDERED_NAME
from ..sql.compiler import RM_TYPE
from ..sql.type_api import TypeEngine
-from ..util.typing import Literal
from ..util.typing import Self
from ..util.typing import TupleAny
from ..util.typing import TypeVarTuple
from typing import Dict
from typing import Final
from typing import List
+from typing import Literal
from typing import Mapping
from typing import MutableMapping
from typing import MutableSequence
from ..sql.compiler import InsertmanyvaluesSentinelOpts
from ..sql.compiler import SQLCompiler
from ..sql.elements import quoted_name
-from ..util.typing import Literal
from ..util.typing import TupleAny
from ..util.typing import Unpack
import typing
from typing import Any
from typing import Dict
+from typing import Literal
from typing import Optional
from typing import Tuple
from typing import Type
from .interfaces import Dialect
from .. import event
from .. import exc
-from ..util.typing import Literal
from ..util.typing import TupleAny
from ..util.typing import Unpack
from typing import Iterable
from typing import Iterator
from typing import List
+from typing import Literal
from typing import Mapping
from typing import MutableMapping
from typing import Optional
from ..sql.compiler import TypeCompiler # noqa
from ..util import immutabledict
from ..util.concurrency import await_
-from ..util.typing import Literal
from ..util.typing import NotRequired
if TYPE_CHECKING:
from typing import Iterable
from typing import Iterator
from typing import List
+from typing import Literal
from typing import Mapping
from typing import NoReturn
from typing import Optional
from ..util import deprecated
from ..util import HasMemoized_ro_memoized_attribute
from ..util import NONE_SET
-from ..util.typing import Literal
from ..util.typing import Self
from ..util.typing import TupleAny
from ..util.typing import TypeVarTuple
from typing import Generic
from typing import Iterator
from typing import List
+from typing import Literal
from typing import Mapping
from typing import MutableMapping
from typing import Optional
from .registry import _ET
from .registry import _EventKey
from .. import util
-from ..util.typing import Literal
_registrars: MutableMapping[str, List[Type[_HasEventsDispatch[Any]]]] = (
util.defaultdict(list)
from typing import Iterator
from typing import KeysView
from typing import List
+from typing import Literal
from typing import Mapping
from typing import MutableMapping
from typing import MutableSequence
from ..sql import operators
from ..sql import or_
from ..sql.base import _NoArg
-from ..util.typing import Literal
from ..util.typing import Self
from ..util.typing import SupportsKeysAndGetItem
from typing import Dict
from typing import Generator
from typing import Generic
+from typing import Literal
from typing import NoReturn
from typing import Optional
from typing import overload
from . import exc as async_exc
from ... import util
-from ...util.typing import Literal
from ...util.typing import Self
_T = TypeVar("_T", bound=Any)
async def start(self, is_ctxmanager: bool = False) -> _T_co:
try:
- start_value = await util.anext_(self.gen)
+ start_value = await anext(self.gen)
except StopAsyncIteration:
raise RuntimeError("generator didn't yield") from None
# vendored from contextlib.py
if typ is None:
try:
- await util.anext_(self.gen)
+ await anext(self.gen)
except StopAsyncIteration:
return False
else:
from typing import Any
from typing import AsyncIterator
from typing import Callable
+from typing import Concatenate
from typing import Dict
from typing import Generator
from typing import NoReturn
from typing import Optional
from typing import overload
+from typing import ParamSpec
from typing import Type
from typing import TYPE_CHECKING
from typing import TypeVar
from ...engine.base import Transaction
from ...exc import ArgumentError
from ...util.concurrency import greenlet_spawn
-from ...util.typing import Concatenate
-from ...util.typing import ParamSpec
from ...util.typing import TupleAny
from ...util.typing import TypeVarTuple
from ...util.typing import Unpack
import operator
from typing import Any
from typing import AsyncIterator
+from typing import Literal
from typing import Optional
from typing import overload
from typing import Sequence
from ...sql.base import _generative
from ...util import deprecated
from ...util.concurrency import greenlet_spawn
-from ...util.typing import Literal
from ...util.typing import Self
from ...util.typing import TupleAny
from ...util.typing import TypeVarTuple
from typing import Awaitable
from typing import Callable
from typing import cast
+from typing import Concatenate
from typing import Dict
from typing import Generic
from typing import Iterable
from typing import NoReturn
from typing import Optional
from typing import overload
+from typing import ParamSpec
from typing import Sequence
from typing import Tuple
from typing import Type
from ...orm import SessionTransaction
from ...orm import state as _instance_state
from ...util.concurrency import greenlet_spawn
-from ...util.typing import Concatenate
-from ...util.typing import ParamSpec
from ...util.typing import TupleAny
from ...util.typing import TypeVarTuple
from ...util.typing import Unpack
from typing import Any
from typing import Callable
from typing import cast
+from typing import Concatenate
from typing import Generic
from typing import List
+from typing import Literal
from typing import MutableMapping
from typing import Optional
from typing import overload
+from typing import ParamSpec
from typing import Protocol
from typing import Sequence
from typing import Tuple
from ..sql._typing import is_has_clause_element
from ..sql.elements import ColumnElement
from ..sql.elements import SQLCoreOperations
-from ..util.typing import Concatenate
-from ..util.typing import Literal
-from ..util.typing import ParamSpec
from ..util.typing import Self
if TYPE_CHECKING:
from typing import Callable
from typing import Dict
from typing import Generic
+from typing import Literal
from typing import Optional
from typing import overload
from typing import Protocol
from typing import Union
from . import exc
-from .util.typing import Literal
_T = TypeVar("_T", bound=Any)
_TCov = TypeVar("_TCov", bound=Any, covariant=True)
import logging
import sys
from typing import Any
+from typing import Literal
from typing import Optional
from typing import overload
from typing import Set
from typing import Union
from .util import py311
-from .util.typing import Literal
STACKLEVEL = True
from __future__ import annotations
import typing
+from typing import Annotated
from typing import Any
from typing import Callable
from typing import Collection
from typing import Iterable
+from typing import Literal
from typing import Mapping
from typing import NoReturn
from typing import Optional
from ..sql.schema import _InsertSentinelColumnDefault
from ..sql.schema import SchemaConst
from ..sql.selectable import FromClause
-from ..util.typing import Annotated
-from ..util.typing import Literal
if TYPE_CHECKING:
from ._typing import _EntityType
from typing import Tuple
from typing import Type
from typing import TYPE_CHECKING
+from typing import TypeGuard
from typing import TypeVar
from typing import Union
)
from ..sql._typing import _HasClauseElement
from ..sql.elements import ColumnElement
-from ..util.typing import TypeGuard
if TYPE_CHECKING:
from .attributes import _AttributeImpl
from typing import Dict
from typing import Iterable
from typing import List
+from typing import Literal
from typing import NamedTuple
from typing import Optional
from typing import overload
from typing import Tuple
from typing import Type
from typing import TYPE_CHECKING
+from typing import TypeGuard
from typing import TypeVar
from typing import Union
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
if TYPE_CHECKING:
from ._typing import _EntityType
from typing import Callable
from typing import Dict
from typing import Generic
+from typing import Literal
from typing import no_type_check
from typing import Optional
from typing import overload
from ..sql.elements import SQLCoreOperations
from ..util import FastIntFlag
from ..util.langhelpers import TypingOnly
-from ..util.typing import Literal
if typing.TYPE_CHECKING:
from ._typing import _EntityType
from typing import cast
from typing import Dict
from typing import Iterable
+from typing import Literal
from typing import Optional
from typing import overload
from typing import TYPE_CHECKING
from ..sql.dml import InsertDMLState
from ..sql.dml import UpdateDMLState
from ..util import EMPTY_DICT
-from ..util.typing import Literal
from ..util.typing import TupleAny
from ..util.typing import Unpack
from typing import Generic
from typing import Iterable
from typing import Iterator
+from typing import Literal
from typing import Mapping
from typing import Optional
from typing import overload
from ..util.typing import de_optionalize_union_types
from ..util.typing import is_generic
from ..util.typing import is_literal
-from ..util.typing import Literal
from ..util.typing import LITERAL_TYPES
from ..util.typing import Self
from typing import Callable
from typing import cast
from typing import Dict
+from typing import get_args
from typing import Iterable
from typing import List
from typing import Mapping
from ..sql.schema import Table
from ..util import topological
from ..util.typing import _AnnotationScanType
-from ..util.typing import get_args
from ..util.typing import is_fwd_ref
from ..util.typing import is_literal
from typing import Any
from typing import Callable
from typing import Dict
+from typing import get_args
from typing import List
from typing import NoReturn
from typing import Optional
from ..sql import operators
from ..sql.base import _NoArg
from ..sql.elements import BindParameter
-from ..util.typing import get_args
from ..util.typing import is_fwd_ref
from ..util.typing import is_pep593
from ..util.typing import TupleAny
from typing import Generic
from typing import Iterable
from typing import List
+from typing import Literal
from typing import Optional
from typing import Protocol
from typing import Set
from .. import util
from ..event import EventTarget
from ..util import HasMemoized
-from ..util.typing import Literal
if TYPE_CHECKING:
from ._typing import _RegistryType
from typing import Dict
from typing import Generic
from typing import List
+from typing import Literal
from typing import Optional
from typing import Sequence
from typing import Tuple
from ..sql import roles
from ..util.langhelpers import Missing
from ..util.langhelpers import MissingOr
-from ..util.typing import Literal
if TYPE_CHECKING:
from . import AttributeEventToken
from typing import Iterable
from typing import Iterator
from typing import List
+from typing import Literal
from typing import Mapping
from typing import Optional
from typing import Sequence
from ..sql.selectable import LABEL_STYLE_TABLENAME_PLUS_COL
from ..util import HasMemoized
from ..util import HasMemoized_ro_memoized_attribute
-from ..util.typing import Literal
from ..util.typing import TupleAny
from ..util.typing import Unpack
from ..sql.cache_key import HasCacheKey
if TYPE_CHECKING:
+ from typing import TypeGuard
+
from ._typing import _InternalEntityType
from .interfaces import StrategizedProperty
from .mapper import Mapper
from ..sql.elements import BindParameter
from ..sql.visitors import anon_map
from ..util.typing import _LiteralStar
- from ..util.typing import TypeGuard
def is_root(path: PathRegistry) -> TypeGuard[RootRegistry]: ...
from typing import Any
from typing import cast
from typing import Dict
+from typing import get_args
from typing import List
from typing import Optional
from typing import Sequence
from ..sql.schema import SchemaConst
from ..sql.type_api import TypeEngine
from ..util.typing import de_optionalize_union_types
-from ..util.typing import get_args
from ..util.typing import includes_none
from ..util.typing import is_a_type
from ..util.typing import is_fwd_ref
from typing import Iterable
from typing import Iterator
from typing import List
+from typing import Literal
from typing import Mapping
from typing import Optional
from typing import overload
from ..sql.selectable import SelectLabelStyle
from ..util import deprecated
from ..util import warn_deprecated
-from ..util.typing import Literal
from ..util.typing import Self
from ..util.typing import TupleAny
from ..util.typing import TypeVarTuple
from typing import Iterable
from typing import Iterator
from typing import List
+from typing import Literal
from typing import NamedTuple
from typing import NoReturn
from typing import Optional
from ..sql.util import selectables_overlap
from ..sql.util import visit_binary_product
from ..util.typing import de_optionalize_union_types
-from ..util.typing import Literal
from ..util.typing import resolve_name_to_real_class_name
if typing.TYPE_CHECKING:
from typing import Iterable
from typing import Iterator
from typing import List
+from typing import Literal
from typing import NoReturn
from typing import Optional
from typing import overload
from ..sql.selectable import LABEL_STYLE_TABLENAME_PLUS_COL
from ..util import deprecated_params
from ..util import IdentitySet
-from ..util.typing import Literal
from ..util.typing import TupleAny
from ..util.typing import TypeVarTuple
from ..util.typing import Unpack
from typing import Dict
from typing import Generic
from typing import Iterable
+from typing import Literal
from typing import Optional
from typing import Protocol
from typing import Set
from .. import exc as sa_exc
from .. import inspection
from .. import util
-from ..util.typing import Literal
from ..util.typing import TupleAny
from ..util.typing import Unpack
from typing import Callable
from typing import cast
from typing import Iterator
+from typing import Literal
from typing import NoReturn
from typing import Optional
from typing import Tuple
from .. import exc as sa_exc
from .. import util
-from ..util.typing import Literal
_F = TypeVar("_F", bound=Callable[..., Any])
import itertools
from typing import Any
from typing import Dict
+from typing import Literal
from typing import Optional
from typing import Tuple
from typing import TYPE_CHECKING
from ..sql import visitors
from ..sql.selectable import LABEL_STYLE_TABLENAME_PLUS_COL
from ..sql.selectable import Select
-from ..util.typing import Literal
if TYPE_CHECKING:
from .mapper import Mapper
from typing import Dict
from typing import Final
from typing import Iterable
+from typing import Literal
from typing import Optional
from typing import overload
from typing import Sequence
from ..sql import traversals
from ..sql import visitors
from ..sql.base import _generative
-from ..util.typing import Literal
from ..util.typing import Self
_RELATIONSHIP_TOKEN: Final[Literal["relationship"]] = "relationship"
from typing import Dict
from typing import FrozenSet
from typing import Generic
+from typing import get_origin
from typing import Iterable
from typing import Iterator
from typing import List
+from typing import Literal
from typing import Match
from typing import Optional
from typing import Protocol
from ..util.typing import de_stringify_annotation as _de_stringify_annotation
from ..util.typing import eval_name_only as _eval_name_only
from ..util.typing import fixup_container_fwd_refs
-from ..util.typing import get_origin
from ..util.typing import is_origin_of_cls
-from ..util.typing import Literal
from ..util.typing import TupleAny
from ..util.typing import Unpack
from typing import Iterable
from typing import Iterator
from typing import List
+from typing import Literal
from typing import NoReturn
from typing import Optional
from typing import overload
from ..sql.dml import Delete
from ..sql.dml import Insert
from ..sql.dml import Update
-from ..util.typing import Literal
if TYPE_CHECKING:
from . import QueryableAttribute
from typing import Deque
from typing import Dict
from typing import List
+from typing import Literal
from typing import Optional
from typing import Protocol
from typing import Tuple
from .. import exc
from .. import log
from .. import util
-from ..util.typing import Literal
if TYPE_CHECKING:
from ..engine.interfaces import DBAPIConnection
from typing import Any
from typing import cast
from typing import List
+from typing import Literal
from typing import Optional
from typing import Set
from typing import Type
from .. import util
from ..util import chop_traceback
from ..util import queue as sqla_queue
-from ..util.typing import Literal
if typing.TYPE_CHECKING:
from ..engine.interfaces import DBAPIConnection
import typing
from typing import Any
from typing import Callable
+from typing import Literal
from typing import Mapping
from typing import Optional
from typing import overload
from .elements import UnaryExpression
from .elements import WithinGroup
from .functions import FunctionElement
-from ..util.typing import Literal
if typing.TYPE_CHECKING:
from ._typing import _ByArgument
from __future__ import annotations
-from ..util.typing import Literal
+from typing import Literal
SynchronizeSessionArgument = Literal[False, "auto", "evaluate", "fetch"]
DMLStrategyArgument = Literal["bulk", "raw", "orm", "auto"]
from typing import Dict
from typing import Generic
from typing import Iterable
+from typing import Literal
from typing import Mapping
from typing import NoReturn
from typing import Optional
from typing import Set
from typing import Type
from typing import TYPE_CHECKING
+from typing import TypeAlias
from typing import TypeVar
from typing import Union
from .. import exc
from .. import util
from ..inspection import Inspectable
-from ..util.typing import Literal
from ..util.typing import TupleAny
-from ..util.typing import TypeAlias
from ..util.typing import TypeVarTuple
from ..util.typing import Unpack
from datetime import time
from datetime import timedelta
from decimal import Decimal
+ from typing import TypeGuard
from uuid import UUID
from .base import Executable
from ..engine import Dialect
from ..engine import Engine
from ..engine.mock import MockConnection
- from ..util.typing import TypeGuard
_T = TypeVar("_T", bound=Any)
_T_co = TypeVar("_T_co", bound=Any, covariant=True)
from __future__ import annotations
from typing import Dict
+from typing import Literal
from typing import Tuple
from typing import TYPE_CHECKING
from typing import Union
-from ..util.typing import Literal
-
if TYPE_CHECKING:
from .cache_key import CacheConst
from typing import cast
from typing import Dict
from typing import FrozenSet
+from typing import Literal
from typing import Mapping
from typing import Optional
from typing import overload
from .visitors import ExternallyTraversible
from .visitors import InternalTraversal
from .. import util
-from ..util.typing import Literal
from ..util.typing import Self
if TYPE_CHECKING:
from typing import Tuple
from typing import Type
from typing import TYPE_CHECKING
+from typing import TypeGuard
from typing import TypeVar
from typing import Union
from ..util import HasMemoized as HasMemoized
from ..util import hybridmethod
from ..util.typing import Self
-from ..util.typing import TypeGuard
from ..util.typing import TypeVarTuple
from ..util.typing import Unpack
from typing import Iterable
from typing import Iterator
from typing import List
+from typing import Literal
from typing import MutableMapping
from typing import NamedTuple
from typing import Optional
from .. import util
from ..inspection import inspect
from ..util import HasMemoized
-from ..util.typing import Literal
if typing.TYPE_CHECKING:
from .elements import BindParameter
from typing import Iterable
from typing import Iterator
from typing import List
+from typing import Literal
from typing import NoReturn
from typing import Optional
from typing import overload
from .. import exc
from .. import inspection
from .. import util
-from ..util.typing import Literal
if typing.TYPE_CHECKING:
# elements lambdas schema selectable are set by __init__
from typing import Iterable
from typing import Iterator
from typing import List
+from typing import Literal
from typing import Mapping
from typing import MutableMapping
from typing import NamedTuple
from .. import exc
from .. import util
from ..util import FastIntFlag
-from ..util.typing import Literal
from ..util.typing import Self
from ..util.typing import TupleAny
from ..util.typing import Unpack
from typing import Dict
from typing import Iterable
from typing import List
+from typing import Literal
from typing import MutableMapping
from typing import NamedTuple
from typing import Optional
from .selectable import TableClause
from .. import exc
from .. import util
-from ..util.typing import Literal
if TYPE_CHECKING:
from .compiler import _BindNameForColProtocol
from typing import Tuple
from typing import Type
from typing import TYPE_CHECKING
+from typing import TypeGuard
from typing import TypeVar
from typing import Union
from .. import util
from ..util.typing import Self
from ..util.typing import TupleAny
-from ..util.typing import TypeGuard
from ..util.typing import TypeVarTuple
from ..util.typing import Unpack
from typing import Iterable
from typing import Iterator
from typing import List
+from typing import Literal
from typing import Mapping
from typing import Optional
from typing import overload
+from typing import ParamSpec
from typing import Sequence
from typing import Set
from typing import Tuple as typing_Tuple
from .. import util
from ..util import HasMemoized_ro_memoized_attribute
from ..util import TypingOnly
-from ..util.typing import Literal
-from ..util.typing import ParamSpec
from ..util.typing import Self
from ..util.typing import TupleAny
from ..util.typing import Unpack
from typing import Callable
from typing import cast
from typing import List
+from typing import Literal
from typing import MutableMapping
from typing import Optional
from typing import Tuple
from .. import exc
from .. import inspection
from .. import util
-from ..util.typing import Literal
if TYPE_CHECKING:
from typing import cast
from typing import Dict
from typing import Generic
+from typing import Literal
from typing import Optional
from typing import overload
from typing import Protocol
from .. import exc
from .. import util
-from ..util.typing import Literal
if typing.TYPE_CHECKING:
from ._typing import ColumnExpressionArgument
from typing import Any
from typing import Generic
+from typing import Literal
from typing import Optional
from typing import TYPE_CHECKING
from typing import TypeVar
from .. import util
-from ..util.typing import Literal
if TYPE_CHECKING:
from ._typing import _PropagateAttrsType
from typing import Iterable
from typing import Iterator
from typing import List
+from typing import Literal
from typing import Mapping
from typing import NoReturn
from typing import Optional
from typing import Tuple
from typing import TYPE_CHECKING
from typing import TypedDict
+from typing import TypeGuard
from typing import TypeVar
from typing import Union
from .. import inspection
from .. import util
from ..util import HasMemoized
-from ..util.typing import Literal
from ..util.typing import Self
-from ..util.typing import TypeGuard
if typing.TYPE_CHECKING:
from ._typing import _AutoIncrementType
from typing import Iterable
from typing import Iterator
from typing import List
+from typing import Literal
from typing import NamedTuple
from typing import NoReturn
from typing import Optional
from .. import util
from ..util import HasMemoized_ro_memoized_attribute
from ..util import warn_deprecated
-from ..util.typing import Literal
from ..util.typing import Self
from ..util.typing import TupleAny
from ..util.typing import Unpack
from typing import cast
from typing import Dict
from typing import Generic
+from typing import get_args
from typing import Iterable
from typing import List
+from typing import Literal
from typing import Mapping
from typing import Optional
from typing import overload
from ..engine import processors
from ..util import langhelpers
from ..util import OrderedDict
-from ..util.typing import get_args
from ..util.typing import is_literal
from ..util.typing import is_pep695
-from ..util.typing import Literal
from ..util.typing import TupleAny
if TYPE_CHECKING:
from typing import Type
from typing import TYPE_CHECKING
from typing import TypedDict
+from typing import TypeGuard
from typing import TypeVar
from typing import Union
from .. import util
from ..util.typing import Self
from ..util.typing import TypeAliasType
-from ..util.typing import TypeGuard
# these are back-assigned by sqltypes.
if typing.TYPE_CHECKING:
from typing import Iterable
from typing import Iterator
from typing import List
+from typing import Literal
from typing import Optional
from typing import overload
from typing import Protocol
from .visitors import _ET
from .. import exc
from .. import util
-from ..util.typing import Literal
from ..util.typing import Unpack
if typing.TYPE_CHECKING:
from typing import Iterable
from typing import Iterator
from typing import List
+from typing import Literal
from typing import Mapping
from typing import Optional
from typing import overload
from .. import exc
from .. import util
from ..util import langhelpers
-from ..util.typing import Literal
from ..util.typing import Self
if TYPE_CHECKING:
import typing
from typing import Any
from typing import Dict
+from typing import Literal
from typing import Optional
import warnings
import weakref
from .. import event
from .. import pool
from ..util import await_
-from ..util.typing import Literal
if typing.TYPE_CHECKING:
from .base import TestBase
from .. import config
from ..assertions import eq_
-from ... import util
try:
from mypy import version
is_mypy = is_re = True
expected_msg = f'Revealed type is "{expected_msg}"'
- if mypy_14 and util.py310:
- # use_or_syntax, py310 and above
+ if mypy_14:
+ # use_or_syntax
# https://github.com/python/mypy/blob/304997bfb85200fb521ac727ee0ce3e6085e5278/mypy/options.py#L368 # noqa: E501
expected_msg = re.sub(
r"Optional\[(.*?)\]",
return exclusions.only_if(check)
- @property
- def python310(self):
- return exclusions.only_if(
- lambda: util.py310, "Python 3.10 or above required"
- )
-
@property
def python311(self):
return exclusions.only_if(
from ._collections import update_copy as update_copy
from ._collections import WeakPopulateDict as WeakPopulateDict
from ._collections import WeakSequence as WeakSequence
-from .compat import anext_ as anext_
from .compat import arm as arm
from .compat import b as b
from .compat import b64decode as b64decode
from .compat import is64bit as is64bit
from .compat import local_dataclass_fields as local_dataclass_fields
from .compat import osx as osx
-from .compat import py310 as py310
from .compat import py311 as py311
from .compat import py312 as py312
from .compat import py313 as py313
monkeypatch_proxied_specials as monkeypatch_proxied_specials,
)
from .langhelpers import non_memoized_property as non_memoized_property
-from .langhelpers import NoneType as NoneType
from .langhelpers import only_once as only_once
from .langhelpers import (
parse_user_argument_for_enum as parse_user_argument_for_enum,
from typing import Iterable
from typing import Iterator
from typing import List
+from typing import Literal
from typing import Mapping
from typing import NoReturn
from typing import Optional
from ._immutabledict_cy import ImmutableDictBase as ImmutableDictBase
from ._immutabledict_cy import ReadOnlyContainer as ReadOnlyContainer
from .typing import is_non_string_iterable
-from .typing import Literal
_T = TypeVar("_T", bound=Any)
py313 = sys.version_info >= (3, 13)
py312 = sys.version_info >= (3, 12)
py311 = sys.version_info >= (3, 11)
-py310 = sys.version_info >= (3, 10)
pypy = platform.python_implementation() == "PyPy"
cpython = platform.python_implementation() == "CPython"
return hashlib.md5(usedforsecurity=False)
-if py310:
- anext_ = anext
-else:
- _NOT_PROVIDED = object()
- from collections.abc import AsyncIterator
-
- async def anext_(async_iterator, default=_NOT_PROVIDED):
- """vendored from https://github.com/python/cpython/pull/8895"""
-
- if not isinstance(async_iterator, AsyncIterator):
- raise TypeError(
- f"anext expected an AsyncIterator, got {type(async_iterator)}"
- )
- anxt = type(async_iterator).__anext__
- try:
- return await anxt(async_iterator)
- except StopAsyncIteration:
- if default is _NOT_PROVIDED:
- raise
- return default
-
-
def importlib_metadata_get(group):
ep = importlib_metadata.entry_points()
if typing.TYPE_CHECKING or hasattr(ep, "select"):
from typing import Awaitable
from typing import Callable
from typing import Coroutine
+from typing import Literal
from typing import NoReturn
from typing import TYPE_CHECKING
+from typing import TypeGuard
from typing import TypeVar
from typing import Union
from .compat import py311
from .langhelpers import memoized_property
-from .typing import Literal
from .typing import Self
-from .typing import TypeGuard
from .. import exc
_T = TypeVar("_T")
from typing import Generic
from typing import Iterator
from typing import List
+from typing import Literal
from typing import Mapping
from typing import NoReturn
from typing import Optional
from . import _collections
from . import compat
-from .typing import Literal
from .. import exc
_T = TypeVar("_T")
# away in future python as a separate mode
return _vendored_get_annotations(obj, format=Format.FORWARDREF)
-elif compat.py310:
-
- def get_annotations(obj: Any) -> Mapping[str, Any]:
- return inspect.get_annotations(obj)
-
else:
def get_annotations(obj: Any) -> Mapping[str, Any]:
- # https://docs.python.org/3/howto/annotations.html#annotations-howto
- if isinstance(obj, type):
- ann = obj.__dict__.get("__annotations__", None)
- else:
- ann = obj.__annotations__
-
- if ann is None:
- return _collections.EMPTY_DICT
- else:
- return cast("Mapping[str, Any]", ann)
+ return inspect.get_annotations(obj)
def md5_hex(x: Any) -> str:
return tb[start : end + 1]
-NoneType = type(None)
-
-
def attrsetter(attrname):
code = "def set(obj, value): obj.%s = value" % attrname
env = locals().copy()
import collections.abc as collections_abc
import re
import sys
+from types import NoneType
import typing
from typing import Any
from typing import Callable
from typing import Dict
from typing import ForwardRef
from typing import Generic
+from typing import get_args
+from typing import get_origin
from typing import Iterable
+from typing import Literal
from typing import Mapping
from typing import NewType
from typing import NoReturn
from typing import Tuple
from typing import Type
from typing import TYPE_CHECKING
+from typing import TypeGuard
from typing import TypeVar
from typing import Union
from . import compat
if True: # zimports removes the tailing comments
- from typing_extensions import Annotated as Annotated # 3.9
- from typing_extensions import Concatenate as Concatenate # 3.10
from typing_extensions import (
dataclass_transform as dataclass_transform, # 3.11,
)
- from typing_extensions import get_args as get_args # 3.10
- from typing_extensions import get_origin as get_origin # 3.10
- from typing_extensions import (
- Literal as Literal,
- ) # 3.8 but has bugs before 3.10
from typing_extensions import NotRequired as NotRequired # 3.11
- from typing_extensions import ParamSpec as ParamSpec # 3.10
- from typing_extensions import TypeAlias as TypeAlias # 3.10
- from typing_extensions import TypeGuard as TypeGuard # 3.10
from typing_extensions import TypeVarTuple as TypeVarTuple # 3.11
from typing_extensions import Self as Self # 3.11
from typing_extensions import TypeAliasType as TypeAliasType # 3.12
TupleAny = Tuple[Any, ...]
-if compat.py310:
- # why they took until py310 to put this in stdlib is beyond me,
- # I've been wanting it since py27
- from types import NoneType as NoneType
-else:
- NoneType = type(None) # type: ignore
-
-
def is_fwd_none(typ: Any) -> bool:
return isinstance(typ, ForwardRef) and typ.__forward_arg__ == "None"
def is_newtype(type_: Optional[_AnnotationScanType]) -> TypeGuard[NewType]:
- return hasattr(type_, "__supertype__")
- # doesn't work in 3.9, 3.8, 3.7 as it passes a closure, not an
- # object instance
- # isinstance(type, type_instances.NewType)
+ return isinstance(type_, _type_tuples.NewType)
def is_generic(type_: _AnnotationScanType) -> TypeGuard[GenericProtocol[Any]]:
if origin is None:
return False
- return _get_type_name(origin) in names and (
+ return origin.__name__ in names and (
module is None or origin.__module__.startswith(module)
)
-def _get_type_name(type_: Type[Any]) -> str:
- if compat.py310:
- return type_.__name__
- else:
- typ_name = getattr(type_, "__name__", None)
- if typ_name is None:
- typ_name = getattr(type_, "_name", None)
-
- return typ_name # type: ignore
-
-
class DescriptorProto(Protocol):
def __get__(self, instance: object, owner: Any) -> Any: ...
"Operating System :: OS Independent",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
- "Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: Implementation :: PyPy",
"Topic :: Database :: Front-Ends",
]
-requires-python = ">=3.9"
+requires-python = ">=3.10"
dependencies = [
"typing-extensions >= 4.6.0",
]
[tool.black]
line-length = 79
-target-version = ['py39']
+target-version = ['py310']
[tool.zimports]
class DocTest(fixtures.TestBase):
- __requires__ = ("python310", "insert_returning", "insertmanyvalues")
+ __requires__ = ("insert_returning", "insertmanyvalues")
__only_on__ = "sqlite+pysqlite"
def _setup_logger(self):
from sqlalchemy.testing import requires
from sqlalchemy.testing.assertions import eq_
from sqlalchemy.testing.assertions import is_
-from sqlalchemy.util import py310
from sqlalchemy.util import py312
from sqlalchemy.util import py314
from sqlalchemy.util import typing as sa_typing
def union_types():
- res = [typing.Union[int, str]]
- if py310:
- res.append(int | str)
+ res = [typing.Union[int, str], int | str]
return res
typing.Optional[typing.Union[int, str]],
typing.Union[int, str, None],
typing.Union[int, str, "None"],
+ int | str | None,
+ typing.Optional[int | str],
+ typing.Union[int, str] | None,
+ typing.Optional[int] | str,
]
- if py310:
- res.append(int | str | None)
- res.append(typing.Optional[int | str])
- res.append(typing.Union[int, str] | None)
- res.append(typing.Optional[int] | str)
return res
def generic_unions():
res = union_types() + null_union_types()
- if py310 and not py314:
+ if not py314:
# for py310 through py313, remove new-style unions `int | str` that
# are not generic
new_ut = type(int | str)
return [NT_str, NT_null, NT_union]
-A_str = typing_extensions.Annotated[str, "meta"]
-A_null_str = typing_extensions.Annotated[
- typing.Union[str, None], "other_meta", "null"
-]
-A_union = typing_extensions.Annotated[typing.Union[str, int], "other_meta"]
-A_null_union = typing_extensions.Annotated[
+A_str = typing.Annotated[str, "meta"]
+A_null_str = typing.Annotated[typing.Union[str, None], "other_meta", "null"]
+A_union = typing.Annotated[typing.Union[str, int], "other_meta"]
+A_null_union = typing.Annotated[
typing.Union[str, int, None], "other_meta", "null"
]
eq_(sa_typing.is_pep593(str), False)
eq_(sa_typing.is_pep593(None), False)
eq_(sa_typing.is_pep593(typing_extensions.Annotated[int, "a"]), True)
- if py310:
- eq_(sa_typing.is_pep593(typing.Annotated[int, "a"]), True)
+ eq_(sa_typing.is_pep593(typing.Annotated[int, "a"]), True)
for t in annotated_l():
eq_(sa_typing.is_pep593(t), True)
with expect_raises(exc.TimeoutError):
await engine.connect()
- @testing.requires.python310
@async_test
async def test_engine_aclose(self, async_engine):
users = self.tables.users
result = await async_session.scalar(stmt)
eq_(result, 7)
- @testing.requires.python310
@async_test
async def test_session_aclose(self, async_session):
User = self.classes.User
{},
{"repr": False},
{"repr": True},
- ({"kw_only": True}, testing.requires.python310),
+ {"kw_only": True},
{"init": False},
{"default_factory": True},
argnames="field_kw",
import functools
import inspect as pyinspect
from itertools import product
+from typing import Annotated
from typing import Any
from typing import ClassVar
from typing import Dict
from typing import TypeVar
from unittest import mock
-from typing_extensions import Annotated
-
from sqlalchemy import BigInteger
from sqlalchemy import Column
from sqlalchemy import exc
from sqlalchemy.testing import is_true
from sqlalchemy.testing import ne_
from sqlalchemy.testing import Variation
-from sqlalchemy.util import compat
def _dataclass_mixin_warning(clsname, attrnames):
a2 = A(id=1, data="foo")
eq_(a1, a2)
- @testing.requires.python310
def test_kw_only_attribute(self, dc_decl_base: Type[MappedAsDataclass]):
class A(dc_decl_base):
__tablename__ = "a"
a.data = "y"
ne_(hash(a), a_hash1)
- @testing.requires.python310
def test_kw_only_dataclass_constant(
self, dc_decl_base: Type[MappedAsDataclass]
):
class DataclassArgsTest(fixtures.TestBase):
- dc_arg_names = ("init", "repr", "eq", "order", "unsafe_hash")
- if compat.py310:
- dc_arg_names += ("match_args", "kw_only")
+ dc_arg_names = (
+ "init",
+ "repr",
+ "eq",
+ "order",
+ "unsafe_hash",
+ "match_args",
+ "kw_only",
+ )
@testing.fixture(params=product(dc_arg_names, (True, False)))
def dc_argument_fixture(self, request: Any, registry: _RegistryType):
"eq": True,
"order": False,
"unsafe_hash": False,
+ "match_args": True,
+ "kw_only": False,
}
- if compat.py310:
- default |= {"match_args": True, "kw_only": False}
to_apply = {k: v for k, v in args.items() if v}
effective = {**default, **to_apply}
return to_apply, effective
"eq": True,
"order": True,
"unsafe_hash": False,
+ "match_args": True,
+ "kw_only": False,
}
- if compat.py310:
- effective |= {"match_args": True, "kw_only": False}
self._assert_cls(A, effective)
def test_dc_base_unsupported_argument(self, registry: _RegistryType):
import functools
import inspect as pyinspect
from itertools import product
+from typing import Annotated
from typing import Any
from typing import ClassVar
from typing import Dict
from typing import TypeVar
from unittest import mock
-from typing_extensions import Annotated
-
from sqlalchemy import BigInteger
from sqlalchemy import Column
from sqlalchemy import exc
from sqlalchemy.testing import is_true
from sqlalchemy.testing import ne_
from sqlalchemy.testing import Variation
-from sqlalchemy.util import compat
def _dataclass_mixin_warning(clsname, attrnames):
a2 = A(id=1, data="foo")
eq_(a1, a2)
- @testing.requires.python310
def test_kw_only_attribute(self, dc_decl_base: Type[MappedAsDataclass]):
class A(dc_decl_base):
__tablename__ = "a"
a.data = "y"
ne_(hash(a), a_hash1)
- @testing.requires.python310
def test_kw_only_dataclass_constant(
self, dc_decl_base: Type[MappedAsDataclass]
):
class DataclassArgsTest(fixtures.TestBase):
- dc_arg_names = ("init", "repr", "eq", "order", "unsafe_hash")
- if compat.py310:
- dc_arg_names += ("match_args", "kw_only")
+ dc_arg_names = (
+ "init",
+ "repr",
+ "eq",
+ "order",
+ "unsafe_hash",
+ "match_args",
+ "kw_only",
+ )
@testing.fixture(params=product(dc_arg_names, (True, False)))
def dc_argument_fixture(self, request: Any, registry: _RegistryType):
"eq": True,
"order": False,
"unsafe_hash": False,
+ "match_args": True,
+ "kw_only": False,
}
- if compat.py310:
- default |= {"match_args": True, "kw_only": False}
to_apply = {k: v for k, v in args.items() if v}
effective = {**default, **to_apply}
return to_apply, effective
"eq": True,
"order": True,
"unsafe_hash": False,
+ "match_args": True,
+ "kw_only": False,
}
- if compat.py310:
- effective |= {"match_args": True, "kw_only": False}
self._assert_cls(A, effective)
def test_dc_base_unsupported_argument(self, registry: _RegistryType):
from operator import is_not
-
-from typing_extensions import Annotated
+from typing import Annotated
import sqlalchemy as sa
from sqlalchemy import ForeignKey
import inspect as _py_inspect
import re
import typing
+from typing import Annotated
from typing import Any
from typing import cast
from typing import ClassVar
from typing import Dict
from typing import Generic
+from typing import get_args as get_args
from typing import List
+from typing import Literal as Literal
from typing import NewType
from typing import Optional
from typing import Set
from typing import Type
from typing import TYPE_CHECKING
+from typing import TypeAlias as TypeAlias
from typing import TypedDict
from typing import TypeVar
from typing import Union
import uuid
import typing_extensions
-from typing_extensions import get_args as get_args
-from typing_extensions import Literal as Literal
-from typing_extensions import TypeAlias as TypeAlias
from typing_extensions import TypeAliasType
from sqlalchemy import BIGINT
from sqlalchemy.testing import Variation
from sqlalchemy.testing.assertions import ne_
from sqlalchemy.testing.fixtures import fixture_session
-from sqlalchemy.util import compat
-from sqlalchemy.util.typing import Annotated
TV = typing.TypeVar("TV")
_JsonObject: TypeAlias = Dict[str, "_Json"]
_JsonArray: TypeAlias = List["_Json"]
_Json: TypeAlias = Union[_JsonObject, _JsonArray, _JsonPrimitive]
+_JsonPrimitivePep604: TypeAlias = str | int | float | bool | None
+_JsonObjectPep604: TypeAlias = dict[str, "_JsonPep604"]
+_JsonArrayPep604: TypeAlias = list["_JsonPep604"]
+_JsonPep604: TypeAlias = (
+ _JsonObjectPep604 | _JsonArrayPep604 | _JsonPrimitivePep604
+)
+_JsonPep695 = TypeAliasType("_JsonPep695", _JsonPep604)
-if compat.py310:
- _JsonPrimitivePep604: TypeAlias = str | int | float | bool | None
- _JsonObjectPep604: TypeAlias = dict[str, "_JsonPep604"]
- _JsonArrayPep604: TypeAlias = list["_JsonPep604"]
- _JsonPep604: TypeAlias = (
- _JsonObjectPep604 | _JsonArrayPep604 | _JsonPrimitivePep604
- )
- _JsonPep695 = TypeAliasType("_JsonPep695", _JsonPep604)
TypingTypeAliasType = getattr(typing, "TypeAliasType", TypeAliasType)
strtypalias_keyword = TypeAliasType(
"strtypalias_keyword", Annotated[str, mapped_column(info={"hi": "there"})]
)
-if compat.py310:
- strtypalias_keyword_nested = TypeAliasType(
- "strtypalias_keyword_nested",
- int | Annotated[str, mapped_column(info={"hi": "there"})],
- )
+strtypalias_keyword_nested = TypeAliasType(
+ "strtypalias_keyword_nested",
+ int | Annotated[str, mapped_column(info={"hi": "there"})],
+)
strtypalias_ta: TypeAlias = Annotated[str, mapped_column(info={"hi": "there"})]
strtypalias_plain = Annotated[str, mapped_column(info={"hi": "there"})]
_Literal695 = TypeAliasType(
"argtype",
[
"type",
- ("column", testing.requires.python310),
- ("mapped_column", testing.requires.python310),
+ "column",
+ "mapped_column",
"column_class",
"ref_to_type",
- ("ref_to_column", testing.requires.python310),
+ "ref_to_column",
],
)
def test_construct_lhs_sqlalchemy_type(self, decl_base, argtype):
eq_(col.type.enums, ["a", "b"])
is_(col.type.native_enum, False)
- @testing.requires.python310
def test_we_got_all_attrs_test_annotated(self):
argnames = _py_inspect.getfullargspec(mapped_column)
assert _annotated_names_tested.issuperset(argnames.kwonlyargs), (
exc.SADeprecationWarning(
"Argument 'kw_only' is a dataclass argument "
),
- testing.requires.python310,
),
(
"compare",
exc.SADeprecationWarning(
"Argument 'compare' is a dataclass argument "
),
- testing.requires.python310,
),
(
"default_factory",
str50 = NewType("str50", str)
- if compat.py310:
- text = ".*str50"
- else:
- # NewTypes before 3.10 had a very bad repr
- # <function NewType.<locals>.new_type at 0x...>
- text = ".*NewType.*"
-
with expect_raises_message(
orm_exc.MappedAnnotationError,
"Could not locate SQLAlchemy Core type for Python type "
- f"{text} inside the 'data_one' attribute Mapped annotation",
+ ".*str50 inside the 'data_one' attribute Mapped annotation",
):
class MyClass(decl_base):
to_assert.fail()
@testing.combinations(
- (collections.abc.Sequence, (str,), testing.requires.python310),
- (collections.abc.MutableSequence, (str,), testing.requires.python310),
- (collections.abc.Mapping, (str, str), testing.requires.python310),
- (
- collections.abc.MutableMapping,
- (str, str),
- testing.requires.python310,
- ),
- (typing.Mapping, (str, str), testing.requires.python310),
- (typing.MutableMapping, (str, str), testing.requires.python310),
+ (collections.abc.Sequence, (str,)),
+ (collections.abc.MutableSequence, (str,)),
+ (collections.abc.Mapping, (str, str)),
+ (collections.abc.MutableMapping, (str, str)),
+ (typing.Mapping, (str, str)),
+ (typing.MutableMapping, (str, str)),
(typing.Sequence, (str,)),
(typing.MutableSequence, (str,)),
- (list, (str,), testing.requires.python310),
- (
- List,
- (str,),
- ),
- (dict, (str, str), testing.requires.python310),
- (
- Dict,
- (str, str),
- ),
- (list, None, testing.requires.python310),
- (
- List,
- None,
- ),
- (dict, None, testing.requires.python310),
- (
- Dict,
- None,
- ),
+ (list, (str,)),
+ (List, (str,)),
+ (dict, (str, str)),
+ (Dict, (str, str)),
+ (list, None),
+ (List, None),
+ (dict, None),
+ (Dict, None),
id_="sa",
argnames="container_typ,args",
)
@testing.variation(
"union",
- [
- "union",
- ("pep604", requires.python310),
- "union_null",
- ("pep604_null", requires.python310),
- ],
+ ["union", "pep604", "union_null", "pep604_null"],
)
def test_unions(self, union):
global UnionType
float_data: Mapped[float] = mapped_column()
decimal_data: Mapped[Decimal] = mapped_column()
- if compat.py310:
- pep604_data: Mapped[float | Decimal] = mapped_column()
- pep604_reverse: Mapped[Decimal | float] = mapped_column()
- pep604_optional: Mapped[Decimal | float | None] = (
- mapped_column()
- )
- pep604_data_fwd: Mapped["float | Decimal"] = mapped_column()
- pep604_reverse_fwd: Mapped["Decimal | float"] = mapped_column()
- pep604_optional_fwd: Mapped["Decimal | float | None"] = (
- mapped_column()
- )
+ pep604_data: Mapped[float | Decimal] = mapped_column()
+ pep604_reverse: Mapped[Decimal | float] = mapped_column()
+ pep604_optional: Mapped[Decimal | float | None] = mapped_column()
+ pep604_data_fwd: Mapped["float | Decimal"] = mapped_column()
+ pep604_reverse_fwd: Mapped["Decimal | float"] = mapped_column()
+ pep604_optional_fwd: Mapped["Decimal | float | None"] = (
+ mapped_column()
+ )
info = [
("data", False),
("refer_union", "null" in union.name),
("refer_union_optional", True),
("unflat_union_optional_data", True),
+ ("pep604_data", False),
+ ("pep604_reverse", False),
+ ("pep604_optional", True),
+ ("pep604_data_fwd", False),
+ ("pep604_reverse_fwd", False),
+ ("pep604_optional_fwd", True),
]
- if compat.py310:
- info += [
- ("pep604_data", False),
- ("pep604_reverse", False),
- ("pep604_optional", True),
- ("pep604_data_fwd", False),
- ("pep604_reverse_fwd", False),
- ("pep604_optional_fwd", True),
- ]
for name, nullable in info:
col = User.__table__.c[name]
"union",
[
"union",
- ("pep604", requires.python310),
+ "pep604",
("pep695", requires.python312),
],
)
"optional",
"optional_fwd_ref",
"union_none",
- ("pep604", testing.requires.python310),
- ("pep604_fwd_ref", testing.requires.python310),
+ "pep604",
+ "pep604_fwd_ref",
],
)
@testing.variation("brackets", ["oneset", "twosets"])
#12207"""
class Base(DeclarativeBase):
- if testing.requires.python310.enabled:
- type_annotation_map = {
- Dict[str, Decimal]: JSON,
- dict[str, Decimal]: JSON,
- Union[List[int], List[str]]: JSON,
- list[int] | list[str]: JSON,
- }
- else:
- type_annotation_map = {
- Dict[str, Decimal]: JSON,
- Union[List[int], List[str]]: JSON,
- }
+ type_annotation_map = {
+ Dict[str, Decimal]: JSON,
+ dict[str, Decimal]: JSON,
+ Union[List[int], List[str]]: JSON,
+ list[int] | list[str]: JSON,
+ }
if include_mc_type == "include_mc_type":
mc = mapped_column(JSON)
if brackets.oneset:
if option.not_optional:
json: Mapped[Dict[str, Decimal]] = mapped_column() # type: ignore # noqa: E501
- if testing.requires.python310.enabled:
- json2: Mapped[dict[str, Decimal]] = mapped_column() # type: ignore # noqa: E501
+ json2: Mapped[dict[str, Decimal]] = mapped_column() # type: ignore # noqa: E501
elif option.optional:
json: Mapped[Optional[Dict[str, Decimal]]] = mc
- if testing.requires.python310.enabled:
- json2: Mapped[Optional[dict[str, Decimal]]] = mc2
+ json2: Mapped[Optional[dict[str, Decimal]]] = mc2
elif option.optional_fwd_ref:
json: Mapped["Optional[Dict[str, Decimal]]"] = mc
- if testing.requires.python310.enabled:
- json2: Mapped["Optional[dict[str, Decimal]]"] = mc2
+ json2: Mapped["Optional[dict[str, Decimal]]"] = mc2
elif option.union_none:
json: Mapped[Union[Dict[str, Decimal], None]] = mc
json2: Mapped[Union[None, Dict[str, Decimal]]] = mc2
elif option.pep604:
json: Mapped[dict[str, Decimal] | None] = mc
- if testing.requires.python310.enabled:
- json2: Mapped[None | dict[str, Decimal]] = mc2
+ json2: Mapped[None | dict[str, Decimal]] = mc2
elif option.pep604_fwd_ref:
json: Mapped["dict[str, Decimal] | None"] = mc
- if testing.requires.python310.enabled:
- json2: Mapped["None | dict[str, Decimal]"] = mc2
+ json2: Mapped["None | dict[str, Decimal]"] = mc2
elif brackets.twosets:
if option.not_optional:
json: Mapped[Union[List[int], List[str]]] = mapped_column() # type: ignore # noqa: E501
elif option.optional:
json: Mapped[Optional[Union[List[int], List[str]]]] = mc
- if testing.requires.python310.enabled:
- json2: Mapped[
- Optional[Union[list[int], list[str]]]
- ] = mc2
+ json2: Mapped[Optional[Union[list[int], list[str]]]] = mc2
elif option.optional_fwd_ref:
json: Mapped["Optional[Union[List[int], List[str]]]"] = mc
- if testing.requires.python310.enabled:
- json2: Mapped[
- "Optional[Union[list[int], list[str]]]"
- ] = mc2
+ json2: Mapped["Optional[Union[list[int], list[str]]]"] = (
+ mc2
+ )
elif option.union_none:
json: Mapped[Union[List[int], List[str], None]] = mc
- if testing.requires.python310.enabled:
- json2: Mapped[Union[None, list[int], list[str]]] = mc2
+ json2: Mapped[Union[None, list[int], list[str]]] = mc2
elif option.pep604:
json: Mapped[list[int] | list[str] | None] = mc
json2: Mapped[None | list[int] | list[str]] = mc2
id: Mapped[int] = mapped_column(primary_key=True)
data: Mapped[int_sub]
- @testing.variation(
- "dict_key", ["typing", ("plain", testing.requires.python310)]
- )
+ @testing.variation("dict_key", ["typing", "plain"])
def test_type_dont_mis_resolve_on_non_generic(self, dict_key):
"""test for #8859.
"datatype",
[
"typing_sequence",
- ("collections_sequence", testing.requires.python310),
+ "collections_sequence",
"typing_mutable_sequence",
- ("collections_mutable_sequence", testing.requires.python310),
+ "collections_mutable_sequence",
],
)
@testing.variation("include_explicit", [True, False])
@testing.variation(
"collection_type",
- [
- ("list", testing.requires.python310),
- "List",
- ("set", testing.requires.python310),
- "Set",
- ],
+ ["list", "List", "set", "Set"],
)
def test_14_style_anno_accepted_w_allow_unmapped(self, collection_type):
"""test for #8692 and #10385"""
("optional",),
("optional_fwd_ref",),
("union_none",),
- ("pep604", testing.requires.python310),
+ ("pep604",),
argnames="optional_on_m2o",
)
def test_basic_bidirectional(self, decl_base, optional_on_m2o):
import inspect as _py_inspect
import re
import typing
+from typing import Annotated
from typing import Any
from typing import cast
from typing import ClassVar
from typing import Dict
from typing import Generic
+from typing import get_args as get_args
from typing import List
+from typing import Literal as Literal
from typing import NewType
from typing import Optional
from typing import Set
from typing import Type
from typing import TYPE_CHECKING
+from typing import TypeAlias as TypeAlias
from typing import TypedDict
from typing import TypeVar
from typing import Union
import uuid
import typing_extensions
-from typing_extensions import get_args as get_args
-from typing_extensions import Literal as Literal
-from typing_extensions import TypeAlias as TypeAlias
from typing_extensions import TypeAliasType
from sqlalchemy import BIGINT
from sqlalchemy.testing import Variation
from sqlalchemy.testing.assertions import ne_
from sqlalchemy.testing.fixtures import fixture_session
-from sqlalchemy.util import compat
-from sqlalchemy.util.typing import Annotated
TV = typing.TypeVar("TV")
_JsonObject: TypeAlias = Dict[str, "_Json"]
_JsonArray: TypeAlias = List["_Json"]
_Json: TypeAlias = Union[_JsonObject, _JsonArray, _JsonPrimitive]
+_JsonPrimitivePep604: TypeAlias = str | int | float | bool | None
+_JsonObjectPep604: TypeAlias = dict[str, "_JsonPep604"]
+_JsonArrayPep604: TypeAlias = list["_JsonPep604"]
+_JsonPep604: TypeAlias = (
+ _JsonObjectPep604 | _JsonArrayPep604 | _JsonPrimitivePep604
+)
+_JsonPep695 = TypeAliasType("_JsonPep695", _JsonPep604)
-if compat.py310:
- _JsonPrimitivePep604: TypeAlias = str | int | float | bool | None
- _JsonObjectPep604: TypeAlias = dict[str, "_JsonPep604"]
- _JsonArrayPep604: TypeAlias = list["_JsonPep604"]
- _JsonPep604: TypeAlias = (
- _JsonObjectPep604 | _JsonArrayPep604 | _JsonPrimitivePep604
- )
- _JsonPep695 = TypeAliasType("_JsonPep695", _JsonPep604)
TypingTypeAliasType = getattr(typing, "TypeAliasType", TypeAliasType)
strtypalias_keyword = TypeAliasType(
"strtypalias_keyword", Annotated[str, mapped_column(info={"hi": "there"})]
)
-if compat.py310:
- strtypalias_keyword_nested = TypeAliasType(
- "strtypalias_keyword_nested",
- int | Annotated[str, mapped_column(info={"hi": "there"})],
- )
+strtypalias_keyword_nested = TypeAliasType(
+ "strtypalias_keyword_nested",
+ int | Annotated[str, mapped_column(info={"hi": "there"})],
+)
strtypalias_ta: TypeAlias = Annotated[str, mapped_column(info={"hi": "there"})]
strtypalias_plain = Annotated[str, mapped_column(info={"hi": "there"})]
_Literal695 = TypeAliasType(
"argtype",
[
"type",
- ("column", testing.requires.python310),
- ("mapped_column", testing.requires.python310),
+ "column",
+ "mapped_column",
"column_class",
"ref_to_type",
- ("ref_to_column", testing.requires.python310),
+ "ref_to_column",
],
)
def test_construct_lhs_sqlalchemy_type(self, decl_base, argtype):
eq_(col.type.enums, ["a", "b"])
is_(col.type.native_enum, False)
- @testing.requires.python310
def test_we_got_all_attrs_test_annotated(self):
argnames = _py_inspect.getfullargspec(mapped_column)
assert _annotated_names_tested.issuperset(argnames.kwonlyargs), (
exc.SADeprecationWarning(
"Argument 'kw_only' is a dataclass argument "
),
- testing.requires.python310,
),
(
"compare",
exc.SADeprecationWarning(
"Argument 'compare' is a dataclass argument "
),
- testing.requires.python310,
),
(
"default_factory",
str50 = NewType("str50", str)
- if compat.py310:
- text = ".*str50"
- else:
- # NewTypes before 3.10 had a very bad repr
- # <function NewType.<locals>.new_type at 0x...>
- text = ".*NewType.*"
-
with expect_raises_message(
orm_exc.MappedAnnotationError,
"Could not locate SQLAlchemy Core type for Python type "
- f"{text} inside the 'data_one' attribute Mapped annotation",
+ ".*str50 inside the 'data_one' attribute Mapped annotation",
):
class MyClass(decl_base):
to_assert.fail()
@testing.combinations(
- (collections.abc.Sequence, (str,), testing.requires.python310),
- (collections.abc.MutableSequence, (str,), testing.requires.python310),
- (collections.abc.Mapping, (str, str), testing.requires.python310),
- (
- collections.abc.MutableMapping,
- (str, str),
- testing.requires.python310,
- ),
- (typing.Mapping, (str, str), testing.requires.python310),
- (typing.MutableMapping, (str, str), testing.requires.python310),
+ (collections.abc.Sequence, (str,)),
+ (collections.abc.MutableSequence, (str,)),
+ (collections.abc.Mapping, (str, str)),
+ (collections.abc.MutableMapping, (str, str)),
+ (typing.Mapping, (str, str)),
+ (typing.MutableMapping, (str, str)),
(typing.Sequence, (str,)),
(typing.MutableSequence, (str,)),
- (list, (str,), testing.requires.python310),
- (
- List,
- (str,),
- ),
- (dict, (str, str), testing.requires.python310),
- (
- Dict,
- (str, str),
- ),
- (list, None, testing.requires.python310),
- (
- List,
- None,
- ),
- (dict, None, testing.requires.python310),
- (
- Dict,
- None,
- ),
+ (list, (str,)),
+ (List, (str,)),
+ (dict, (str, str)),
+ (Dict, (str, str)),
+ (list, None),
+ (List, None),
+ (dict, None),
+ (Dict, None),
id_="sa",
argnames="container_typ,args",
)
@testing.variation(
"union",
- [
- "union",
- ("pep604", requires.python310),
- "union_null",
- ("pep604_null", requires.python310),
- ],
+ ["union", "pep604", "union_null", "pep604_null"],
)
def test_unions(self, union):
# anno only: global UnionType
float_data: Mapped[float] = mapped_column()
decimal_data: Mapped[Decimal] = mapped_column()
- if compat.py310:
- pep604_data: Mapped[float | Decimal] = mapped_column()
- pep604_reverse: Mapped[Decimal | float] = mapped_column()
- pep604_optional: Mapped[Decimal | float | None] = (
- mapped_column()
- )
- pep604_data_fwd: Mapped["float | Decimal"] = mapped_column()
- pep604_reverse_fwd: Mapped["Decimal | float"] = mapped_column()
- pep604_optional_fwd: Mapped["Decimal | float | None"] = (
- mapped_column()
- )
+ pep604_data: Mapped[float | Decimal] = mapped_column()
+ pep604_reverse: Mapped[Decimal | float] = mapped_column()
+ pep604_optional: Mapped[Decimal | float | None] = mapped_column()
+ pep604_data_fwd: Mapped["float | Decimal"] = mapped_column()
+ pep604_reverse_fwd: Mapped["Decimal | float"] = mapped_column()
+ pep604_optional_fwd: Mapped["Decimal | float | None"] = (
+ mapped_column()
+ )
info = [
("data", False),
("refer_union", "null" in union.name),
("refer_union_optional", True),
("unflat_union_optional_data", True),
+ ("pep604_data", False),
+ ("pep604_reverse", False),
+ ("pep604_optional", True),
+ ("pep604_data_fwd", False),
+ ("pep604_reverse_fwd", False),
+ ("pep604_optional_fwd", True),
]
- if compat.py310:
- info += [
- ("pep604_data", False),
- ("pep604_reverse", False),
- ("pep604_optional", True),
- ("pep604_data_fwd", False),
- ("pep604_reverse_fwd", False),
- ("pep604_optional_fwd", True),
- ]
for name, nullable in info:
col = User.__table__.c[name]
"union",
[
"union",
- ("pep604", requires.python310),
+ "pep604",
("pep695", requires.python312),
],
)
"optional",
"optional_fwd_ref",
"union_none",
- ("pep604", testing.requires.python310),
- ("pep604_fwd_ref", testing.requires.python310),
+ "pep604",
+ "pep604_fwd_ref",
],
)
@testing.variation("brackets", ["oneset", "twosets"])
#12207"""
class Base(DeclarativeBase):
- if testing.requires.python310.enabled:
- type_annotation_map = {
- Dict[str, Decimal]: JSON,
- dict[str, Decimal]: JSON,
- Union[List[int], List[str]]: JSON,
- list[int] | list[str]: JSON,
- }
- else:
- type_annotation_map = {
- Dict[str, Decimal]: JSON,
- Union[List[int], List[str]]: JSON,
- }
+ type_annotation_map = {
+ Dict[str, Decimal]: JSON,
+ dict[str, Decimal]: JSON,
+ Union[List[int], List[str]]: JSON,
+ list[int] | list[str]: JSON,
+ }
if include_mc_type == "include_mc_type":
mc = mapped_column(JSON)
if brackets.oneset:
if option.not_optional:
json: Mapped[Dict[str, Decimal]] = mapped_column() # type: ignore # noqa: E501
- if testing.requires.python310.enabled:
- json2: Mapped[dict[str, Decimal]] = mapped_column() # type: ignore # noqa: E501
+ json2: Mapped[dict[str, Decimal]] = mapped_column() # type: ignore # noqa: E501
elif option.optional:
json: Mapped[Optional[Dict[str, Decimal]]] = mc
- if testing.requires.python310.enabled:
- json2: Mapped[Optional[dict[str, Decimal]]] = mc2
+ json2: Mapped[Optional[dict[str, Decimal]]] = mc2
elif option.optional_fwd_ref:
json: Mapped["Optional[Dict[str, Decimal]]"] = mc
- if testing.requires.python310.enabled:
- json2: Mapped["Optional[dict[str, Decimal]]"] = mc2
+ json2: Mapped["Optional[dict[str, Decimal]]"] = mc2
elif option.union_none:
json: Mapped[Union[Dict[str, Decimal], None]] = mc
json2: Mapped[Union[None, Dict[str, Decimal]]] = mc2
elif option.pep604:
json: Mapped[dict[str, Decimal] | None] = mc
- if testing.requires.python310.enabled:
- json2: Mapped[None | dict[str, Decimal]] = mc2
+ json2: Mapped[None | dict[str, Decimal]] = mc2
elif option.pep604_fwd_ref:
json: Mapped["dict[str, Decimal] | None"] = mc
- if testing.requires.python310.enabled:
- json2: Mapped["None | dict[str, Decimal]"] = mc2
+ json2: Mapped["None | dict[str, Decimal]"] = mc2
elif brackets.twosets:
if option.not_optional:
json: Mapped[Union[List[int], List[str]]] = mapped_column() # type: ignore # noqa: E501
elif option.optional:
json: Mapped[Optional[Union[List[int], List[str]]]] = mc
- if testing.requires.python310.enabled:
- json2: Mapped[
- Optional[Union[list[int], list[str]]]
- ] = mc2
+ json2: Mapped[Optional[Union[list[int], list[str]]]] = mc2
elif option.optional_fwd_ref:
json: Mapped["Optional[Union[List[int], List[str]]]"] = mc
- if testing.requires.python310.enabled:
- json2: Mapped[
- "Optional[Union[list[int], list[str]]]"
- ] = mc2
+ json2: Mapped["Optional[Union[list[int], list[str]]]"] = (
+ mc2
+ )
elif option.union_none:
json: Mapped[Union[List[int], List[str], None]] = mc
- if testing.requires.python310.enabled:
- json2: Mapped[Union[None, list[int], list[str]]] = mc2
+ json2: Mapped[Union[None, list[int], list[str]]] = mc2
elif option.pep604:
json: Mapped[list[int] | list[str] | None] = mc
json2: Mapped[None | list[int] | list[str]] = mc2
id: Mapped[int] = mapped_column(primary_key=True)
data: Mapped[int_sub]
- @testing.variation(
- "dict_key", ["typing", ("plain", testing.requires.python310)]
- )
+ @testing.variation("dict_key", ["typing", "plain"])
def test_type_dont_mis_resolve_on_non_generic(self, dict_key):
"""test for #8859.
"datatype",
[
"typing_sequence",
- ("collections_sequence", testing.requires.python310),
+ "collections_sequence",
"typing_mutable_sequence",
- ("collections_mutable_sequence", testing.requires.python310),
+ "collections_mutable_sequence",
],
)
@testing.variation("include_explicit", [True, False])
@testing.variation(
"collection_type",
- [
- ("list", testing.requires.python310),
- "List",
- ("set", testing.requires.python310),
- "Set",
- ],
+ ["list", "List", "set", "Set"],
)
def test_14_style_anno_accepted_w_allow_unmapped(self, collection_type):
"""test for #8692 and #10385"""
("optional",),
("optional_fwd_ref",),
("union_none",),
- ("pep604", testing.requires.python310),
+ ("pep604",),
argnames="optional_on_m2o",
)
def test_basic_bidirectional(self, decl_base, optional_on_m2o):
testing.skip_test("python platform not available")
elif util.py311:
int_within_variance(39996, total_size(ck), 0.05)
- elif util.py310:
- int_within_variance(29796, total_size(ck), 0.05)
else:
- testing.skip_test("python platform not available")
+ int_within_variance(29796, total_size(ck), 0.05)
class WithExpresionLoaderOptTest(DeclarativeMappedTest):
@testing.combinations(
("init", True),
- ("kw_only", True, testing.requires.python310),
+ ("kw_only", True),
("default", 5),
("default_factory", lambda: 10),
argnames="paramname, value",
):
column_property(column("q"), **{paramname: value})
- @testing.requires.python310
def test_column_property_dc_attributes_still_function(self, dc_decl_base):
with expect_deprecated(
r"The column_property.init parameter is deprecated "