Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes15kdownloads
requirements.py1946 linesDownload Raw Back to testing
1# testing/requirements.py
2# Copyright (C) 2005-2026 the SQLAlchemy authors and contributors
3# <see AUTHORS file>
4#
5# This module is part of SQLAlchemy and is released under
6# the MIT License: https://www.opensource.org/licenses/mit-license.php
7# mypy: ignore-errors
8
9
10"""Global database feature support policy.
11
12Provides decorators to mark tests requiring specific feature support from the
13target database.
14
15External dialect test suites should subclass SuiteRequirements
16to provide specific inclusion/exclusions.
17
18"""
19
20from __future__ import annotations
21
22import os
23import platform
24
25from . import asyncio as _test_asyncio
26from . import exclusions
27from .exclusions import only_on
28from .. import create_engine
29from .. import util
30from ..pool import QueuePool
31
32
33class Requirements:
34    pass
35
36
37class SuiteRequirements(Requirements):
38    @property
39    def create_table(self):
40        """target platform can emit basic CreateTable DDL."""
41
42        return exclusions.open()
43
44    @property
45    def drop_table(self):
46        """target platform can emit basic DropTable DDL."""
47
48        return exclusions.open()
49
50    @property
51    def table_ddl_if_exists(self):
52        """target platform supports IF NOT EXISTS / IF EXISTS for tables."""
53
54        return exclusions.closed()
55
56    @property
57    def index_ddl_if_exists(self):
58        """target platform supports IF NOT EXISTS / IF EXISTS for indexes."""
59
60        return exclusions.closed()
61
62    @property
63    def uuid_data_type(self):
64        """Return databases that support the UUID datatype."""
65
66        return exclusions.closed()
67
68    @property
69    def foreign_keys(self):
70        """Target database must support foreign keys."""
71
72        return exclusions.open()
73
74    @property
75    def foreign_keys_reflect_as_index(self):
76        """Target database creates an index that's reflected for
77        foreign keys."""
78
79        return exclusions.closed()
80
81    @property
82    def unique_index_reflect_as_unique_constraints(self):
83        """Target database reflects unique indexes as unique constrains."""
84
85        return exclusions.closed()
86
87    @property
88    def unique_constraints_reflect_as_index(self):
89        """Target database reflects unique constraints as indexes."""
90
91        return exclusions.closed()
92
93    @property
94    def table_value_constructor(self):
95        """Database / dialect supports a query like:
96
97        .. sourcecode:: sql
98
99             SELECT * FROM VALUES ( (c1, c2), (c1, c2), ...)
100             AS some_table(col1, col2)
101
102        SQLAlchemy generates this with the :func:`_sql.values` function.
103
104        """
105        return exclusions.closed()
106
107    @property
108    def standard_cursor_sql(self):
109        """Target database passes SQL-92 style statements to cursor.execute()
110        when a statement like select() or insert() is run.
111
112        A very small portion of dialect-level tests will ensure that certain
113        conditions are present in SQL strings, and these tests use very basic
114        SQL that will work on any SQL-like platform in order to assert results.
115
116        It's normally a given for any pep-249 DBAPI that a statement like
117        "SELECT id, name FROM table WHERE some_table.id=5" will work.
118        However, there are dialects that don't actually produce SQL Strings
119        and instead may work with symbolic objects instead, or dialects that
120        aren't working with SQL, so for those this requirement can be marked
121        as excluded.
122
123        """
124
125        return exclusions.open()
126
127    @property
128    def on_update_cascade(self):
129        """target database must support ON UPDATE..CASCADE behavior in
130        foreign keys."""
131
132        return exclusions.open()
133
134    @property
135    def non_updating_cascade(self):
136        """target database must *not* support ON UPDATE..CASCADE behavior in
137        foreign keys."""
138        return exclusions.closed()
139
140    @property
141    def deferrable_fks(self):
142        return exclusions.closed()
143
144    @property
145    def on_update_or_deferrable_fks(self):
146        # TODO: exclusions should be composable,
147        # somehow only_if([x, y]) isn't working here, negation/conjunctions
148        # getting confused.
149        return exclusions.only_if(
150            lambda: self.on_update_cascade.enabled
151            or self.deferrable_fks.enabled
152        )
153
154    @property
155    def queue_pool(self):
156        """target database is using QueuePool"""
157
158        def go(config):
159            return isinstance(config.db.pool, QueuePool)
160
161        return exclusions.only_if(go)
162
163    @property
164    def self_referential_foreign_keys(self):
165        """Target database must support self-referential foreign keys."""
166
167        return exclusions.open()
168
169    @property
170    def foreign_key_ddl(self):
171        """Target database must support the DDL phrases for FOREIGN KEY."""
172
173        return exclusions.open()
174
175    @property
176    def named_constraints(self):
177        """target database must support names for constraints."""
178
179        return exclusions.open()
180
181    @property
182    def implicitly_named_constraints(self):
183        """target database must apply names to unnamed constraints."""
184
185        return exclusions.open()
186
187    @property
188    def unusual_column_name_characters(self):
189        """target database allows column names that have unusual characters
190        in them, such as dots, spaces, slashes, or percent signs.
191
192        The column names are as always in such a case quoted, however the
193        DB still needs to support those characters in the name somehow.
194
195        """
196        return exclusions.open()
197
198    @property
199    def subqueries(self):
200        """Target database must support subqueries."""
201
202        return exclusions.open()
203
204    @property
205    def offset(self):
206        """target database can render OFFSET, or an equivalent, in a
207        SELECT.
208        """
209
210        return exclusions.open()
211
212    @property
213    def bound_limit_offset(self):
214        """target database can render LIMIT and/or OFFSET using a bound
215        parameter
216        """
217
218        return exclusions.open()
219
220    @property
221    def sql_expression_limit_offset(self):
222        """target database can render LIMIT and/or OFFSET with a complete
223        SQL expression, such as one that uses the addition operator.
224        parameter
225        """
226
227        return exclusions.open()
228
229    @property
230    def parens_in_union_contained_select_w_limit_offset(self):
231        """Target database must support parenthesized SELECT in UNION
232        when LIMIT/OFFSET is specifically present.
233
234        E.g. (SELECT ...) UNION (SELECT ..)
235
236        This is known to fail on SQLite.
237
238        """
239        return exclusions.open()
240
241    @property
242    def parens_in_union_contained_select_wo_limit_offset(self):
243        """Target database must support parenthesized SELECT in UNION
244        when OFFSET/LIMIT is specifically not present.
245
246        E.g. (SELECT ... LIMIT ..) UNION (SELECT .. OFFSET ..)
247
248        This is known to fail on SQLite.  It also fails on Oracle
249        because without LIMIT/OFFSET, there is currently no step that
250        creates an additional subquery.
251
252        """
253        return exclusions.open()
254
255    @property
256    def boolean_col_expressions(self):
257        """Target database must support boolean expressions as columns"""
258
259        return exclusions.closed()
260
261    @property
262    def nullable_booleans(self):
263        """Target database allows boolean columns to store NULL."""
264
265        return exclusions.open()
266
267    @property
268    def nullsordering(self):
269        """Target backends that support nulls ordering."""
270
271        return exclusions.closed()
272
273    @property
274    def standalone_binds(self):
275        """target database/driver supports bound parameters as column
276        expressions without being in the context of a typed column.
277        """
278        return exclusions.open()
279
280    @property
281    def standalone_null_binds_whereclause(self):
282        """target database/driver supports bound parameters with NULL in the
283        WHERE clause, in situations where it has to be typed.
284
285        """
286        return exclusions.open()
287
288    @property
289    def intersect(self):
290        """Target database must support INTERSECT or equivalent."""
291        return exclusions.closed()
292
293    @property
294    def except_(self):
295        """Target database must support EXCEPT or equivalent (i.e. MINUS)."""
296        return exclusions.closed()
297
298    @property
299    def window_functions(self):
300        """Target database must support window functions."""
301        return exclusions.closed()
302
303    @property
304    def ctes(self):
305        """Target database supports CTEs"""
306
307        return exclusions.closed()
308
309    @property
310    def ctes_with_update_delete(self):
311        """target database supports CTES that ride on top of a normal UPDATE
312        or DELETE statement which refers to the CTE in a correlated subquery.
313
314        """
315
316        return exclusions.closed()
317
318    @property
319    def ctes_with_values(self):
320        """target database supports CTES that ride on top of a VALUES
321        clause."""
322
323        return exclusions.closed()
324
325    @property
326    def ctes_on_dml(self):
327        """target database supports CTES which consist of INSERT, UPDATE
328        or DELETE *within* the CTE, e.g. WITH x AS (UPDATE....)"""
329
330        return exclusions.closed()
331
332    @property
333    def autoincrement_insert(self):
334        """target platform generates new surrogate integer primary key values
335        when insert() is executed, excluding the pk column."""
336
337        return exclusions.open()
338
339    @property
340    def fetch_rows_post_commit(self):
341        """target platform will allow cursor.fetchone() to proceed after a
342        COMMIT.
343
344        Typically this refers to an INSERT statement with RETURNING which
345        is invoked within "autocommit".   If the row can be returned
346        after the autocommit, then this rule can be open.
347
348        """
349
350        return exclusions.open()
351
352    @property
353    def group_by_complex_expression(self):
354        """target platform supports SQL expressions in GROUP BY
355
356        e.g.
357
358        SELECT x + y AS somelabel FROM table GROUP BY x + y
359
360        """
361
362        return exclusions.open()
363
364    @property
365    def sane_rowcount(self):
366        return exclusions.skip_if(
367            lambda config: not config.db.dialect.supports_sane_rowcount,
368            "driver doesn't support 'sane' rowcount",
369        )
370
371    @property
372    def sane_multi_rowcount(self):
373        return exclusions.fails_if(
374            lambda config: not config.db.dialect.supports_sane_multi_rowcount,
375            "driver %(driver)s %(doesnt_support)s 'sane' multi row count",
376        )
377
378    @property
379    def sane_rowcount_w_returning(self):
380        return exclusions.fails_if(
381            lambda config: not (
382                config.db.dialect.supports_sane_rowcount_returning
383            ),
384            "driver doesn't support 'sane' rowcount when returning is on",
385        )
386
387    @property
388    def empty_inserts(self):
389        """target platform supports INSERT with no values, i.e.
390        INSERT DEFAULT VALUES or equivalent."""
391
392        return exclusions.only_if(
393            lambda config: config.db.dialect.supports_empty_insert
394            or config.db.dialect.supports_default_values
395            or config.db.dialect.supports_default_metavalue,
396            "empty inserts not supported",
397        )
398
399    @property
400    def empty_inserts_executemany(self):
401        """target platform supports INSERT with no values, i.e.
402        INSERT DEFAULT VALUES or equivalent, within executemany()"""
403
404        return self.empty_inserts
405
406    @property
407    def insert_from_select(self):
408        """target platform supports INSERT from a SELECT."""
409
410        return exclusions.open()
411
412    @property
413    def delete_returning(self):
414        """target platform supports DELETE ... RETURNING."""
415
416        return exclusions.only_if(
417            lambda config: config.db.dialect.delete_returning,
418            "%(database)s %(does_support)s 'DELETE ... RETURNING'",
419        )
420
421    @property
422    def insert_returning(self):
423        """target platform supports INSERT ... RETURNING."""
424
425        return exclusions.only_if(
426            lambda config: config.db.dialect.insert_returning,
427            "%(database)s %(does_support)s 'INSERT ... RETURNING'",
428        )
429
430    @property
431    def update_returning(self):
432        """target platform supports UPDATE ... RETURNING."""
433
434        return exclusions.only_if(
435            lambda config: config.db.dialect.update_returning,
436            "%(database)s %(does_support)s 'UPDATE ... RETURNING'",
437        )
438
439    @property
440    def insert_executemany_returning(self):
441        """target platform supports RETURNING when INSERT is used with
442        executemany(), e.g. multiple parameter sets, indicating
443        as many rows come back as do parameter sets were passed.
444
445        """
446
447        return exclusions.only_if(
448            lambda config: config.db.dialect.insert_executemany_returning,
449            "%(database)s %(does_support)s 'RETURNING of "
450            "multiple rows with INSERT executemany'",
451        )
452
453    @property
454    def insertmanyvalues(self):
455        return exclusions.only_if(
456            lambda config: config.db.dialect.supports_multivalues_insert
457            and config.db.dialect.insert_returning
458            and config.db.dialect.use_insertmanyvalues,
459            "%(database)s %(does_support)s 'insertmanyvalues functionality",
460        )
461
462    @property
463    def tuple_in(self):
464        """Target platform supports the syntax
465        "(x, y) IN ((x1, y1), (x2, y2), ...)"
466        """
467
468        return exclusions.closed()
469
470    @property
471    def tuple_in_w_empty(self):
472        """Target platform tuple IN w/ empty set"""
473        return self.tuple_in
474
475    @property
476    def duplicate_names_in_cursor_description(self):
477        """target platform supports a SELECT statement that has
478        the same name repeated more than once in the columns list."""
479
480        return exclusions.open()
481
482    @property
483    def denormalized_names(self):
484        """Target database must have 'denormalized', i.e.
485        UPPERCASE as case insensitive names."""
486
487        return exclusions.skip_if(
488            lambda config: not config.db.dialect.requires_name_normalize,
489            "Backend does not require denormalized names.",
490        )
491
492    @property
493    def multivalues_inserts(self):
494        """target database must support multiple VALUES clauses in an
495        INSERT statement."""
496
497        return exclusions.skip_if(
498            lambda config: not config.db.dialect.supports_multivalues_insert,
499            "Backend does not support multirow inserts.",
500        )
501
502    @property
503    def implements_get_lastrowid(self):
504        """target dialect implements the executioncontext.get_lastrowid()
505        method without reliance on RETURNING.
506
507        """
508        return exclusions.open()
509
510    @property
511    def arraysize(self):
512        """dialect includes the required pep-249 attribute
513        ``cursor.arraysize``"""
514
515        return exclusions.open()
516
517    @property
518    def emulated_lastrowid(self):
519        """target dialect retrieves cursor.lastrowid, or fetches
520        from a database-side function after an insert() construct executes,
521        within the get_lastrowid() method.
522
523        Only dialects that "pre-execute", or need RETURNING to get last
524        inserted id, would return closed/fail/skip for this.
525
526        """
527        return exclusions.closed()
528
529    @property
530    def emulated_lastrowid_even_with_sequences(self):
531        """target dialect retrieves cursor.lastrowid or an equivalent
532        after an insert() construct executes, even if the table has a
533        Sequence on it.
534
535        """
536        return exclusions.closed()
537
538    @property
539    def dbapi_lastrowid(self):
540        """target platform includes a 'lastrowid' accessor on the DBAPI
541        cursor object.
542
543        """
544        return exclusions.closed()
545
546    @property
547    def views(self):
548        """Target database must support VIEWs."""
549
550        return exclusions.closed()
551
552    @property
553    def schemas(self):
554        """Target database must support external schemas, and have one
555        named 'test_schema'."""
556
557        return only_on(lambda config: config.db.dialect.supports_schemas)
558
559    @property
560    def cross_schema_fk_reflection(self):
561        """target system must support reflection of inter-schema
562        foreign keys"""
563        return exclusions.closed()
564
565    @property
566    def foreign_key_constraint_name_reflection(self):
567        """Target supports reflection of FOREIGN KEY constraints and
568        will return the name of the constraint that was used in the
569        "CONSTRAINT <name> FOREIGN KEY" DDL.
570
571        MySQL prior to version 8 and MariaDB prior to version 10.5
572        don't support this.
573
574        """
575        return exclusions.closed()
576
577    @property
578    def implicit_default_schema(self):
579        """target system has a strong concept of 'default' schema that can
580        be referred to implicitly.
581
582        basically, PostgreSQL.
583
584        """
585        return exclusions.closed()
586
587    @property
588    def default_schema_name_switch(self):
589        """target dialect implements provisioning module including
590        set_default_schema_on_connection"""
591
592        return exclusions.closed()
593
594    @property
595    def server_side_cursors(self):
596        """Target dialect must support server side cursors."""
597
598        return exclusions.only_if(
599            [lambda config: config.db.dialect.supports_server_side_cursors],
600            "no server side cursors support",
601        )
602
603    @property
604    def sequences(self):
605        """Target database must support SEQUENCEs."""
606
607        return exclusions.only_if(
608            [lambda config: config.db.dialect.supports_sequences],
609            "no sequence support",
610        )
611
612    @property
613    def no_sequences(self):
614        """the opposite of "sequences", DB does not support sequences at
615        all."""
616
617        return exclusions.NotPredicate(self.sequences)
618
619    @property
620    def sequences_optional(self):
621        """Target database supports sequences, but also optionally
622        as a means of generating new PK values."""
623
624        return exclusions.only_if(
625            [
626                lambda config: config.db.dialect.supports_sequences
627                and config.db.dialect.sequences_optional
628            ],
629            "no sequence support, or sequences not optional",
630        )
631
632    @property
633    def supports_lastrowid(self):
634        """target database / driver supports cursor.lastrowid as a means
635        of retrieving the last inserted primary key value.
636
637        note that if the target DB supports sequences also, this is still
638        assumed to work.  This is a new use case brought on by MariaDB 10.3.
639
640        """
641        return exclusions.only_if(
642            [lambda config: config.db.dialect.postfetch_lastrowid]
643        )
644
645    @property
646    def no_lastrowid_support(self):
647        """the opposite of supports_lastrowid"""
648        return exclusions.only_if(
649            [lambda config: not config.db.dialect.postfetch_lastrowid]
650        )
651
652    @property
653    def reflects_pk_names(self):
654        return exclusions.closed()
655
656    @property
657    def table_reflection(self):
658        """target database has general support for table reflection"""
659        return exclusions.open()
660
661    @property
662    def reflect_tables_no_columns(self):
663        """target database supports creation and reflection of tables with no
664        columns, or at least tables that seem to have no columns."""
665
666        return exclusions.closed()
667
668    @property
669    def temp_table_comment_reflection(self):
670        """indicates if database supports comments on temp tables and
671        the dialect can reflect them"""
672        return exclusions.closed()
673
674    @property
675    def comment_reflection(self):
676        """Indicates if the database support table comment reflection"""
677        return exclusions.closed()
678
679    @property
680    def comment_reflection_full_unicode(self):
681        """Indicates if the database support table comment reflection in the
682        full unicode range, including emoji etc.
683        """
684        return exclusions.closed()
685
686    @property
687    def constraint_comment_reflection(self):
688        """indicates if the database support comments on constraints
689        and their reflection"""
690        return exclusions.closed()
691
692    @property
693    def column_collation_reflection(self):
694        """Indicates if the database support column collation reflection.
695
696        This requirement also uses ``get_order_by_collation`` to get
697        an available collation.
698        """
699        return exclusions.closed()
700
701    @property
702    def view_column_reflection(self):
703        """target database must support retrieval of the columns in a view,
704        similarly to how a table is inspected.
705
706        This does not include the full CREATE VIEW definition.
707
708        """
709        return self.views
710
711    @property
712    def view_reflection(self):
713        """target database must support inspection of the full CREATE VIEW
714        definition."""
715        return self.views
716
717    @property
718    def schema_reflection(self):
719        return self.schemas
720
721    @property
722    def schema_create_delete(self):
723        """target database supports schema create and dropped with
724        'CREATE SCHEMA' and 'DROP SCHEMA'"""
725        return exclusions.closed()
726
727    @property
728    def primary_key_constraint_reflection(self):
729        return exclusions.open()
730
731    @property
732    def foreign_key_constraint_reflection(self):
733        return exclusions.open()
734
735    @property
736    def foreign_key_constraint_option_reflection_ondelete(self):
737        return exclusions.closed()
738
739    @property
740    def fk_constraint_option_reflection_ondelete_restrict(self):
741        return exclusions.closed()
742
743    @property
744    def fk_constraint_option_reflection_ondelete_noaction(self):
745        return exclusions.closed()
746
747    @property
748    def foreign_key_constraint_option_reflection_onupdate(self):
749        return exclusions.closed()
750
751    @property
752    def fk_constraint_option_reflection_onupdate_restrict(self):
753        return exclusions.closed()
754
755    @property
756    def temp_table_reflection(self):
757        return exclusions.open()
758
759    @property
760    def temp_table_reflect_indexes(self):
761        return self.temp_table_reflection
762
763    @property
764    def temp_table_names(self):
765        """target dialect supports listing of temporary table names"""
766        return exclusions.closed()
767
768    @property
769    def has_temp_table(self):
770        """target dialect supports checking a single temp table name"""
771        return exclusions.closed()
772
773    @property
774    def temporary_tables(self):
775        """target database supports temporary tables"""
776        return exclusions.open()
777
778    @property
779    def temporary_views(self):
780        """target database supports temporary views"""
781        return exclusions.closed()
782
783    @property
784    def index_reflection(self):
785        return exclusions.open()
786
787    @property
788    def index_reflects_included_columns(self):
789        return exclusions.closed()
790
791    @property
792    def indexes_with_ascdesc(self):
793        """target database supports CREATE INDEX with per-column ASC/DESC."""
794        return exclusions.open()
795
796    @property
797    def reflect_indexes_with_ascdesc(self):
798        """target database supports reflecting INDEX with per-column
799        ASC/DESC."""
800        return exclusions.open()
801
802    @property
803    def reflect_indexes_with_ascdesc_as_expression(self):
804        """target database supports reflecting INDEX with per-column
805        ASC/DESC but reflects them as expressions (like oracle)."""
806        return exclusions.closed()
807
808    @property
809    def indexes_check_column_order(self):
810        """target database supports CREATE INDEX with column order check."""
811        return exclusions.closed()
812
813    @property
814    def indexes_with_expressions(self):
815        """target database supports CREATE INDEX against SQL expressions."""
816        return exclusions.closed()
817
818    @property
819    def reflect_indexes_with_expressions(self):
820        """target database supports reflection of indexes with
821        SQL expressions."""
822        return exclusions.closed()
823
824    @property
825    def unique_constraint_reflection(self):
826        """target dialect supports reflection of unique constraints"""
827        return exclusions.open()
828
829    @property
830    def inline_check_constraint_reflection(self):
831        """target dialect supports reflection of inline check constraints"""
832        return exclusions.closed()
833
834    @property
835    def check_constraint_reflection(self):
836        """target dialect supports reflection of check constraints"""
837        return exclusions.closed()
838
839    @property
840    def duplicate_key_raises_integrity_error(self):
841        """target dialect raises IntegrityError when reporting an INSERT
842        with a primary key violation.  (hint: it should)
843
844        """
845        return exclusions.open()
846
847    @property
848    def unbounded_varchar(self):
849        """Target database must support VARCHAR with no length"""
850
851        return exclusions.open()
852
853    @property
854    def nvarchar_types(self):
855        """target database supports NVARCHAR and NCHAR as an actual datatype"""
856        return exclusions.closed()
857
858    @property
859    def unicode_data_no_special_types(self):
860        """Target database/dialect can receive / deliver / compare data with
861        non-ASCII characters in plain VARCHAR, TEXT columns, without the need
862        for special "national" datatypes like NVARCHAR or similar.
863
864        """
865        return exclusions.open()
866
867    @property
868    def unicode_data(self):
869        """Target database/dialect must support Python unicode objects with
870        non-ASCII characters represented, delivered as bound parameters
871        as well as in result rows.
872
873        """
874        return exclusions.open()
875
876    @property
877    def unicode_ddl(self):
878        """Target driver must support some degree of non-ascii symbol
879        names.
880        """
881        return exclusions.closed()
882
883    @property
884    def symbol_names_w_double_quote(self):
885        """Target driver can create tables with a name like 'some " table'"""
886        return exclusions.open()
887
888    @property
889    def datetime_interval(self):
890        """target dialect supports rendering of a datetime.timedelta as a
891        literal string, e.g. via the TypeEngine.literal_processor() method.
892
893        """
894        return exclusions.closed()
895
896    @property
897    def datetime_literals(self):
898        """target dialect supports rendering of a date, time, or datetime as a
899        literal string, e.g. via the TypeEngine.literal_processor() method.
900
901        """
902
903        return exclusions.closed()
904
905    @property
906    def datetime(self):
907        """target dialect supports representation of Python
908        datetime.datetime() objects."""
909
910        return exclusions.open()
911
912    @property
913    def datetime_timezone(self):
914        """target dialect supports representation of Python
915        datetime.datetime() with tzinfo with DateTime(timezone=True)."""
916
917        return exclusions.closed()
918
919    @property
920    def time_timezone(self):
921        """target dialect supports representation of Python
922        datetime.time() with tzinfo with Time(timezone=True)."""
923
924        return exclusions.closed()
925
926    @property
927    def date_implicit_bound(self):
928        """target dialect when given a date object will bind it such
929        that the database server knows the object is a date, and not
930        a plain string.
931
932        """
933        return exclusions.open()
934
935    @property
936    def time_implicit_bound(self):
937        """target dialect when given a time object will bind it such
938        that the database server knows the object is a time, and not
939        a plain string.
940
941        """
942        return exclusions.open()
943
944    @property
945    def datetime_implicit_bound(self):
946        """target dialect when given a datetime object will bind it such
947        that the database server knows the object is a datetime, and not
948        a plain string.
949
950        """
951        return exclusions.open()
952
953    @property
954    def datetime_microseconds(self):
955        """target dialect supports representation of Python
956        datetime.datetime() with microsecond objects."""
957
958        return exclusions.open()
959
960    @property
961    def timestamp_microseconds(self):
962        """target dialect supports representation of Python
963        datetime.datetime() with microsecond objects but only
964        if TIMESTAMP is used."""
965        return exclusions.closed()
966
967    @property
968    def timestamp_microseconds_implicit_bound(self):
969        """target dialect when given a datetime object which also includes
970        a microseconds portion when using the TIMESTAMP data type
971        will bind it such that the database server knows
972        the object is a datetime with microseconds, and not a plain string.
973
974        """
975        return self.timestamp_microseconds
976
977    @property
978    def datetime_historic(self):
979        """target dialect supports representation of Python
980        datetime.datetime() objects with historic (pre 1970) values."""
981
982        return exclusions.closed()
983
984    @property
985    def date(self):
986        """target dialect supports representation of Python
987        datetime.date() objects."""
988
989        return exclusions.open()
990
991    @property
992    def date_coerces_from_datetime(self):
993        """target dialect accepts a datetime object as the target
994        of a date column."""
995
996        return exclusions.open()
997
998    @property
999    def date_historic(self):
1000        """target dialect supports representation of Python
1001        datetime.datetime() objects with historic (pre 1970) values."""
1002
1003        return exclusions.closed()
1004
1005    @property
1006    def time(self):
1007        """target dialect supports representation of Python
1008        datetime.time() objects."""
1009
1010        return exclusions.open()
1011
1012    @property
1013    def time_microseconds(self):
1014        """target dialect supports representation of Python
1015        datetime.time() with microsecond objects."""
1016
1017        return exclusions.open()
1018
1019    @property
1020    def binary_comparisons(self):
1021        """target database/driver can allow BLOB/BINARY fields to be compared
1022        against a bound parameter value.
1023        """
1024
1025        return exclusions.open()
1026
1027    @property
1028    def binary_literals(self):
1029        """target backend supports simple binary literals, e.g. an
1030        expression like:
1031
1032        .. sourcecode:: sql
1033
1034            SELECT CAST('foo' AS BINARY)
1035
1036        Where ``BINARY`` is the type emitted from :class:`.LargeBinary`,
1037        e.g. it could be ``BLOB`` or similar.
1038
1039        Basically fails on Oracle.
1040
1041        """
1042
1043        return exclusions.open()
1044
1045    @property
1046    def autocommit(self):
1047        """target dialect supports 'AUTOCOMMIT' as an isolation_level"""
1048        return exclusions.closed()
1049
1050    @property
1051    def skip_autocommit_rollback(self):
1052        """target dialect supports the detect_autocommit_setting() method and
1053        uses the default implementation of do_rollback()"""
1054
1055        return exclusions.closed()
1056
1057    @property
1058    def isolation_level(self):
1059        """target dialect supports general isolation level settings.
1060
1061        Note that this requirement, when enabled, also requires that
1062        the get_isolation_levels() method be implemented.
1063
1064        """
1065        return exclusions.closed()
1066
1067    def get_isolation_levels(self, config):
1068        """Return a structure of supported isolation levels for the current
1069        testing dialect.
1070
1071        The structure indicates to the testing suite what the expected
1072        "default" isolation should be, as well as the other values that
1073        are accepted.  The dictionary has two keys, "default" and "supported".
1074        The "supported" key refers to a list of all supported levels and
1075        it should include AUTOCOMMIT if the dialect supports it.
1076
1077        If the :meth:`.DefaultRequirements.isolation_level` requirement is
1078        not open, then this method has no return value.
1079
1080        E.g.::
1081
1082            >>> testing.requirements.get_isolation_levels()
1083            {
1084                "default": "READ_COMMITTED",
1085                "supported": [
1086                    "SERIALIZABLE", "READ UNCOMMITTED",
1087                    "READ COMMITTED", "REPEATABLE READ",
1088                    "AUTOCOMMIT"
1089                ]
1090            }
1091        """
1092        with config.db.connect() as conn:
1093            try:
1094                supported = conn.dialect.get_isolation_level_values(
1095                    conn.connection.dbapi_connection
1096                )
1097            except NotImplementedError:
1098                return None
1099            else:
1100                return {
1101                    "default": conn.dialect.default_isolation_level,
1102                    "supported": supported,
1103                }
1104
1105    @property
1106    def get_isolation_level_values(self):
1107        """target dialect supports the
1108        :meth:`_engine.Dialect.get_isolation_level_values`
1109        method added in SQLAlchemy 2.0.
1110
1111        """
1112
1113        def go(config):
1114            with config.db.connect() as conn:
1115                try:
1116                    conn.dialect.get_isolation_level_values(
1117                        conn.connection.dbapi_connection
1118                    )
1119                except NotImplementedError:
1120                    return False
1121                else:
1122                    return True
1123
1124        return exclusions.only_if(go)
1125
1126    @property
1127    def dialect_level_isolation_level_param(self):
1128        """test that the dialect allows the 'isolation_level' argument
1129        to be handled by DefaultDialect"""
1130
1131        def go(config):
1132            try:
1133                e = create_engine(
1134                    config.db.url, isolation_level="READ COMMITTED"
1135                )
1136            except:
1137                return False
1138            else:
1139                return (
1140                    e.dialect._on_connect_isolation_level == "READ COMMITTED"
1141                )
1142
1143        return exclusions.only_if(go)
1144
1145    @property
1146    def array_type(self):
1147        """Target platform implements a native ARRAY type"""
1148        return exclusions.closed()
1149
1150    @property
1151    def json_type(self):
1152        """target platform implements a native JSON type."""
1153
1154        return exclusions.closed()
1155
1156    @property
1157    def json_array_indexes(self):
1158        """target platform supports numeric array indexes
1159        within a JSON structure"""
1160
1161        return self.json_type
1162
1163    @property
1164    def json_index_supplementary_unicode_element(self):
1165        return exclusions.open()
1166
1167    @property
1168    def legacy_unconditional_json_extract(self):
1169        """Backend has a JSON_EXTRACT or similar function that returns a
1170        valid JSON string in all cases.
1171
1172        Used to test a legacy feature and is not needed.
1173
1174        """
1175        return exclusions.closed()
1176
1177    @property
1178    def precision_numerics_general(self):
1179        """target backend has general support for moderately high-precision
1180        numerics."""
1181        return exclusions.open()
1182
1183    @property
1184    def precision_numerics_enotation_small(self):
1185        """target backend supports Decimal() objects using E notation
1186        to represent very small values."""
1187        return exclusions.closed()
1188
1189    @property
1190    def precision_numerics_enotation_large(self):
1191        """target backend supports Decimal() objects using E notation
1192        to represent very large values."""
1193        return exclusions.open()
1194
1195    @property
1196    def precision_numerics_many_significant_digits(self):
1197        """target backend supports values with many digits on both sides,
1198        such as 319438950232418390.273596, 87673.594069654243
1199
1200        """

Showing the first 1,200 of 1946 lines. Download the file for the rest.

codekingpro/portable-devtools · Team Ai