Team Ai
Datasetpublic

codekingpro/portable-devtools

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

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

codekingpro/portable-devtools · Team Ai