8000 skip dunders for langhelper symbol redefine; update tox · sqlalchemy/sqlalchemy@7548046 · GitHub
[go: up one dir, main page]

Skip to content

Commit 7548046

Browse files
committed
skip dunders for langhelper symbol redefine; update tox
Set up full Python 3.13 support to the extent currently possible, repairing issues within internal language helpers as well as the serializer extension module. update tox for what will be a regular condition: greenlet is not available (and possibly other things like pymssql): 1. dont use "sqlalchemy[asyncio]" in pyproejct.toml as an extra; this goes out to pypi and ignores the local file 2. add py{3,38,39,...} qualifiers for asyncio deps in tox.ini. After many attempts I seem to have something that's fairly non-repetetive though I'd still prefer a single variable for this, somehow Fixes: #11417 Change-Id: Ib2ceccd9583d8776700f0da5b591906efcfe6e6f
1 parent deb2855 commit 7548046

File tree

6 files changed

+84
-48
lines changed

6 files changed

+84
-48
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
.. change::
2+
:tags: bug, general
3+
:tickets: 11417
4+
5+
Set up full Python 3.13 support to the extent currently possible, repairing
6+
issues within internal language helpers as well as the serializer extension
7+
module.

lib/sqlalchemy/ext/serializer.py

Lines changed: 19 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -82,10 +82,9 @@
8282
__all__ = ["Serializer", "Deserializer", "dumps", "loads"]
8383

8484

85-
def Serializer(*args, **kw):
86-
pickler = pickle.Pickler(*args, **kw)
85+
class Serializer(pickle.Pickler):
8786

88-
def persistent_id(obj):
87+
def persistent_id(self, obj):
8988
# print "serializing:", repr(obj)
9089
if isinstance(obj, Mapper) and not obj.non_primary:
9190
id_ = "mapper:" + b64encode(pickle.dumps(obj.class_))
@@ -113,30 +112,30 @@ def persistent_id(obj):
113112
return None
114113
return id_
115114

116-
pickler.persistent_id = persistent_id
117-
return pickler
118-
119115

120116
our_ids = re.compile(
121117
r"(mapperprop|mapper|mapper_selectable|table|column|"
122118
r"session|attribute|engine):(.*)"
123119
)
124120

125121

126-
def Deserializer(file, metadata=None, scoped_session=None, engine=None):
127-
unpickler = pickle.Unpickler(file)
122+
class Deserializer(pickle.Unpickler):
123+
124+
def __init__(self, file, metadata=None, scoped_session=None, engine=None):
125+
super().__init__(file)
126+
self.metadata = metadata
127+
self.scoped_session = scoped_session
128+
self.engine = engine
128129

129-
def get_engine():
130-
if engine:
131-
return engine
132-
elif scoped_session and scoped_session().bind:
133-
return scoped_session().bind
134-
elif metadata and metadata.bind:
135-
return metadata.bind
130+
def get_engine(self):
131+
if self.engine:
132+
return self.engine
133+
elif self.scoped_session and self.scoped_session().bind:
134+
return self.scoped_session().bind
136135
else:
137136
return None
138137

139-
def persistent_load(id_):
138+
def persistent_load(self, id_):
140139
m = our_ids.match(str(id_))
141140
if not m:
142141
return None
@@ -157,20 +156,17 @@ def persistent_load(id_):
157156
cls = pickle.loads(b64decode(mapper))
158157
return class_mapper(cls).attrs[keyname]
159158
elif type_ == "table":
160-
return metadata.tables[args]
159+
return self.metadata.tables[args]
161160
elif type_ == "column":
162161
table, colname = args.split(":")
163-
return metadata.tables[table].c[colname]
162+
return self.metadata.tables[table].c[colname]
164163
elif type_ == "session":
165-
return scoped_session()
164+
return self.scoped_session()
166165
elif type_ == "engine":
167-
return get_engine()
166+
return self.get_engine()
168167
else:
169168
raise Exception("Unknown token: %s" % type_)
170169

171-
unpickler.persistent_load = persistent_load
172-
return unpickler
173-
174170

175171
def dumps(obj, protocol=pickle.HIGHEST_PROTOCOL):
176172
buf = BytesIO()

lib/sqlalchemy/util/langhelpers.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1657,6 +1657,8 @@ def __init__(
16571657
items: List[symbol]
16581658
cls._items = items = []
16591659
for k, v in dict_.items():
1660+
if re.match(r"^__.*__$", k):
1661+
continue
16601662
if isinstance(v, int):
16611663
sym = symbol(k, canonical=v)
16621664
elif not k.startswith("_"):

pyproject.toml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ oracle-oracledb = ["oracledb>=1.0.1"]
5959
postgresql = ["psycopg2>=2.7"]
6060
postgresql-pg8000 = ["pg8000>=1.29.3"]
6161
postgresql-asyncpg = [
62-
"sqlalchemy[asyncio]",
62+
"greenlet!=0.4.17", # same as ".[asyncio]" if this syntax were supported
6363
"asyncpg",
6464
]
6565
postgresql-psycopg2binary = ["psycopg2-binary"]
@@ -68,19 +68,19 @@ postgresql-psycopg = ["psycopg>=3.0.7,!=3.1.15"]
6868
postgresql-psycopgbinary = ["psycopg[binary]>=3.0.7,!=3.1.15"]
6969
pymysql = ["pymysql"]
7070
aiomysql = [
71-
"sqlalchemy[asyncio]",
71+
"greenlet!=0.4.17", # same as ".[asyncio]" if this syntax were supported
7272
"aiomysql",
7373
]
7474
aioodbc = [
75-
"sqlalchemy[asyncio]",
75+
"greenlet!=0.4.17", # same as ".[asyncio]" if this syntax were supported
7676
"aioodbc",
7777
]
7878
asyncmy = [
79-
"sqlalchemy[asyncio]",
79+
"greenlet!=0.4.17", # same as ".[asyncio]" if this syntax were supported
8080
"asyncmy>=0.2.3,!=0.2.4,!=0.2.6",
8181
]
8282
aiosqlite = [
83-
"sqlalchemy[asyncio]",
83+
"greenlet!=0.4.17", # same as ".[asyncio]" if this syntax were supported
8484
"aiosqlite",
8585
]
8686
sqlcipher = ["sqlcipher3_binary"]

test/orm/test_mapper.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2010,12 +2010,12 @@ def _x(self):
20102010
)
20112011

20122012
# object gracefully handles this condition
2013-
assert not hasattr(User.x, "__name__")
2013+
assert not hasattr(User.x, "foobar")
20142014
assert not hasattr(User.x, "comparator")
20152015

20162016
m.add_property("some_attr", column_property(users.c.name))
20172017

2018-
assert not hasattr(User.x, "__name__")
2018+
assert not hasattr(User.x, "foobar")
20192019
assert hasattr(User.x, "comparator")
20202020

20212021
def test_synonym_of_non_property_raises(self):

tox.ini

Lines changed: 49 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,20 @@
22
[tox]
33
envlist = py
44

5+
[greenletextras]
6+
extras=
7+
asyncio
8+
sqlite: aiosqlite
9+
sqlite_file: aiosqlite
10+
postgresql: postgresql_asyncpg
11+
mysql: asyncmy
12+
mysql: aiomysql
13+
mssql: aioodbc
14+
15+
# not greenlet, but tends to not have packaging until the py version
16+
# has been fully released
17+
mssql: mssql_pymssql
18+
519
[testenv]
620
cov_args=--cov=sqlalchemy --cov-report term --cov-append --cov-report xml --exclude-tag memory-intensive --exclude-tag timing-intensive -k "not aaa_profiling"
721

@@ -14,26 +28,20 @@ usedevelop=
1428
cov: True
1529

1630
extras=
17-
asyncio
18-
sqlite: aiosqlite
19-
sqlite_file: aiosqlite
20-
sqlite_file: sqlcipher; python_version < '3.10'
31+
py{3,38,39,310,311,312}: {[greenletextras]extras}
32+
33+
py{38,39,310}-sqlite_file: sqlcipher
2134
postgresql: postgresql
22-
postgresql: postgresql_asyncpg
2335
postgresql: postgresql_pg8000
2436
postgresql: postgresql_psycopg
2537

