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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: SQLAlchemy
3
- Version: 2.0.34
3
+ Version: 2.0.35
4
4
  Summary: Database Abstraction Library
5
5
  Home-page: https://www.sqlalchemy.org
6
6
  Author: Mike Bayer
@@ -1,4 +1,4 @@
1
- sqlalchemy/__init__.py,sha256=kW5kNSOI0cHm2Ioc_-ahxqHWmCDAWb_iqZZJsMYrKMU,13033
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=sRlzRFU5E1512aFyEhmmL1ffeU1u5meaLqtRYTcrH7Y,8568
42
- sqlalchemy/dialects/mysql/mysqlconnector.py,sha256=qiQdfLPze3QHuASAZ9iqRzD0hDW8FbKoQnfAEQCF7tM,5675
43
- sqlalchemy/dialects/mysql/mysqldb.py,sha256=zPHKMQbHu8bFuD7YvOJewn2axQbfwA93NZoeX3bbbiQ,9502
44
- sqlalchemy/dialects/mysql/provision.py,sha256=4oGkClQ8jC3YLPF54sB4kCjFc8HRTwf5zl5zftAAXGo,3474
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=cav9QxSLT75-JXhhFSneYT_y3coF6TmFkBa5fqQMrRI,119615
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=9-ZvkLVMfQNSz0aHGml_B8sNg3gVq3-gxLnb5BO7Pog,11217
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=i1LolkwQLI86l_YwEpiIfN5Lh469H1mairKdmTxa9k4,99832
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=cMs3mMXZBbfQXahxHbT3-6h5uMM--GZIcdtwhRrZoio,61589
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=MfFALcRkE3eKwxkntVM1ZcUhOphUFwAr1Fc21qJoobo,71403
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=pFFc-1ZjaV3aQMAO27UIh0W6NyLc30n2IbuWNprMtS8,112445
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=q292K5vdpP69G7Z9y1RqI5GFAk2diUPwnsXE8De_Wgw,11925
154
- sqlalchemy/orm/events.py,sha256=0lxP-EluVWSUr07ny2nsuQ8QhrDu9Qc4ON6QRUhuJnA,127703
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=woZDL-vAvu_CWQUgxf7geh7Bkl1gUE2zmrdF5UmTrFk,117630
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=Sd6IKV_ya_CBKzebwazRrWWabvZ0PqariUB7KKUIUrc,115275
172
- sqlalchemy/orm/strategy_options.py,sha256=-n44NV8QX-3uWjhFMA_R_7vYy-d57gJY9snB9JeOj-w,85341
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=7QpgbIVz9AanhodMICFwDvaY2RdsTRSTvsRzD9Cnsds,236460
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=uD7ZYOMZ0LQ0Lf8EsKWmDdRSnfcrjnXa8eSgTiIibOk,52655
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=tJSbJFg5fw0sSUv3I_FPmhN7rWWeJtq3YyxmylWJUlM,106466
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=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,,
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,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (74.1.1)
2
+ Generator: setuptools (75.1.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
sqlalchemy/__init__.py CHANGED
@@ -269,7 +269,7 @@ from .types import Uuid as Uuid
269
269
  from .types import VARBINARY as VARBINARY
270
270
  from .types import VARCHAR as VARCHAR
271
271
 
272
- __version__ = "2.0.34"
272
+ __version__ = "2.0.35"
273
273
 
274
274
 
275
275
  def __go(lcls: Any) -> None:
@@ -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", int)
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. Note that the
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
- # 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
- """
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
- for match in re.finditer(
2688
- CHECK_PATTERN, table_data or "", re.I | re.S | re.VERBOSE
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://sqlsoup.readthedocs.io/en/latest/>`_
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
@@ -619,6 +619,7 @@ class ORMDMLState(AbstractORMCompileState):
619
619
  querycontext = QueryContext(
620
620
  compile_state.from_statement_ctx,
621
621
  compile_state.select_statement,
622
+ statement,
622
623
  params,
623
624
  session,
624
625
  load_options,
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 = statement._with_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,
@@ -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'] = datetime.utcnow()
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,
@@ -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.query
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.query:
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.query._with_options
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.query._generate_cache_key()
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
@@ -4160,7 +4160,7 @@ class GenerativeSelect(SelectBase, Generative):
4160
4160
 
4161
4161
  For example, ::
4162
4162
 
4163
- stmt = select(User).order_by(User).id.slice(1, 3)
4163
+ stmt = select(User).order_by(User.id).slice(1, 3)
4164
4164
 
4165
4165
  renders as
4166
4166
 
@@ -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.combinations(
2458
- (True, testing.requires.schemas), (False,), argnames="use_schema"
2459
- )
2460
- @testing.requires.check_constraint_reflection
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
- schema = None
2463
+ return None
2466
2464
 
2467
- Table(
2468
- "sa_cc",
2469
- metadata,
2470
- Column("a", Integer()),
2471
- sa.CheckConstraint("a > 1 AND a < 5", name="cc1"),
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
- metadata.create_all(connection)
2471
+ metadata.create_all(connection)
2485
2472
 
2486
- insp = inspect(connection)
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
- {"name": item["name"], "sqltext": normalize(item["sqltext"])}
2502
- for item in reflected
2503
- ]
2504
- eq_(
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": "UsesCasing", "sqltext": "a = 1 or a > 2 and a < 5"},
2508
- {"name": "cc1", "sqltext": "a > 1 and a < 5"},
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_) is Literal
366
+ return get_origin(type_) in _LITERAL_TYPES
360
367
 
361
368
 
362
369
  def is_newtype(type_: Optional[_AnnotationScanType]) -> TypeGuard[NewType]: