Files
aitsc/.venv/Lib/site-packages/sqlalchemy/testing/__pycache__/requirements.cpython-312.pyc

644 lines
89 KiB
Plaintext
Raw Normal View History

2025-02-23 09:07:52 +08:00
<EFBFBD>
2025-08-29 00:34:40 +08:00
<00><19>hK<68><00><01><><00>dZddlmZddlZddlZddlmZddlmZddlm Z dd lm
2025-02-23 09:07:52 +08:00
Z
2025-08-29 00:34:40 +08:00
dd
lm Z dd l m Z Gd <0C>d <0A>ZGd<0E>de<0E>Zy)z<>Global database feature support policy.
2025-02-23 09:07:52 +08:00
Provides decorators to mark tests requiring specific feature support from the
target database.
External dialect test suites should subclass SuiteRequirements
to provide specific inclusion/exclusions.
<EFBFBD>)<01> annotationsN<73>)<01>asyncio)<01>
exclusions<EFBFBD><01>only_on<6F><00><01> create_engine)<01>util)<01> QueuePoolc<01> <00>eZdZy)<02> RequirementsN)<03>__name__<5F>
2025-08-29 00:34:40 +08:00
__module__<EFBFBD> __qualname__<5F><00><00>LD:\pythonpj\aitsc\.venv\Lib\site-packages\sqlalchemy/testing/requirements.pyrr!s<00><00>rrc<01>0<00>eZdZed<01><00>Zed<02><00>Zed<03><00>Zed<04><00>Zed<05><00>Zed<06><00>Z ed<07><00>Z
2025-02-23 09:07:52 +08:00
ed<08><00>Z ed <09><00>Z ed
2025-08-29 00:34:40 +08:00
<EFBFBD><00>Z ed <0B><00>Zed <0C><00>Zed <0A><00>Zed<0E><00>Zed<0F><00>Zed<10><00>Zed<11><00>Zed<12><00>Zed<13><00>Zed<14><00>Zed<15><00>Zed<16><00>Zed<17><00>Zed<18><00>Zed<19><00>Zed<1A><00>Zed<1B><00>Zed<1C><00>Zed<1D><00>Z ed<1E><00>Z!ed<1F><00>Z"ed <20><00>Z#ed!<21><00>Z$ed"<22><00>Z%ed#<23><00>Z&ed$<24><00>Z'ed%<25><00>Z(ed&<26><00>Z)ed'<27><00>Z*ed(<28><00>Z+ed)<29><00>Z,ed*<2A><00>Z-ed+<2B><00>Z.ed,<2C><00>Z/ed-<2D><00>Z0ed.<2E><00>Z1ed/<2F><00>Z2ed0<64><00>Z3ed1<64><00>Z4ed2<64><00>Z5ed3<64><00>Z6ed4<64><00>Z7ed5<64><00>Z8ed6<64><00>Z9ed7<64><00>Z:ed8<64><00>Z;ed9<64><00>Z<ed:<3A><00>Z=ed;<3B><00>Z>ed<<3C><00>Z?ed=<3D><00>Z@ed><3E><00>ZAed?<3F><00>ZBed@<40><00>ZCedA<64><00>ZDedB<64><00>ZEedC<64><00>ZFedD<64><00>ZGedE<64><00>ZHedF<64><00>ZIedG<64><00>ZJedH<64><00>ZKedI<64><00>ZLedJ<64><00>ZMedK<64><00>ZNedL<64><00>ZOedM<64><00>ZPedN<64><00>ZQedO<64><00>ZRedP<64><00>ZSedQ<64><00>ZTedR<64><00>ZUedS<64><00>ZVedT<64><00>ZWedU<64><00>ZXedV<64><00>ZYedW<64><00>ZZedX<64><00>Z[edY<64><00>Z\edZ<64><00>Z]ed[<5B><00>Z^ed\<5C><00>Z_ed]<5D><00>Z`ed^<5E><00>Zaed_<64><00>Zbed`<60><00>Zceda<64><00>Zdedb<64><00>Zeedc<64><00>Zfedd<64><00>Zgede<64><00>Zhedf<64><00>Ziedg<64><00>Zjedh<64><00>Zkedi<64><00>Zledj<64><00>Zmedk<64><00>Znedl<64><00>Zoedm<64><00>Zpedn<64><00>Zqedo<64><00>Zredp<64><00>Zsedq<64><00>Ztedr<64><00>Zueds<64><00>Zvedt<64><00>Zwedu<64><00>Zxedv<64><00>Zyedw<64><00>Zzedx<64><00>Z{edy<64><00>Z|edz<64><00>Z}ed{<7B><00>Z~ed|<7C><00>Zed}<7D><00>Z<>ed~<7E><00>Z<>ed<64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>d<EFBFBD><64>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>d<EFBFBD><64>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>d<EFBFBD><64>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed„<00>Z<>e<00>Z<>e<00>Z<>e<00>Z<>edƄ<00>Z<>e<00>Z<>e<00>Z<>e<00>Z<>e<00>Z<>ed˄<00>Z<>e<00>Z<>e<00>Z<>ed΄<00>Z<>e<00>Z<>e<00>Z<>Z<>Z<>e<00>Z<>e<00>Z<>Z<>edք<00>Z<>e<00>Z<>e<00>Z<>e<00>Z<>e<00>Z<>e<00>Z<>ed܄<00>Z<>e<00>Z<>e<00>Z<>e<00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>ed<><64><00>Z<>y<EFBFBD>)<29><>SuiteRequirementsc<01>*<00>tj<00>S)z/target platform can emit basic CreateTable DDL.<2E>r<00>open<65><01>selfs r<00> create_tablezSuiteRequirements.create_table&<00><00><00><1A><EFBFBD><EFBFBD> <20> rc<01>*<00>tj<00>S)z-target platform can emit basic DropTable DDL
drop_tablezSuiteRequirements.drop_table,rrc<01>*<00>tj<00>S)z>target platform supports IF NOT EXISTS / IF EXISTS for tables.<2E>r<00>closedrs r<00>table_ddl_if_existsz%SuiteRequirements.table_ddl_if_exists2<00><00><00><1A> <20> <20>"<22>"rc<01>*<00>tj<00>S)z?target platform supports IF NOT EXISTS / IF EXISTS for indexes.r"rs r<00>index_ddl_if_existsz%SuiteRequirements.index_ddl_if_exists8r%rc<01>*<00>tj<00>S)z0Return databases that support the UUID datatype.r"rs r<00>uuid_data_typez SuiteRequirements.uuid_data_type>r%rc<01>*<00>tj<00>S)z*Target database must support foreign keys.rrs r<00> foreign_keyszSuiteRequirements.foreign_keysDrrc<01>*<00>tj<00>S)zKTarget database creates an index that's reflected for
foreign keys.r"rs r<00>foreign_keys_reflect_as_indexz/SuiteRequirements.foreign_keys_reflect_as_indexJ<00><00><00>
<1A> <20> <20>"<22>"rc<01>*<00>tj<00>S)z=Target database reflects unique indexes as unique constrains.r"rs r<00>*unique_index_reflect_as_unique_constraintsz<SuiteRequirements.unique_index_reflect_as_unique_constraintsQr%rc<01>*<00>tj<00>S)z7Target database reflects unique constraints as indexes.r"rs r<00>#unique_constraints_reflect_as_indexz5SuiteRequirements.unique_constraints_reflect_as_indexWr%rc<01>*<00>tj<00>S)z<>Database / dialect supports a query like:
2025-02-23 09:07:52 +08:00
.. sourcecode:: sql
SELECT * FROM VALUES ( (c1, c2), (c1, c2), ...)
AS some_table(col1, col2)
SQLAlchemy generates this with the :func:`_sql.values` function.
2025-08-29 00:34:40 +08:00
r"rs r<00>table_value_constructorz)SuiteRequirements.table_value_constructor]s<00><00><1A> <20> <20>"<22>"rc<01>*<00>tj<00>S)a<>Target database passes SQL-92 style statements to cursor.execute()
2025-02-23 09:07:52 +08:00
when a statement like select() or insert() is run.
A very small portion of dialect-level tests will ensure that certain
conditions are present in SQL strings, and these tests use very basic
SQL that will work on any SQL-like platform in order to assert results.
It's normally a given for any pep-249 DBAPI that a statement like
"SELECT id, name FROM table WHERE some_table.id=5" will work.
However, there are dialects that don't actually produce SQL Strings
and instead may work with symbolic objects instead, or dialects that
aren't working with SQL, so for those this requirement can be marked
as excluded.
2025-08-29 00:34:40 +08:00
rrs r<00>standard_cursor_sqlz%SuiteRequirements.standard_cursor_sqlks<00><00>$<1A><EFBFBD><EFBFBD> <20> rc<01>*<00>tj<00>S)zQtarget database must support ON UPDATE..CASCADE behavior in
foreign keys.rrs r<00>on_update_cascadez#SuiteRequirements.on_update_cascade<00><00><00>
2025-02-23 09:07:52 +08:00
<1A><EFBFBD><EFBFBD> <20> rc<01>*<00>tj<00>S)zWtarget database must *not* support ON UPDATE..CASCADE behavior in
2025-08-29 00:34:40 +08:00
foreign keys.r"rs r<00>non_updating_cascadez&SuiteRequirements.non_updating_cascade<64>r%rc<01>*<00>tj<00>S<00>Nr"rs r<00>deferrable_fksz SuiteRequirements.deferrable_fks<6B><00><00><00><19> <20> <20>"<22>"rc<01>4<00><00>tj<00>fd<01><08>S)Nc<01>`<00><01><00>jjxs<00>jjSr=)r8<00>enabledr>rs<00>r<00><lambda>z?SuiteRequirements.on_update_or_deferrable_fks.<locals>.<lambda><3E>s*<00><><00>D<EFBFBD>*<2A>*<2A>2<>2<>+<2B><13>"<22>"<22>*<2A>*<2A>+r<00>r<00>only_ifrs`r<00>on_update_or_deferrable_fksz-SuiteRequirements.on_update_or_deferrable_fks<6B>s<00><><00>
2025-02-23 09:07:52 +08:00
<1A>!<21>!<21> +<2B>
<EFBFBD>
rc<01>2<00>d<01>}tj|<01>S)z"target database is using QueuePoolc<01>J<00>t|jjt<00>Sr=)<04>
2025-08-29 00:34:40 +08:00
isinstance<EFBFBD>db<64>poolr <00><01>configs r<00>goz(SuiteRequirements.queue_pool.<locals>.go<67>s<00><00><1D>f<EFBFBD>i<EFBFBD>i<EFBFBD>n<EFBFBD>n<EFBFBD>i<EFBFBD>8<> 8rrD<00>rrNs r<00>
queue_poolzSuiteRequirements.queue_pool<6F>s<00><00> 9<><1A>!<21>!<21>"<22>%<25>%rc<01>*<00>tj<00>S)z;Target database must support self-referential foreign keys.rrs r<00>self_referential_foreign_keysz/SuiteRequirements.self_referential_foreign_keys<79>rrc<01>*<00>tj<00>S)z=Target database must support the DDL phrases for FOREIGN KEY.rrs r<00>foreign_key_ddlz!SuiteRequirements.foreign_key_ddl<64>rrc<01>*<00>tj<00>S)z3target database must support names for constraints.rrs r<00>named_constraintsz#SuiteRequirements.named_constraints<74>rrc<01>*<00>tj<00>S)z8target database must apply names to unnamed constraints.rrs r<00>implicitly_named_constraintsz.SuiteRequirements.implicitly_named_constraints<74>rrc<01>*<00>tj<00>S)atarget database allows column names that have unusual characters
2025-02-23 09:07:52 +08:00
in them, such as dots, spaces, slashes, or percent signs.
The column names are as always in such a case quoted, however the
DB still needs to support those characters in the name somehow.
2025-08-29 00:34:40 +08:00
rrs r<00>unusual_column_name_charactersz0SuiteRequirements.unusual_column_name_characters<72>s<00><00><1A><EFBFBD><EFBFBD> <20> rc<01>*<00>tj<00>S)z(Target database must support subqueries.rrs r<00>
subquerieszSuiteRequirements.subqueries<65>rrc<01>*<00>tj<00>S)zRtarget database can render OFFSET, or an equivalent, in a
2025-02-23 09:07:52 +08:00
SELECT.
2025-08-29 00:34:40 +08:00
rrs r<00>offsetzSuiteRequirements.offset<65><00><00><00> <1A><EFBFBD><EFBFBD> <20> rc<01>*<00>tj<00>S)zWtarget database can render LIMIT and/or OFFSET using a bound
2025-02-23 09:07:52 +08:00
parameter
2025-08-29 00:34:40 +08:00
rrs r<00>bound_limit_offsetz$SuiteRequirements.bound_limit_offset<65>r_rc<01>*<00>tj<00>S)z<>target database can render LIMIT and/or OFFSET with a complete
2025-02-23 09:07:52 +08:00
SQL expression, such as one that uses the addition operator.
parameter
2025-08-29 00:34:40 +08:00
rrs r<00>sql_expression_limit_offsetz-SuiteRequirements.sql_expression_limit_offset<65><00><00><00><1A><EFBFBD><EFBFBD> <20> rc<01>*<00>tj<00>S)z<>Target database must support parenthesized SELECT in UNION
2025-02-23 09:07:52 +08:00
when LIMIT/OFFSET is specifically present.
E.g. (SELECT ...) UNION (SELECT ..)
This is known to fail on SQLite.
2025-08-29 00:34:40 +08:00
rrs r<00>/parens_in_union_contained_select_w_limit_offsetzASuiteRequirements.parens_in_union_contained_select_w_limit_offset<65><00><00><00><1A><EFBFBD><EFBFBD> <20> rc<01>*<00>tj<00>S)alTarget database must support parenthesized SELECT in UNION
2025-02-23 09:07:52 +08:00
when OFFSET/LIMIT is specifically not present.
E.g. (SELECT ... LIMIT ..) UNION (SELECT .. OFFSET ..)
This is known to fail on SQLite. It also fails on Oracle
because without LIMIT/OFFSET, there is currently no step that
creates an additional subquery.
2025-08-29 00:34:40 +08:00
rrs r<00>0parens_in_union_contained_select_wo_limit_offsetzBSuiteRequirements.parens_in_union_contained_select_wo_limit_offset<65><00><00><00><1A><EFBFBD><EFBFBD> <20> rc<01>*<00>tj<00>S)z;Target database must support boolean expressions as columnsr"rs r<00>boolean_col_expressionsz)SuiteRequirements.boolean_col_expressions<6E>r%rc<01>*<00>tj<00>S)z5Target database allows boolean columns to store NULL.rrs r<00>nullable_booleansz#SuiteRequirements.nullable_booleansrrc<01>*<00>tj<00>S)z,Target backends that support nulls ordering.r"rs r<00> nullsorderingzSuiteRequirements.nullsordering r%rc<01>*<00>tj<00>S)z<>target database/driver supports bound parameters as column
2025-02-23 09:07:52 +08:00
expressions without being in the context of a typed column.
2025-08-29 00:34:40 +08:00
rrs r<00>standalone_bindsz"SuiteRequirements.standalone_bindsr9rc<01>*<00>tj<00>S)z<>target database/driver supports bound parameters with NULL in the
2025-02-23 09:07:52 +08:00
WHERE clause, in situations where it has to be typed.
2025-08-29 00:34:40 +08:00
rrs r<00>!standalone_null_binds_whereclausez3SuiteRequirements.standalone_null_binds_whereclauser_rc<01>*<00>tj<00>S)z5Target database must support INTERSECT or equivalent.r"rs r<00> intersectzSuiteRequirements.intersect <00><00><00><1A> <20> <20>"<22>"rc<01>*<00>tj<00>S)z?Target database must support EXCEPT or equivalent (i.e. MINUS).r"rs r<00>except_zSuiteRequirements.except_%rwrc<01>*<00>tj<00>S)z.Target database must support window functions.r"rs r<00>window_functionsz"SuiteRequirements.window_functions*rwrc<01>*<00>tj<00>S)zTarget database supports CTEsr"rs r<00>cteszSuiteRequirements.ctes/r%rc<01>*<00>tj<00>S)z<>target database supports CTES that ride on top of a normal UPDATE
2025-02-23 09:07:52 +08:00
or DELETE statement which refers to the CTE in a correlated subquery.
2025-08-29 00:34:40 +08:00
r"rs r<00>ctes_with_update_deletez)SuiteRequirements.ctes_with_update_delete5<00><00><00><1A> <20> <20>"<22>"rc<01>*<00>tj<00>S)zJtarget database supports CTES that ride on top of a VALUES
clause.r"rs r<00>ctes_with_valuesz"SuiteRequirements.ctes_with_values>r.rc<01>*<00>tj<00>S)z}target database supports CTES which consist of INSERT, UPDATE
or DELETE *within* the CTE, e.g. WITH x AS (UPDATE....)r"rs r<00> ctes_on_dmlzSuiteRequirements.ctes_on_dmlEr.rc<01>*<00>tj<00>S)z~target platform generates new surrogate integer primary key values
when insert() is executed, excluding the pk column.rrs r<00>autoincrement_insertz&SuiteRequirements.autoincrement_insertLr9rc<01>*<00>tj<00>S)a#target platform will allow cursor.fetchone() to proceed after a
2025-02-23 09:07:52 +08:00
COMMIT.
Typically this refers to an INSERT statement with RETURNING which
is invoked within "autocommit". If the row can be returned
after the autocommit, then this rule can be open.
2025-08-29 00:34:40 +08:00
rrs r<00>fetch_rows_post_commitz(SuiteRequirements.fetch_rows_post_commitSs<00><00><1A><EFBFBD><EFBFBD> <20> rc<01>*<00>tj<00>S)z<>target platform supports SQL expressions in GROUP BY
2025-02-23 09:07:52 +08:00
e.g.
SELECT x + y AS somelabel FROM table GROUP BY x + y
2025-08-29 00:34:40 +08:00
rrs r<00>group_by_complex_expressionz-SuiteRequirements.group_by_complex_expression`rgrc<01>0<00>tjd<01>d<02>S)Nc<01>D<00>|jjj Sr=)rJ<00>dialect<63>supports_sane_rowcountrLs rrCz1SuiteRequirements.sane_rowcount.<locals>.<lambda>os<00><00>v<EFBFBD>y<EFBFBD>y<EFBFBD>0<>0<>G<>G<>Grz&driver doesn't support 'sane' rowcount<6E>r<00>skip_ifrs r<00> sane_rowcountzSuiteRequirements.sane_rowcountls<00><00><19>!<21>!<21> G<> 4<>
2025-02-23 09:07:52 +08:00
<EFBFBD>
2025-08-29 00:34:40 +08:00
rc<01>0<00>tjd<01>d<02>S)Nc<01>D<00>|jjj Sr=)rJr<><00>supports_sane_multi_rowcountrLs rrCz7SuiteRequirements.sane_multi_rowcount.<locals>.<lambda>vs<00><00>v<EFBFBD>y<EFBFBD>y<EFBFBD>0<>0<>M<>M<>Mrz;driver %(driver)s %(doesnt_support)s 'sane' multi row count<6E>r<00>fails_ifrs r<00>sane_multi_rowcountz%SuiteRequirements.sane_multi_rowcountss<00><00><19>"<22>"<22> M<> I<>
2025-02-23 09:07:52 +08:00
<EFBFBD>
2025-08-29 00:34:40 +08:00
rc<01>0<00>tjd<01>d<02>S)Nc<01>D<00>|jjj Sr=)rJr<><00> supports_sane_rowcount_returningrLs rrCz=SuiteRequirements.sane_rowcount_w_returning.<locals>.<lambda>}s<00><00><16> <09> <09>!<21>!<21>B<>B<>rz;driver doesn't support 'sane' rowcount when returning is onr<6E>rs r<00>sane_rowcount_w_returningz+SuiteRequirements.sane_rowcount_w_returningzs <00><00><19>"<22>"<22> <0E> J<01> 
2025-02-23 09:07:52 +08:00
<EFBFBD>
rc<01>0<00>tjd<01>d<02>S)zatarget platform supports INSERT with no values, i.e.
2025-08-29 00:34:40 +08:00
INSERT DEFAULT VALUES or equivalent.c<01><><00>|jjjxsB|jjjxs |jjjSr=)rJr<><00>supports_empty_insert<72>supports_default_values<65>supports_default_metavaluerLs rrCz1SuiteRequirements.empty_inserts.<locals>.<lambda><3E>sI<00><00>6<EFBFBD>9<EFBFBD>9<EFBFBD>,<2C>,<2C>B<>B<><<3C><15>y<EFBFBD>y<EFBFBD> <20> <20>8<>8<><<3C><15>y<EFBFBD>y<EFBFBD> <20> <20>;<3B>;<3B><rzempty inserts not supportedrDrs r<00> empty_insertszSuiteRequirements.empty_inserts<74>s!<00><00>
2025-02-23 09:07:52 +08:00
<1A>!<21>!<21> <<3C> *<2A> 
<EFBFBD>
rc<01><00>|jS)zvtarget platform supports INSERT with no values, i.e.
2025-08-29 00:34:40 +08:00
INSERT DEFAULT VALUES or equivalent, within executemany())r<>rs r<00>empty_inserts_executemanyz+SuiteRequirements.empty_inserts_executemany<6E>s<00><00>
<14>!<21>!<21>!rc<01>*<00>tj<00>S)z.target platform supports INSERT from a SELECT.rrs r<00>insert_from_selectz$SuiteRequirements.insert_from_select<63>rrc<01>0<00>tjd<01>d<02>S)z.target platform supports DELETE ... RETURNING.c<01>B<00>|jjjSr=)rJr<><00>delete_returningrLs rrCz4SuiteRequirements.delete_returning.<locals>.<lambda><3E><00><00><00>6<EFBFBD>9<EFBFBD>9<EFBFBD>,<2C>,<2C>=<3D>=rz4%(database)s %(does_support)s 'DELETE ... RETURNING'rDrs rr<>z"SuiteRequirements.delete_returning<6E><00><00><00><1A>!<21>!<21> =<3D> B<>
2025-02-23 09:07:52 +08:00
<EFBFBD>
2025-08-29 00:34:40 +08:00
rc<01>0<00>tjd<01>d<02>S)z.target platform supports INSERT ... RETURNING.c<01>B<00>|jjjSr=)rJr<><00>insert_returningrLs rrCz4SuiteRequirements.insert_returning.<locals>.<lambda><3E>r<>rz4%(database)s %(does_support)s 'INSERT ... RETURNING'rDrs rr<>z"SuiteRequirements.insert_returning<6E>r<>rc<01>0<00>tjd<01>d<02>S)z.target platform supports UPDATE ... RETURNING.c<01>B<00>|jjjSr=)rJr<><00>update_returningrLs rrCz4SuiteRequirements.update_returning.<locals>.<lambda><3E>r<>rz4%(database)s %(does_support)s 'UPDATE ... RETURNING'rDrs rr<>z"SuiteRequirements.update_returning<6E>r<>rc<01>0<00>tjd<01>d<02>S)z<>target platform supports RETURNING when INSERT is used with
2025-02-23 09:07:52 +08:00
executemany(), e.g. multiple parameter sets, indicating
as many rows come back as do parameter sets were passed.
2025-08-29 00:34:40 +08:00
c<01>B<00>|jjjSr=)rJr<><00>insert_executemany_returningrLs rrCz@SuiteRequirements.insert_executemany_returning.<locals>.<lambda><3E>s<00><00>6<EFBFBD>9<EFBFBD>9<EFBFBD>,<2C>,<2C>I<>IrzR%(database)s %(does_support)s 'RETURNING of multiple rows with INSERT executemany'rDrs rr<>z.SuiteRequirements.insert_executemany_returning<6E>s<00><00><1A>!<21>!<21> I<> 5<>
2025-02-23 09:07:52 +08:00
<EFBFBD>
2025-08-29 00:34:40 +08:00
rc<01>0<00>tjd<01>d<02>S)Nc<01><><00>|jjjxrB|jjjxr |jjjSr=)rJr<><00>supports_multivalues_insertr<74><00>use_insertmanyvaluesrLs rrCz4SuiteRequirements.insertmanyvalues.<locals>.<lambda><3E>sI<00><00>6<EFBFBD>9<EFBFBD>9<EFBFBD>,<2C>,<2C>H<>H<>7<><16> <09> <09>!<21>!<21>2<>2<>7<><16> <09> <09>!<21>!<21>6<>6<>7rz=%(database)s %(does_support)s 'insertmanyvalues functionalityrDrs r<00>insertmanyvaluesz"SuiteRequirements.insertmanyvalues<65>s <00><00><19>!<21>!<21> 7<> L<01> 
2025-02-23 09:07:52 +08:00
<EFBFBD>
rc<01>*<00>tj<00>S)zZTarget platform supports the syntax
"(x, y) IN ((x1, y1), (x2, y2), ...)"
2025-08-29 00:34:40 +08:00
r"rs r<00>tuple_inzSuiteRequirements.tuple_in<69><00><00><00> <1A> <20> <20>"<22>"rc<01><00>|jS)z%Target platform tuple IN w/ empty set)r<>rs r<00>tuple_in_w_emptyz"SuiteRequirements.tuple_in_w_empty<74>s<00><00><14>}<7D>}<7D>rc<01>*<00>tj<00>S)zwtarget platform supports a SELECT statement that has
the same name repeated more than once in the columns list.rrs r<00>%duplicate_names_in_cursor_descriptionz7SuiteRequirements.duplicate_names_in_cursor_description<6F>r9rc<01>0<00>tjd<01>d<02>S)z[Target database must have 'denormalized', i.e.
UPPERCASE as case insensitive names.c<01>D<00>|jjj Sr=)rJr<><00>requires_name_normalizerLs rrCz6SuiteRequirements.denormalized_names.<locals>.<lambda><3E>s<00><00>v<EFBFBD>y<EFBFBD>y<EFBFBD>0<>0<>H<>H<>Hrz,Backend does not require denormalized names.r<>rs r<00>denormalized_namesz$SuiteRequirements.denormalized_names<65>s<00><00>
2025-02-23 09:07:52 +08:00
<1A>!<21>!<21> H<> :<3A>
<EFBFBD>
rc<01>0<00>tjd<01>d<02>S)zTtarget database must support multiple VALUES clauses in an
2025-08-29 00:34:40 +08:00
INSERT statement.c<01>D<00>|jjj Sr=)rJr<>r<>rLs rrCz7SuiteRequirements.multivalues_inserts.<locals>.<lambda><3E>s<00><00>v<EFBFBD>y<EFBFBD>y<EFBFBD>0<>0<>L<>L<>Lrz*Backend does not support multirow inserts.r<>rs r<00>multivalues_insertsz%SuiteRequirements.multivalues_inserts<74>s<00><00>
2025-02-23 09:07:52 +08:00
<1A>!<21>!<21> L<> 8<>
<EFBFBD>
rc<01>*<00>tj<00>S)zvtarget dialect implements the executioncontext.get_lastrowid()
method without reliance on RETURNING.
2025-08-29 00:34:40 +08:00
rrs r<00>implements_get_lastrowidz*SuiteRequirements.implements_get_lastrowid<69>r_rc<01>*<00>tj<00>S)zLdialect includes the required pep-249 attribute
``cursor.arraysize``rrs r<00> arraysizezSuiteRequirements.arraysize<7A>r9rc<01>*<00>tj<00>S)a<target dialect retrieves cursor.lastrowid, or fetches
2025-02-23 09:07:52 +08:00
from a database-side function after an insert() construct executes,
within the get_lastrowid() method.
Only dialects that "pre-execute", or need RETURNING to get last
inserted id, would return closed/fail/skip for this.
2025-08-29 00:34:40 +08:00
r"rs r<00>emulated_lastrowidz$SuiteRequirements.emulated_lastrowid<00><00><00><1A> <20> <20>"<22>"rc<01>*<00>tj<00>S)z<>target dialect retrieves cursor.lastrowid or an equivalent
2025-02-23 09:07:52 +08:00
after an insert() construct executes, even if the table has a
Sequence on it.
2025-08-29 00:34:40 +08:00
r"rs r<00>&emulated_lastrowid_even_with_sequencesz8SuiteRequirements.emulated_lastrowid_even_with_sequencesr<>rc<01>*<00>tj<00>S)z]target platform includes a 'lastrowid' accessor on the DBAPI
2025-02-23 09:07:52 +08:00
cursor object.
2025-08-29 00:34:40 +08:00
r"rs r<00>dbapi_lastrowidz!SuiteRequirements.dbapi_lastrowidr<>rc<01>*<00>tj<00>S)z#Target database must support VIEWs.r"rs r<00>viewszSuiteRequirements.views"r%rc<01><00>td<01><00>S)zXTarget database must support external schemas, and have one
named 'test_schema'.c<01>B<00>|jjjSr=)rJr<><00>supports_schemasrLs rrCz+SuiteRequirements.schemas.<locals>.<lambda>-s<00><00>f<EFBFBD>i<EFBFBD>i<EFBFBD>&7<>&7<>&H<>&Hrrrs r<00>schemaszSuiteRequirements.schemas(s<00><00>
2025-02-23 09:07:52 +08:00
<17>H<>I<>Irc<01>*<00>tj<00>S)zJtarget system must support reflection of inter-schema
2025-08-29 00:34:40 +08:00
foreign keysr"rs r<00>cross_schema_fk_reflectionz,SuiteRequirements.cross_schema_fk_reflection/r%rc<01>*<00>tj<00>S)aTarget supports reflection of FOREIGN KEY constraints and
2025-02-23 09:07:52 +08:00
will return the name of the constraint that was used in the
"CONSTRAINT <name> FOREIGN KEY" DDL.
MySQL prior to version 8 and MariaDB prior to version 10.5
don't support this.
2025-08-29 00:34:40 +08:00
r"rs r<00>&foreign_key_constraint_name_reflectionz8SuiteRequirements.foreign_key_constraint_name_reflection5r<>rc<01>*<00>tj<00>S)z<>target system has a strong concept of 'default' schema that can
2025-02-23 09:07:52 +08:00
be referred to implicitly.
basically, PostgreSQL.
2025-08-29 00:34:40 +08:00
r"rs r<00>implicit_default_schemaz)SuiteRequirements.implicit_default_schemaA<00><00><00><1A> <20> <20>"<22>"rc<01>*<00>tj<00>S)z`target dialect implements provisioning module including
set_default_schema_on_connectionr"rs r<00>default_schema_name_switchz,SuiteRequirements.default_schema_name_switchKr.rc<01>2<00>tjd<01>gd<02>S)z0Target dialect must support server side cursors.c<01>B<00>|jjjSr=)rJr<><00>supports_server_side_cursorsrLs rrCz7SuiteRequirements.server_side_cursors.<locals>.<lambda>Ws<00><00>F<EFBFBD>I<EFBFBD>I<EFBFBD>-<2D>-<2D>J<>Jrzno server side cursors supportrDrs r<00>server_side_cursorsz%SuiteRequirements.server_side_cursorsRs <00><00><1A>!<21>!<21> J<> K<> ,<2C>
2025-02-23 09:07:52 +08:00
<EFBFBD>
2025-08-29 00:34:40 +08:00
rc<01>2<00>tjd<01>gd<02>S)z'Target database must support SEQUENCEs.c<01>B<00>|jjjSr=)rJr<><00>supports_sequencesrLs rrCz-SuiteRequirements.sequences.<locals>.<lambda>`s<00><00>F<EFBFBD>I<EFBFBD>I<EFBFBD>-<2D>-<2D>@<40>@rzno sequence supportrDrs r<00> sequenceszSuiteRequirements.sequences[s <00><00><1A>!<21>!<21> @<40> A<> !<21>
2025-02-23 09:07:52 +08:00
<EFBFBD>
rc<01>@<00>tj|j<00>S)zJthe opposite of "sequences", DB does not support sequences at
2025-08-29 00:34:40 +08:00
all.)r<00> NotPredicater<65>rs r<00> no_sequenceszSuiteRequirements.no_sequencesds<00><00>
2025-02-23 09:07:52 +08:00
<1A>&<26>&<26>t<EFBFBD>~<7E>~<7E>6<>6rc<01>2<00>tjd<01>gd<02>S)zgTarget database supports sequences, but also optionally
2025-08-29 00:34:40 +08:00
as a means of generating new PK values.c<01><><00>|jjjxr |jjjSr=)rJr<>r<><00>sequences_optionalrLs rrCz6SuiteRequirements.sequences_optional.<locals>.<lambda>rs1<00><00>v<EFBFBD>y<EFBFBD>y<EFBFBD>0<>0<>C<>C<> 9<><1A>I<EFBFBD>I<EFBFBD>%<25>%<25>8<>8<> 9rz.no sequence support, or sequences not optionalrDrs rr<>z$SuiteRequirements.sequences_optionalks&<00><00>
2025-02-23 09:07:52 +08:00
<1A>!<21>!<21>9<> <0E> =<3D> 
<EFBFBD>
rc<01>0<00>tjd<01>g<01>S)atarget database / driver supports cursor.lastrowid as a means
of retrieving the last inserted primary key value.
note that if the target DB supports sequences also, this is still
assumed to work. This is a new use case brought on by MariaDB 10.3.
2025-08-29 00:34:40 +08:00
c<01>B<00>|jjjSr=<00>rJr<><00>postfetch_lastrowidrLs rrCz6SuiteRequirements.supports_lastrowid.<locals>.<lambda><3E>s<00><00>F<EFBFBD>I<EFBFBD>I<EFBFBD>-<2D>-<2D>A<>ArrDrs r<00>supports_lastrowidz$SuiteRequirements.supports_lastrowidxs<00><00><1A>!<21>!<21> A<> B<>
2025-02-23 09:07:52 +08:00
<EFBFBD>
2025-08-29 00:34:40 +08:00
rc<01>0<00>tjd<01>g<01>S)z"the opposite of supports_lastrowidc<01>D<00>|jjj Sr=r<>rLs rrCz8SuiteRequirements.no_lastrowid_support.<locals>.<lambda><3E>s<00><00><06> <09> <09> 1<> 1<> E<> E<>ErrDrs r<00>no_lastrowid_supportz&SuiteRequirements.no_lastrowid_support<72>s<00><00><1A>!<21>!<21> E<> F<>
2025-02-23 09:07:52 +08:00
<EFBFBD>
2025-08-29 00:34:40 +08:00
rc<01>*<00>tj<00>Sr=r"rs r<00>reflects_pk_namesz#SuiteRequirements.reflects_pk_names<65>r?rc<01>*<00>tj<00>S)z8target database has general support for table reflectionrrs r<00>table_reflectionz"SuiteRequirements.table_reflection<6F><00><00><00><1A><EFBFBD><EFBFBD> <20> rc<01>*<00>tj<00>S)z<>target database supports creation and reflection of tables with no
columns, or at least tables that seem to have no columns.r"rs r<00>reflect_tables_no_columnsz+SuiteRequirements.reflect_tables_no_columns<6E>r.rc<01>*<00>tj<00>S)z_indicates if database supports comments on temp tables and
the dialect can reflect themr"rs r<00>temp_table_comment_reflectionz/SuiteRequirements.temp_table_comment_reflection<6F>r%rc<01>*<00>tj<00>S)z:Indicates if the database support table comment reflectionr"rs r<00>comment_reflectionz$SuiteRequirements.comment_reflection<6F>rwrc<01>*<00>tj<00>S)z{Indicates if the database support table comment reflection in the
2025-02-23 09:07:52 +08:00
full unicode range, including emoji etc.
2025-08-29 00:34:40 +08:00
r"rs r<00>comment_reflection_full_unicodez1SuiteRequirements.comment_reflection_full_unicode<64>r.rc<01>*<00>tj<00>S)zVindicates if the database support comments on constraints
and their reflectionr"rs r<00>constraint_comment_reflectionz/SuiteRequirements.constraint_comment_reflection<6F>r%rc<01><00>|jS)z<>target database must support retrieval of the columns in a view,
2025-02-23 09:07:52 +08:00
similarly to how a table is inspected.
This does not include the full CREATE VIEW definition.
2025-08-29 00:34:40 +08:00
<20>r<>rs r<00>view_column_reflectionz(SuiteRequirements.view_column_reflection<6F>s<00><00><14>z<EFBFBD>z<EFBFBD>rc<01><00>|jS)zStarget database must support inspection of the full CREATE VIEW
definition.rrs r<00>view_reflectionz!SuiteRequirements.view_reflection<6F>s<00><00><14>z<EFBFBD>z<EFBFBD>rc<01><00>|jSr=)r<>rs r<00>schema_reflectionz#SuiteRequirements.schema_reflection<6F>s <00><00><13>|<7C>|<7C>rc<01>*<00>tj<00>S)zatarget database supports schema create and dropped with
'CREATE SCHEMA' and 'DROP SCHEMA'r"rs r<00>schema_create_deletez&SuiteRequirements.schema_create_delete<74>r%rc<01>*<00>tj<00>Sr=rrs r<00>!primary_key_constraint_reflectionz3SuiteRequirements.primary_key_constraint_reflection<6F><00><00><00><19><EFBFBD><EFBFBD> <20> rc<01>*<00>tj<00>Sr=rrs r<00>!foreign_key_constraint_reflectionz3SuiteRequirements.foreign_key_constraint_reflection<6F>rrc<01>*<00>tj<00>Sr=r"rs r<00>1foreign_key_constraint_option_reflection_ondeletezCSuiteRequirements.foreign_key_constraint_option_reflection_ondelete<74>r?rc<01>*<00>tj<00>Sr=r"rs r<00>1fk_constraint_option_reflection_ondelete_restrictzCSuiteRequirements.fk_constraint_option_reflection_ondelete_restrict<63>r?rc<01>*<00>tj<00>Sr=r"rs r<00>1fk_constraint_option_reflection_ondelete_noactionzCSuiteRequirements.fk_constraint_option_reflection_ondelete_noaction<6F>r?rc<01>*<00>tj<00>Sr=r"rs r<00>1foreign_key_constraint_option_reflection_onupdatezCSuiteRequirements.foreign_key_constraint_option_reflection_onupdate<74>r?rc<01>*<00>tj<00>Sr=r"rs r<00>1fk_constraint_option_reflection_onupdate_restrictzCSuiteRequirements.fk_constraint_option_reflection_onupdate_restrict<63>r?rc<01>*<00>tj<00>Sr=rrs r<00>temp_table_reflectionz'SuiteRequirements.temp_table_reflection<6F>rrc<01><00>|jSr=)rrs r<00>temp_table_reflect_indexesz,SuiteRequirements.temp_table_reflect_indexes<65>s<00><00><13>)<29>)<29>)rc<01>*<00>tj<00>S)z8target dialect supports listing of temporary table namesr"rs r<00>temp_table_namesz"SuiteRequirements.temp_table_names<65>rwrc<01>*<00>tj<00>S)z9target dialect supports checking a single temp table namer"rs r<00>has_temp_tablez SuiteRequirements.has_temp_table<6C>rwrc<01>*<00>tj<00>S)z)target database supports temporary tablesrrs r<00>temporary_tablesz"SuiteRequirements.temporary_tables<65>r<>rc<01>*<00>tj<00>S)z(target database supports temporary viewsr"rs r<00>temporary_viewsz!SuiteRequirements.temporary_viewsrwrc<01>*<00>tj<00>Sr=rrs r<00>index_reflectionz"SuiteRequirements.index_reflectionrrc<01>*<00>tj<00>Sr=r"rs r<00>index_reflects_included_columnsz1SuiteRequirements.index_reflects_included_columns
r?rc<01>*<00>tj<00>S)z?target database supports CREATE INDEX with per-column ASC/DESC.rrs r<00>indexes_with_ascdescz&SuiteRequirements.indexes_with_ascdescr<>rc<01>*<00>tj<00>S)zKtarget database supports reflecting INDEX with per-column
ASC/DESC.rrs r<00>reflect_indexes_with_ascdescz.SuiteRequirements.reflect_indexes_with_ascdescrrc<01>*<00>tj<00>S)zztarget database supports reflecting INDEX with per-column
ASC/DESC but reflects them as expressions (like oracle).r"rs r<00>*reflect_indexes_with_ascdesc_as_expressionz<SuiteRequirements.reflect_indexes_with_ascdesc_as_expressionr%rc<01>*<00>tj<00>S)z>target database supports CREATE INDEX against SQL expressions.r"rs r<00>indexes_with_expressionsz*SuiteRequirements.indexes_with_expressionsrwrc<01>*<00>tj<00>S)zLtarget database supports reflection of indexes with
SQL expressions.r"rs r<00> reflect_indexes_with_expressionsz2SuiteRequirements.reflect_indexes_with_expressions$r%rc<01>*<00>tj<00>S)z8target dialect supports reflection of unique constraintsrrs r<00>unique_constraint_reflectionz.SuiteRequirements.unique_constraint_reflection*r<>rc<01>*<00>tj<00>S)z>target dialect supports reflection of inline check constraintsr"rs r<00>"inline_check_constraint_reflectionz4SuiteRequirements.inline_check_constraint_reflection/rwrc<01>*<00>tj<00>S)z7target dialect supports reflection of check constraintsr"rs r<00>check_constraint_reflectionz-SuiteRequirements.check_constraint_reflection4rwrc<01>*<00>tj<00>S)z<>target dialect raises IntegrityError when reporting an INSERT
2025-02-23 09:07:52 +08:00
with a primary key violation. (hint: it should)
2025-08-29 00:34:40 +08:00
rrs r<00>$duplicate_key_raises_integrity_errorz6SuiteRequirements.duplicate_key_raises_integrity_error9r_rc<01>*<00>tj<00>S)z3Target database must support VARCHAR with no lengthrrs r<00>unbounded_varcharz#SuiteRequirements.unbounded_varcharArrc<01>*<00>tj<00>S)zAtarget database supports NVARCHAR and NCHAR as an actual datatyper"rs r<00>nvarchar_typesz SuiteRequirements.nvarchar_typesGrwrc<01>*<00>tj<00>S)z<>Target database/dialect can receive / deliver / compare data with
2025-02-23 09:07:52 +08:00
non-ASCII characters in plain VARCHAR, TEXT columns, without the need
for special "national" datatypes like NVARCHAR or similar.
2025-08-29 00:34:40 +08:00
rrs r<00>unicode_data_no_special_typesz/SuiteRequirements.unicode_data_no_special_typesLrdrc<01>*<00>tj<00>S)z<>Target database/dialect must support Python unicode objects with
2025-02-23 09:07:52 +08:00
non-ASCII characters represented, delivered as bound parameters
as well as in result rows.
2025-08-29 00:34:40 +08:00
rrs r<00> unicode_datazSuiteRequirements.unicode_dataUrdrc<01>*<00>tj<00>S)zRTarget driver must support some degree of non-ascii symbol
2025-02-23 09:07:52 +08:00
names.
2025-08-29 00:34:40 +08:00
r"rs r<00> unicode_ddlzSuiteRequirements.unicode_ddl^r.rc<01>*<00>tj<00>S)z?Target driver can create tables with a name like 'some " table'rrs r<00>symbol_names_w_double_quotez-SuiteRequirements.symbol_names_w_double_quoteer<>rc<01>*<00>tj<00>S)z<>target dialect supports rendering of a datetime.timedelta as a
2025-02-23 09:07:52 +08:00
literal string, e.g. via the TypeEngine.literal_processor() method.
2025-08-29 00:34:40 +08:00
r"rs r<00>datetime_intervalz#SuiteRequirements.datetime_intervaljr<>rc<01>*<00>tj<00>S)z<>target dialect supports rendering of a date, time, or datetime as a
2025-02-23 09:07:52 +08:00
literal string, e.g. via the TypeEngine.literal_processor() method.
2025-08-29 00:34:40 +08:00
r"rs r<00>datetime_literalsz#SuiteRequirements.datetime_literalsrr<>rc<01>*<00>tj<00>S)zUtarget dialect supports representation of Python
datetime.datetime() objects.rrs r<00>datetimezSuiteRequirements.datetime{r9rc<01>*<00>tj<00>S)zvtarget dialect supports representation of Python
datetime.datetime() with tzinfo with DateTime(timezone=True).r"rs r<00>datetime_timezonez#SuiteRequirements.datetime_timezone<6E>r.rc<01>*<00>tj<00>S)zntarget dialect supports representation of Python
datetime.time() with tzinfo with Time(timezone=True).r"rs r<00> time_timezonezSuiteRequirements.time_timezone<6E>r.rc<01>*<00>tj<00>S)z<>target dialect when given a date object will bind it such
2025-02-23 09:07:52 +08:00
that the database server knows the object is a date, and not
a plain string.
2025-08-29 00:34:40 +08:00
rrs r<00>date_implicit_boundz%SuiteRequirements.date_implicit_bound<6E>rdrc<01>*<00>tj<00>S)z<>target dialect when given a time object will bind it such
2025-02-23 09:07:52 +08:00
that the database server knows the object is a time, and not
a plain string.
2025-08-29 00:34:40 +08:00
rrs r<00>time_implicit_boundz%SuiteRequirements.time_implicit_bound<6E>rdrc<01>*<00>tj<00>S)z<>target dialect when given a datetime object will bind it such
2025-02-23 09:07:52 +08:00
that the database server knows the object is a datetime, and not
a plain string.
2025-08-29 00:34:40 +08:00
rrs r<00>datetime_implicit_boundz)SuiteRequirements.datetime_implicit_bound<6E>rdrc<01>*<00>tj<00>S)zftarget dialect supports representation of Python
datetime.datetime() with microsecond objects.rrs r<00>datetime_microsecondsz'SuiteRequirements.datetime_microseconds<64>r9rc<01>*<00>tj<00>S)z<>target dialect supports representation of Python
2025-02-23 09:07:52 +08:00
datetime.datetime() with microsecond objects but only
2025-08-29 00:34:40 +08:00
if TIMESTAMP is used.r"rs r<00>timestamp_microsecondsz(SuiteRequirements.timestamp_microseconds<64>r.rc<01><00>|jS)atarget dialect when given a datetime object which also includes
2025-02-23 09:07:52 +08:00
a microseconds portion when using the TIMESTAMP data type
will bind it such that the database server knows
the object is a datetime with microseconds, and not a plain string.
2025-08-29 00:34:40 +08:00
)r_rs r<00>%timestamp_microseconds_implicit_boundz7SuiteRequirements.timestamp_microseconds_implicit_bound<6E>s<00><00><14>*<2A>*<2A>*rc<01>*<00>tj<00>S<00>zutarget dialect supports representation of Python
datetime.datetime() objects with historic (pre 1970) values.r"rs r<00>datetime_historicz#SuiteRequirements.datetime_historic<69>r.rc<01>*<00>tj<00>S)zQtarget dialect supports representation of Python
datetime.date() objects.rrs r<00>datezSuiteRequirements.date<74>r9rc<01>*<00>tj<00>S)zPtarget dialect accepts a datetime object as the target
of a date column.rrs r<00>date_coerces_from_datetimez,SuiteRequirements.date_coerces_from_datetime<6D>r9rc<01>*<00>tj<00>Srcr"rs r<00> date_historiczSuiteRequirements.date_historic<69>r.rc<01>*<00>tj<00>S)zQtarget dialect supports representation of Python
datetime.time() objects.rrs r<00>timezSuiteRequirements.time<6D>r9rc<01>*<00>tj<00>S)zbtarget dialect supports representation of Python
datetime.time() with microsecond objects.rrs r<00>time_microsecondsz#SuiteRequirements.time_microseconds<64>r9rc<01>*<00>tj<00>S)zttarget database/driver can allow BLOB/BINARY fields to be compared
2025-02-23 09:07:52 +08:00
against a bound parameter value.
2025-08-29 00:34:40 +08:00
rrs r<00>binary_comparisonsz$SuiteRequirements.binary_comparisons<6E>r_rc<01>*<00>tj<00>S)a=target backend supports simple binary literals, e.g. an
2025-02-23 09:07:52 +08:00
expression like:
.. sourcecode:: sql
SELECT CAST('foo' AS BINARY)
Where ``BINARY`` is the type emitted from :class:`.LargeBinary`,
e.g. it could be ``BLOB`` or similar.
Basically fails on Oracle.
2025-08-29 00:34:40 +08:00
rrs r<00>binary_literalsz!SuiteRequirements.binary_literals<6C><00><00><00> <1A><EFBFBD><EFBFBD> <20> rc<01>*<00>tj<00>S)z:target dialect supports 'AUTOCOMMIT' as an isolation_levelr"rs r<00>
autocommitzSuiteRequirements.autocommitrwrc<01>*<00>tj<00>S)z{target dialect supports the detect_autocommit_setting() method and
uses the default implementation of do_rollback()r"rs r<00>skip_autocommit_rollbackz*SuiteRequirements.skip_autocommit_rollback r.rc<01>*<00>tj<00>S)z<>target dialect supports general isolation level settings.
2025-02-23 09:07:52 +08:00
Note that this requirement, when enabled, also requires that
the get_isolation_levels() method be implemented.
2025-08-29 00:34:40 +08:00
r"rs r<00>isolation_levelz!SuiteRequirements.isolation_levelr<>rc<01>"<00>|jj<00>5} |jj|jj
2025-02-23 09:07:52 +08:00
<00>}|jj |d<01>cddd<02>S#t$r Yddd<02>ywxYw#1swYyxYw)a<>Return a structure of supported isolation levels for the current
testing dialect.
The structure indicates to the testing suite what the expected
"default" isolation should be, as well as the other values that
are accepted. The dictionary has two keys, "default" and "supported".
The "supported" key refers to a list of all supported levels and
it should include AUTOCOMMIT if the dialect supports it.
If the :meth:`.DefaultRequirements.isolation_level` requirement is
not open, then this method has no return value.
E.g.::
>>> testing.requirements.get_isolation_levels()
{
"default": "READ_COMMITTED",
"supported": [
"SERIALIZABLE", "READ UNCOMMITTED",
"READ COMMITTED", "REPEATABLE READ",
"AUTOCOMMIT"
]
}
2025-08-29 00:34:40 +08:00
)<02>default<6C> supportedN)rJ<00>connectr<74><00>get_isolation_level_values<65>
connection<EFBFBD>dbapi_connection<6F>default_isolation_level<65>NotImplementedError)rrM<00>connr|s r<00>get_isolation_levelsz&SuiteRequirements.get_isolation_levelss<><00><00>2<14>Y<EFBFBD>Y<EFBFBD> <1E> <1E> <20>D<EFBFBD>
2025-02-23 09:07:52 +08:00
<12> <20>L<EFBFBD>L<EFBFBD>C<>C<><18>O<EFBFBD>O<EFBFBD>4<>4<><12> <09> $<24>|<7C>|<7C>C<>C<>!*<2A><12>!<21> <20><>
'<27> <1C><1B> !<21> <20>
 <1C><> !<21> <20>s.<00>B<03>/A.<02> B<03>. B<05>7B<03>B<05>B<03>Bc<01>2<00>d<01>}tj|<01>S)z<>target dialect supports the
:meth:`_engine.Dialect.get_isolation_level_values`
method added in SQLAlchemy 2.0.
c<01><><00>|jj<00>5} |jj|jj
2025-08-29 00:34:40 +08:00
<00> ddd<00>y#t $r Yddd<00>ywxYw#1swYyxYw)NTF)rJr}r<>r~rr<>r<>)rMr<>s rrNz8SuiteRequirements.get_isolation_level_values.<locals>.goKsj<00><00><17><19><19>"<22>"<22>$<24><04> <20><18>L<EFBFBD>L<EFBFBD>;<3B>;<3B><1C><0F><0F>8<>8<><16>  <20>%<25>$<24><>
2025-02-23 09:07:52 +08:00
+<2B>!<21> <20> %<25>$<24>
2025-08-29 00:34:40 +08:00
!<21><> %<25>$<24>s.<00>A-<03>/A<02> A-<03> A*<05>A-<03>)A*<05>*A-<03>-A6rDrOs rr~z,SuiteRequirements.get_isolation_level_valuesCs<00><00> <20><1A>!<21>!<21>"<22>%<25>%rc<01>2<00>d<01>}tj|<01>S)zctest that the dialect allows the 'isolation_level' argument
to be handled by DefaultDialectc<01><><00> t|jjd<01><02>}|jjdk(S#YyxYw)NzREAD COMMITTED)ryF)r rJ<00>urlr<6C><00>_on_connect_isolation_level)rM<00>es rrNzASuiteRequirements.dialect_level_isolation_level_param.<locals>.go]sC<00><00> <12>!<21><1A>I<EFBFBD>I<EFBFBD>M<EFBFBD>M<EFBFBD>3C<33><12><01><16>I<EFBFBD>I<EFBFBD>9<>9<>=M<>M<><12><> <1D><1C>s <00>!<<00>ArDrOs r<00>#dialect_level_isolation_level_paramz5SuiteRequirements.dialect_level_isolation_level_paramXs<00><00>
2025-02-23 09:07:52 +08:00
<12><1A>!<21>!<21>"<22>%<25>%rc<01>*<00>tj<00>S)z.Target platform implements a native ARRAY typer"rs r<00>
2025-08-29 00:34:40 +08:00
array_typezSuiteRequirements.array_typekrwrc<01>*<00>tj<00>S)z.target platform implements a native JSON type.r"rs r<00> json_typezSuiteRequirements.json_typepr%rc<01><00>|jS)zNtarget platform supports numeric array indexes
within a JSON structure)r<>rs r<00>json_array_indexesz$SuiteRequirements.json_array_indexesvs<00><00>
<14>~<7E>~<7E>rc<01>*<00>tj<00>Sr=rrs r<00>(json_index_supplementary_unicode_elementz:SuiteRequirements.json_index_supplementary_unicode_element}rrc<01>*<00>tj<00>S)z<>Backend has a JSON_EXTRACT or similar function that returns a
2025-02-23 09:07:52 +08:00
valid JSON string in all cases.
Used to test a legacy feature and is not needed.
2025-08-29 00:34:40 +08:00
r"rs r<00>!legacy_unconditional_json_extractz3SuiteRequirements.legacy_unconditional_json_extract<63>r<>rc<01>*<00>tj<00>S)zRtarget backend has general support for moderately high-precision
numerics.rrs r<00>precision_numerics_generalz,SuiteRequirements.precision_numerics_general<61>rrc<01>*<00>tj<00>S)zbtarget backend supports Decimal() objects using E notation
to represent very small values.r"rs r<00>"precision_numerics_enotation_smallz4SuiteRequirements.precision_numerics_enotation_small<6C>r%rc<01>*<00>tj<00>S)zbtarget backend supports Decimal() objects using E notation
to represent very large values.rrs r<00>"precision_numerics_enotation_largez4SuiteRequirements.precision_numerics_enotation_large<67>rrc<01>*<00>tj<00>S)z<>target backend supports values with many digits on both sides,
2025-02-23 09:07:52 +08:00
such as 319438950232418390.273596, 87673.594069654243
2025-08-29 00:34:40 +08:00
r"rs r<00>*precision_numerics_many_significant_digitsz<SuiteRequirements.precision_numerics_many_significant_digits<74>r<>rc<01><00>|jS)z}same as precision_numerics_many_significant_digits but within the
2025-02-23 09:07:52 +08:00
context of a CAST statement (hello MySQL)
2025-08-29 00:34:40 +08:00
)r<>rs r<00>/cast_precision_numerics_many_significant_digitszASuiteRequirements.cast_precision_numerics_many_significant_digits<74>s<00><00> <14>><3E>><3E>>rc<01>*<00>tj<00>S)z8Target backend supports server side defaults for columnsr"rs r<00>server_defaultsz!SuiteRequirements.server_defaults<74>r%rc<01>*<00>tj<00>S)zUTarget backend supports server side defaults with SQL expressions
for columnsr"rs r<00>expression_server_defaultsz,SuiteRequirements.expression_server_defaults<74>r.rc<01>*<00>tj<00>S)a target backend will return a selected Decimal as a Decimal, not
2025-02-23 09:07:52 +08:00
a string.
e.g.::
expr = decimal.Decimal("15.7563")
value = e.scalar(select(literal(expr)))
assert value == expr
See :ticket:`4036`
2025-08-29 00:34:40 +08:00
rrs r<00>implicit_decimal_bindsz(SuiteRequirements.implicit_decimal_binds<64>s<00><00>"<1A><EFBFBD><EFBFBD> <20> rc<01>*<00>tj<00>S)aFtarget backend will return result columns that are explicitly
2025-02-23 09:07:52 +08:00
against NUMERIC or similar precision-numeric datatypes (not including
FLOAT or INT types) as Python Decimal objects, and not as floats
or ints, including when no SQLAlchemy-side typing information is
associated with the statement (e.g. such as a raw SQL string).
This should be enabled if either the DBAPI itself returns Decimal
objects, or if the dialect has set up DBAPI-specific return type
handlers such that Decimal objects come back automatically.
2025-08-29 00:34:40 +08:00
rrs r<00>#numeric_received_as_decimal_untypedz5SuiteRequirements.numeric_received_as_decimal_untyped<65>s<00><00><1A><EFBFBD><EFBFBD> <20> rc<01>*<00>tj<00>S)zhtarget database can select an aggregate from a subquery that's
2025-02-23 09:07:52 +08:00
also using an aggregate
2025-08-29 00:34:40 +08:00
rrs r<00>nested_aggregatesz#SuiteRequirements.nested_aggregates<65>r_rc<01>*<00>tj<00>S)zbtarget database must support ON DELETE CASCADE on a self-referential
2025-02-23 09:07:52 +08:00
foreign key
2025-08-29 00:34:40 +08:00
rrs r<00>recursive_fk_cascadez&SuiteRequirements.recursive_fk_cascade<64>r_rc<01>*<00>tj<00>S)z<>A precision numeric type will return empty significant digits,
2025-02-23 09:07:52 +08:00
i.e. a value such as 10.000 will come back in Decimal form with
2025-08-29 00:34:40 +08:00
the .000 maintained.r"rs r<00>-precision_numerics_retains_significant_digitsz?SuiteRequirements.precision_numerics_retains_significant_digits<74>r<>rc<01>*<00>tj<00>S)z@The Float type can persist and load float('inf'), float('-inf').r"rs r<00>infinity_floatsz!SuiteRequirements.infinity_floats<74>r%rc<01>*<00>tj<00>Sr=r"rs r<00>-float_or_double_precision_behaves_genericallyz?SuiteRequirements.float_or_double_precision_behaves_generically<6C>r?rc<01>*<00>tj<00>S)z<>target backend will return native floating point numbers with at
2025-02-23 09:07:52 +08:00
least seven decimal places when using the generic Float type.
2025-08-29 00:34:40 +08:00
rrs r<00>precision_generic_float_typez.SuiteRequirements.precision_generic_float_type<70>r_rc<01>*<00>tj<00>S)z<>target backend will return the exact float value 15.7563
2025-02-23 09:07:52 +08:00
with only four significant digits from this statement:
SELECT :param
where :param is the Python float 15.7563
i.e. it does not return 15.75629997253418
2025-08-29 00:34:40 +08:00
rrs r<00>literal_float_coercionz(SuiteRequirements.literal_float_coercionrjrc<01>*<00>tj<00>S)z<>target backend can return a floating-point number with four
2025-02-23 09:07:52 +08:00
significant digits (such as 15.7563) accurately
(i.e. without FP inaccuracies, such as 15.75629997253418).
2025-08-29 00:34:40 +08:00
rrs r<00>floats_to_four_decimalsz)SuiteRequirements.floats_to_four_decimalsrdrc<01>*<00>tj<00>S)z<>target backend doesn't crash when you try to select a NUMERIC
2025-02-23 09:07:52 +08:00
value that has a value of NULL.
Added to support Pyodbc bug #351.
2025-08-29 00:34:40 +08:00
rrs r<00>fetch_null_from_numericz)SuiteRequirements.fetch_null_from_numerics<00><00><1A><EFBFBD><EFBFBD> <20> rc<01>*<00>tj<00>S)z*target backend uses Numeric for Float/Dualrrs r<00>float_is_numericz"SuiteRequirements.float_is_numeric'rrc<01>*<00>tj<00>S)zUTarget database must support an unbounded Text() "
"type such as TEXT or CLOBrrs r<00> text_typezSuiteRequirements.text_type-r9rc<01>*<00>tj<00>S)zTtarget database can persist/return an empty string with a
2025-02-23 09:07:52 +08:00
varchar.
2025-08-29 00:34:40 +08:00
rrs r<00>empty_strings_varcharz'SuiteRequirements.empty_strings_varchar4r_rc<01>*<00>tj<00>S)zRtarget database can persist/return an empty string with an
unbounded text.rrs r<00>empty_strings_textz$SuiteRequirements.empty_strings_text<r9rc<01>*<00>tj<00>S)zUtarget database supports use of an unbounded textual field in a
WHERE clause.rrs r<00>"expressions_against_unbounded_textz4SuiteRequirements.expressions_against_unbounded_textCr9rc<01>*<00>tj<00>S)z;target driver must support the literal statement 'select 1'rrs r<00> selectonezSuiteRequirements.selectoneJr<>rc<01>*<00>tj<00>S)z(Target database must support savepoints.r"rs r<00>
savepointszSuiteRequirements.savepointsOr%rc<01>*<00>tj<00>S)z4Target database must support two-phase transactions.r"rs r<00>two_phase_transactionsz(SuiteRequirements.two_phase_transactionsUr%rc<01>*<00>tj<00>S)z'Target must support UPDATE..FROM syntaxr"rs r<00> update_fromzSuiteRequirements.update_from[rwrc<01>*<00>tj<00>S)z=Target must support DELETE FROM..FROM or DELETE..USING syntaxr"rs r<00> delete_fromzSuiteRequirements.delete_from`rwrc<01>*<00>tj<00>S)a<>Target must support UPDATE (or DELETE) where the same table is
2025-02-23 09:07:52 +08:00
present in a subquery in the WHERE clause.
This is an ANSI-standard syntax that apparently MySQL can't handle,
such as:
.. sourcecode:: sql
UPDATE documents SET flag=1 WHERE documents.title IN
(SELECT max(documents.title) AS title
FROM documents GROUP BY documents.user_id
)
2025-08-29 00:34:40 +08:00
rrs r<00>update_where_target_in_subqueryz1SuiteRequirements.update_where_target_in_subqueryersrc<01>*<00>tj<00>S)zOtarget database must use a plain percent '%' as the 'modulus'
operator.r"rs r<00>mod_operator_as_percent_signz.SuiteRequirements.mod_operator_as_percent_signwr%rc<01>*<00>tj<00>S)atarget backend supports weird identifiers with percent signs
2025-02-23 09:07:52 +08:00
in them, e.g. 'some % column'.
this is a very weird use case but often has problems because of
DBAPIs that use python formatting. It's not a critical use
case either.
2025-08-29 00:34:40 +08:00
r"rs r<00>percent_schema_namesz&SuiteRequirements.percent_schema_names}r<>rc<01>*<00>tj<00>S)z<>target database supports ordering by a column from a SELECT
2025-02-23 09:07:52 +08:00
inside of a UNION
E.g.:
.. sourcecode:: sql
(SELECT id, ...) UNION (SELECT id, ...) ORDER BY id
2025-08-29 00:34:40 +08:00
rrs r<00>order_by_col_from_unionz)SuiteRequirements.order_by_col_from_union<6F>rjrc<01>*<00>tj<00>S)a4target backend supports ORDER BY a column label within an
2025-02-23 09:07:52 +08:00
expression.
Basically this:
.. sourcecode:: sql
select data as foo from test order by foo || 'bar'
Lots of databases including PostgreSQL don't support this,
so this is off by default.
2025-08-29 00:34:40 +08:00
r"rs r<00>order_by_label_with_expressionz0SuiteRequirements.order_by_label_with_expression<6F>s<00><00><1A> <20> <20>"<22>"rc<01>8<00><00><00>fd<01>}tj|<01>S)Nc<01>H<00><01> <00>j|<00>y#t$rYywxYw)NFT)<02>get_order_by_collationr<6E>)rMrs <20>r<00>checkz3SuiteRequirements.order_by_collation.<locals>.check<63>s+<00><><00> <1C><14>+<2B>+<2B>F<EFBFBD>3<><1C><>&<26> <1C><1B> <1C>s <00><00> !<03>!r<><00>rr<>s` r<00>order_by_collationz$SuiteRequirements.order_by_collation<6F>s<00><><00> <1C><1A>!<21>!<21>%<25>(<28>(rc<01><00>t<00><00>r=)r<><00>rrMs rr<>z(SuiteRequirements.get_order_by_collation<6F>s <00><00>!<21>#<23>#rc<01>*<00>tj<00>S)zUTarget driver must support non-ASCII characters being passed at
2025-02-23 09:07:52 +08:00
all.
2025-08-29 00:34:40 +08:00
rrs r<00>unicode_connectionsz%SuiteRequirements.unicode_connections<6E>r9rc<01>*<00>tj<00>S)z<>Target driver must raise a DBAPI-level exception, such as
2025-02-23 09:07:52 +08:00
InterfaceError, when the underlying connection has been closed
and the execute() method is called.
2025-08-29 00:34:40 +08:00
rrs r<00>graceful_disconnectsz&SuiteRequirements.graceful_disconnects<74>r_rc<01>*<00>tj<00>S)zU
2025-02-23 09:07:52 +08:00
Target must support simultaneous, independent database connections.
2025-08-29 00:34:40 +08:00
rrs r<00>independent_connectionsz)SuiteRequirements.independent_connections<6E>r9rc<01>*<00>tj<00>S)z<>
2025-02-23 09:07:52 +08:00
Target must support simultaneous, independent database connections
that will be used in a readonly fashion.
2025-08-29 00:34:40 +08:00
rrs r<00> independent_readonly_connectionsz2SuiteRequirements.independent_readonly_connections<6E>rdrc<01>*<00>tj<00>S)z9Catchall for a large variety of MySQL on Windows failuresrrs r<00>skip_mysql_on_windowsz'SuiteRequirements.skip_mysql_on_windows<77>r<>rc<01>.<00>tjd<01><00>S)aTest environment must allow ad-hoc engine/connection creation.
2025-02-23 09:07:52 +08:00
DBs that scale poorly for many connections, even when closed, i.e.
Oracle, may use the "--low-connections" option which flags this
requirement as not present.
2025-08-29 00:34:40 +08:00
c<01>.<00>|jjSr=)<02>options<6E>low_connectionsrLs rrCz2SuiteRequirements.ad_hoc_engines.<locals>.<lambda><3E>s<00><00>6<EFBFBD>><3E>><3E>9<>9rr<>rs r<00>ad_hoc_enginesz SuiteRequirements.ad_hoc_engines<65>s<00><00><1A>!<21>!<21> 9<>
2025-02-23 09:07:52 +08:00
<EFBFBD>
2025-08-29 00:34:40 +08:00
rc<01>H<00>tj|j<00><00>Sr=)rr<><00>_running_on_windowsrs r<00>
no_windowszSuiteRequirements.no_windows<77>s<00><00><19>!<21>!<21>$<24>":<3A>":<3A>"<<3C>=<3D>=rc<01>2<00>tjd<01>d<02><03>S)Nc<01>0<00>tj<00>dk(S)N<>Windows)<02>platform<72>systemrrrrCz7SuiteRequirements._running_on_windows.<locals>.<lambda><3E>s<00><00>H<EFBFBD>O<EFBFBD>O<EFBFBD>%<25><19>2rzrunning on Windows)<01> description)r<00>LambdaPredicaters rr<>z%SuiteRequirements._running_on_windows<77>s<00><00><19>)<29>)<29> 2<>,<2C>
2025-02-23 09:07:52 +08:00
<EFBFBD>
2025-08-29 00:34:40 +08:00
rc<01>:<00>ddlm}|jjS<00>NrrL)<04>rM<00> add_to_marker<65>timing_intensiver<65>s rr<>z"SuiteRequirements.timing_intensive<76><00><00><00><1C><15>#<23>#<23>4<>4<>4rc<01>.<00>tjd<01><00>S)Nc<01>(<00>tjdk7S)N<>posix)<02>os<6F>namerrrrCz)SuiteRequirements.posix.<locals>.<lambda><3E>s <00><00>"<22>'<27>'<27>W<EFBFBD>*<rr<>rs rrzSuiteRequirements.posix<69>s<00><00><19>!<21>!<21>"<<3C>=<3D>=rc<01>:<00>ddlm}|jjSr<>)r<>rMr<><00>memory_intensiver<65>s rrz"SuiteRequirements.memory_intensive<76>r<>rc<01>0<00>tjd<01>d<02>S)z}Mark tests that use threading and mock at the same time - stability
2025-02-23 09:07:52 +08:00
issues have been observed with coverage
2025-08-29 00:34:40 +08:00
c<01>.<00>|jjSr=<00>r<><00> has_coveragerLs rrCz7SuiteRequirements.threading_with_mock.<locals>.<lambda><00><00><00>6<EFBFBD>><3E>><3E>6<>6rzStability issues with coverager<65>rs r<00>threading_with_mockz%SuiteRequirements.threading_with_mocks<00><00> <1A>!<21>!<21> 6<> ,<2C>
2025-02-23 09:07:52 +08:00
<EFBFBD>
rc<01>2<00>d<01>}tj|<01>S)Nc<01>:<00> td<01>y#t$rYywxYw<01>Nzsqlalchemy-stubs.ext.mypyTF<54><02>
2025-08-29 00:34:40 +08:00
__import__<EFBFBD> ImportErrorrLs rr<>z2SuiteRequirements.sqlalchemy2_stubs.<locals>.check<00>)<00><00> <1C><1A>6<>7<><1C><><1F> <1D><1C> <1D><> <00> <00> <03>rDr<>s r<00>sqlalchemy2_stubsz#SuiteRequirements.sqlalchemy2_stubs <00><00><00> <1C><1A>!<21>!<21>%<25>(<28>(rc<01>2<00>d<01>}tj|<01>S)Nc<01>:<00> td<01>y#t$rYywxYwrrrLs rr<>z5SuiteRequirements.no_sqlalchemy2_stubs.<locals>.checkrrr<>r<>s r<00>no_sqlalchemy2_stubsz&SuiteRequirements.no_sqlalchemy2_stubsrrc<01>2<00>d<01>}tj|<01>S)Nc<01><><00>ddl}ddl}t|d|j<00>}|j d<03>}|d|j
||f<01><05>}t |td<06>S)Nr<00> TypeAliasType<70>TV<54>
TA_generic)<01> type_params<6D> __value__)<08>typing<6E>typing_extensions<6E>getattrr<00>TypeVar<61>List<73>hasattr<74>int)rMr!r"rrrs rr<>z:SuiteRequirements.up_to_date_typealias_type.<locals>.check*s^<00><00> <19> $<24>#<23><16><0F>):<3A>)H<>)H<><0E>M<EFBFBD><18><1E><1E><04>%<25>B<EFBFBD>&<26><1C>f<EFBFBD>k<EFBFBD>k<EFBFBD>"<22>o<EFBFBD>B<EFBFBD>5<EFBFBD><0E>J<EFBFBD><1B>:<3A>c<EFBFBD>?<3F>K<EFBFBD>8<> 8rrDr<>s r<00>up_to_date_typealias_typez+SuiteRequirements.up_to_date_typealias_type$s<00><00> 9<><1A>!<21>!<21>%<25>(<28>(rc<01>0<00>tjd<01>d<02>S)Nc<01>"<00>tjSr=)r <00>py38rrrrCz,SuiteRequirements.python38.<locals>.<lambda><<00><00><00>D<EFBFBD>I<EFBFBD>IrzPython 3.8 or above requiredrDrs r<00>python38zSuiteRequirements.python389<00><00><00><19>!<21>!<21> <1D>=<3D>
2025-02-23 09:07:52 +08:00
<EFBFBD>
2025-08-29 00:34:40 +08:00
rc<01>0<00>tjd<01>d<02>S)Nc<01>"<00>tjSr=)r <00>py39rrrrCz,SuiteRequirements.python39.<locals>.<lambda>Br,rzPython 3.9 or above requiredrDrs r<00>python39zSuiteRequirements.python39?r.rc<01>0<00>tjd<01>d<02>S)Nc<01>"<00>tjSr=)r <00>py310rrrrCz-SuiteRequirements.python310.<locals>.<lambda>H<00><00><00>D<EFBFBD>J<EFBFBD>JrzPython 3.10 or above requiredrDrs r<00> python310zSuiteRequirements.python310E<00><00><00><19>!<21>!<21> <1E> ?<3F>
2025-02-23 09:07:52 +08:00
<EFBFBD>
2025-08-29 00:34:40 +08:00
rc<01>0<00>tjd<01>d<02>S)Nc<01>"<00>tjSr=)r <00>py311rrrrCz-SuiteRequirements.python311.<locals>.<lambda>Nr6rzPython 3.11 or above requiredrDrs r<00> python311zSuiteRequirements.python311Kr8rc<01>0<00>tjd<01>d<02>S)Nc<01>"<00>tjSr=)r <00>py312rrrrCz-SuiteRequirements.python312.<locals>.<lambda>Tr6rzPython 3.12 or above requiredrDrs r<00> python312zSuiteRequirements.python312Qr8rc<01>0<00>tjd<01>d<02>S)Nc<01>6<00>tjjSr=)r <00>compat<61>py314b1rrrrCz4SuiteRequirements.fail_python314b1.<locals>.<lambda>Zs<00><00>D<EFBFBD>K<EFBFBD>K<EFBFBD>'<27>'rzFails as of python 3.14.0b1r<EFBFBD>rs r<00>fail_python314b1z"SuiteRequirements.fail_python314b1Ws<00><00><19>"<22>"<22> '<27>)F<>
2025-02-23 09:07:52 +08:00
<EFBFBD>
2025-08-29 00:34:40 +08:00
rc<01>0<00>tjd<01>d<02>S)a This requirement is interim to assist with backporting of
issue #12405.
SQLAlchemy 2.0 still includes the ``await_fallback()`` method that
makes use of ``asyncio.get_event_loop_policy()``. This is removed
in SQLAlchemy 2.1.
c<01>"<00>tjSr=)r <00>py314rrrrCz1SuiteRequirements.not_python314.<locals>.<lambda>hr6rz"Python 3.14 or above not supportedr<64>rs r<00> not_python314zSuiteRequirements.not_python314]s<00><00><1A>!<21>!<21> <1E> D<>
<EFBFBD>
rc<01>0<00>tjd<01>d<02>S)Nc<01>"<00>tjSr=)r <00>cpythonrrrrCz+SuiteRequirements.cpython.<locals>.<lambda>ns<00><00>D<EFBFBD>L<EFBFBD>LrzcPython interpreter neededrDrs rrLzSuiteRequirements.cpythonks<00><00><19>!<21>!<21> <20>"><3E>
<EFBFBD>
rc<01>0<00>tjd<01>d<02>S)Nc<01>"<00>tjSr=)r <00>is64bitrrrrCz+SuiteRequirements.is64bit.<locals>.<lambda>ss<00><00>$<24>,<2C>,rz64bit requiredrDrs rrOzSuiteRequirements.is64bitqs<00><00><19>!<21>!<21>"6<>8H<38>I<>Irc<01>4<00>d<01>}tj|d<02>S)Nc<01>:<00> td<01>y#t$rYywxYw)N<>patchTFrrrr<00> check_libz2SuiteRequirements.patch_library.<locals>.check_libws(<00><00> <1C><1A>7<EFBFBD>#<23><1C><><1F> <1D><1C> <1D>rzpatch library neededrD)rrSs r<00> patch_libraryzSuiteRequirements.patch_libraryus<00><00> <1C><1A>!<21>!<21>)<29>-C<>D<>Drc<01><00>|jS)z<>target platform must remove all cycles unconditionally when
2025-02-23 09:07:52 +08:00
gc.collect() is called, as well as clean out unreferenced subclasses.
2025-08-29 00:34:40 +08:00
)rLrs r<00>predictable_gcz SuiteRequirements.predictable_gc<67>s<00><00> <14>|<7C>|<7C>rc<01>0<00>tjd<01>d<02>S)z<>Test should be skipped if coverage is enabled.
2025-02-23 09:07:52 +08:00
This is to block tests that exercise libraries that seem to be
sensitive to coverage, such as PostgreSQL notice logging.
2025-08-29 00:34:40 +08:00
c<01>.<00>|jjSr=r rLs rrCz/SuiteRequirements.no_coverage.<locals>.<lambda><3E>r rz(Issues observed when coverage is enabledr<64>rs r<00> no_coveragezSuiteRequirements.no_coverage<67>s<00><00><1A>!<21>!<21> 6<> 6<>
2025-02-23 09:07:52 +08:00
<EFBFBD>
2025-08-29 00:34:40 +08:00
rc<01><00>y<01>NFrr<>s r<00>_has_mysql_on_windowsz'SuiteRequirements._has_mysql_on_windows<77><00><00><00>rc<01><00>yr[rr<>s r<00>_has_mysql_fully_case_sensitivez1SuiteRequirements._has_mysql_fully_case_sensitive<76>r]rc<01>4<00><00>tj<00>fd<01><08>S)Nc<01>&<00><01><00>j<00> Sr=)<01> _has_sqliters<00>rrCz*SuiteRequirements.sqlite.<locals>.<lambda><3E>s<00><><00>d<EFBFBD>.><3E>.><3E>.@<40>*@rr<>rs`r<00>sqlitezSuiteRequirements.sqlite<74>s<00><><00><19>!<21>!<21>"@<40>A<>Arc<01>0<00>tjd<01>d<02>S)Nc<01>,<00>tj<00> Sr=)r <00>has_compiled_extrrrrCz/SuiteRequirements.cextensions.<locals>.<lambda><3E>s<00><00><04>-<2D>-<2D>/<2F>/rzCython extensions not installedr<64>rs r<00> cextensionszSuiteRequirements.cextensions<6E>s<00><00><19>!<21>!<21> /<2F> -<2D>
2025-02-23 09:07:52 +08:00
<EFBFBD>
rc<01>@<00>ddlm} |d<03>y#t$rYywxYw)Nrr
z sqlite://TF)<03>
2025-08-29 00:34:40 +08:00
sqlalchemyr r)rr s rrbzSuiteRequirements._has_sqlite<74>s'<00><00>,<2C> <19> <19>+<2B> &<26><17><><1A> <19><18> <19>s <00><00> <03>c<01>*<00>tj<00>S)z@dialect makes use of await_() to invoke operations on the DBAPI.r"rs r<00> async_dialectzSuiteRequirements.async_dialect<63>r%rc<01><00>|jSr=)<01>greenletrs rrzSuiteRequirements.asyncio<69>s <00><00><13>}<7D>}<7D>rc<01>2<00>d<01>}tj|<01>S)Nc<01>,<00> ddl}y#t$rYywxYw)NrFT)rmr<00>rMrms rrNz)SuiteRequirements.no_greenlet.<locals>.go<67>s#<00><00> <1D><1F><1D><><1F> <1C><1B> <1C>s <00><00> <03>rDrOs r<00> no_greenletzSuiteRequirements.no_greenlet<65>s<00><00> <1D><1A>!<21>!<21>"<22>%<25>%rc<01>2<00>d<01>}tj|<01>S)Nc<01>N<00>tjsy ddl}y#t$rYywxYw)NFrT)<04> _test_asyncio<69>ENABLE_ASYNCIOrmrrps rrNz&SuiteRequirements.greenlet.<locals>.go<67>s/<00><00> <20>/<2F>/<2F><1C> <1C><1F><1C><><1F> <1D><1C> <1D>s <00><00> $<03>$rDrOs rrmzSuiteRequirements.greenlet<65>s<00><00> <1C><1A>!<21>!<21>"<22>%<25>%rc<01>*<00>tj<00>S)zSupports computed columnsr"rs r<00>computed_columnsz"SuiteRequirements.computed_columns<6E>rwrc<01>*<00>tj<00>S)z/Supports computed columns with `persisted=True`r"rs r<00>computed_columns_storedz)SuiteRequirements.computed_columns_stored<65>rwrc<01>*<00>tj<00>S)z0Supports computed columns with `persisted=False`r"rs r<00>computed_columns_virtualz*SuiteRequirements.computed_columns_virtual<61>rwrc<01>*<00>tj<00>S)zSIf the default persistence is virtual or stored when `persisted`
is omittedr"rs r<00>"computed_columns_default_persistedz4SuiteRequirements.computed_columns_default_persisted<65>r%rc<01>*<00>tj<00>S)zTIf persistence information is returned by the reflection of
computed columnsr"rs r<00>"computed_columns_reflect_persistedz4SuiteRequirements.computed_columns_reflect_persisted<65>r%rc<01>*<00>tj<00>S)z1If a backend supports the DISTINCT ON in a selectr"rs r<00>supports_distinct_onz&SuiteRequirements.supports_distinct_on<6F>rwrc<01>0<00>tjd<01>d<02>S)a Supports some form of "x IS [NOT] DISTINCT FROM y" construct.
2025-02-23 09:07:52 +08:00
Different dialects will implement their own flavour, e.g.,
sqlite will emit "x IS NOT y" instead of "x IS DISTINCT FROM y".
.. seealso::
:meth:`.ColumnOperators.is_distinct_from`
2025-08-29 00:34:40 +08:00
c<01>D<00>|jjj Sr=)rJr<><00>supports_is_distinct_fromrLs rrCz=SuiteRequirements.supports_is_distinct_from.<locals>.<lambda>s<00><00>v<EFBFBD>y<EFBFBD>y<EFBFBD>0<>0<>J<>J<>Jrz4driver doesn't support an IS DISTINCT FROM constructr<74>rs rr<>z+SuiteRequirements.supports_is_distinct_from<6F>s<00><00><1A>!<21>!<21> J<> B<>
2025-02-23 09:07:52 +08:00
<EFBFBD>
rc<01>*<00>tj<00>S)zKIf a backend supports GENERATED { ALWAYS | BY DEFAULT }
2025-08-29 00:34:40 +08:00
AS IDENTITYr"rs r<00>identity_columnsz"SuiteRequirements.identity_columnsr%rc<01>*<00>tj<00>S)z<>If a backend supports GENERATED { ALWAYS | BY DEFAULT }
2025-02-23 09:07:52 +08:00
AS IDENTITY with a standard syntax.
This is mainly to exclude MSSql.
2025-08-29 00:34:40 +08:00
r"rs r<00>identity_columns_standardz+SuiteRequirements.identity_columns_standard r<>rc<01>*<00>tj<00>S)z+backend supports the regexp_match operator.r"rs r<00> regexp_matchzSuiteRequirements.regexp_matchrwrc<01>*<00>tj<00>S)z-backend supports the regexp_replace operator.r"rs r<00>regexp_replacez SuiteRequirements.regexp_replacerwrc<01>*<00>tj<00>S)z(backend supports the fetch first clause.r"rs r<00> fetch_firstzSuiteRequirements.fetch_firstrwrc<01>*<00>tj<00>S)z5backend supports the fetch first clause with percent.r"rs r<00> fetch_percentzSuiteRequirements.fetch_percent"rwrc<01>*<00>tj<00>S)z2backend supports the fetch first clause with ties.r"rs r<00>
fetch_tieszSuiteRequirements.fetch_ties'rwrc<01>*<00>tj<00>S)z1backend supports the fetch first without order byr"rs r<00>fetch_no_order_byz#SuiteRequirements.fetch_no_order_by,rwrc<01>*<00>tj<00>S)zwbackend supports the offset when using fetch first with percent
2025-02-23 09:07:52 +08:00
or ties. basically this is "not mssql"
2025-08-29 00:34:40 +08:00
r"rs r<00>fetch_offset_with_optionsz+SuiteRequirements.fetch_offset_with_options1r.rc<01>*<00>tj<00>S)z<>backend supports fetch / offset with expression in them, like
2025-02-23 09:07:52 +08:00
SELECT * FROM some_table
OFFSET 1 + 1 ROWS FETCH FIRST 1 + 1 ROWS ONLY
2025-08-29 00:34:40 +08:00
r"rs r<00>fetch_expressionz"SuiteRequirements.fetch_expression8r<>rc<01>*<00>tj<00>S)zIf autoincrement=True on a column does not require an explicit
2025-02-23 09:07:52 +08:00
sequence. This should be false only for oracle.
2025-08-29 00:34:40 +08:00
rrs r<00>autoincrement_without_sequencez0SuiteRequirements.autoincrement_without_sequenceAr9rc<01>*<00>tj<00>S)z=If X[Y] can be implemented with ``__class_getitem__``. py3.7+rrs r<00>generic_classesz!SuiteRequirements.generic_classesHr<>rc<01>*<00>tj<00>S)z@indicates if the json_deserializer function is called with bytesr"rs r<00>json_deserializer_binaryz*SuiteRequirements.json_deserializer_binaryMrwrc<01>*<00>tj<00>S)z6Target database must support reflecting table_options.r"rs r<00>reflect_table_optionsz'SuiteRequirements.reflect_table_optionsRrwrc<01>*<00>tj<00>S)z0Target database must support MATERIALIZED VIEWs.r"rs r<00>materialized_viewsz$SuiteRequirements.materialized_viewsWrwrc<01>*<00>tj<00>S)z/Target database reflect MATERIALIZED VIEWs pks.r"rs r<00>materialized_views_reflect_pkz/SuiteRequirements.materialized_views_reflect_pk\rwrc<01>*<00>tj<00>S)z#Target database supports bitwise orr"rs r<00>supports_bitwise_orz%SuiteRequirements.supports_bitwise_orarwrc<01>*<00>tj<00>S)z$Target database supports bitwise andr"rs r<00>supports_bitwise_andz&SuiteRequirements.supports_bitwise_andfrwrc<01>*<00>tj<00>S)z$Target database supports bitwise notr"rs r<00>supports_bitwise_notz&SuiteRequirements.supports_bitwise_notkrwrc<01>*<00>tj<00>S)z$Target database supports bitwise xorr"rs r<00>supports_bitwise_xorz&SuiteRequirements.supports_bitwise_xorprwrc<01>*<00>tj<00>S)z4Target database supports bitwise left or right shiftr"rs r<00>supports_bitwise_shiftz(SuiteRequirements.supports_bitwise_shifturwrc<01>*<00>tj<00>S)zNTarget backend supports custom ESCAPE characters
with LIKE comparisonsrrs r<00> like_escapeszSuiteRequirements.like_escapeszrrN)<29>rrr<00>propertyrr r$r'r)r+r-r0r2r4r6r8r;r>rFrPrRrTrVrXrZr\r^rarcrfrirlrnrprrrtrvryr{r}rr<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>rrrrr
r rrrrrrrrrr!r#r%r'r)r+r-r/r1r3r5r7r9r;r=r?rArCrErGrIrKrMrOrQrSrUrWrYr[r]r_rardrfrhrjrlrnrprrrurwryr<>r~r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>rrr rrr(r-r2r7r<r@rErIrLrOrTrVrYr\r_rcrgrbrkrrqrmrwryr{r}rr<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>r<>rrrrr%s<><00><00> <0A>!<21><0E>!<21>
2025-02-23 09:07:52 +08:00
<0E>!<21><0E>!<21>
<0E>#<23><0E>#<23>
<0E>#<23><0E>#<23>
<0E>#<23><0E>#<23>
<0E>!<21><0E>!<21>
<0E>#<23><0E>#<23> <0E>#<23><0E>#<23>
<0E>#<23><0E>#<23>
<0E> #<23><0E> #<23><0E>!<21><0E>!<21>&<0E>!<21><0E>!<21> <0E>#<23><0E>#<23>
<0E>#<23><0E>#<23><0E>
<EFBFBD><0E>
<EFBFBD><0E>&<26><0E>&<26><0E>!<21><0E>!<21>
<0E>!<21><0E>!<21>
<0E>!<21><0E>!<21>
<0E>!<21><0E>!<21>
<0E>!<21><0E>!<21><0E>!<21><0E>!<21>
<0E>!<21><0E>!<21><0E>!<21><0E>!<21><0E>!<21><0E>!<21><0E> !<21><0E> !<21><0E> !<21><0E> !<21><0E>#<23><0E>#<23>
<0E>!<21><0E>!<21>
<0E>#<23><0E>#<23>
<0E>!<21><0E>!<21> <0E>!<21><0E>!<21><0E>#<23><0E>#<23><0E>#<23><0E>#<23><0E>#<23><0E>#<23><0E>#<23><0E>#<23>
2025-08-29 00:34:40 +08:00
<0E>#<23><0E>#<23><0E>#<23><0E>#<23> <0E>#<23><0E>#<23> <0E>!<21><0E>!<21> <0E>
2025-02-23 09:07:52 +08:00
!<21><0E>
!<21><0E> !<21><0E> !<21><0E>
<EFBFBD><0E>
<EFBFBD> <0E>
<EFBFBD><0E>
<EFBFBD> <0E>
<EFBFBD><0E>
<EFBFBD><0E> 
<EFBFBD><0E> 
<EFBFBD><0E>"<22><0E>"<22> <0E>!<21><0E>!<21>
<0E>
<EFBFBD><0E>
<EFBFBD><0E>
<EFBFBD><0E>
<EFBFBD><0E>
<EFBFBD><0E>
<EFBFBD><0E> 
<EFBFBD><0E> 
<EFBFBD><0E>
<EFBFBD><0E>
<EFBFBD><0E>#<23><0E>#<23><0E><1D><0E><1D><0E>!<21><0E>!<21> <0E>
<EFBFBD><0E>
<EFBFBD><0E>
<EFBFBD><0E>
<EFBFBD><0E>!<21><0E>!<21><0E>!<21><0E>!<21> <0E> #<23><0E> #<23><0E>#<23><0E>#<23><0E>#<23><0E>#<23><0E>#<23><0E>#<23>
<0E>J<01><0E>J<01> <0E>#<23><0E>#<23>
<0E> #<23><0E> #<23><0E>#<23><0E>#<23><0E>#<23><0E>#<23> <0E>
<EFBFBD><0E>
<EFBFBD><0E>
<EFBFBD><0E>
<EFBFBD><0E>7<><0E>7<> <0E>

<EFBFBD><0E>

<EFBFBD><0E>

<EFBFBD><0E>

<EFBFBD><0E>
<EFBFBD><0E>
2025-08-29 00:34:40 +08:00
<EFBFBD> <0E>#<23><0E>#<23><0E>!<21><0E>!<21><0E>#<23><0E>#<23> <0E>#<23><0E>#<23>
<0E>#<23><0E>#<23><0E>#<23><0E>#<23> <0E>#<23><0E>#<23>
2025-02-23 09:07:52 +08:00
<0E><1A><0E><1A><0E><1A><0E><1A>
<0E><1C><0E><1C><0E>#<23><0E>#<23>
<0E>!<21><0E>!<21><0E>!<21><0E>!<21><0E>#<23><0E>#<23><0E>#<23><0E>#<23><0E>#<23><0E>#<23><0E>#<23><0E>#<23><0E>#<23><0E>#<23><0E>!<21><0E>!<21><0E>*<2A><0E>*<2A><0E>#<23><0E>#<23><0E>#<23><0E>#<23><0E>!<21><0E>!<21><0E>#<23><0E>#<23><0E>!<21><0E>!<21><0E>#<23><0E>#<23><0E>!<21><0E>!<21><0E>!<21><0E>!<21>
<0E>#<23><0E>#<23>
<0E>#<23><0E>#<23><0E>#<23><0E>#<23>
<0E>!<21><0E>!<21><0E>#<23><0E>#<23><0E>#<23><0E>#<23><0E>!<21><0E>!<21><0E>!<21><0E>!<21>
2025-08-29 00:34:40 +08:00
<0E>#<23><0E>#<23><0E>!<21><0E>!<21><0E>!<21><0E>!<21><0E>#<23><0E>#<23> <0E>!<21><0E>!<21><0E>#<23><0E>#<23><0E>#<23><0E>#<23><0E>!<21><0E>!<21> <0E>#<23><0E>#<23> <0E>#<23><0E>#<23> <0E>!<21><0E>!<21><0E>!<21><0E>!<21><0E>!<21><0E>!<21><0E>!<21><0E>!<21> <0E>#<23><0E>#<23> <0E>+<2B><0E>+<2B><0E>#<23><0E>#<23> <0E>!<21><0E>!<21> <0E>!<21><0E>!<21> <0E>#<23><0E>#<23> <0E>!<21><0E>!<21> <0E>!<21><0E>!<21> <0E>!<21><0E>!<21><0E>!<21><0E>!<21>"<0E>#<23><0E>#<23><0E>#<23><0E>#<23> <0E>#<23><0E>#<23>$<12>L<0E>&<26><0E>&<26>(<0E>&<26><0E>&<26>$<0E>#<23><0E>#<23><0E>#<23><0E>#<23>
2025-02-23 09:07:52 +08:00
<0E><1E><0E><1E> <0E>!<21><0E>!<21><0E>#<23><0E>#<23><0E>!<21><0E>!<21>
<0E>#<23><0E>#<23>
<0E>!<21><0E>!<21>
2025-08-29 00:34:40 +08:00
<0E>#<23><0E>#<23><0E>?<3F><0E>?<3F><0E>#<23><0E>#<23>
<0E>#<23><0E>#<23> <0E>!<21><0E>!<21>$<0E> !<21><0E> !<21><0E>!<21><0E>!<21><0E>!<21><0E>!<21><0E>#<23><0E>#<23><0E>#<23><0E>#<23>
2025-02-23 09:07:52 +08:00
<0E>#<23><0E>#<23><0E>!<21><0E>!<21><0E> !<21><0E> !<21><0E>!<21><0E>!<21><0E>!<21><0E>!<21><0E>!<21><0E>!<21>
<0E>!<21><0E>!<21> <0E>!<21><0E>!<21><0E>!<21><0E>!<21> <0E>!<21><0E>!<21> <0E>!<21><0E>!<21><0E>#<23><0E>#<23>
<0E>#<23><0E>#<23>
<0E>#<23><0E>#<23><0E>#<23><0E>#<23><0E>!<21><0E>!<21>"<0E>#<23><0E>#<23>
<0E> #<23><0E> #<23><0E> !<21><0E> !<21><0E>#<23><0E>#<23> <0E>)<29><0E>)<29>$<24><0E>!<21><0E>!<21> <0E>!<21><0E>!<21><0E>!<21><0E>!<21> <0E>!<21><0E>!<21><0E>!<21><0E>!<21><0E>

<EFBFBD><0E>

<EFBFBD><0E>><3E><0E>><3E>
<EFBFBD> <0E>5<><0E>5<>
2025-08-29 00:34:40 +08:00
<0E>><3E><0E>><3E><0E>5<><0E>5<>
2025-02-23 09:07:52 +08:00
<0E>
<EFBFBD><0E>
2025-08-29 00:34:40 +08:00
<EFBFBD><0E> )<29><0E> )<29><0E> )<29><0E> )<29><0E>)<29><0E>)<29>(<0E>
2025-02-23 09:07:52 +08:00
<EFBFBD><0E>
<EFBFBD>
<0E>
<EFBFBD><0E>
<EFBFBD>
<0E>
<EFBFBD><0E>
<EFBFBD>
<0E>
<EFBFBD><0E>
<EFBFBD>
<0E>
<EFBFBD><0E>
<EFBFBD>
<0E>
<EFBFBD><0E>
<EFBFBD>
2025-08-29 00:34:40 +08:00
<0E> 
<EFBFBD><0E> 
<EFBFBD><0E>
<EFBFBD><0E>
<EFBFBD>
2025-02-23 09:07:52 +08:00
<0E>J<01><0E>J<01><0E> E<01><0E> E<01><0E><1C><0E><1C><0E>

<EFBFBD><0E>

<EFBFBD><15><15><0E>B<01><0E>B<01><0E>
<EFBFBD><0E>
<EFBFBD> <19><0E>#<23><0E>#<23>
<0E><1D><0E><1D><0E> &<26><0E> &<26><0E> &<26><0E> &<26><0E>#<23><0E>#<23><0E>#<23><0E>#<23><0E>#<23><0E>#<23><0E>#<23><0E>#<23>
<0E>#<23><0E>#<23>
<0E>#<23><0E>#<23><0E> 
<EFBFBD><0E> 
<EFBFBD><0E>#<23><0E>#<23>
2025-08-29 00:34:40 +08:00
<0E>#<23><0E>#<23><0E>#<23><0E>#<23><0E>#<23><0E>#<23><0E>#<23><0E>#<23><0E>#<23><0E>#<23><0E>#<23><0E>#<23><0E>#<23><0E>#<23><0E>#<23><0E>#<23> <0E>#<23><0E>#<23><0E>!<21><0E>!<21> <0E>!<21><0E>!<21><0E>#<23><0E>#<23><0E>#<23><0E>#<23><0E>#<23><0E>#<23><0E>#<23><0E>#<23><0E>#<23><0E>#<23><0E>#<23><0E>#<23><0E>#<23><0E>#<23><0E>#<23><0E>#<23><0E>#<23><0E>#<23><0E>!<21><0E>!rr)<10>__doc__<5F>
__future__rrr<>r<>rrtrrr r rKr rrrrr<00><module>r<>s?<00><01><04>#<23> <09><0F>&<26><18><1F><1C><13><1C> <09> <09>Y!<21> <0C>Y!r