2638
mysql: mysql
2739
mysql: pymysql
28-
mysql: asyncmy
29-
mysql: aiomysql
3040
mysql: mariadb_connector
3141

3242
oracle: oracle
3343
oracle: oracle_oracledb
3444
mssql: mssql
35-
mssql: aioodbc
36-
py{3,37,38,39,310,311}-mssql: mssql_pymssql
3745

3846
install_command=
3947
# TODO: I can find no way to get pip / tox / anyone to have this
@@ -46,8 +54,6 @@ deps=
4654
# tracked by https://github.com/pytest-dev/pytest-xdist/issues/907
4755
pytest-xdist!=3.3.0
4856

49-
py312: greenlet>=3.0.0a1
50-
5157
dbapimain-sqlite: git+https://github.com/omnilib/aiosqlite.git\#egg=aiosqlite
5258
dbapimain-sqlite: git+https://github.com/coleifer/sqlcipher3.git\#egg=sqlcipher3
5359

@@ -64,7 +70,7 @@ deps=
6470

6571
dbapimain-oracle: git+https://github.com/oracle/python-cx_Oracle.git\#egg=cx_Oracle
6672

67-
py312-mssql: git+https://github.com/mkleehammer/pyodbc.git\#egg=pyodbc
73+
py313-mssql: git+https://github.com/mkleehammer/pyodbc.git\#egg=pyodbc
6874
dbapimain-mssql: git+https://github.com/mkleehammer/pyodbc.git\#egg=pyodbc
6975

7076
cov: pytest-cov
@@ -101,8 +107,6 @@ setenv=
101107

102108
WORKERS={env:TOX_WORKERS:-n4 --max-worker-restart=5}
103109

104-
105-
106110
nocext: DISABLE_SQLALCHEMY_CEXT=1
107111
cext: REQUIRE_SQLALCHEMY_CEXT=1
108112
cov: COVERAGE={[testenv]cov_args}
@@ -111,12 +115,16 @@ setenv=
111115

112116
oracle: WORKERS={env:TOX_WORKERS:-n2 --max-worker-restart=5}
113117
oracle: ORACLE={env:TOX_ORACLE:--db oracle}
118+
114119
oracle: EXTRA_ORACLE_DRIVERS={env:EXTRA_ORACLE_DRIVERS:--dbdriver cx_oracle --dbdriver oracledb --dbdriver oracledb_async}
120+
py{313,314}-oracle: EXTRA_ORACLE_DRIVERS={env:EXTRA_ORACLE_DRIVERS:--dbdriver cx_oracle --dbdriver oracledb}
115121

116122
sqlite: SQLITE={env:TOX_SQLITE:--db sqlite}
117123
sqlite_file: SQLITE={env:TOX_SQLITE_FILE:--db sqlite_file}
118124

119125
sqlite: EXTRA_SQLITE_DRIVERS={env:EXTRA_SQLITE_DRIVERS:--dbdriver sqlite --dbdriver pysqlite_numeric --dbdriver aiosqlite}
126+
py{313,314}-sqlite: EXTRA_SQLITE_DRIVERS={env:EXTRA_SQLITE_DRIVERS:--dbdriver sqlite --dbdriver pysqlite_numeric}
127+
120128
sqlite-nogreenlet: EXTRA_SQLITE_DRIVERS={env:EXTRA_SQLITE_DRIVERS:--dbdriver sqlite --dbdriver pysqlite_numeric}
121129

122130
py{37,38,39}-sqlite_file: EXTRA_SQLITE_DRIVERS={env:EXTRA_SQLITE_DRIVERS:--dbdriver sqlite --dbdriver aiosqlite --dbdriver pysqlcipher}
@@ -140,10 +148,12 @@ setenv=
140148
mysql-nogreenlet: EXTRA_MYSQL_DRIVERS={env:EXTRA_MYSQL_DRIVERS:--dbdriver mysqldb --dbdriver pymysql --dbdriver mariadbconnector}
141149

142150
mssql: MSSQL={env:TOX_MSSQL:--db mssql}
143-
py{3,38,39,310,311}-mssql: EXTRA_MSSQL_DRIVERS={env:EXTRA_MSSQL_DRIVERS:--dbdriver pyodbc --dbdriver aioodbc --dbdriver pymssql}
144-
py{3,38,39,310,311}-mssql-nogreenlet: EXTRA_MSSQL_DRIVERS={env:EXTRA_MSSQL_DRIVERS:--dbdriver pyodbc --dbdriver pymssql}
145-
py312-mssql: EXTRA_MSSQL_DRIVERS={env:EXTRA_MSSQL_DRIVERS:--dbdriver pyodbc --dbdriver aioodbc}
146-
py312-mssql-nogreenlet: EXTRA_MSSQL_DRIVERS={env:EXTRA_MSSQL_DRIVERS:--dbdriver pyodbc}
151+
152+
mssql: EXTRA_MSSQL_DRIVERS={env:EXTRA_MSSQL_DRIVERS:--dbdriver pyodbc --dbdriver aioodbc --dbdriver pymssql}
153+
py{313,314}-mssql: EXTRA_MSSQL_DRIVERS={env:EXTRA_MSSQL_DRIVERS:--dbdriver pyodbc --dbdriver aioodbc}
154+
155+
mssql-nogreenlet: EXTRA_MSSQL_DRIVERS={env:EXTRA_MSSQL_DRIVERS:--dbdriver pyodbc --dbdriver pymssql}
156+
py{313,314}-mssql-nogreenlet: EXTRA_MSSQL_DRIVERS={env:EXTRA_MSSQL_DRIVERS:--dbdriver pyodbc}
147157

148158
oracle,mssql,sqlite_file: IDENTS=--write-idents db_idents.txt
149159

@@ -188,6 +198,9 @@ commands =
188198
# suddently appearing for it to be stable enough for CI
189199
# pyright
190200

201+
extras =
202+
{[greenletextras]extras}
203+
191204
[testenv:mypy]
192205
deps=
193206
pytest>=7.0.0rc1,<8
@@ -196,6 +209,9 @@ deps=
196209
mypy >= 1.7.0
197210
patch==1.*
198211
types-greenlet
212+
extras=
213+
{[greenletextras]extras}
214+
199215
commands =
200216
pytest {env:PYTEST_COLOR} -m mypy {posargs}
201217

@@ -205,6 +221,9 @@ deps=
205221
{[testenv:mypy]deps}
206222
pytest-cov
207223

224+
extras=
225+
{[greenletextras]extras}
226+
208227
commands =
209228
pytest {env:PYTEST_COLOR} -m mypy {env:COVERAGE} {posargs}
210229

@@ -214,6 +233,10 @@ setenv=
214233
# thanks to https://julien.danjou.info/the-best-flake8-extensions/
215234
[testenv:lint]
216235
basepython = python3
236+
237+
extras=
238+
{[greenletextras]extras}
239+
217240
deps=
218241
flake8==6.1.0
219242
flake8-import-order
@@ -259,10 +282,15 @@ basepython = {[testenv:lint]basepython}
259282
deps = {[testenv:lint]deps}
260283
allowlist_externals = {[testenv:lint]allowlist_externals}
261284
commands = {[testenv:lint]commands}
285+
extras = {[testenv:lint]extras}
286+
262287

263288

264289
# command run in the github action when cext are active. 90FA
265290
[testenv:github-cext]
291+
extras=
292+
{[greenletextras]extras}
293+
266294
deps = {[testenv]deps}
267295
.[aiosqlite]
268296
commands=
@@ -271,6 +299,9 @@ commands=
271299

272300
# command run in the github action when cext are not active.
273301
[testenv:github-nocext]
302+
extras=
303+
{[greenletextras]extras}
304+
274305
deps = {[testenv]deps}
275306
.[aiosqlite]
276307
commands=

0 commit comments

Comments
 (0)
0