SQLAlchemy 2.0.32__py3-none-any.whl → 2.0.34__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {SQLAlchemy-2.0.32.dist-info → SQLAlchemy-2.0.34.dist-info}/METADATA +33 -33
- {SQLAlchemy-2.0.32.dist-info → SQLAlchemy-2.0.34.dist-info}/RECORD +24 -24
- {SQLAlchemy-2.0.32.dist-info → SQLAlchemy-2.0.34.dist-info}/WHEEL +1 -1
- sqlalchemy/__init__.py +1 -1
- sqlalchemy/dialects/mssql/provision.py +7 -0
- sqlalchemy/dialects/mssql/pymssql.py +1 -0
- sqlalchemy/dialects/mysql/base.py +1 -1
- sqlalchemy/dialects/oracle/cx_oracle.py +1 -1
- sqlalchemy/dialects/postgresql/asyncpg.py +29 -8
- sqlalchemy/dialects/sqlite/base.py +64 -10
- sqlalchemy/dialects/sqlite/pysqlite.py +3 -3
- sqlalchemy/engine/reflection.py +11 -2
- sqlalchemy/orm/clsregistry.py +3 -2
- sqlalchemy/orm/decl_base.py +1 -1
- sqlalchemy/orm/util.py +7 -2
- sqlalchemy/sql/elements.py +8 -1
- sqlalchemy/sql/schema.py +3 -1
- sqlalchemy/sql/selectable.py +57 -10
- sqlalchemy/sql/sqltypes.py +12 -0
- sqlalchemy/testing/provision.py +1 -1
- sqlalchemy/testing/requirements.py +5 -0
- sqlalchemy/util/typing.py +42 -0
- {SQLAlchemy-2.0.32.dist-info → SQLAlchemy-2.0.34.dist-info}/LICENSE +0 -0
- {SQLAlchemy-2.0.32.dist-info → SQLAlchemy-2.0.34.dist-info}/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: SQLAlchemy
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.34
|
|
4
4
|
Summary: Database Abstraction Library
|
|
5
5
|
Home-page: https://www.sqlalchemy.org
|
|
6
6
|
Author: Mike Bayer
|
|
@@ -26,61 +26,61 @@ Classifier: Topic :: Database :: Front-Ends
|
|
|
26
26
|
Requires-Python: >=3.7
|
|
27
27
|
Description-Content-Type: text/x-rst
|
|
28
28
|
License-File: LICENSE
|
|
29
|
-
Requires-Dist: typing-extensions>=4.6.0
|
|
30
|
-
Requires-Dist: greenlet!=0.4.17; python_version < "3.13" and (platform_machine == "aarch64" or (platform_machine == "ppc64le" or (platform_machine == "x86_64" or (platform_machine == "amd64" or (platform_machine == "AMD64" or (platform_machine == "win32" or platform_machine == "WIN32"))))))
|
|
31
|
-
Requires-Dist: importlib-metadata; python_version < "3.8"
|
|
29
|
+
Requires-Dist: typing-extensions >=4.6.0
|
|
30
|
+
Requires-Dist: greenlet !=0.4.17 ; python_version < "3.13" and (platform_machine == "aarch64" or (platform_machine == "ppc64le" or (platform_machine == "x86_64" or (platform_machine == "amd64" or (platform_machine == "AMD64" or (platform_machine == "win32" or platform_machine == "WIN32"))))))
|
|
31
|
+
Requires-Dist: importlib-metadata ; python_version < "3.8"
|
|
32
32
|
Provides-Extra: aiomysql
|
|
33
|
-
Requires-Dist: greenlet!=0.4.17; extra ==
|
|
34
|
-
Requires-Dist: aiomysql>=0.2.0; extra ==
|
|
33
|
+
Requires-Dist: greenlet !=0.4.17 ; extra == 'aiomysql'
|
|
34
|
+
Requires-Dist: aiomysql >=0.2.0 ; extra == 'aiomysql'
|
|
35
35
|
Provides-Extra: aioodbc
|
|
36
|
-
Requires-Dist: greenlet!=0.4.17; extra ==
|
|
37
|
-
Requires-Dist: aioodbc; extra ==
|
|
36
|
+
Requires-Dist: greenlet !=0.4.17 ; extra == 'aioodbc'
|
|
37
|
+
Requires-Dist: aioodbc ; extra == 'aioodbc'
|
|
38
38
|
Provides-Extra: aiosqlite
|
|
39
|
-
Requires-Dist: greenlet!=0.4.17; extra ==
|
|
40
|
-
Requires-Dist: aiosqlite; extra ==
|
|
41
|
-
Requires-Dist: typing-extensions!=3.10.0.1; extra ==
|
|
39
|
+
Requires-Dist: greenlet !=0.4.17 ; extra == 'aiosqlite'
|
|
40
|
+
Requires-Dist: aiosqlite ; extra == 'aiosqlite'
|
|
41
|
+
Requires-Dist: typing-extensions !=3.10.0.1 ; extra == 'aiosqlite'
|
|
42
42
|
Provides-Extra: asyncio
|
|
43
|
-
Requires-Dist: greenlet!=0.4.17; extra ==
|
|
43
|
+
Requires-Dist: greenlet !=0.4.17 ; extra == 'asyncio'
|
|
44
44
|
Provides-Extra: asyncmy
|
|
45
|
-
Requires-Dist: greenlet!=0.4.17; extra ==
|
|
46
|
-
Requires-Dist: asyncmy!=0.2.4,!=0.2.6,>=0.2.3; extra ==
|
|
45
|
+
Requires-Dist: greenlet !=0.4.17 ; extra == 'asyncmy'
|
|
46
|
+
Requires-Dist: asyncmy !=0.2.4,!=0.2.6,>=0.2.3 ; extra == 'asyncmy'
|
|
47
47
|
Provides-Extra: mariadb_connector
|
|
48
|
-
Requires-Dist: mariadb!=1.1.2,!=1.1.5,>=1.0.1; extra ==
|
|
48
|
+
Requires-Dist: mariadb !=1.1.2,!=1.1.5,>=1.0.1 ; extra == 'mariadb_connector'
|
|
49
49
|
Provides-Extra: mssql
|
|
50
|
-
Requires-Dist: pyodbc; extra ==
|
|
50
|
+
Requires-Dist: pyodbc ; extra == 'mssql'
|
|
51
51
|
Provides-Extra: mssql_pymssql
|
|
52
|
-
Requires-Dist: pymssql; extra ==
|
|
52
|
+
Requires-Dist: pymssql ; extra == 'mssql_pymssql'
|
|
53
53
|
Provides-Extra: mssql_pyodbc
|
|
54
|
-
Requires-Dist: pyodbc; extra ==
|
|
54
|
+
Requires-Dist: pyodbc ; extra == 'mssql_pyodbc'
|
|
55
55
|
Provides-Extra: mypy
|
|
56
|
-
Requires-Dist: mypy>=0.910; extra ==
|
|
56
|
+
Requires-Dist: mypy >=0.910 ; extra == 'mypy'
|
|
57
57
|
Provides-Extra: mysql
|
|
58
|
-
Requires-Dist: mysqlclient>=1.4.0; extra ==
|
|
58
|
+
Requires-Dist: mysqlclient >=1.4.0 ; extra == 'mysql'
|
|
59
59
|
Provides-Extra: mysql_connector
|
|
60
|
-
Requires-Dist: mysql-connector-python; extra ==
|
|
60
|
+
Requires-Dist: mysql-connector-python ; extra == 'mysql_connector'
|
|
61
61
|
Provides-Extra: oracle
|
|
62
|
-
Requires-Dist: cx-oracle>=8; extra ==
|
|
62
|
+
Requires-Dist: cx-oracle >=8 ; extra == 'oracle'
|
|
63
63
|
Provides-Extra: oracle_oracledb
|
|
64
|
-
Requires-Dist: oracledb>=1.0.1; extra ==
|
|
64
|
+
Requires-Dist: oracledb >=1.0.1 ; extra == 'oracle_oracledb'
|
|
65
65
|
Provides-Extra: postgresql
|
|
66
|
-
Requires-Dist: psycopg2>=2.7; extra ==
|
|
66
|
+
Requires-Dist: psycopg2 >=2.7 ; extra == 'postgresql'
|
|
67
67
|
Provides-Extra: postgresql_asyncpg
|
|
68
|
-
Requires-Dist: greenlet!=0.4.17; extra ==
|
|
69
|
-
Requires-Dist: asyncpg; extra ==
|
|
68
|
+
Requires-Dist: greenlet !=0.4.17 ; extra == 'postgresql_asyncpg'
|
|
69
|
+
Requires-Dist: asyncpg ; extra == 'postgresql_asyncpg'
|
|
70
70
|
Provides-Extra: postgresql_pg8000
|
|
71
|
-
Requires-Dist: pg8000>=1.29.1; extra ==
|
|
71
|
+
Requires-Dist: pg8000 >=1.29.1 ; extra == 'postgresql_pg8000'
|
|
72
72
|
Provides-Extra: postgresql_psycopg
|
|
73
|
-
Requires-Dist: psycopg>=3.0.7; extra ==
|
|
73
|
+
Requires-Dist: psycopg >=3.0.7 ; extra == 'postgresql_psycopg'
|
|
74
74
|
Provides-Extra: postgresql_psycopg2binary
|
|
75
|
-
Requires-Dist: psycopg2-binary; extra ==
|
|
75
|
+
Requires-Dist: psycopg2-binary ; extra == 'postgresql_psycopg2binary'
|
|
76
76
|
Provides-Extra: postgresql_psycopg2cffi
|
|
77
|
-
Requires-Dist: psycopg2cffi; extra ==
|
|
77
|
+
Requires-Dist: psycopg2cffi ; extra == 'postgresql_psycopg2cffi'
|
|
78
78
|
Provides-Extra: postgresql_psycopgbinary
|
|
79
|
-
Requires-Dist: psycopg[binary]>=3.0.7; extra ==
|
|
79
|
+
Requires-Dist: psycopg[binary] >=3.0.7 ; extra == 'postgresql_psycopgbinary'
|
|
80
80
|
Provides-Extra: pymysql
|
|
81
|
-
Requires-Dist: pymysql; extra ==
|
|
81
|
+
Requires-Dist: pymysql ; extra == 'pymysql'
|
|
82
82
|
Provides-Extra: sqlcipher
|
|
83
|
-
Requires-Dist: sqlcipher3-binary; extra ==
|
|
83
|
+
Requires-Dist: sqlcipher3-binary ; extra == 'sqlcipher'
|
|
84
84
|
|
|
85
85
|
SQLAlchemy
|
|
86
86
|
==========
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
sqlalchemy/__init__.py,sha256=
|
|
1
|
+
sqlalchemy/__init__.py,sha256=kW5kNSOI0cHm2Ioc_-ahxqHWmCDAWb_iqZZJsMYrKMU,13033
|
|
2
2
|
sqlalchemy/events.py,sha256=k-ZD38aSPD29LYhED7CBqttp5MDVVx_YSaWC2-cu9ec,525
|
|
3
3
|
sqlalchemy/exc.py,sha256=M_8-O1hd8i6gbyx-TapV400p_Lxq2QqTGMXUAO-YgCc,23976
|
|
4
4
|
sqlalchemy/inspection.py,sha256=MF-LE358wZDUEl1IH8-Uwt2HI65EsQpQW5o5udHkZwA,5063
|
|
@@ -25,13 +25,13 @@ sqlalchemy/dialects/mssql/aioodbc.py,sha256=UQd9ecSMIML713TDnLAviuBVJle7P7i1FtqG
|
|
|
25
25
|
sqlalchemy/dialects/mssql/base.py,sha256=TQekFOsor8Rc-cnDPmbq_JLQekKrHPtUdBdNsCYFw7w,132447
|
|
26
26
|
sqlalchemy/dialects/mssql/information_schema.py,sha256=HswjDc6y0mPXCf_x6VyylHlBdBa4PSY6Evxmmlch700,8084
|
|
27
27
|
sqlalchemy/dialects/mssql/json.py,sha256=evUACW2O62TAPq8B7QIPagz7jfc664ql9ms68JqiYzg,4816
|
|
28
|
-
sqlalchemy/dialects/mssql/provision.py,sha256=
|
|
29
|
-
sqlalchemy/dialects/mssql/pymssql.py,sha256=
|
|
28
|
+
sqlalchemy/dialects/mssql/provision.py,sha256=ZAtt6Div9NLIngMs8kyloxfphw0KDNMsnRCAVd7-esE,5593
|
|
29
|
+
sqlalchemy/dialects/mssql/pymssql.py,sha256=LAv43q4vBCB85OsAwHQItaQUYTYIO0QJ-jvzaBrswmY,4097
|
|
30
30
|
sqlalchemy/dialects/mssql/pyodbc.py,sha256=vwM-vBlmRwrqxOc73P0sFOrBSwn24wzc5IkEOpalbXQ,27056
|
|
31
31
|
sqlalchemy/dialects/mysql/__init__.py,sha256=bxbi4hkysUK2OOVvr1F49akUj1cky27kKb07tgFzI9U,2153
|
|
32
32
|
sqlalchemy/dialects/mysql/aiomysql.py,sha256=-oMZnCqNsSki8mlQRTWIwiQPT1OVdZIuANkb90q8LAs,9999
|
|
33
33
|
sqlalchemy/dialects/mysql/asyncmy.py,sha256=YpuuOh8VknEeqHqUXQGfQ3jhfO3Xb-vZv78Jq5cscJ0,10067
|
|
34
|
-
sqlalchemy/dialects/mysql/base.py,sha256=
|
|
34
|
+
sqlalchemy/dialects/mysql/base.py,sha256=8shrZRSnVwDXtl6ybaO6cvul_RZ34zEWqvpYW5sNfOQ,120986
|
|
35
35
|
sqlalchemy/dialects/mysql/cymysql.py,sha256=eXT1ry0w_qRxjiO24M980c-8PZ9qSsbhqBHntjEiKB0,2300
|
|
36
36
|
sqlalchemy/dialects/mysql/dml.py,sha256=HXJMAvimJsqvhj3UZO4vW_6LkF5RqaKbHvklAjor7yU,7645
|
|
37
37
|
sqlalchemy/dialects/mysql/enumerated.py,sha256=ipEPPQqoXfFwcywNdcLlZCEzHBtnitHRah1Gn6nItcg,8448
|
|
@@ -49,7 +49,7 @@ sqlalchemy/dialects/mysql/reserved_words.py,sha256=ucKX2p2c3UnMq2ayZuOHuf73eXhu7
|
|
|
49
49
|
sqlalchemy/dialects/mysql/types.py,sha256=L5cTCsMT1pTedszNEM3jSxFNZEMcHQLprYCZ0vmfsnA,24343
|
|
50
50
|
sqlalchemy/dialects/oracle/__init__.py,sha256=p4-2gw7TT0bX_MoJXTGD4i8WHctYsK9kCRbkpzykBrc,1493
|
|
51
51
|
sqlalchemy/dialects/oracle/base.py,sha256=cav9QxSLT75-JXhhFSneYT_y3coF6TmFkBa5fqQMrRI,119615
|
|
52
|
-
sqlalchemy/dialects/oracle/cx_oracle.py,sha256=
|
|
52
|
+
sqlalchemy/dialects/oracle/cx_oracle.py,sha256=q8Nyj15UZCE2TWOmxuWp5ZsxiCiGMzqfd_9UkmjIja0,55235
|
|
53
53
|
sqlalchemy/dialects/oracle/dictionary.py,sha256=7WMrbPkqo8ZdGjaEZyQr-5f2pajSOF1OTGb8P97z8-g,19519
|
|
54
54
|
sqlalchemy/dialects/oracle/oracledb.py,sha256=fZRKGqNIwW9LG4i8yDOXABrucbfzn_yC86Od-BJ3PcM,13619
|
|
55
55
|
sqlalchemy/dialects/oracle/provision.py,sha256=O9ZpF4OG6Cx4mMzLRfZwhs8dZjrJETWR402n9c7726A,8304
|
|
@@ -57,7 +57,7 @@ sqlalchemy/dialects/oracle/types.py,sha256=QK3hJvWzKnnCe3oD3rItwEEIwcoBze8qGg7VF
|
|
|
57
57
|
sqlalchemy/dialects/postgresql/__init__.py,sha256=wwnNAq4wDQzrlPRzDNB06ayuq3L2HNO99nzeEvq-YcU,3892
|
|
58
58
|
sqlalchemy/dialects/postgresql/_psycopg_common.py,sha256=7TudtgsPiSB8O5kX8W8KxcNYR8t5h_UHb86b_ChL0P8,5696
|
|
59
59
|
sqlalchemy/dialects/postgresql/array.py,sha256=bWcame7ntmI_Kx6gmBX0-chwADFdLHeCvaDQ4iX8id8,13734
|
|
60
|
-
sqlalchemy/dialects/postgresql/asyncpg.py,sha256=
|
|
60
|
+
sqlalchemy/dialects/postgresql/asyncpg.py,sha256=se1HXkikKQFcR2D-15jS6iKIaQs-M8Y8ke99ih0Y4NM,41132
|
|
61
61
|
sqlalchemy/dialects/postgresql/base.py,sha256=ed49Ode09deJF3jXr8V5sSHTwVoFVq0dlvNdP3mJaBQ,178989
|
|
62
62
|
sqlalchemy/dialects/postgresql/dml.py,sha256=Pc69Le6qzmUHHb1FT5zeUSD31dWm6SBgdCAGW89cs3s,11212
|
|
63
63
|
sqlalchemy/dialects/postgresql/ext.py,sha256=1bZ--iNh2O9ym7l2gXZX48yP3yMO4dqb9RpYro2Mj2Q,16262
|
|
@@ -75,12 +75,12 @@ sqlalchemy/dialects/postgresql/ranges.py,sha256=6CgV7qkxEMJ9AQsiibo_XBLJYzGh-2Zx
|
|
|
75
75
|
sqlalchemy/dialects/postgresql/types.py,sha256=Jfxqw9JaKNOq29JRWBublywgb3lLMyzx8YZI7CXpS2s,7300
|
|
76
76
|
sqlalchemy/dialects/sqlite/__init__.py,sha256=lp9DIggNn349M-7IYhUA8et8--e8FRExWD2V_r1LJk4,1182
|
|
77
77
|
sqlalchemy/dialects/sqlite/aiosqlite.py,sha256=g3qGV6jmiXabWyb3282g_Nmxtj1jThxGSe9C9yalb-U,12345
|
|
78
|
-
sqlalchemy/dialects/sqlite/base.py,sha256=
|
|
78
|
+
sqlalchemy/dialects/sqlite/base.py,sha256=i1LolkwQLI86l_YwEpiIfN5Lh469H1mairKdmTxa9k4,99832
|
|
79
79
|
sqlalchemy/dialects/sqlite/dml.py,sha256=9GE55WvwoktKy2fHeT-Wbc9xPHgsbh5oBfd_fckMH5Q,8443
|
|
80
80
|
sqlalchemy/dialects/sqlite/json.py,sha256=Eoplbb_4dYlfrtmQaI8Xddd2suAIHA-IdbDQYM-LIhs,2777
|
|
81
81
|
sqlalchemy/dialects/sqlite/provision.py,sha256=UCpmwxf4IWlrpb2eLHGbPTpCFVbdI_KAh2mKtjiLYao,5632
|
|
82
82
|
sqlalchemy/dialects/sqlite/pysqlcipher.py,sha256=OL2S_05DK9kllZj6DOz7QtEl7jI7syxjW6woS725ii4,5356
|
|
83
|
-
sqlalchemy/dialects/sqlite/pysqlite.py,sha256=
|
|
83
|
+
sqlalchemy/dialects/sqlite/pysqlite.py,sha256=aDp47n0J509kl2hDchoaBKXEQVZtkux54DwfKytUAe4,28068
|
|
84
84
|
sqlalchemy/engine/__init__.py,sha256=Stb2oV6l8w65JvqEo6J4qtKoApcmOpXy3AAxQud4C1o,2818
|
|
85
85
|
sqlalchemy/engine/_py_processors.py,sha256=j9i_lcYYQOYJMcsDerPxI0sVFBIlX5sqoYMdMJlgWPI,3744
|
|
86
86
|
sqlalchemy/engine/_py_row.py,sha256=wSqoUFzLOJ1f89kgDb6sJm9LUrF5LMFpXPcK1vUsKcs,3787
|
|
@@ -94,7 +94,7 @@ sqlalchemy/engine/events.py,sha256=c0unNFFiHzTAvkUtXoJaxzMFMDwurBkHiiUhuN8qluc,3
|
|
|
94
94
|
sqlalchemy/engine/interfaces.py,sha256=fcVHOmnMo7JZLHzgSKoK3QsdVHH7kJ_AmrDvwW9Ka3k,112936
|
|
95
95
|
sqlalchemy/engine/mock.py,sha256=yvpxgFmRw5G4QsHeF-ZwQGHKES-HqQOucTxFtN1uzdk,4179
|
|
96
96
|
sqlalchemy/engine/processors.py,sha256=XyfINKbo-2fjN-mW55YybvFyQMOil50_kVqsunahkNs,2379
|
|
97
|
-
sqlalchemy/engine/reflection.py,sha256=
|
|
97
|
+
sqlalchemy/engine/reflection.py,sha256=gwGs8y7x6py5z-ZWx3hQqQrwpHepMCTJyQcFwWJjPlw,75364
|
|
98
98
|
sqlalchemy/engine/result.py,sha256=j6BI4Wj2bziQNQG5OlG_Cm4KcNWY9AoYvTXVlJUU-D8,77603
|
|
99
99
|
sqlalchemy/engine/row.py,sha256=9AAQo9zYDL88GcZ3bjcQTwMT-YIcuGTSMAyTfmBJ_yM,12032
|
|
100
100
|
sqlalchemy/engine/strategies.py,sha256=DqFSWaXJPL-29Omot9O0aOcuGL8KmCGyOvnPGDkAJoE,442
|
|
@@ -142,11 +142,11 @@ sqlalchemy/orm/_typing.py,sha256=DVBfpHmDVK4x1zxaGJPY2GoTrAsyR6uexv20Lzf1afc,497
|
|
|
142
142
|
sqlalchemy/orm/attributes.py,sha256=lorOHBJvJJYndOuafWJhHBbQ1pR6FAyimhqz-mErBRQ,92534
|
|
143
143
|
sqlalchemy/orm/base.py,sha256=re6A8ooMxLyfCAeQfhBwwxeJQkiH7EtzzOZIVIiTPlw,27466
|
|
144
144
|
sqlalchemy/orm/bulk_persistence.py,sha256=MfFALcRkE3eKwxkntVM1ZcUhOphUFwAr1Fc21qJoobo,71403
|
|
145
|
-
sqlalchemy/orm/clsregistry.py,sha256=
|
|
145
|
+
sqlalchemy/orm/clsregistry.py,sha256=IjoDZwWpjG42ji59L4M1EZvjBEoXPZykzENDtKWxU8A,17974
|
|
146
146
|
sqlalchemy/orm/collections.py,sha256=WEKuUCRgLhDhJEIBhZ21UrE0pBOyRm2zxD20GvbgA9g,52243
|
|
147
147
|
sqlalchemy/orm/context.py,sha256=pFFc-1ZjaV3aQMAO27UIh0W6NyLc30n2IbuWNprMtS8,112445
|
|
148
148
|
sqlalchemy/orm/decl_api.py,sha256=_WPKQ_vSE5k2TLtNmkaxxYmvbhZvkRMrrvCeDxdqDQE,63998
|
|
149
|
-
sqlalchemy/orm/decl_base.py,sha256=
|
|
149
|
+
sqlalchemy/orm/decl_base.py,sha256=FTHf3bCVlg52KR6JWVEwuG3XjOaGQ5KJMYFYXastGhw,82832
|
|
150
150
|
sqlalchemy/orm/dependency.py,sha256=hgjksUWhgbmgHK5GdJdiDCBgDAIGQXIrY-Tj79tbL2k,47631
|
|
151
151
|
sqlalchemy/orm/descriptor_props.py,sha256=dR_h4Gvdtpcdp4sj_ZOR4P5Nng2J2vhsvFHouRLlntc,37244
|
|
152
152
|
sqlalchemy/orm/dynamic.py,sha256=rWAZ-nfAkREuNjt8e_FRdqYrvHDdbODn1CcfyP8Y18k,9816
|
|
@@ -172,7 +172,7 @@ sqlalchemy/orm/strategies.py,sha256=Sd6IKV_ya_CBKzebwazRrWWabvZ0PqariUB7KKUIUrc,
|
|
|
172
172
|
sqlalchemy/orm/strategy_options.py,sha256=-n44NV8QX-3uWjhFMA_R_7vYy-d57gJY9snB9JeOj-w,85341
|
|
173
173
|
sqlalchemy/orm/sync.py,sha256=g7iZfSge1HgxMk9SKRgUgtHEbpbZ1kP_CBqOIdTOXqc,5779
|
|
174
174
|
sqlalchemy/orm/unitofwork.py,sha256=fiVaqcymbDDHRa1NjS90N9Z466nd5pkJOEi1dHO6QLY,27033
|
|
175
|
-
sqlalchemy/orm/util.py,sha256=
|
|
175
|
+
sqlalchemy/orm/util.py,sha256=Q0JT2JydyGiNiYT8AVe9B6jOdBRVHSOVDIcWOsXXIUQ,80929
|
|
176
176
|
sqlalchemy/orm/writeonly.py,sha256=SYu2sAaHZONk2pW4PmtE871LG-O0P_bjidvKzY1H_zI,22305
|
|
177
177
|
sqlalchemy/pool/__init__.py,sha256=qiDdq4r4FFAoDrK6ncugF_i6usi_X1LeJt-CuBHey0s,1804
|
|
178
178
|
sqlalchemy/pool/base.py,sha256=WF4az4ZKuzQGuKeSJeyexaYjmWZUvYdC6KIi8zTGodw,52236
|
|
@@ -194,7 +194,7 @@ sqlalchemy/sql/crud.py,sha256=HBX4QPtW_PYYJmIKfNr-wE8IdEr963N24WXzFBUZOo0,56514
|
|
|
194
194
|
sqlalchemy/sql/ddl.py,sha256=CIqMilCKfuQnF0lrZsQdTxgrbXqcTauKr0Ojzj77PFQ,45602
|
|
195
195
|
sqlalchemy/sql/default_comparator.py,sha256=utXWsZVGEjflhFfCT4ywa6RnhORc1Rryo87Hga71Rps,16707
|
|
196
196
|
sqlalchemy/sql/dml.py,sha256=pn0Lm1ofC5qVZzwGWFW73lPCiNba8OsTeemurJgwRyg,65614
|
|
197
|
-
sqlalchemy/sql/elements.py,sha256=
|
|
197
|
+
sqlalchemy/sql/elements.py,sha256=YfccXzQc9DlgF8q15kDf-zKBUY_vpIe0FGaVDBPoic4,176544
|
|
198
198
|
sqlalchemy/sql/events.py,sha256=iC_Q1Htm1Aobt5tOYxWfHHqNpoytrULORmUKcusH_-E,18290
|
|
199
199
|
sqlalchemy/sql/expression.py,sha256=VMX-dLpsZYnVRJpYNDozDUgaj7iQ0HuewUKVefD57PE,7586
|
|
200
200
|
sqlalchemy/sql/functions.py,sha256=kMMYplvuIHFAPwxBI03SizwaLcYEHzysecWk-R1V-JM,63762
|
|
@@ -202,9 +202,9 @@ sqlalchemy/sql/lambdas.py,sha256=DP0Qz7Ypo8QhzMwygGHYgRhwJMx-rNezO1euouH3iYU,492
|
|
|
202
202
|
sqlalchemy/sql/naming.py,sha256=ZHs1qSV3ou8TYmZ92uvU3sfdklUQlIz4uhe330n05SU,6858
|
|
203
203
|
sqlalchemy/sql/operators.py,sha256=himArRqBzrljob3Zfhi_ZS-Jleg1u6YFp0g3d7Co6IM,76106
|
|
204
204
|
sqlalchemy/sql/roles.py,sha256=pOsVn_OZD7mF2gJByHf24Rjopt0_Hu3dUCEOK5t4KS8,7662
|
|
205
|
-
sqlalchemy/sql/schema.py,sha256=
|
|
206
|
-
sqlalchemy/sql/selectable.py,sha256=
|
|
207
|
-
sqlalchemy/sql/sqltypes.py,sha256=
|
|
205
|
+
sqlalchemy/sql/schema.py,sha256=iFleWHkxi-3mKGiK_N1TzUqxnNwOpypB4bWDuAVQe8c,229717
|
|
206
|
+
sqlalchemy/sql/selectable.py,sha256=7QpgbIVz9AanhodMICFwDvaY2RdsTRSTvsRzD9Cnsds,236460
|
|
207
|
+
sqlalchemy/sql/sqltypes.py,sha256=fajBVE_CCJykrQpOOnb8_HFOKCSoUF48AxljJymvGk4,127330
|
|
208
208
|
sqlalchemy/sql/traversals.py,sha256=3ScTC1fh1-y8Y478h_2Azmd2xdQdWPWkDve4YgrwMf8,33664
|
|
209
209
|
sqlalchemy/sql/type_api.py,sha256=q_FieFRALHiRkhy5Bj-cVgFHa7DXF1dP23FaRRYKeho,83717
|
|
210
210
|
sqlalchemy/sql/util.py,sha256=qGHQF-tPCj-m1FBerzT7weCanGcXU7dK5m-W7NHio-4,48077
|
|
@@ -219,8 +219,8 @@ sqlalchemy/testing/entities.py,sha256=IphFegPKbff3Un47jY6bi7_MQXy6qkx_50jX2tHZJR
|
|
|
219
219
|
sqlalchemy/testing/exclusions.py,sha256=T8B01hmm8WVs-EKcUOQRzabahPqblWJfOidi6bHJ6GA,12460
|
|
220
220
|
sqlalchemy/testing/pickleable.py,sha256=U9mIqk-zaxq9Xfy7HErP7UrKgTov-A3QFnhZh-NiOjI,2833
|
|
221
221
|
sqlalchemy/testing/profiling.py,sha256=PbuPhRFbauFilUONeY3tV_Y_5lBkD7iCa8VVyH2Sk9Y,10148
|
|
222
|
-
sqlalchemy/testing/provision.py,sha256=
|
|
223
|
-
sqlalchemy/testing/requirements.py,sha256=
|
|
222
|
+
sqlalchemy/testing/provision.py,sha256=3qFor_sN1FFlS7odUGkKqLUxGmQZC9XM67I9vQ_zeXo,14626
|
|
223
|
+
sqlalchemy/testing/requirements.py,sha256=uD7ZYOMZ0LQ0Lf8EsKWmDdRSnfcrjnXa8eSgTiIibOk,52655
|
|
224
224
|
sqlalchemy/testing/schema.py,sha256=lr4GkGrGwagaHMuSGzWdzkMaj3HnS7dgfLLWfxt__-U,6513
|
|
225
225
|
sqlalchemy/testing/util.py,sha256=qldXKw8gRJ4I2x3uXsBssYMqwatmcMFMTOveRQCmfDU,14469
|
|
226
226
|
sqlalchemy/testing/warnings.py,sha256=fJ-QJUY2zY2PPxZJKv9medW-BKKbCNbA4Ns_V3YwFXM,1546
|
|
@@ -260,9 +260,9 @@ sqlalchemy/util/preloaded.py,sha256=az7NmLJLsqs0mtM9uBkIu10-841RYDq8wOyqJ7xXvqE,
|
|
|
260
260
|
sqlalchemy/util/queue.py,sha256=CaeSEaYZ57YwtmLdNdOIjT5PK_LCuwMFiO0mpp39ybM,10185
|
|
261
261
|
sqlalchemy/util/tool_support.py,sha256=9braZyidaiNrZVsWtGmkSmus50-byhuYrlAqvhjcmnA,6135
|
|
262
262
|
sqlalchemy/util/topological.py,sha256=N3M3Le7KzGHCmqPGg0ZBqixTDGwmFLhOZvBtc4rHL_g,3458
|
|
263
|
-
sqlalchemy/util/typing.py,sha256=
|
|
264
|
-
SQLAlchemy-2.0.
|
|
265
|
-
SQLAlchemy-2.0.
|
|
266
|
-
SQLAlchemy-2.0.
|
|
267
|
-
SQLAlchemy-2.0.
|
|
268
|
-
SQLAlchemy-2.0.
|
|
263
|
+
sqlalchemy/util/typing.py,sha256=VUVyYOXmPPlAW9e8OuVQ55Ij4b6jc0GPDEjY-Rlpnwo,17961
|
|
264
|
+
SQLAlchemy-2.0.34.dist-info/LICENSE,sha256=PA9Zq4h9BB3mpOUv_j6e212VIt6Qn66abNettue-MpM,1100
|
|
265
|
+
SQLAlchemy-2.0.34.dist-info/METADATA,sha256=TdwTMOhRN3N7sdV1_zHpx9GCBE_dm2jeU9_9UMTGYM8,9632
|
|
266
|
+
SQLAlchemy-2.0.34.dist-info/WHEEL,sha256=uCRv0ZEik_232NlR4YDw4Pv3Ajt5bKvMH13NUU7hFuI,91
|
|
267
|
+
SQLAlchemy-2.0.34.dist-info/top_level.txt,sha256=rp-ZgB7D8G11ivXON5VGPjupT1voYmWqkciDt5Uaw_Q,11
|
|
268
|
+
SQLAlchemy-2.0.34.dist-info/RECORD,,
|
sqlalchemy/__init__.py
CHANGED
|
@@ -22,10 +22,17 @@ from ...testing.provision import generate_driver_url
|
|
|
22
22
|
from ...testing.provision import get_temp_table_name
|
|
23
23
|
from ...testing.provision import log
|
|
24
24
|
from ...testing.provision import normalize_sequence
|
|
25
|
+
from ...testing.provision import post_configure_engine
|
|
25
26
|
from ...testing.provision import run_reap_dbs
|
|
26
27
|
from ...testing.provision import temp_table_keyword_args
|
|
27
28
|
|
|
28
29
|
|
|
30
|
+
@post_configure_engine.for_db("mssql")
|
|
31
|
+
def post_configure_engine(url, engine, follower_ident):
|
|
32
|
+
if engine.driver == "pyodbc":
|
|
33
|
+
engine.dialect.dbapi.pooling = False
|
|
34
|
+
|
|
35
|
+
|
|
29
36
|
@generate_driver_url.for_db("mssql")
|
|
30
37
|
def generate_driver_url(url, driver, query_str):
|
|
31
38
|
backend = url.get_backend_name()
|
|
@@ -103,6 +103,7 @@ class MSDialect_pymssql(MSDialect):
|
|
|
103
103
|
"message 20006", # Write to the server failed
|
|
104
104
|
"message 20017", # Unexpected EOF from the server
|
|
105
105
|
"message 20047", # DBPROCESS is dead or not enabled
|
|
106
|
+
"The server failed to resume the transaction",
|
|
106
107
|
):
|
|
107
108
|
if msg in str(e):
|
|
108
109
|
return True
|
|
@@ -62,7 +62,7 @@ hostname portion of the URL, without specifying a port, database name or
|
|
|
62
62
|
|
|
63
63
|
Users of Oracle Cloud should use this syntax and also configure the cloud
|
|
64
64
|
wallet as shown in cx_Oracle documentation `Connecting to Autononmous Databases
|
|
65
|
-
<https://cx-oracle.readthedocs.io/en/latest/user_guide/connection_handling.html#
|
|
65
|
+
<https://cx-oracle.readthedocs.io/en/latest/user_guide/connection_handling.html#autonomousdb>`_.
|
|
66
66
|
|
|
67
67
|
SID Connections
|
|
68
68
|
^^^^^^^^^^^^^^^
|
|
@@ -844,25 +844,45 @@ class AsyncAdapt_asyncpg_connection(AdaptedConnection):
|
|
|
844
844
|
else:
|
|
845
845
|
return AsyncAdapt_asyncpg_cursor(self)
|
|
846
846
|
|
|
847
|
+
async def _rollback_and_discard(self):
|
|
848
|
+
try:
|
|
849
|
+
await self._transaction.rollback()
|
|
850
|
+
finally:
|
|
851
|
+
# if asyncpg .rollback() was actually called, then whether or
|
|
852
|
+
# not it raised or succeeded, the transation is done, discard it
|
|
853
|
+
self._transaction = None
|
|
854
|
+
self._started = False
|
|
855
|
+
|
|
856
|
+
async def _commit_and_discard(self):
|
|
857
|
+
try:
|
|
858
|
+
await self._transaction.commit()
|
|
859
|
+
finally:
|
|
860
|
+
# if asyncpg .commit() was actually called, then whether or
|
|
861
|
+
# not it raised or succeeded, the transation is done, discard it
|
|
862
|
+
self._transaction = None
|
|
863
|
+
self._started = False
|
|
864
|
+
|
|
847
865
|
def rollback(self):
|
|
848
866
|
if self._started:
|
|
849
867
|
try:
|
|
850
|
-
self.await_(self.
|
|
851
|
-
except Exception as error:
|
|
852
|
-
self._handle_exception(error)
|
|
853
|
-
finally:
|
|
868
|
+
self.await_(self._rollback_and_discard())
|
|
854
869
|
self._transaction = None
|
|
855
870
|
self._started = False
|
|
871
|
+
except Exception as error:
|
|
872
|
+
# don't dereference asyncpg transaction if we didn't
|
|
873
|
+
# actually try to call rollback() on it
|
|
874
|
+
self._handle_exception(error)
|
|
856
875
|
|
|
857
876
|
def commit(self):
|
|
858
877
|
if self._started:
|
|
859
878
|
try:
|
|
860
|
-
self.await_(self.
|
|
861
|
-
except Exception as error:
|
|
862
|
-
self._handle_exception(error)
|
|
863
|
-
finally:
|
|
879
|
+
self.await_(self._commit_and_discard())
|
|
864
880
|
self._transaction = None
|
|
865
881
|
self._started = False
|
|
882
|
+
except Exception as error:
|
|
883
|
+
# don't dereference asyncpg transaction if we didn't
|
|
884
|
+
# actually try to call commit() on it
|
|
885
|
+
self._handle_exception(error)
|
|
866
886
|
|
|
867
887
|
def close(self):
|
|
868
888
|
self.rollback()
|
|
@@ -879,6 +899,7 @@ class AsyncAdapt_asyncpg_connection(AdaptedConnection):
|
|
|
879
899
|
self.await_(self._connection.close(timeout=2))
|
|
880
900
|
except (
|
|
881
901
|
asyncio.TimeoutError,
|
|
902
|
+
asyncio.CancelledError,
|
|
882
903
|
OSError,
|
|
883
904
|
self.dbapi.asyncpg.PostgresError,
|
|
884
905
|
):
|
|
@@ -2588,8 +2588,8 @@ class SQLiteDialect(default.DefaultDialect):
|
|
|
2588
2588
|
return
|
|
2589
2589
|
UNIQUE_PATTERN = r'(?:CONSTRAINT "?(.+?)"? +)?UNIQUE *\((.+?)\)'
|
|
2590
2590
|
INLINE_UNIQUE_PATTERN = (
|
|
2591
|
-
r'(?:(".+?")|(?:[\[`])?([a-z0-9_]+)(?:[\]`])?) '
|
|
2592
|
-
r"+[a-z0-9_ ]+? +UNIQUE"
|
|
2591
|
+
r'(?:(".+?")|(?:[\[`])?([a-z0-9_]+)(?:[\]`])?)[\t ]'
|
|
2592
|
+
r"+[a-z0-9_ ]+?[\t ]+UNIQUE"
|
|
2593
2593
|
)
|
|
2594
2594
|
|
|
2595
2595
|
for match in re.finditer(UNIQUE_PATTERN, table_data, re.I):
|
|
@@ -2624,15 +2624,69 @@ class SQLiteDialect(default.DefaultDialect):
|
|
|
2624
2624
|
connection, table_name, schema=schema, **kw
|
|
2625
2625
|
)
|
|
2626
2626
|
|
|
2627
|
-
|
|
2627
|
+
# Notes:
|
|
2628
|
+
# * The pattern currently matches any character for the name of the
|
|
2629
|
+
# constraint, including newline characters (re.S flag) as long as
|
|
2630
|
+
# none of the SQLite's table constraints keywords are encountered
|
|
2631
|
+
# by a negative lookahead.
|
|
2632
|
+
# This prevents the pattern from matching subsequent constraints
|
|
2633
|
+
# as part of the name.
|
|
2634
|
+
# This is only done for those keywords if seperated by spaces, to
|
|
2635
|
+
# support constraint names that contains them e.g. "check_value".
|
|
2636
|
+
#
|
|
2637
|
+
# * Because check constraint definitions can also contain newline
|
|
2638
|
+
# or tab characters, the pattern matches any character untill either
|
|
2639
|
+
# the beginning of the next constraint statement using a
|
|
2640
|
+
# non-capturing and non-consuming group, allowing the next one
|
|
2641
|
+
# to match, or the end of the table definition
|
|
2642
|
+
# e.g. newline and closing ')'.
|
|
2643
|
+
CHECK_PATTERN = r"""
|
|
2644
|
+
# Non-capturing group for the name part of named check constraints.
|
|
2645
|
+
# This group is optional as unnamed check constraints can exist.
|
|
2646
|
+
(?:
|
|
2647
|
+
# Match beginning of constraint definition seperated by whitespace.
|
|
2648
|
+
CONSTRAINT\s
|
|
2649
|
+
|
|
2650
|
+
# First capturing group that matches the actual name of the constraint.
|
|
2651
|
+
# Any characters is allowed, as long as none of the reserved table
|
|
2652
|
+
# constraint keywords are encountered using a negative lookahead.
|
|
2653
|
+
((?:(?!\sPRIMARY\s|\sFOREIGN\sKEY|\sUNIQUE\s|\sCHECK\s).)+)
|
|
2654
|
+
|
|
2655
|
+
# End of optional non-capturing name group seperated by whitespace.
|
|
2656
|
+
\s)?
|
|
2657
|
+
|
|
2658
|
+
# Match beginning of the check expression with starting parenthesis
|
|
2659
|
+
# and optional whitespace.
|
|
2660
|
+
CHECK\s?\(
|
|
2661
|
+
|
|
2662
|
+
# Match actual expression, which can be any character.
|
|
2663
|
+
(.+?)
|
|
2664
|
+
|
|
2665
|
+
# End parenthesis of the check expression.
|
|
2666
|
+
\)
|
|
2667
|
+
|
|
2668
|
+
# Non-capturing group that helps denote the end of the check
|
|
2669
|
+
# expression part.
|
|
2670
|
+
# This can either be (1) the beginning of the next constraint,
|
|
2671
|
+
# or (2) the end of the table definition.
|
|
2672
|
+
(?:
|
|
2673
|
+
|
|
2674
|
+
# (1) Matches end of check constraint with trailing comma,
|
|
2675
|
+
# optional whitespace (including newline), and the beginning
|
|
2676
|
+
# of the next constraint (either named or unnamed).
|
|
2677
|
+
,[\s\n]*(?=CONSTRAINT|CHECK|UNIQUE|FOREIGN|PRIMARY)
|
|
2678
|
+
# OR operator, seperating (1) & (2)
|
|
2679
|
+
|
|
|
2680
|
+
# (2) Matches end parenthesis of table definition, seperated by
|
|
2681
|
+
# newline.
|
|
2682
|
+
\n\)
|
|
2683
|
+
# End of non-capturing group.
|
|
2684
|
+
)
|
|
2685
|
+
"""
|
|
2628
2686
|
cks = []
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
# necessarily makes assumptions as to how the CREATE TABLE
|
|
2633
|
-
# was emitted.
|
|
2634
|
-
|
|
2635
|
-
for match in re.finditer(CHECK_PATTERN, table_data or "", re.I):
|
|
2687
|
+
for match in re.finditer(
|
|
2688
|
+
CHECK_PATTERN, table_data or "", re.I | re.S | re.VERBOSE
|
|
2689
|
+
):
|
|
2636
2690
|
name = match.group(1)
|
|
2637
2691
|
|
|
2638
2692
|
if name:
|
|
@@ -52,11 +52,11 @@ used. Double backslashes are probably needed::
|
|
|
52
52
|
e = create_engine('sqlite:///C:\\path\\to\\database.db')
|
|
53
53
|
|
|
54
54
|
To use sqlite ``:memory:`` database specify it as the filename using
|
|
55
|
-
``sqlite
|
|
55
|
+
``sqlite:///:memory:``. It's also the default if no filepath is
|
|
56
56
|
present, specifying only ``sqlite://`` and nothing else::
|
|
57
57
|
|
|
58
|
-
# in-memory database
|
|
59
|
-
e = create_engine('sqlite
|
|
58
|
+
# in-memory database (note three slashes)
|
|
59
|
+
e = create_engine('sqlite:///:memory:')
|
|
60
60
|
# also in-memory database
|
|
61
61
|
e2 = create_engine('sqlite://')
|
|
62
62
|
|
sqlalchemy/engine/reflection.py
CHANGED
|
@@ -55,6 +55,7 @@ from .. import util
|
|
|
55
55
|
from ..sql import operators
|
|
56
56
|
from ..sql import schema as sa_schema
|
|
57
57
|
from ..sql.cache_key import _ad_hoc_cache_key_from_args
|
|
58
|
+
from ..sql.elements import quoted_name
|
|
58
59
|
from ..sql.elements import TextClause
|
|
59
60
|
from ..sql.type_api import TypeEngine
|
|
60
61
|
from ..sql.visitors import InternalTraversal
|
|
@@ -89,8 +90,16 @@ def cache(
|
|
|
89
90
|
exclude = {"info_cache", "unreflectable"}
|
|
90
91
|
key = (
|
|
91
92
|
fn.__name__,
|
|
92
|
-
tuple(
|
|
93
|
-
|
|
93
|
+
tuple(
|
|
94
|
+
(str(a), a.quote) if isinstance(a, quoted_name) else a
|
|
95
|
+
for a in args
|
|
96
|
+
if isinstance(a, str)
|
|
97
|
+
),
|
|
98
|
+
tuple(
|
|
99
|
+
(k, (str(v), v.quote) if isinstance(v, quoted_name) else v)
|
|
100
|
+
for k, v in kw.items()
|
|
101
|
+
if k not in exclude
|
|
102
|
+
),
|
|
94
103
|
)
|
|
95
104
|
ret: _R = info_cache.get(key)
|
|
96
105
|
if ret is None:
|
sqlalchemy/orm/clsregistry.py
CHANGED
|
@@ -287,8 +287,9 @@ class _ModuleMarker(ClsRegistryToken):
|
|
|
287
287
|
|
|
288
288
|
def _remove_item(self, name: str) -> None:
|
|
289
289
|
self.contents.pop(name, None)
|
|
290
|
-
if not self.contents
|
|
291
|
-
self.parent
|
|
290
|
+
if not self.contents:
|
|
291
|
+
if self.parent is not None:
|
|
292
|
+
self.parent._remove_item(self.name)
|
|
292
293
|
_registries.discard(self)
|
|
293
294
|
|
|
294
295
|
def resolve_attr(self, key: str) -> Union[_ModNS, Type[Any]]:
|
sqlalchemy/orm/decl_base.py
CHANGED
|
@@ -431,7 +431,7 @@ class _ImperativeMapperConfig(_MapperConfig):
|
|
|
431
431
|
class _CollectedAnnotation(NamedTuple):
|
|
432
432
|
raw_annotation: _AnnotationScanType
|
|
433
433
|
mapped_container: Optional[Type[Mapped[Any]]]
|
|
434
|
-
extracted_mapped_annotation: Union[
|
|
434
|
+
extracted_mapped_annotation: Union[_AnnotationScanType, str]
|
|
435
435
|
is_dataclass: bool
|
|
436
436
|
attr_value: Any
|
|
437
437
|
originating_module: str
|
sqlalchemy/orm/util.py
CHANGED
|
@@ -89,6 +89,7 @@ from ..util.typing import (
|
|
|
89
89
|
de_stringify_union_elements as _de_stringify_union_elements,
|
|
90
90
|
)
|
|
91
91
|
from ..util.typing import eval_name_only as _eval_name_only
|
|
92
|
+
from ..util.typing import fixup_container_fwd_refs
|
|
92
93
|
from ..util.typing import is_origin_of_cls
|
|
93
94
|
from ..util.typing import Literal
|
|
94
95
|
from ..util.typing import Protocol
|
|
@@ -2321,7 +2322,7 @@ def _extract_mapped_subtype(
|
|
|
2321
2322
|
is_dataclass_field: bool,
|
|
2322
2323
|
expect_mapped: bool = True,
|
|
2323
2324
|
raiseerr: bool = True,
|
|
2324
|
-
) -> Optional[Tuple[Union[
|
|
2325
|
+
) -> Optional[Tuple[Union[_AnnotationScanType, str], Optional[type]]]:
|
|
2325
2326
|
"""given an annotation, figure out if it's ``Mapped[something]`` and if
|
|
2326
2327
|
so, return the ``something`` part.
|
|
2327
2328
|
|
|
@@ -2407,7 +2408,11 @@ def _extract_mapped_subtype(
|
|
|
2407
2408
|
"Expected sub-type for Mapped[] annotation"
|
|
2408
2409
|
)
|
|
2409
2410
|
|
|
2410
|
-
return
|
|
2411
|
+
return (
|
|
2412
|
+
# fix dict/list/set args to be ForwardRef, see #11814
|
|
2413
|
+
fixup_container_fwd_refs(annotated.__args__[0]),
|
|
2414
|
+
annotated.__origin__,
|
|
2415
|
+
)
|
|
2411
2416
|
|
|
2412
2417
|
|
|
2413
2418
|
def _mapper_property_as_plain_name(prop: Type[Any]) -> str:
|
sqlalchemy/sql/elements.py
CHANGED
|
@@ -5315,7 +5315,14 @@ class AnnotatedColumnElement(Annotated):
|
|
|
5315
5315
|
|
|
5316
5316
|
def _with_annotations(self, values):
|
|
5317
5317
|
clone = super()._with_annotations(values)
|
|
5318
|
-
|
|
5318
|
+
for attr in (
|
|
5319
|
+
"comparator",
|
|
5320
|
+
"_proxy_key",
|
|
5321
|
+
"_tq_key_label",
|
|
5322
|
+
"_tq_label",
|
|
5323
|
+
"_non_anon_label",
|
|
5324
|
+
):
|
|
5325
|
+
clone.__dict__.pop(attr, None)
|
|
5319
5326
|
return clone
|
|
5320
5327
|
|
|
5321
5328
|
@util.memoized_property
|
sqlalchemy/sql/schema.py
CHANGED
|
@@ -1434,7 +1434,7 @@ class Table(
|
|
|
1434
1434
|
|
|
1435
1435
|
args = []
|
|
1436
1436
|
for col in self.columns:
|
|
1437
|
-
args.append(col._copy(schema=actual_schema))
|
|
1437
|
+
args.append(col._copy(schema=actual_schema, _to_metadata=metadata))
|
|
1438
1438
|
table = Table(
|
|
1439
1439
|
name,
|
|
1440
1440
|
metadata,
|
|
@@ -2475,6 +2475,8 @@ class Column(DialectKWArgs, SchemaItem, ColumnClause[_T]):
|
|
|
2475
2475
|
server_onupdate = self.server_onupdate
|
|
2476
2476
|
if isinstance(server_default, (Computed, Identity)):
|
|
2477
2477
|
# TODO: likely should be copied in all cases
|
|
2478
|
+
# TODO: if a Sequence, we would need to transfer the Sequence
|
|
2479
|
+
# .metadata as well
|
|
2478
2480
|
args.append(server_default._copy(**kw))
|
|
2479
2481
|
server_default = server_onupdate = None
|
|
2480
2482
|
|
sqlalchemy/sql/selectable.py
CHANGED
|
@@ -473,14 +473,25 @@ class HasHints:
|
|
|
473
473
|
("_hints", InternalTraversal.dp_table_hint_list),
|
|
474
474
|
]
|
|
475
475
|
|
|
476
|
+
@_generative
|
|
476
477
|
def with_statement_hint(self, text: str, dialect_name: str = "*") -> Self:
|
|
477
478
|
"""Add a statement hint to this :class:`_expression.Select` or
|
|
478
479
|
other selectable object.
|
|
479
480
|
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
481
|
+
.. tip::
|
|
482
|
+
|
|
483
|
+
:meth:`_expression.Select.with_statement_hint` generally adds hints
|
|
484
|
+
**at the trailing end** of a SELECT statement. To place
|
|
485
|
+
dialect-specific hints such as optimizer hints at the **front** of
|
|
486
|
+
the SELECT statement after the SELECT keyword, use the
|
|
487
|
+
:meth:`_expression.Select.prefix_with` method for an open-ended
|
|
488
|
+
space, or for table-specific hints the
|
|
489
|
+
:meth:`_expression.Select.with_hint` may be used, which places
|
|
490
|
+
hints in a dialect-specific location.
|
|
491
|
+
|
|
492
|
+
This method is similar to :meth:`_expression.Select.with_hint` except
|
|
493
|
+
that it does not require an individual table, and instead applies to
|
|
494
|
+
the statement as a whole.
|
|
484
495
|
|
|
485
496
|
Hints here are specific to the backend database and may include
|
|
486
497
|
directives such as isolation levels, file directives, fetch directives,
|
|
@@ -492,7 +503,7 @@ class HasHints:
|
|
|
492
503
|
|
|
493
504
|
:meth:`_expression.Select.prefix_with` - generic SELECT prefixing
|
|
494
505
|
which also can suit some database-specific HINT syntaxes such as
|
|
495
|
-
MySQL optimizer hints
|
|
506
|
+
MySQL or Oracle optimizer hints
|
|
496
507
|
|
|
497
508
|
"""
|
|
498
509
|
return self._with_hint(None, text, dialect_name)
|
|
@@ -508,6 +519,17 @@ class HasHints:
|
|
|
508
519
|
selectable to this :class:`_expression.Select` or other selectable
|
|
509
520
|
object.
|
|
510
521
|
|
|
522
|
+
.. tip::
|
|
523
|
+
|
|
524
|
+
The :meth:`_expression.Select.with_hint` method adds hints that are
|
|
525
|
+
**specific to a single table** to a statement, in a location that
|
|
526
|
+
is **dialect-specific**. To add generic optimizer hints to the
|
|
527
|
+
**beginning** of a statement ahead of the SELECT keyword such as
|
|
528
|
+
for MySQL or Oracle, use the :meth:`_expression.Select.prefix_with`
|
|
529
|
+
method. To add optimizer hints to the **end** of a statement such
|
|
530
|
+
as for PostgreSQL, use the
|
|
531
|
+
:meth:`_expression.Select.with_statement_hint` method.
|
|
532
|
+
|
|
511
533
|
The text of the hint is rendered in the appropriate
|
|
512
534
|
location for the database backend in use, relative
|
|
513
535
|
to the given :class:`_schema.Table` or :class:`_expression.Alias`
|
|
@@ -537,6 +559,10 @@ class HasHints:
|
|
|
537
559
|
|
|
538
560
|
:meth:`_expression.Select.with_statement_hint`
|
|
539
561
|
|
|
562
|
+
:meth:`_expression.Select.prefix_with` - generic SELECT prefixing
|
|
563
|
+
which also can suit some database-specific HINT syntaxes such as
|
|
564
|
+
MySQL or Oracle optimizer hints
|
|
565
|
+
|
|
540
566
|
"""
|
|
541
567
|
|
|
542
568
|
return self._with_hint(selectable, text, dialect_name)
|
|
@@ -5793,22 +5819,33 @@ class Select(
|
|
|
5793
5819
|
)
|
|
5794
5820
|
return woc
|
|
5795
5821
|
|
|
5796
|
-
# START OVERLOADED FUNCTIONS self.with_only_columns Select 8
|
|
5822
|
+
# START OVERLOADED FUNCTIONS self.with_only_columns Select 1-8 ", *, maintain_column_froms: bool =..." # noqa: E501
|
|
5797
5823
|
|
|
5798
5824
|
# code within this block is **programmatically,
|
|
5799
|
-
# statically generated** by tools/
|
|
5825
|
+
# statically generated** by tools/generate_tuple_map_overloads.py
|
|
5800
5826
|
|
|
5801
5827
|
@overload
|
|
5802
|
-
def with_only_columns(
|
|
5828
|
+
def with_only_columns(
|
|
5829
|
+
self, __ent0: _TCCA[_T0], *, maintain_column_froms: bool = ...
|
|
5830
|
+
) -> Select[Tuple[_T0]]: ...
|
|
5803
5831
|
|
|
5804
5832
|
@overload
|
|
5805
5833
|
def with_only_columns(
|
|
5806
|
-
self,
|
|
5834
|
+
self,
|
|
5835
|
+
__ent0: _TCCA[_T0],
|
|
5836
|
+
__ent1: _TCCA[_T1],
|
|
5837
|
+
*,
|
|
5838
|
+
maintain_column_froms: bool = ...,
|
|
5807
5839
|
) -> Select[Tuple[_T0, _T1]]: ...
|
|
5808
5840
|
|
|
5809
5841
|
@overload
|
|
5810
5842
|
def with_only_columns(
|
|
5811
|
-
self,
|
|
5843
|
+
self,
|
|
5844
|
+
__ent0: _TCCA[_T0],
|
|
5845
|
+
__ent1: _TCCA[_T1],
|
|
5846
|
+
__ent2: _TCCA[_T2],
|
|
5847
|
+
*,
|
|
5848
|
+
maintain_column_froms: bool = ...,
|
|
5812
5849
|
) -> Select[Tuple[_T0, _T1, _T2]]: ...
|
|
5813
5850
|
|
|
5814
5851
|
@overload
|
|
@@ -5818,6 +5855,8 @@ class Select(
|
|
|
5818
5855
|
__ent1: _TCCA[_T1],
|
|
5819
5856
|
__ent2: _TCCA[_T2],
|
|
5820
5857
|
__ent3: _TCCA[_T3],
|
|
5858
|
+
*,
|
|
5859
|
+
maintain_column_froms: bool = ...,
|
|
5821
5860
|
) -> Select[Tuple[_T0, _T1, _T2, _T3]]: ...
|
|
5822
5861
|
|
|
5823
5862
|
@overload
|
|
@@ -5828,6 +5867,8 @@ class Select(
|
|
|
5828
5867
|
__ent2: _TCCA[_T2],
|
|
5829
5868
|
__ent3: _TCCA[_T3],
|
|
5830
5869
|
__ent4: _TCCA[_T4],
|
|
5870
|
+
*,
|
|
5871
|
+
maintain_column_froms: bool = ...,
|
|
5831
5872
|
) -> Select[Tuple[_T0, _T1, _T2, _T3, _T4]]: ...
|
|
5832
5873
|
|
|
5833
5874
|
@overload
|
|
@@ -5839,6 +5880,8 @@ class Select(
|
|
|
5839
5880
|
__ent3: _TCCA[_T3],
|
|
5840
5881
|
__ent4: _TCCA[_T4],
|
|
5841
5882
|
__ent5: _TCCA[_T5],
|
|
5883
|
+
*,
|
|
5884
|
+
maintain_column_froms: bool = ...,
|
|
5842
5885
|
) -> Select[Tuple[_T0, _T1, _T2, _T3, _T4, _T5]]: ...
|
|
5843
5886
|
|
|
5844
5887
|
@overload
|
|
@@ -5851,6 +5894,8 @@ class Select(
|
|
|
5851
5894
|
__ent4: _TCCA[_T4],
|
|
5852
5895
|
__ent5: _TCCA[_T5],
|
|
5853
5896
|
__ent6: _TCCA[_T6],
|
|
5897
|
+
*,
|
|
5898
|
+
maintain_column_froms: bool = ...,
|
|
5854
5899
|
) -> Select[Tuple[_T0, _T1, _T2, _T3, _T4, _T5, _T6]]: ...
|
|
5855
5900
|
|
|
5856
5901
|
@overload
|
|
@@ -5864,6 +5909,8 @@ class Select(
|
|
|
5864
5909
|
__ent5: _TCCA[_T5],
|
|
5865
5910
|
__ent6: _TCCA[_T6],
|
|
5866
5911
|
__ent7: _TCCA[_T7],
|
|
5912
|
+
*,
|
|
5913
|
+
maintain_column_froms: bool = ...,
|
|
5867
5914
|
) -> Select[Tuple[_T0, _T1, _T2, _T3, _T4, _T5, _T6, _T7]]: ...
|
|
5868
5915
|
|
|
5869
5916
|
# END OVERLOADED FUNCTIONS self.with_only_columns
|
sqlalchemy/sql/sqltypes.py
CHANGED
|
@@ -1085,6 +1085,11 @@ class SchemaType(SchemaEventTarget, TypeEngineMixin):
|
|
|
1085
1085
|
return self.adapt(
|
|
1086
1086
|
cast("Type[TypeEngine[Any]]", self.__class__),
|
|
1087
1087
|
_create_events=True,
|
|
1088
|
+
metadata=(
|
|
1089
|
+
kw.get("_to_metadata", self.metadata)
|
|
1090
|
+
if self.metadata is not None
|
|
1091
|
+
else None
|
|
1092
|
+
),
|
|
1088
1093
|
)
|
|
1089
1094
|
|
|
1090
1095
|
@overload
|
|
@@ -1908,6 +1913,13 @@ class Boolean(SchemaType, Emulated, TypeEngine[bool]):
|
|
|
1908
1913
|
if _adapted_from:
|
|
1909
1914
|
self.dispatch = self.dispatch._join(_adapted_from.dispatch)
|
|
1910
1915
|
|
|
1916
|
+
def copy(self, **kw):
|
|
1917
|
+
# override SchemaType.copy() to not include to_metadata logic
|
|
1918
|
+
return self.adapt(
|
|
1919
|
+
cast("Type[TypeEngine[Any]]", self.__class__),
|
|
1920
|
+
_create_events=True,
|
|
1921
|
+
)
|
|
1922
|
+
|
|
1911
1923
|
def _should_create_constraint(self, compiler, **kw):
|
|
1912
1924
|
if not self._is_impl_for_variant(compiler.dialect, kw):
|
|
1913
1925
|
return False
|
sqlalchemy/testing/provision.py
CHANGED
|
@@ -362,7 +362,7 @@ def update_db_opts(db_url, db_opts, options):
|
|
|
362
362
|
def post_configure_engine(url, engine, follower_ident):
|
|
363
363
|
"""Perform extra steps after configuring an engine for testing.
|
|
364
364
|
|
|
365
|
-
(For the internal dialects, currently only used by sqlite, oracle)
|
|
365
|
+
(For the internal dialects, currently only used by sqlite, oracle, mssql)
|
|
366
366
|
"""
|
|
367
367
|
|
|
368
368
|
|
|
@@ -1093,6 +1093,11 @@ class SuiteRequirements(Requirements):
|
|
|
1093
1093
|
|
|
1094
1094
|
return exclusions.only_if(go)
|
|
1095
1095
|
|
|
1096
|
+
@property
|
|
1097
|
+
def array_type(self):
|
|
1098
|
+
"""Target platform implements a native ARRAY type"""
|
|
1099
|
+
return exclusions.closed()
|
|
1100
|
+
|
|
1096
1101
|
@property
|
|
1097
1102
|
def json_type(self):
|
|
1098
1103
|
"""target platform implements a native JSON type."""
|
sqlalchemy/util/typing.py
CHANGED
|
@@ -188,9 +188,51 @@ def de_stringify_annotation(
|
|
|
188
188
|
)
|
|
189
189
|
|
|
190
190
|
return _copy_generic_annotation_with(annotation, elements)
|
|
191
|
+
|
|
191
192
|
return annotation # type: ignore
|
|
192
193
|
|
|
193
194
|
|
|
195
|
+
def fixup_container_fwd_refs(
|
|
196
|
+
type_: _AnnotationScanType,
|
|
197
|
+
) -> _AnnotationScanType:
|
|
198
|
+
"""Correct dict['x', 'y'] into dict[ForwardRef('x'), ForwardRef('y')]
|
|
199
|
+
and similar for list, set
|
|
200
|
+
|
|
201
|
+
"""
|
|
202
|
+
|
|
203
|
+
if (
|
|
204
|
+
is_generic(type_)
|
|
205
|
+
and typing_get_origin(type_)
|
|
206
|
+
in (
|
|
207
|
+
dict,
|
|
208
|
+
set,
|
|
209
|
+
list,
|
|
210
|
+
collections_abc.MutableSet,
|
|
211
|
+
collections_abc.MutableMapping,
|
|
212
|
+
collections_abc.MutableSequence,
|
|
213
|
+
collections_abc.Mapping,
|
|
214
|
+
collections_abc.Sequence,
|
|
215
|
+
)
|
|
216
|
+
# fight, kick and scream to struggle to tell the difference between
|
|
217
|
+
# dict[] and typing.Dict[] which DO NOT compare the same and DO NOT
|
|
218
|
+
# behave the same yet there is NO WAY to distinguish between which type
|
|
219
|
+
# it is using public attributes
|
|
220
|
+
and not re.match(
|
|
221
|
+
"typing.(?:Dict|List|Set|.*Mapping|.*Sequence|.*Set)", repr(type_)
|
|
222
|
+
)
|
|
223
|
+
):
|
|
224
|
+
# compat with py3.10 and earlier
|
|
225
|
+
return typing_get_origin(type_).__class_getitem__( # type: ignore
|
|
226
|
+
tuple(
|
|
227
|
+
[
|
|
228
|
+
ForwardRef(elem) if isinstance(elem, str) else elem
|
|
229
|
+
for elem in typing_get_args(type_)
|
|
230
|
+
]
|
|
231
|
+
)
|
|
232
|
+
)
|
|
233
|
+
return type_
|
|
234
|
+
|
|
235
|
+
|
|
194
236
|
def _copy_generic_annotation_with(
|
|
195
237
|
annotation: GenericProtocol[_T], elements: Tuple[_AnnotationScanType, ...]
|
|
196
238
|
) -> Type[_T]:
|
|
File without changes
|
|
File without changes
|