SQLAlchemy 2.0.34__py3-none-any.whl → 2.0.35__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.34.dist-info → SQLAlchemy-2.0.35.dist-info}/METADATA +1 -1
- {SQLAlchemy-2.0.34.dist-info → SQLAlchemy-2.0.35.dist-info}/RECORD +25 -25
- {SQLAlchemy-2.0.34.dist-info → SQLAlchemy-2.0.35.dist-info}/WHEEL +1 -1
- sqlalchemy/__init__.py +1 -1
- sqlalchemy/dialects/mysql/mariadbconnector.py +2 -0
- sqlalchemy/dialects/mysql/mysqlconnector.py +1 -0
- sqlalchemy/dialects/mysql/mysqldb.py +1 -1
- sqlalchemy/dialects/mysql/provision.py +3 -0
- sqlalchemy/dialects/oracle/base.py +2 -2
- sqlalchemy/dialects/postgresql/json.py +16 -9
- sqlalchemy/dialects/sqlite/base.py +14 -62
- sqlalchemy/ext/automap.py +1 -1
- sqlalchemy/orm/bulk_persistence.py +1 -0
- sqlalchemy/orm/context.py +14 -1
- sqlalchemy/orm/evaluator.py +11 -0
- sqlalchemy/orm/events.py +3 -1
- sqlalchemy/orm/query.py +2 -0
- sqlalchemy/orm/strategies.py +26 -3
- sqlalchemy/orm/strategy_options.py +1 -1
- sqlalchemy/sql/selectable.py +1 -1
- sqlalchemy/testing/requirements.py +5 -0
- sqlalchemy/testing/suite/test_reflection.py +137 -40
- sqlalchemy/util/typing.py +8 -1
- {SQLAlchemy-2.0.34.dist-info → SQLAlchemy-2.0.35.dist-info}/LICENSE +0 -0
- {SQLAlchemy-2.0.34.dist-info → SQLAlchemy-2.0.35.dist-info}/top_level.txt +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
sqlalchemy/__init__.py,sha256=
|
|
1
|
+
sqlalchemy/__init__.py,sha256=xHEMNoAWZaZfX2Zdm2gnVT8EWjaBfg6HpzG4ncSmPrk,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
|
|
@@ -38,17 +38,17 @@ sqlalchemy/dialects/mysql/enumerated.py,sha256=ipEPPQqoXfFwcywNdcLlZCEzHBtnitHRa
|
|
|
38
38
|
sqlalchemy/dialects/mysql/expression.py,sha256=lsmQCHKwfPezUnt27d2kR6ohk4IRFCA64KBS16kx5dc,4097
|
|
39
39
|
sqlalchemy/dialects/mysql/json.py,sha256=l6MEZ0qp8FgiRrIQvOMhyEJq0q6OqiEnvDTx5Cbt9uQ,2269
|
|
40
40
|
sqlalchemy/dialects/mysql/mariadb.py,sha256=kTfBLioLKk4JFFst4TY_iWqPtnvvQXFHknLfm89H2N8,853
|
|
41
|
-
sqlalchemy/dialects/mysql/mariadbconnector.py,sha256=
|
|
42
|
-
sqlalchemy/dialects/mysql/mysqlconnector.py,sha256=
|
|
43
|
-
sqlalchemy/dialects/mysql/mysqldb.py,sha256=
|
|
44
|
-
sqlalchemy/dialects/mysql/provision.py,sha256=
|
|
41
|
+
sqlalchemy/dialects/mysql/mariadbconnector.py,sha256=_S1aV93kyP52Nvj7HR9weThML4oUvSLsLqiVFdoLR2o,8623
|
|
42
|
+
sqlalchemy/dialects/mysql/mysqlconnector.py,sha256=oq3mtsNOMldUjs32JbJG2u3Hy3DObyVzUUMYfOkwkHg,5729
|
|
43
|
+
sqlalchemy/dialects/mysql/mysqldb.py,sha256=qUBbA6STeYGozutyTxHCo5p1W3p59QFFS2FwCgPrjBA,9503
|
|
44
|
+
sqlalchemy/dialects/mysql/provision.py,sha256=Jnk8UO9_Apd2odR2IQFLrscCfAmYxuBKcB8giS3bBog,3575
|
|
45
45
|
sqlalchemy/dialects/mysql/pymysql.py,sha256=GUnSHd2M2uKjmN46Hheymtm26g7phEgwYOXrX0zLY8M,4083
|
|
46
46
|
sqlalchemy/dialects/mysql/pyodbc.py,sha256=072crI4qVyPhajYvHnsfFeSrNjLFVPIjBQKo5uyz5yk,4297
|
|
47
47
|
sqlalchemy/dialects/mysql/reflection.py,sha256=3u34YwT1JJh3uThGZJZ3FKdnUcT7v08QB-tAl1r7VRk,22834
|
|
48
48
|
sqlalchemy/dialects/mysql/reserved_words.py,sha256=ucKX2p2c3UnMq2ayZuOHuf73eXhu7SKsOsTlIN1Q83I,9258
|
|
49
49
|
sqlalchemy/dialects/mysql/types.py,sha256=L5cTCsMT1pTedszNEM3jSxFNZEMcHQLprYCZ0vmfsnA,24343
|
|
50
50
|
sqlalchemy/dialects/oracle/__init__.py,sha256=p4-2gw7TT0bX_MoJXTGD4i8WHctYsK9kCRbkpzykBrc,1493
|
|
51
|
-
sqlalchemy/dialects/oracle/base.py,sha256=
|
|
51
|
+
sqlalchemy/dialects/oracle/base.py,sha256=HykzMCkN1LSRteoEttWb_ln9Q0YmOJ5tLbJan7TuWZ4,119699
|
|
52
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
|
|
@@ -62,7 +62,7 @@ sqlalchemy/dialects/postgresql/base.py,sha256=ed49Ode09deJF3jXr8V5sSHTwVoFVq0dlv
|
|
|
62
62
|
sqlalchemy/dialects/postgresql/dml.py,sha256=Pc69Le6qzmUHHb1FT5zeUSD31dWm6SBgdCAGW89cs3s,11212
|
|
63
63
|
sqlalchemy/dialects/postgresql/ext.py,sha256=1bZ--iNh2O9ym7l2gXZX48yP3yMO4dqb9RpYro2Mj2Q,16262
|
|
64
64
|
sqlalchemy/dialects/postgresql/hstore.py,sha256=otAx-RTDfpi_tcXkMuQV0JOIXtYgevgnsikLKKOkI6U,11541
|
|
65
|
-
sqlalchemy/dialects/postgresql/json.py,sha256=
|
|
65
|
+
sqlalchemy/dialects/postgresql/json.py,sha256=73nmtG-7TN01DytjIJnG8CHa8Q7KwlRdN0bhx4fEAT0,11590
|
|
66
66
|
sqlalchemy/dialects/postgresql/named_types.py,sha256=3IV1ufo7zJjKmX4VtGDEnoXE6xEqLJAtGG82IiqHXwY,17594
|
|
67
67
|
sqlalchemy/dialects/postgresql/operators.py,sha256=NsAaWun_tL3d_be0fs9YL6T4LPKK6crnmFxxIJHgyeY,2808
|
|
68
68
|
sqlalchemy/dialects/postgresql/pg8000.py,sha256=3yoekiWSF-xnaWMqG76XrYPMqerg-42TdmfsW_ivK9E,18640
|
|
@@ -75,7 +75,7 @@ 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=P15AcHoVWS20mMNQqnCfj94owUsTEX2ULtRn290AoF0,97837
|
|
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
|
|
@@ -108,7 +108,7 @@ sqlalchemy/event/legacy.py,sha256=teMPs00fO-4g8a_z2omcVKkYce5wj_1uvJO2n2MIeuo,82
|
|
|
108
108
|
sqlalchemy/event/registry.py,sha256=nfTSSyhjZZXc5wseWB4sXn-YibSc0LKX8mg17XlWmAo,10835
|
|
109
109
|
sqlalchemy/ext/__init__.py,sha256=S1fGKAbycnQDV01gs-JWGaFQ9GCD4QHwKcU2wnugg_o,322
|
|
110
110
|
sqlalchemy/ext/associationproxy.py,sha256=5O5ANHARO8jytvqBQmOu-QjNVE4Hh3tfYquqKAj5ajs,65771
|
|
111
|
-
sqlalchemy/ext/automap.py,sha256=
|
|
111
|
+
sqlalchemy/ext/automap.py,sha256=r0mUSyogNyqdBL4m9AA1NXbLiTLQmtvyQymsssNEipo,61581
|
|
112
112
|
sqlalchemy/ext/baked.py,sha256=H6T1il7GY84BhzPFj49UECSpZh_eBuiHomA-QIsYOYQ,17807
|
|
113
113
|
sqlalchemy/ext/compiler.py,sha256=ONPoxoKD2yUS9R2-oOhmPsA7efm-Bs0BXo7HE1dGlsU,20391
|
|
114
114
|
sqlalchemy/ext/horizontal_shard.py,sha256=wuwAPnHymln0unSBnyx-cpX0AfESKSsypaSQTYCvzDk,16750
|
|
@@ -141,17 +141,17 @@ sqlalchemy/orm/_orm_constructors.py,sha256=c4RMiYKIXzOTjuPIBbyRIzpizYjUBm2sd7k0n
|
|
|
141
141
|
sqlalchemy/orm/_typing.py,sha256=DVBfpHmDVK4x1zxaGJPY2GoTrAsyR6uexv20Lzf1afc,4973
|
|
142
142
|
sqlalchemy/orm/attributes.py,sha256=lorOHBJvJJYndOuafWJhHBbQ1pR6FAyimhqz-mErBRQ,92534
|
|
143
143
|
sqlalchemy/orm/base.py,sha256=re6A8ooMxLyfCAeQfhBwwxeJQkiH7EtzzOZIVIiTPlw,27466
|
|
144
|
-
sqlalchemy/orm/bulk_persistence.py,sha256=
|
|
144
|
+
sqlalchemy/orm/bulk_persistence.py,sha256=gNp2gFsGvV-5NhOPBL51TqKgR3ZRrS43jSwqUF-SwgY,71430
|
|
145
145
|
sqlalchemy/orm/clsregistry.py,sha256=IjoDZwWpjG42ji59L4M1EZvjBEoXPZykzENDtKWxU8A,17974
|
|
146
146
|
sqlalchemy/orm/collections.py,sha256=WEKuUCRgLhDhJEIBhZ21UrE0pBOyRm2zxD20GvbgA9g,52243
|
|
147
|
-
sqlalchemy/orm/context.py,sha256=
|
|
147
|
+
sqlalchemy/orm/context.py,sha256=FMPyw07OA9OXWQ32RQx52AEa2xTLSkqdYgx9R_yN1x0,112955
|
|
148
148
|
sqlalchemy/orm/decl_api.py,sha256=_WPKQ_vSE5k2TLtNmkaxxYmvbhZvkRMrrvCeDxdqDQE,63998
|
|
149
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
|
|
153
|
-
sqlalchemy/orm/evaluator.py,sha256=
|
|
154
|
-
sqlalchemy/orm/events.py,sha256=
|
|
153
|
+
sqlalchemy/orm/evaluator.py,sha256=tRETz4dNZ71VsEA8nG0hpefByB-W0zBt02IxcSR5H2g,12353
|
|
154
|
+
sqlalchemy/orm/events.py,sha256=1PiGT7JMUWTDAb3X1T79P02BMVDmcWEpatz1FwpLqoA,127777
|
|
155
155
|
sqlalchemy/orm/exc.py,sha256=IP40P-wOeXhkYk0YizuTC3wqm6W9cPTaQU08f5MMaQ0,7413
|
|
156
156
|
sqlalchemy/orm/identity.py,sha256=jHdCxCpCyda_8mFOfGmN_Pr0XZdKiU-2hFZshlNxbHs,9249
|
|
157
157
|
sqlalchemy/orm/instrumentation.py,sha256=M-kZmkUvHUxtf-0mCA8RIM5QmMH1hWlYR_pKMwaidjA,24321
|
|
@@ -162,14 +162,14 @@ sqlalchemy/orm/mapper.py,sha256=bfoRzNKKnjF-CDvr2Df7HZC9TepvtuQ49LRz_fW7DGQ,1710
|
|
|
162
162
|
sqlalchemy/orm/path_registry.py,sha256=sJZMv_WPqUpHfQtKWaX3WYFeKBcNJ8C3wOM2mkBGkTE,25920
|
|
163
163
|
sqlalchemy/orm/persistence.py,sha256=dzyB2JOXNwQgaCbN8kh0sEz00WFePr48qf8NWVCUZH8,61701
|
|
164
164
|
sqlalchemy/orm/properties.py,sha256=eDPFzxYUgdM3uWjHywnb1XW-i0tVKKyx7A2MCD31GQU,29306
|
|
165
|
-
sqlalchemy/orm/query.py,sha256=
|
|
165
|
+
sqlalchemy/orm/query.py,sha256=Cf0e94-u1XyoXJoOAmr4iFvtCwNY98kxUYyMPenaWTE,117708
|
|
166
166
|
sqlalchemy/orm/relationships.py,sha256=dS5SY0v1MiD7iCNnAQlHaI6prUQhL5EkXT7ijc8FR8E,128644
|
|
167
167
|
sqlalchemy/orm/scoping.py,sha256=rJVc7_Lic4V00HZ-UvYFWkVpXqdrMayRmIs4fIwH1UA,78688
|
|
168
168
|
sqlalchemy/orm/session.py,sha256=CZJTQ-wPwIy0c3AMFxgJnBgaft6eEf4JzcCLcaaCSjg,195979
|
|
169
169
|
sqlalchemy/orm/state.py,sha256=327-F4TG29s6mLC8oWRiO2PuvYIUZzY1MqUPjtUy7M4,37670
|
|
170
170
|
sqlalchemy/orm/state_changes.py,sha256=qKYg7NxwrDkuUY3EPygAztym6oAVUFcP2wXn7QD3Mz4,6815
|
|
171
|
-
sqlalchemy/orm/strategies.py,sha256=
|
|
172
|
-
sqlalchemy/orm/strategy_options.py,sha256
|
|
171
|
+
sqlalchemy/orm/strategies.py,sha256=U5EL1FBXOmkIV5HsryIlTvfQfoajYGCnvTbuKBnH0pQ,116224
|
|
172
|
+
sqlalchemy/orm/strategy_options.py,sha256=oeDl_rMDNAC_90N7ytsni-psXWAeQMhABQFyKBSmai0,85353
|
|
173
173
|
sqlalchemy/orm/sync.py,sha256=g7iZfSge1HgxMk9SKRgUgtHEbpbZ1kP_CBqOIdTOXqc,5779
|
|
174
174
|
sqlalchemy/orm/unitofwork.py,sha256=fiVaqcymbDDHRa1NjS90N9Z466nd5pkJOEi1dHO6QLY,27033
|
|
175
175
|
sqlalchemy/orm/util.py,sha256=Q0JT2JydyGiNiYT8AVe9B6jOdBRVHSOVDIcWOsXXIUQ,80929
|
|
@@ -203,7 +203,7 @@ 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
205
|
sqlalchemy/sql/schema.py,sha256=iFleWHkxi-3mKGiK_N1TzUqxnNwOpypB4bWDuAVQe8c,229717
|
|
206
|
-
sqlalchemy/sql/selectable.py,sha256=
|
|
206
|
+
sqlalchemy/sql/selectable.py,sha256=cgyV0AsPy4CXAFdhMiTCkbgaHiFilW9sclzxlHJKH3o,236460
|
|
207
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
|
|
@@ -220,7 +220,7 @@ sqlalchemy/testing/exclusions.py,sha256=T8B01hmm8WVs-EKcUOQRzabahPqblWJfOidi6bHJ
|
|
|
220
220
|
sqlalchemy/testing/pickleable.py,sha256=U9mIqk-zaxq9Xfy7HErP7UrKgTov-A3QFnhZh-NiOjI,2833
|
|
221
221
|
sqlalchemy/testing/profiling.py,sha256=PbuPhRFbauFilUONeY3tV_Y_5lBkD7iCa8VVyH2Sk9Y,10148
|
|
222
222
|
sqlalchemy/testing/provision.py,sha256=3qFor_sN1FFlS7odUGkKqLUxGmQZC9XM67I9vQ_zeXo,14626
|
|
223
|
-
sqlalchemy/testing/requirements.py,sha256=
|
|
223
|
+
sqlalchemy/testing/requirements.py,sha256=Z__o-1Rj9B7dI8E_l3qsKTvsg0rK198vB0A1p7A5dcM,52832
|
|
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
|
|
@@ -239,7 +239,7 @@ sqlalchemy/testing/suite/test_ddl.py,sha256=1Npkf0C_4UNxphthAGjG078n0vPEgnSIHpDu
|
|
|
239
239
|
sqlalchemy/testing/suite/test_deprecations.py,sha256=BcJxZTcjYqeOAENVElCg3hVvU6fkGEW3KGBMfnW8bng,5337
|
|
240
240
|
sqlalchemy/testing/suite/test_dialect.py,sha256=EH4ZQWbnGdtjmx5amZtTyhYmrkXJCvW1SQoLahoE7uk,22923
|
|
241
241
|
sqlalchemy/testing/suite/test_insert.py,sha256=9azifj6-OCD7s8h_tAO1uPw100ibQv8YoKc_VA3hn3c,18824
|
|
242
|
-
sqlalchemy/testing/suite/test_reflection.py,sha256=
|
|
242
|
+
sqlalchemy/testing/suite/test_reflection.py,sha256=7sML8-owubSQeEM7Ve6LbnB8uIVlNV00WWepKwII2a8,109648
|
|
243
243
|
sqlalchemy/testing/suite/test_results.py,sha256=X720GafdA4p75SOGS93j-dXkt6QDEnnJbU2bh18VCcg,16914
|
|
244
244
|
sqlalchemy/testing/suite/test_rowcount.py,sha256=3KDTlRgjpQ1OVfp__1cv8Hvq4CsDKzmrhJQ_WIJWoJg,7900
|
|
245
245
|
sqlalchemy/testing/suite/test_select.py,sha256=ulRZQJlzkwwcewEyisuBEXVWFR0Wshz9MEDxYYiYLwQ,61732
|
|
@@ -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=lFcGo1dJbZIZ9drAnvef-PzP0cX4LMxMSwgk3lJBb0g,18182
|
|
264
|
+
SQLAlchemy-2.0.35.dist-info/LICENSE,sha256=PA9Zq4h9BB3mpOUv_j6e212VIt6Qn66abNettue-MpM,1100
|
|
265
|
+
SQLAlchemy-2.0.35.dist-info/METADATA,sha256=nz-ukujebAhwlZl0txMOxlkTwDyPwTn3tWuKTcw8OMU,9632
|
|
266
|
+
SQLAlchemy-2.0.35.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
|
|
267
|
+
SQLAlchemy-2.0.35.dist-info/top_level.txt,sha256=rp-ZgB7D8G11ivXON5VGPjupT1voYmWqkciDt5Uaw_Q,11
|
|
268
|
+
SQLAlchemy-2.0.35.dist-info/RECORD,,
|
sqlalchemy/__init__.py
CHANGED
|
@@ -165,6 +165,7 @@ class MySQLDialect_mariadbconnector(MySQLDialect):
|
|
|
165
165
|
|
|
166
166
|
def create_connect_args(self, url):
|
|
167
167
|
opts = url.translate_connect_args()
|
|
168
|
+
opts.update(url.query)
|
|
168
169
|
|
|
169
170
|
int_params = [
|
|
170
171
|
"connect_timeout",
|
|
@@ -179,6 +180,7 @@ class MySQLDialect_mariadbconnector(MySQLDialect):
|
|
|
179
180
|
"ssl_verify_cert",
|
|
180
181
|
"ssl",
|
|
181
182
|
"pool_reset_connection",
|
|
183
|
+
"compress",
|
|
182
184
|
]
|
|
183
185
|
|
|
184
186
|
for key in int_params:
|
|
@@ -96,6 +96,7 @@ class MySQLDialect_mysqlconnector(MySQLDialect):
|
|
|
96
96
|
util.coerce_kw_type(opts, "allow_local_infile", bool)
|
|
97
97
|
util.coerce_kw_type(opts, "autocommit", bool)
|
|
98
98
|
util.coerce_kw_type(opts, "buffered", bool)
|
|
99
|
+
util.coerce_kw_type(opts, "client_flag", int)
|
|
99
100
|
util.coerce_kw_type(opts, "compress", bool)
|
|
100
101
|
util.coerce_kw_type(opts, "connection_timeout", int)
|
|
101
102
|
util.coerce_kw_type(opts, "connect_timeout", int)
|
|
@@ -212,7 +212,7 @@ class MySQLDialect_mysqldb(MySQLDialect):
|
|
|
212
212
|
util.coerce_kw_type(opts, "read_timeout", int)
|
|
213
213
|
util.coerce_kw_type(opts, "write_timeout", int)
|
|
214
214
|
util.coerce_kw_type(opts, "client_flag", int)
|
|
215
|
-
util.coerce_kw_type(opts, "local_infile",
|
|
215
|
+
util.coerce_kw_type(opts, "local_infile", bool)
|
|
216
216
|
# Note: using either of the below will cause all strings to be
|
|
217
217
|
# returned as Unicode, both in raw SQL operations and with column
|
|
218
218
|
# types like String and MSString.
|
|
@@ -40,6 +40,9 @@ def generate_driver_url(url, driver, query_str):
|
|
|
40
40
|
drivername="%s+%s" % (backend, driver)
|
|
41
41
|
).update_query_string(query_str)
|
|
42
42
|
|
|
43
|
+
if driver == "mariadbconnector":
|
|
44
|
+
new_url = new_url.difference_update_query(["charset"])
|
|
45
|
+
|
|
43
46
|
try:
|
|
44
47
|
new_url.get_dialect()
|
|
45
48
|
except exc.NoSuchModuleError:
|
|
@@ -331,7 +331,7 @@ ON UPDATE CASCADE
|
|
|
331
331
|
|
|
332
332
|
Oracle doesn't have native ON UPDATE CASCADE functionality. A trigger based
|
|
333
333
|
solution is available at
|
|
334
|
-
https://asktom.oracle.com/tkyte/update_cascade/index.html
|
|
334
|
+
https://web.archive.org/web/20090317041251/https://asktom.oracle.com/tkyte/update_cascade/index.html
|
|
335
335
|
|
|
336
336
|
When using the SQLAlchemy ORM, the ORM has limited ability to manually issue
|
|
337
337
|
cascading updates - specify ForeignKey objects using the
|
|
@@ -1277,7 +1277,7 @@ class OracleDDLCompiler(compiler.DDLCompiler):
|
|
|
1277
1277
|
|
|
1278
1278
|
# oracle has no ON UPDATE CASCADE -
|
|
1279
1279
|
# its only available via triggers
|
|
1280
|
-
# https://asktom.oracle.com/tkyte/update_cascade/index.html
|
|
1280
|
+
# https://web.archive.org/web/20090317041251/https://asktom.oracle.com/tkyte/update_cascade/index.html
|
|
1281
1281
|
if constraint.onupdate is not None:
|
|
1282
1282
|
util.warn(
|
|
1283
1283
|
"Oracle does not contain native UPDATE CASCADE "
|
|
@@ -256,22 +256,27 @@ class JSONB(JSON):
|
|
|
256
256
|
"""Define comparison operations for :class:`_types.JSON`."""
|
|
257
257
|
|
|
258
258
|
def has_key(self, other):
|
|
259
|
-
"""Boolean expression. Test for presence of a key
|
|
260
|
-
key may be a SQLA expression.
|
|
259
|
+
"""Boolean expression. Test for presence of a key (equivalent of
|
|
260
|
+
the ``?`` operator). Note that the key may be a SQLA expression.
|
|
261
261
|
"""
|
|
262
262
|
return self.operate(HAS_KEY, other, result_type=sqltypes.Boolean)
|
|
263
263
|
|
|
264
264
|
def has_all(self, other):
|
|
265
|
-
"""Boolean expression. Test for presence of all keys in jsonb
|
|
265
|
+
"""Boolean expression. Test for presence of all keys in jsonb
|
|
266
|
+
(equivalent of the ``?&`` operator)
|
|
267
|
+
"""
|
|
266
268
|
return self.operate(HAS_ALL, other, result_type=sqltypes.Boolean)
|
|
267
269
|
|
|
268
270
|
def has_any(self, other):
|
|
269
|
-
"""Boolean expression. Test for presence of any key in jsonb
|
|
271
|
+
"""Boolean expression. Test for presence of any key in jsonb
|
|
272
|
+
(equivalent of the ``?|`` operator)
|
|
273
|
+
"""
|
|
270
274
|
return self.operate(HAS_ANY, other, result_type=sqltypes.Boolean)
|
|
271
275
|
|
|
272
276
|
def contains(self, other, **kwargs):
|
|
273
277
|
"""Boolean expression. Test if keys (or array) are a superset
|
|
274
|
-
of/contained the keys of the argument jsonb expression
|
|
278
|
+
of/contained the keys of the argument jsonb expression
|
|
279
|
+
(equivalent of the ``@>`` operator).
|
|
275
280
|
|
|
276
281
|
kwargs may be ignored by this operator but are required for API
|
|
277
282
|
conformance.
|
|
@@ -280,7 +285,8 @@ class JSONB(JSON):
|
|
|
280
285
|
|
|
281
286
|
def contained_by(self, other):
|
|
282
287
|
"""Boolean expression. Test if keys are a proper subset of the
|
|
283
|
-
keys of the argument jsonb expression
|
|
288
|
+
keys of the argument jsonb expression
|
|
289
|
+
(equivalent of the ``<@`` operator).
|
|
284
290
|
"""
|
|
285
291
|
return self.operate(
|
|
286
292
|
CONTAINED_BY, other, result_type=sqltypes.Boolean
|
|
@@ -288,7 +294,7 @@ class JSONB(JSON):
|
|
|
288
294
|
|
|
289
295
|
def delete_path(self, array):
|
|
290
296
|
"""JSONB expression. Deletes field or array element specified in
|
|
291
|
-
the argument array.
|
|
297
|
+
the argument array (equivalent of the ``#-`` operator).
|
|
292
298
|
|
|
293
299
|
The input may be a list of strings that will be coerced to an
|
|
294
300
|
``ARRAY`` or an instance of :meth:`_postgres.array`.
|
|
@@ -302,7 +308,7 @@ class JSONB(JSON):
|
|
|
302
308
|
|
|
303
309
|
def path_exists(self, other):
|
|
304
310
|
"""Boolean expression. Test for presence of item given by the
|
|
305
|
-
argument JSONPath expression.
|
|
311
|
+
argument JSONPath expression (equivalent of the ``@?`` operator).
|
|
306
312
|
|
|
307
313
|
.. versionadded:: 2.0
|
|
308
314
|
"""
|
|
@@ -312,7 +318,8 @@ class JSONB(JSON):
|
|
|
312
318
|
|
|
313
319
|
def path_match(self, other):
|
|
314
320
|
"""Boolean expression. Test if JSONPath predicate given by the
|
|
315
|
-
argument JSONPath expression matches
|
|
321
|
+
argument JSONPath expression matches
|
|
322
|
+
(equivalent of the ``@@`` operator).
|
|
316
323
|
|
|
317
324
|
Only the first item of the result is taken into account.
|
|
318
325
|
|
|
@@ -2624,69 +2624,21 @@ class SQLiteDialect(default.DefaultDialect):
|
|
|
2624
2624
|
connection, table_name, schema=schema, **kw
|
|
2625
2625
|
)
|
|
2626
2626
|
|
|
2627
|
-
#
|
|
2628
|
-
#
|
|
2629
|
-
#
|
|
2630
|
-
#
|
|
2631
|
-
#
|
|
2632
|
-
#
|
|
2633
|
-
#
|
|
2634
|
-
#
|
|
2635
|
-
#
|
|
2636
|
-
#
|
|
2637
|
-
|
|
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
|
-
"""
|
|
2627
|
+
# NOTE NOTE NOTE
|
|
2628
|
+
# DO NOT CHANGE THIS REGULAR EXPRESSION. There is no known way
|
|
2629
|
+
# to parse CHECK constraints that contain newlines themselves using
|
|
2630
|
+
# regular expressions, and the approach here relies upon each
|
|
2631
|
+
# individual
|
|
2632
|
+
# CHECK constraint being on a single line by itself. This
|
|
2633
|
+
# necessarily makes assumptions as to how the CREATE TABLE
|
|
2634
|
+
# was emitted. A more comprehensive DDL parsing solution would be
|
|
2635
|
+
# needed to improve upon the current situation. See #11840 for
|
|
2636
|
+
# background
|
|
2637
|
+
CHECK_PATTERN = r"(?:CONSTRAINT (.+) +)?CHECK *\( *(.+) *\),? *"
|
|
2686
2638
|
cks = []
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
2639
|
+
|
|
2640
|
+
for match in re.finditer(CHECK_PATTERN, table_data or "", re.I):
|
|
2641
|
+
|
|
2690
2642
|
name = match.group(1)
|
|
2691
2643
|
|
|
2692
2644
|
if name:
|
sqlalchemy/ext/automap.py
CHANGED
|
@@ -11,7 +11,7 @@ schema, typically though not necessarily one which is reflected.
|
|
|
11
11
|
|
|
12
12
|
It is hoped that the :class:`.AutomapBase` system provides a quick
|
|
13
13
|
and modernized solution to the problem that the very famous
|
|
14
|
-
`SQLSoup <https://
|
|
14
|
+
`SQLSoup <https://pypi.org/project/sqlsoup/>`_
|
|
15
15
|
also tries to solve, that of generating a quick and rudimentary object
|
|
16
16
|
model from an existing database on the fly. By addressing the issue strictly
|
|
17
17
|
at the mapper configuration level, and integrating fully with existing
|
sqlalchemy/orm/context.py
CHANGED
|
@@ -104,6 +104,7 @@ class QueryContext:
|
|
|
104
104
|
"top_level_context",
|
|
105
105
|
"compile_state",
|
|
106
106
|
"query",
|
|
107
|
+
"user_passed_query",
|
|
107
108
|
"params",
|
|
108
109
|
"load_options",
|
|
109
110
|
"bind_arguments",
|
|
@@ -148,6 +149,10 @@ class QueryContext:
|
|
|
148
149
|
self,
|
|
149
150
|
compile_state: CompileState,
|
|
150
151
|
statement: Union[Select[Any], FromStatement[Any]],
|
|
152
|
+
user_passed_query: Union[
|
|
153
|
+
Select[Any],
|
|
154
|
+
FromStatement[Any],
|
|
155
|
+
],
|
|
151
156
|
params: _CoreSingleExecuteParams,
|
|
152
157
|
session: Session,
|
|
153
158
|
load_options: Union[
|
|
@@ -162,6 +167,13 @@ class QueryContext:
|
|
|
162
167
|
self.bind_arguments = bind_arguments or _EMPTY_DICT
|
|
163
168
|
self.compile_state = compile_state
|
|
164
169
|
self.query = statement
|
|
170
|
+
|
|
171
|
+
# the query that the end user passed to Session.execute() or similar.
|
|
172
|
+
# this is usually the same as .query, except in the bulk_persistence
|
|
173
|
+
# routines where a separate FromStatement is manufactured in the
|
|
174
|
+
# compile stage; this allows differentiation in that case.
|
|
175
|
+
self.user_passed_query = user_passed_query
|
|
176
|
+
|
|
165
177
|
self.session = session
|
|
166
178
|
self.loaders_require_buffering = False
|
|
167
179
|
self.loaders_require_uniquing = False
|
|
@@ -169,7 +181,7 @@ class QueryContext:
|
|
|
169
181
|
self.top_level_context = load_options._sa_top_level_orm_context
|
|
170
182
|
|
|
171
183
|
cached_options = compile_state.select_statement._with_options
|
|
172
|
-
uncached_options =
|
|
184
|
+
uncached_options = user_passed_query._with_options
|
|
173
185
|
|
|
174
186
|
# see issue #7447 , #8399 for some background
|
|
175
187
|
# propagated loader options will be present on loaded InstanceState
|
|
@@ -578,6 +590,7 @@ class ORMCompileState(AbstractORMCompileState):
|
|
|
578
590
|
querycontext = QueryContext(
|
|
579
591
|
compile_state,
|
|
580
592
|
statement,
|
|
593
|
+
statement,
|
|
581
594
|
params,
|
|
582
595
|
session,
|
|
583
596
|
load_options,
|
sqlalchemy/orm/evaluator.py
CHANGED
|
@@ -28,6 +28,7 @@ from .. import exc
|
|
|
28
28
|
from .. import inspect
|
|
29
29
|
from ..sql import and_
|
|
30
30
|
from ..sql import operators
|
|
31
|
+
from ..sql.sqltypes import Concatenable
|
|
31
32
|
from ..sql.sqltypes import Integer
|
|
32
33
|
from ..sql.sqltypes import Numeric
|
|
33
34
|
from ..util import warn_deprecated
|
|
@@ -311,6 +312,16 @@ class _EvaluatorCompiler:
|
|
|
311
312
|
def visit_concat_op_binary_op(
|
|
312
313
|
self, operator, eval_left, eval_right, clause
|
|
313
314
|
):
|
|
315
|
+
|
|
316
|
+
if not issubclass(
|
|
317
|
+
clause.left.type._type_affinity, Concatenable
|
|
318
|
+
) or not issubclass(clause.right.type._type_affinity, Concatenable):
|
|
319
|
+
raise UnevaluatableError(
|
|
320
|
+
f"Cannot evaluate concatenate operator "
|
|
321
|
+
f'"{operator.__name__}" for '
|
|
322
|
+
f"datatypes {clause.left.type}, {clause.right.type}"
|
|
323
|
+
)
|
|
324
|
+
|
|
314
325
|
return self._straight_evaluate(
|
|
315
326
|
lambda a, b: a + b, eval_left, eval_right, clause
|
|
316
327
|
)
|
sqlalchemy/orm/events.py
CHANGED
|
@@ -3155,7 +3155,9 @@ class QueryEvents(event.Events[Query[Any]]):
|
|
|
3155
3155
|
entity = desc['entity']
|
|
3156
3156
|
query = query.filter(entity.deleted == False)
|
|
3157
3157
|
|
|
3158
|
-
update_context.values['timestamp'] =
|
|
3158
|
+
update_context.values['timestamp'] = (
|
|
3159
|
+
datetime.datetime.now(datetime.UTC)
|
|
3160
|
+
)
|
|
3159
3161
|
return query
|
|
3160
3162
|
|
|
3161
3163
|
The ``.values`` dictionary of the "update context" object can also
|
sqlalchemy/orm/query.py
CHANGED
|
@@ -2939,6 +2939,7 @@ class Query(
|
|
|
2939
2939
|
context = QueryContext(
|
|
2940
2940
|
compile_state,
|
|
2941
2941
|
compile_state.statement,
|
|
2942
|
+
compile_state.statement,
|
|
2942
2943
|
self._params,
|
|
2943
2944
|
self.session,
|
|
2944
2945
|
self.load_options,
|
|
@@ -3298,6 +3299,7 @@ class Query(
|
|
|
3298
3299
|
context = QueryContext(
|
|
3299
3300
|
compile_state,
|
|
3300
3301
|
compile_state.statement,
|
|
3302
|
+
compile_state.statement,
|
|
3301
3303
|
self._params,
|
|
3302
3304
|
self.session,
|
|
3303
3305
|
self.load_options,
|
sqlalchemy/orm/strategies.py
CHANGED
|
@@ -1961,6 +1961,18 @@ class SubqueryLoader(PostLoader):
|
|
|
1961
1961
|
adapter,
|
|
1962
1962
|
populators,
|
|
1963
1963
|
):
|
|
1964
|
+
if (
|
|
1965
|
+
loadopt
|
|
1966
|
+
and context.compile_state.statement is not None
|
|
1967
|
+
and context.compile_state.statement.is_dml
|
|
1968
|
+
):
|
|
1969
|
+
util.warn_deprecated(
|
|
1970
|
+
"The subqueryload loader option is not compatible with DML "
|
|
1971
|
+
"statements such as INSERT, UPDATE. Only SELECT may be used."
|
|
1972
|
+
"This warning will become an exception in a future release.",
|
|
1973
|
+
"2.0",
|
|
1974
|
+
)
|
|
1975
|
+
|
|
1964
1976
|
if context.refresh_state:
|
|
1965
1977
|
return self._immediateload_create_row_processor(
|
|
1966
1978
|
context,
|
|
@@ -2126,6 +2138,17 @@ class JoinedLoader(AbstractRelationshipLoader):
|
|
|
2126
2138
|
|
|
2127
2139
|
if not compile_state.compile_options._enable_eagerloads:
|
|
2128
2140
|
return
|
|
2141
|
+
elif (
|
|
2142
|
+
loadopt
|
|
2143
|
+
and compile_state.statement is not None
|
|
2144
|
+
and compile_state.statement.is_dml
|
|
2145
|
+
):
|
|
2146
|
+
util.warn_deprecated(
|
|
2147
|
+
"The joinedload loader option is not compatible with DML "
|
|
2148
|
+
"statements such as INSERT, UPDATE. Only SELECT may be used."
|
|
2149
|
+
"This warning will become an exception in a future release.",
|
|
2150
|
+
"2.0",
|
|
2151
|
+
)
|
|
2129
2152
|
elif self.uselist:
|
|
2130
2153
|
compile_state.multi_row_eager_loaders = True
|
|
2131
2154
|
|
|
@@ -3152,7 +3175,7 @@ class SelectInLoader(PostLoader, util.MemoizedSlots):
|
|
|
3152
3175
|
orig_query = context.compile_state.select_statement
|
|
3153
3176
|
|
|
3154
3177
|
# the actual statement that was requested is this one:
|
|
3155
|
-
# context_query = context.
|
|
3178
|
+
# context_query = context.user_passed_query
|
|
3156
3179
|
#
|
|
3157
3180
|
# that's not the cached one, however. So while it is of the identical
|
|
3158
3181
|
# structure, if it has entities like AliasedInsp, which we get from
|
|
@@ -3176,11 +3199,11 @@ class SelectInLoader(PostLoader, util.MemoizedSlots):
|
|
|
3176
3199
|
|
|
3177
3200
|
effective_path = path[self.parent_property]
|
|
3178
3201
|
|
|
3179
|
-
if orig_query is context.
|
|
3202
|
+
if orig_query is context.user_passed_query:
|
|
3180
3203
|
new_options = orig_query._with_options
|
|
3181
3204
|
else:
|
|
3182
3205
|
cached_options = orig_query._with_options
|
|
3183
|
-
uncached_options = context.
|
|
3206
|
+
uncached_options = context.user_passed_query._with_options
|
|
3184
3207
|
|
|
3185
3208
|
# propagate compile state options from the original query,
|
|
3186
3209
|
# updating their "extra_criteria" as necessary.
|
|
@@ -1081,7 +1081,7 @@ class Load(_AbstractLoad):
|
|
|
1081
1081
|
else:
|
|
1082
1082
|
return self
|
|
1083
1083
|
|
|
1084
|
-
replacement_cache_key = context.
|
|
1084
|
+
replacement_cache_key = context.user_passed_query._generate_cache_key()
|
|
1085
1085
|
|
|
1086
1086
|
if replacement_cache_key is None:
|
|
1087
1087
|
return self
|
sqlalchemy/sql/selectable.py
CHANGED
|
@@ -796,6 +796,11 @@ class SuiteRequirements(Requirements):
|
|
|
796
796
|
"""target dialect supports reflection of unique constraints"""
|
|
797
797
|
return exclusions.open()
|
|
798
798
|
|
|
799
|
+
@property
|
|
800
|
+
def inline_check_constraint_reflection(self):
|
|
801
|
+
"""target dialect supports reflection of inline check constraints"""
|
|
802
|
+
return exclusions.closed()
|
|
803
|
+
|
|
799
804
|
@property
|
|
800
805
|
def check_constraint_reflection(self):
|
|
801
806
|
"""target dialect supports reflection of check constraints"""
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
# the MIT License: https://www.opensource.org/licenses/mit-license.php
|
|
7
7
|
# mypy: ignore-errors
|
|
8
8
|
|
|
9
|
+
import contextlib
|
|
9
10
|
import operator
|
|
10
11
|
import re
|
|
11
12
|
|
|
@@ -2454,62 +2455,158 @@ class TableNoColumnsTest(fixtures.TestBase):
|
|
|
2454
2455
|
class ComponentReflectionTestExtra(ComparesIndexes, fixtures.TestBase):
|
|
2455
2456
|
__backend__ = True
|
|
2456
2457
|
|
|
2457
|
-
@testing.
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
def test_get_check_constraints(self, metadata, connection, use_schema):
|
|
2462
|
-
if use_schema:
|
|
2463
|
-
schema = config.test_schema
|
|
2458
|
+
@testing.fixture(params=[True, False])
|
|
2459
|
+
def use_schema_fixture(self, request):
|
|
2460
|
+
if request.param:
|
|
2461
|
+
return config.test_schema
|
|
2464
2462
|
else:
|
|
2465
|
-
|
|
2463
|
+
return None
|
|
2466
2464
|
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
sa.CheckConstraint(
|
|
2473
|
-
"a = 1 OR (a > 2 AND a < 5)", name="UsesCasing"
|
|
2474
|
-
),
|
|
2475
|
-
schema=schema,
|
|
2476
|
-
)
|
|
2477
|
-
Table(
|
|
2478
|
-
"no_constraints",
|
|
2479
|
-
metadata,
|
|
2480
|
-
Column("data", sa.String(20)),
|
|
2481
|
-
schema=schema,
|
|
2482
|
-
)
|
|
2465
|
+
@testing.fixture()
|
|
2466
|
+
def inspect_for_table(self, metadata, connection, use_schema_fixture):
|
|
2467
|
+
@contextlib.contextmanager
|
|
2468
|
+
def go(tablename):
|
|
2469
|
+
yield use_schema_fixture, inspect(connection)
|
|
2483
2470
|
|
|
2484
|
-
|
|
2471
|
+
metadata.create_all(connection)
|
|
2485
2472
|
|
|
2486
|
-
|
|
2487
|
-
reflected = sorted(
|
|
2488
|
-
insp.get_check_constraints("sa_cc", schema=schema),
|
|
2489
|
-
key=operator.itemgetter("name"),
|
|
2490
|
-
)
|
|
2473
|
+
return go
|
|
2491
2474
|
|
|
2475
|
+
def ck_eq(self, reflected, expected):
|
|
2492
2476
|
# trying to minimize effect of quoting, parenthesis, etc.
|
|
2493
2477
|
# may need to add more to this as new dialects get CHECK
|
|
2494
2478
|
# constraint reflection support
|
|
2495
2479
|
def normalize(sqltext):
|
|
2496
2480
|
return " ".join(
|
|
2497
|
-
re.findall(r"and|\d|=|a|or|<|>", sqltext.lower(), re.I)
|
|
2481
|
+
re.findall(r"and|\d|=|a|b|c|or|<|>", sqltext.lower(), re.I)
|
|
2498
2482
|
)
|
|
2499
2483
|
|
|
2500
|
-
reflected =
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2484
|
+
reflected = sorted(
|
|
2485
|
+
[
|
|
2486
|
+
{"name": item["name"], "sqltext": normalize(item["sqltext"])}
|
|
2487
|
+
for item in reflected
|
|
2488
|
+
],
|
|
2489
|
+
key=lambda item: (item["sqltext"]),
|
|
2490
|
+
)
|
|
2491
|
+
|
|
2492
|
+
expected = sorted(
|
|
2493
|
+
expected,
|
|
2494
|
+
key=lambda item: (item["sqltext"]),
|
|
2495
|
+
)
|
|
2496
|
+
eq_(reflected, expected)
|
|
2497
|
+
|
|
2498
|
+
@testing.requires.check_constraint_reflection
|
|
2499
|
+
def test_check_constraint_no_constraint(self, metadata, inspect_for_table):
|
|
2500
|
+
with inspect_for_table("no_constraints") as (schema, inspector):
|
|
2501
|
+
Table(
|
|
2502
|
+
"no_constraints",
|
|
2503
|
+
metadata,
|
|
2504
|
+
Column("data", sa.String(20)),
|
|
2505
|
+
schema=schema,
|
|
2506
|
+
)
|
|
2507
|
+
|
|
2508
|
+
self.ck_eq(
|
|
2509
|
+
inspector.get_check_constraints("no_constraints", schema=schema),
|
|
2510
|
+
[],
|
|
2511
|
+
)
|
|
2512
|
+
|
|
2513
|
+
@testing.requires.inline_check_constraint_reflection
|
|
2514
|
+
@testing.combinations(
|
|
2515
|
+
"my_inline", "MyInline", None, argnames="constraint_name"
|
|
2516
|
+
)
|
|
2517
|
+
def test_check_constraint_inline(
|
|
2518
|
+
self, metadata, inspect_for_table, constraint_name
|
|
2519
|
+
):
|
|
2520
|
+
|
|
2521
|
+
with inspect_for_table("sa_cc") as (schema, inspector):
|
|
2522
|
+
Table(
|
|
2523
|
+
"sa_cc",
|
|
2524
|
+
metadata,
|
|
2525
|
+
Column("id", Integer(), primary_key=True),
|
|
2526
|
+
Column(
|
|
2527
|
+
"a",
|
|
2528
|
+
Integer(),
|
|
2529
|
+
sa.CheckConstraint(
|
|
2530
|
+
"a > 1 AND a < 5", name=constraint_name
|
|
2531
|
+
),
|
|
2532
|
+
),
|
|
2533
|
+
Column("data", String(50)),
|
|
2534
|
+
schema=schema,
|
|
2535
|
+
)
|
|
2536
|
+
|
|
2537
|
+
reflected = inspector.get_check_constraints("sa_cc", schema=schema)
|
|
2538
|
+
|
|
2539
|
+
self.ck_eq(
|
|
2540
|
+
reflected,
|
|
2541
|
+
[
|
|
2542
|
+
{
|
|
2543
|
+
"name": constraint_name or mock.ANY,
|
|
2544
|
+
"sqltext": "a > 1 and a < 5",
|
|
2545
|
+
},
|
|
2546
|
+
],
|
|
2547
|
+
)
|
|
2548
|
+
|
|
2549
|
+
@testing.requires.check_constraint_reflection
|
|
2550
|
+
@testing.combinations(
|
|
2551
|
+
"my_ck_const", "MyCkConst", None, argnames="constraint_name"
|
|
2552
|
+
)
|
|
2553
|
+
def test_check_constraint_standalone(
|
|
2554
|
+
self, metadata, inspect_for_table, constraint_name
|
|
2555
|
+
):
|
|
2556
|
+
with inspect_for_table("sa_cc") as (schema, inspector):
|
|
2557
|
+
Table(
|
|
2558
|
+
"sa_cc",
|
|
2559
|
+
metadata,
|
|
2560
|
+
Column("a", Integer()),
|
|
2561
|
+
sa.CheckConstraint(
|
|
2562
|
+
"a = 1 OR (a > 2 AND a < 5)", name=constraint_name
|
|
2563
|
+
),
|
|
2564
|
+
schema=schema,
|
|
2565
|
+
)
|
|
2566
|
+
|
|
2567
|
+
reflected = inspector.get_check_constraints("sa_cc", schema=schema)
|
|
2568
|
+
|
|
2569
|
+
self.ck_eq(
|
|
2570
|
+
reflected,
|
|
2571
|
+
[
|
|
2572
|
+
{
|
|
2573
|
+
"name": constraint_name or mock.ANY,
|
|
2574
|
+
"sqltext": "a = 1 or a > 2 and a < 5",
|
|
2575
|
+
},
|
|
2576
|
+
],
|
|
2577
|
+
)
|
|
2578
|
+
|
|
2579
|
+
@testing.requires.inline_check_constraint_reflection
|
|
2580
|
+
def test_check_constraint_mixed(self, metadata, inspect_for_table):
|
|
2581
|
+
with inspect_for_table("sa_cc") as (schema, inspector):
|
|
2582
|
+
Table(
|
|
2583
|
+
"sa_cc",
|
|
2584
|
+
metadata,
|
|
2585
|
+
Column("id", Integer(), primary_key=True),
|
|
2586
|
+
Column("a", Integer(), sa.CheckConstraint("a > 1 AND a < 5")),
|
|
2587
|
+
Column(
|
|
2588
|
+
"b",
|
|
2589
|
+
Integer(),
|
|
2590
|
+
sa.CheckConstraint("b > 1 AND b < 5", name="my_inline"),
|
|
2591
|
+
),
|
|
2592
|
+
Column("c", Integer()),
|
|
2593
|
+
Column("data", String(50)),
|
|
2594
|
+
sa.UniqueConstraint("data", name="some_uq"),
|
|
2595
|
+
sa.CheckConstraint("c > 1 AND c < 5", name="cc1"),
|
|
2596
|
+
sa.UniqueConstraint("c", name="some_c_uq"),
|
|
2597
|
+
schema=schema,
|
|
2598
|
+
)
|
|
2599
|
+
|
|
2600
|
+
reflected = inspector.get_check_constraints("sa_cc", schema=schema)
|
|
2601
|
+
|
|
2602
|
+
self.ck_eq(
|
|
2505
2603
|
reflected,
|
|
2506
2604
|
[
|
|
2507
|
-
{"name": "
|
|
2508
|
-
{"name": "
|
|
2605
|
+
{"name": "cc1", "sqltext": "c > 1 and c < 5"},
|
|
2606
|
+
{"name": "my_inline", "sqltext": "b > 1 and b < 5"},
|
|
2607
|
+
{"name": mock.ANY, "sqltext": "a > 1 and a < 5"},
|
|
2509
2608
|
],
|
|
2510
2609
|
)
|
|
2511
|
-
no_cst = "no_constraints"
|
|
2512
|
-
eq_(insp.get_check_constraints(no_cst, schema=schema), [])
|
|
2513
2610
|
|
|
2514
2611
|
@testing.requires.indexes_with_expressions
|
|
2515
2612
|
def test_reflect_expression_based_indexes(self, metadata, connection):
|
sqlalchemy/util/typing.py
CHANGED
|
@@ -62,6 +62,13 @@ _KT_contra = TypeVar("_KT_contra", contravariant=True)
|
|
|
62
62
|
_VT = TypeVar("_VT")
|
|
63
63
|
_VT_co = TypeVar("_VT_co", covariant=True)
|
|
64
64
|
|
|
65
|
+
if compat.py38:
|
|
66
|
+
# typing_extensions.Literal is different from typing.Literal until
|
|
67
|
+
# Python 3.10.1
|
|
68
|
+
_LITERAL_TYPES = frozenset([typing.Literal, Literal])
|
|
69
|
+
else:
|
|
70
|
+
_LITERAL_TYPES = frozenset([Literal])
|
|
71
|
+
|
|
65
72
|
|
|
66
73
|
if compat.py310:
|
|
67
74
|
# why they took until py310 to put this in stdlib is beyond me,
|
|
@@ -356,7 +363,7 @@ def is_non_string_iterable(obj: Any) -> TypeGuard[Iterable[Any]]:
|
|
|
356
363
|
|
|
357
364
|
|
|
358
365
|
def is_literal(type_: _AnnotationScanType) -> bool:
|
|
359
|
-
return get_origin(type_)
|
|
366
|
+
return get_origin(type_) in _LITERAL_TYPES
|
|
360
367
|
|
|
361
368
|
|
|
362
369
|
def is_newtype(type_: Optional[_AnnotationScanType]) -> TypeGuard[NewType]:
|
|
File without changes
|
|
File without changes
|