pytest-args: "-k 'not test_autocommit_on and not test_turn_autocommit_off_via_default_iso_level and not test_autocommit_isolation_level'"
- os: "ubuntu-latest"
pytest-args: "--dbdriver pysqlite --dbdriver aiosqlite"
- # do not run aiosqlite on python 3.11
- # wait for https://github.com/python/cpython/issues/99205 to be fixed
- - os: "ubuntu-latest"
- python-version: "3.11"
- pytest-args: "--dbdriver pysqlite"
-
exclude:
# linux and osx do not have x86 python
--- /dev/null
+.. change::
+ :tags: installation
+
+ Compatibility improvements to work fully with Python 3.12
Column(
"changed",
DateTime,
- default=datetime.datetime.utcnow,
+ default=lambda: datetime.datetime.now(datetime.timezone.utc),
info=version_meta,
)
)
# tell if we get the same exception back
value = typ()
try:
- await self.gen.athrow(typ, value, traceback)
+ await util.athrow(self.gen, typ, value, traceback)
except StopAsyncIteration as exc:
# Suppress StopIteration *unless* it's the same exception that
# was passed to throw(). This prevents a StopIteration
"""
impl = DateTime
- epoch = dt.datetime.utcfromtimestamp(0)
+ epoch = dt.datetime.fromtimestamp(0, dt.timezone.utc).replace(tzinfo=None)
cache_ok = True
def __init__(
from ._collections import WeakSequence as WeakSequence
from .compat import anext_ as anext_
from .compat import arm as arm
+from .compat import athrow as athrow
from .compat import b as b
from .compat import b64decode as b64decode
from .compat import b64encode as b64encode
import sys
import typing
from typing import Any
+from typing import AsyncGenerator
+from typing import Awaitable
from typing import Callable
from typing import Dict
from typing import Iterable
from typing import Set
from typing import Tuple
from typing import Type
+from typing import TypeVar
py312 = sys.version_info >= (3, 12)
dottedgetter = operator.attrgetter
+_T_co = TypeVar("_T_co", covariant=True)
+
class FullArgSpec(typing.NamedTuple):
args: List[str]
)
+if py312:
+ # we are 95% certain this form of athrow works in former Python
+ # versions, however we are unable to get confirmation;
+ # see https://github.com/python/cpython/issues/105269 where have
+ # been unable to get a straight answer so far
+ def athrow( # noqa
+ gen: AsyncGenerator[_T_co, Any], typ: Any, value: Any, traceback: Any
+ ) -> Awaitable[_T_co]:
+ return gen.athrow(value)
+
+else:
+
+ def athrow( # noqa
+ gen: AsyncGenerator[_T_co, Any], typ: Any, value: Any, traceback: Any
+ ) -> Awaitable[_T_co]:
+ return gen.athrow(typ, value, traceback)
+
+
if typing.TYPE_CHECKING or py38:
from importlib import metadata as importlib_metadata
else:
# here as pytest loads them immediately, which breaks coverage as well
# as sys.path adjustments in conftest.py
"error::DeprecationWarning:test",
- "error::DeprecationWarning:sqlalchemy"
+ "error::DeprecationWarning:sqlalchemy",
+
+ # sqlite3 warnings due to test/dialect/test_sqlite.py->test_native_datetime,
+ # which is asserting that these deprecated-in-py312 handlers are functional
+ "ignore:The default (date)?(time)?(stamp)? (adapter|converter):DeprecationWarning",
]
markers = [
"memory_intensive: memory / CPU intensive suite tests",
from sqlalchemy.testing import fixtures
from sqlalchemy.testing import is_false
from sqlalchemy.testing import is_true
+from sqlalchemy.testing.assertions import expect_raises
from sqlalchemy.testing.util import picklers
+from sqlalchemy.util import compat
class ResultTupleTest(fixtures.TestBase):
def test_slices_arent_in_mappings(self):
keyed_tuple = self._fixture([1, 2], ["a", "b"])
- assert_raises(TypeError, lambda: keyed_tuple._mapping[0:2])
+ if compat.py312:
+ with expect_raises(KeyError):
+ keyed_tuple._mapping[0:2]
+ else:
+ with expect_raises(TypeError):
+ keyed_tuple._mapping[0:2]
def test_integers_arent_in_mappings(self):
keyed_tuple = self._fixture([1, 2], ["a", "b"])
assert canary.call_args_list[0][0][0] is dbapi_con
assert canary.call_args_list[0][0][2] is exc
- @testing.variation("is_asyncio", [True, False])
+ @testing.variation("is_asyncio", [(True, testing.requires.asyncio), False])
@testing.variation("has_terminate", [True, False])
def test_checkin_event_gc(self, is_asyncio, has_terminate):
"""tests for #8419, which have been modified for 2.0 in #9237"""
exc_cls=TimeoutThing if exc_type.base_exception else Exception,
)
- @testing.combinations((True,), (False,))
+ @testing.variation(
+ "detach_gced",
+ [("detached_gc", testing.requires.asyncio), "normal_gc"],
+ )
@testing.emits_warning("The garbage collector")
def test_userspace_disconnectionerror_weakref_finalizer(self, detach_gced):
dbapi, pool = self._queuepool_dbapi_fixture(
self.meta.drop_all(conn)
self.engine.dispose()
- @testing.fails_if(
- [
- "+mysqlconnector",
- "+mysqldb",
- "+cymysql",
- "+pymysql",
- "+pg8000",
- "+asyncpg",
- "+aiosqlite",
- "+aiomysql",
- "+asyncmy",
- "+psycopg",
- ],
- "Buffers the result set and doesn't check for connection close",
- )
def test_invalidate_on_results(self):
conn = self.engine.connect()
- result = conn.exec_driver_sql("select * from sometable")
+ result = conn.exec_driver_sql(
+ "select * from sometable",
+ )
for x in range(20):
result.fetchone()
+
+ real_cursor = result.cursor
self.engine.test_shutdown()
+
+ def produce_side_effect():
+ # will fail because connection was closed, with an exception
+ # that should trigger disconnect routines
+ real_cursor.execute("select * from sometable")
+
+ result.cursor = Mock(
+ fetchone=mock.Mock(side_effect=produce_side_effect)
+ )
try:
_assert_invalidated(result.fetchone)
assert conn.invalidated
sqlite_file: aiosqlite
sqlite_file: sqlcipher; python_version < '3.10'
postgresql: postgresql
- postgresql: postgresql_asyncpg
+ py3{,7,8,9,10,11}-postgresql: postgresql_asyncpg
postgresql: postgresql_pg8000
postgresql: postgresql_psycopg
mysql: pymysql
mysql: asyncmy
-# mysql: mariadb_connector
-
oracle: oracle
oracle: oracle_oracledb
- mssql: mssql
- mssql: mssql_pymssql
+ py3{,7,8,9,10,11}-mssql: mssql
+ py3{,7,8,9,10,11}-mssql: mssql_pymssql
+
deps=
pytest>=7.0.0rc1,<8
# tracked by https://github.com/pytest-dev/pytest-xdist/issues/907
pytest-xdist!=3.3.0
+ py312: git+https://github.com/mdboom/greenlet.git@python-312#egg=greenlet
+
dbapimain-sqlite: git+https://github.com/omnilib/aiosqlite.git#egg=aiosqlite
dbapimain-sqlite: git+https://github.com/coleifer/sqlcipher3.git#egg=sqlcipher3
PYTEST_COLOR={tty:--color=yes}
MYPY_COLOR={tty:--color-output}
- BASECOMMAND=python -m pytest {env:PYTEST_COLOR} --rootdir {toxinidir} --log-info=sqlalchemy.testing
+ # pytest 'rewrite' is hitting lots of deprecation warnings under py312 and
+ # i can't find any way to ignore those warnings, so this turns it off
+ py312: PYTEST_ARGS=--assert plain
+
+ BASECOMMAND=python -m pytest {env:PYTEST_ARGS} {env:PYTEST_COLOR} --rootdir {toxinidir} --log-info=sqlalchemy.testing
WORKERS={env:TOX_WORKERS:-n4 --max-worker-restart=5}
+
+
nocext: DISABLE_SQLALCHEMY_CEXT=1
cext: REQUIRE_SQLALCHEMY_CEXT=1
cov: COVERAGE={[testenv]cov_args}
py3{,10,11}-sqlite_file: EXTRA_SQLITE_DRIVERS={env:EXTRA_SQLITE_DRIVERS:--dbdriver sqlite --dbdriver aiosqlite}
postgresql: POSTGRESQL={env:TOX_POSTGRESQL:--db postgresql}
+
py3{,7,8,9,10,11}-postgresql: EXTRA_PG_DRIVERS={env:EXTRA_PG_DRIVERS:--dbdriver psycopg2 --dbdriver asyncpg --dbdriver pg8000 --dbdriver psycopg --dbdriver psycopg_async}
+ py312-postgresql: EXTRA_PG_DRIVERS={env:EXTRA_PG_DRIVERS:--dbdriver psycopg2 --dbdriver pg8000 --dbdriver psycopg --dbdriver psycopg_async}
mysql: MYSQL={env:TOX_MYSQL:--db mysql}
py2{,7}-mysql: MYSQL={env:TOX_MYSQL_PY2K:{env:TOX_MYSQL:--db mysql}}