~ubuntu-branches/debian/jessie/sqlalchemy/jessie

« back to all changes in this revision

Viewing changes to lib/sqlalchemy/testing/requirements.py

  • Committer: Package Import Robot
  • Author(s): Piotr Ożarowski, Jakub Wilk, Piotr Ożarowski
  • Date: 2013-07-06 20:53:52 UTC
  • mfrom: (1.4.23) (16.1.17 experimental)
  • Revision ID: package-import@ubuntu.com-20130706205352-ryppl1eto3illd79
Tags: 0.8.2-1
[ Jakub Wilk ]
* Use canonical URIs for Vcs-* fields.

[ Piotr Ożarowski ]
* New upstream release
* Upload to unstable
* Build depend on python3-all instead of -dev, extensions are not built for
  Python 3.X 

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
"""Global database feature support policy.
 
2
 
 
3
Provides decorators to mark tests requiring specific feature support from the
 
4
target database.
 
5
 
 
6
External dialect test suites should subclass SuiteRequirements
 
7
to provide specific inclusion/exlusions.
 
8
 
 
9
"""
 
10
 
 
11
from . import exclusions, config
 
12
 
 
13
 
 
14
class Requirements(object):
 
15
    def __init__(self, config):
 
16
        self.config = config
 
17
 
 
18
    @property
 
19
    def db(self):
 
20
        return config.db
 
21
 
 
22
class SuiteRequirements(Requirements):
 
23
 
 
24
    @property
 
25
    def create_table(self):
 
26
        """target platform can emit basic CreateTable DDL."""
 
27
 
 
28
        return exclusions.open()
 
29
 
 
30
    @property
 
31
    def drop_table(self):
 
32
        """target platform can emit basic DropTable DDL."""
 
33
 
 
34
        return exclusions.open()
 
35
 
 
36
    @property
 
37
    def foreign_keys(self):
 
38
        """Target database must support foreign keys."""
 
39
 
 
40
        return exclusions.open()
 
41
 
 
42
    @property
 
43
    def on_update_cascade(self):
 
44
        """"target database must support ON UPDATE..CASCADE behavior in
 
45
        foreign keys."""
 
46
 
 
47
        return exclusions.open()
 
48
 
 
49
    @property
 
50
    def deferrable_fks(self):
 
51
        return exclusions.closed()
 
52
 
 
53
    @property
 
54
    def on_update_or_deferrable_fks(self):
 
55
        # TODO: exclusions should be composable,
 
56
        # somehow only_if([x, y]) isn't working here, negation/conjunctions
 
57
        # getting confused.
 
58
        return exclusions.only_if(
 
59
                    lambda: self.on_update_cascade.enabled or self.deferrable_fks.enabled
 
60
                )
 
61
 
 
62
 
 
63
    @property
 
64
    def self_referential_foreign_keys(self):
 
65
        """Target database must support self-referential foreign keys."""
 
66
 
 
67
        return exclusions.open()
 
68
 
 
69
    @property
 
70
    def foreign_key_ddl(self):
 
71
        """Target database must support the DDL phrases for FOREIGN KEY."""
 
72
 
 
73
        return exclusions.open()
 
74
 
 
75
    @property
 
76
    def named_constraints(self):
 
77
        """target database must support names for constraints."""
 
78
 
 
79
        return exclusions.open()
 
80
 
 
81
    @property
 
82
    def subqueries(self):
 
83
        """Target database must support subqueries."""
 
84
 
 
85
        return exclusions.open()
 
86
 
 
87
    @property
 
88
    def offset(self):
 
89
        """target database can render OFFSET, or an equivalent, in a SELECT."""
 
90
 
 
91
        return exclusions.open()
 
92
 
 
93
    @property
 
94
    def boolean_col_expressions(self):
 
95
        """Target database must support boolean expressions as columns"""
 
96
 
 
97
        return exclusions.closed()
 
98
 
 
99
    @property
 
100
    def nullsordering(self):
 
101
        """Target backends that support nulls ordering."""
 
102
 
 
103
        return exclusions.closed()
 
104
 
 
105
    @property
 
106
    def standalone_binds(self):
 
107
        """target database/driver supports bound parameters as column expressions
 
108
        without being in the context of a typed column.
 
109
 
 
110
        """
 
111
        return exclusions.closed()
 
112
 
 
113
    @property
 
114
    def intersect(self):
 
115
        """Target database must support INTERSECT or equivalent."""
 
116
        return exclusions.closed()
 
117
 
 
118
    @property
 
119
    def except_(self):
 
120
        """Target database must support EXCEPT or equivalent (i.e. MINUS)."""
 
121
        return exclusions.closed()
 
122
 
 
123
    @property
 
124
    def window_functions(self):
 
125
        """Target database must support window functions."""
 
126
        return exclusions.closed()
 
127
 
 
128
    @property
 
129
    def autoincrement_insert(self):
 
130
        """target platform generates new surrogate integer primary key values
 
131
        when insert() is executed, excluding the pk column."""
 
132
 
 
133
        return exclusions.open()
 
134
 
 
135
    @property
 
136
    def empty_inserts(self):
 
137
        """target platform supports INSERT with no values, i.e.
 
138
        INSERT DEFAULT VALUES or equivalent."""
 
139
 
 
140
        return exclusions.only_if(
 
141
                    lambda: self.config.db.dialect.supports_empty_insert or \
 
142
                        self.config.db.dialect.supports_default_values,
 
143
                    "empty inserts not supported"
 
144
                )
 
145
 
 
146
    @property
 
147
    def returning(self):
 
148
        """target platform supports RETURNING."""
 
149
 
 
150
        return exclusions.only_if(
 
151
                lambda: self.config.db.dialect.implicit_returning,
 
152
                "'returning' not supported by database"
 
153
            )
 
154
 
 
155
    @property
 
156
    def denormalized_names(self):
 
157
        """Target database must have 'denormalized', i.e.
 
158
        UPPERCASE as case insensitive names."""
 
159
 
 
160
        return exclusions.skip_if(
 
161
                    lambda: not self.db.dialect.requires_name_normalize,
 
162
                    "Backend does not require denormalized names."
 
163
                )
 
164
 
 
165
    @property
 
166
    def multivalues_inserts(self):
 
167
        """target database must support multiple VALUES clauses in an
 
168
        INSERT statement."""
 
169
 
 
170
        return exclusions.skip_if(
 
171
                    lambda: not self.db.dialect.supports_multivalues_insert,
 
172
                    "Backend does not support multirow inserts."
 
173
                )
 
174
 
 
175
 
 
176
    @property
 
177
    def implements_get_lastrowid(self):
 
178
        """"target dialect implements the executioncontext.get_lastrowid()
 
179
        method without reliance on RETURNING.
 
180
 
 
181
        """
 
182
        return exclusions.open()
 
183
 
 
184
    @property
 
185
    def emulated_lastrowid(self):
 
186
        """"target dialect retrieves cursor.lastrowid, or fetches
 
187
        from a database-side function after an insert() construct executes,
 
188
        within the get_lastrowid() method.
 
189
 
 
190
        Only dialects that "pre-execute", or need RETURNING to get last
 
191
        inserted id, would return closed/fail/skip for this.
 
192
 
 
193
        """
 
194
        return exclusions.closed()
 
195
 
 
196
    @property
 
197
    def dbapi_lastrowid(self):
 
198
        """"target platform includes a 'lastrowid' accessor on the DBAPI
 
199
        cursor object.
 
200
 
 
201
        """
 
202
        return exclusions.closed()
 
203
 
 
204
    @property
 
205
    def views(self):
 
206
        """Target database must support VIEWs."""
 
207
 
 
208
        return exclusions.closed()
 
209
 
 
210
    @property
 
211
    def schemas(self):
 
212
        """Target database must support external schemas, and have one
 
213
        named 'test_schema'."""
 
214
 
 
215
        return exclusions.closed()
 
216
 
 
217
    @property
 
218
    def sequences(self):
 
219
        """Target database must support SEQUENCEs."""
 
220
 
 
221
        return exclusions.only_if([
 
222
                lambda: self.config.db.dialect.supports_sequences
 
223
            ], "no sequence support")
 
224
 
 
225
    @property
 
226
    def sequences_optional(self):
 
227
        """Target database supports sequences, but also optionally
 
228
        as a means of generating new PK values."""
 
229
 
 
230
        return exclusions.only_if([
 
231
                lambda: self.config.db.dialect.supports_sequences and \
 
232
                    self.config.db.dialect.sequences_optional
 
233
            ], "no sequence support, or sequences not optional")
 
234
 
 
235
 
 
236
 
 
237
 
 
238
 
 
239
    @property
 
240
    def reflects_pk_names(self):
 
241
        return exclusions.closed()
 
242
 
 
243
    @property
 
244
    def table_reflection(self):
 
245
        return exclusions.open()
 
246
 
 
247
    @property
 
248
    def view_reflection(self):
 
249
        return self.views
 
250
 
 
251
    @property
 
252
    def schema_reflection(self):
 
253
        return self.schemas
 
254
 
 
255
    @property
 
256
    def primary_key_constraint_reflection(self):
 
257
        return exclusions.open()
 
258
 
 
259
    @property
 
260
    def foreign_key_constraint_reflection(self):
 
261
        return exclusions.open()
 
262
 
 
263
    @property
 
264
    def index_reflection(self):
 
265
        return exclusions.open()
 
266
 
 
267
    @property
 
268
    def unbounded_varchar(self):
 
269
        """Target database must support VARCHAR with no length"""
 
270
 
 
271
        return exclusions.open()
 
272
 
 
273
    @property
 
274
    def unicode_data(self):
 
275
        """Target database/dialect must support Python unicode objects with
 
276
        non-ASCII characters represented, delivered as bound parameters
 
277
        as well as in result rows.
 
278
 
 
279
        """
 
280
        return exclusions.open()
 
281
 
 
282
    @property
 
283
    def unicode_ddl(self):
 
284
        """Target driver must support some degree of non-ascii symbol names."""
 
285
        return exclusions.closed()
 
286
 
 
287
    @property
 
288
    def datetime(self):
 
289
        """target dialect supports representation of Python
 
290
        datetime.datetime() objects."""
 
291
 
 
292
        return exclusions.open()
 
293
 
 
294
    @property
 
295
    def datetime_microseconds(self):
 
296
        """target dialect supports representation of Python
 
297
        datetime.datetime() with microsecond objects."""
 
298
 
 
299
        return exclusions.open()
 
300
 
 
301
    @property
 
302
    def datetime_historic(self):
 
303
        """target dialect supports representation of Python
 
304
        datetime.datetime() objects with historic (pre 1970) values."""
 
305
 
 
306
        return exclusions.closed()
 
307
 
 
308
    @property
 
309
    def date(self):
 
310
        """target dialect supports representation of Python
 
311
        datetime.date() objects."""
 
312
 
 
313
        return exclusions.open()
 
314
 
 
315
    @property
 
316
    def date_historic(self):
 
317
        """target dialect supports representation of Python
 
318
        datetime.datetime() objects with historic (pre 1970) values."""
 
319
 
 
320
        return exclusions.closed()
 
321
 
 
322
    @property
 
323
    def time(self):
 
324
        """target dialect supports representation of Python
 
325
        datetime.time() objects."""
 
326
 
 
327
        return exclusions.open()
 
328
 
 
329
    @property
 
330
    def time_microseconds(self):
 
331
        """target dialect supports representation of Python
 
332
        datetime.time() with microsecond objects."""
 
333
 
 
334
        return exclusions.open()
 
335
 
 
336
    @property
 
337
    def precision_numerics_general(self):
 
338
        """target backend has general support for moderately high-precision
 
339
        numerics."""
 
340
        return exclusions.open()
 
341
 
 
342
    @property
 
343
    def precision_numerics_enotation_small(self):
 
344
        """target backend supports Decimal() objects using E notation
 
345
        to represent very small values."""
 
346
        return exclusions.closed()
 
347
 
 
348
    @property
 
349
    def precision_numerics_enotation_large(self):
 
350
        """target backend supports Decimal() objects using E notation
 
351
        to represent very large values."""
 
352
        return exclusions.closed()
 
353
 
 
354
    @property
 
355
    def precision_numerics_many_significant_digits(self):
 
356
        """target backend supports values with many digits on both sides,
 
357
        such as 319438950232418390.273596, 87673.594069654243
 
358
 
 
359
        """
 
360
        return exclusions.closed()
 
361
 
 
362
    @property
 
363
    def precision_numerics_retains_significant_digits(self):
 
364
        """A precision numeric type will return empty significant digits,
 
365
        i.e. a value such as 10.000 will come back in Decimal form with
 
366
        the .000 maintained."""
 
367
 
 
368
        return exclusions.closed()
 
369
 
 
370
    @property
 
371
    def text_type(self):
 
372
        """Target database must support an unbounded Text() "
 
373
        "type such as TEXT or CLOB"""
 
374
 
 
375
        return exclusions.open()
 
376
 
 
377
    @property
 
378
    def empty_strings_varchar(self):
 
379
        """target database can persist/return an empty string with a
 
380
        varchar.
 
381
 
 
382
        """
 
383
        return exclusions.open()
 
384
 
 
385
    @property
 
386
    def empty_strings_text(self):
 
387
        """target database can persist/return an empty string with an
 
388
        unbounded text."""
 
389
 
 
390
        return exclusions.open()
 
391
 
 
392
    @property
 
393
    def update_from(self):
 
394
        """Target must support UPDATE..FROM syntax"""
 
395
        return exclusions.closed()
 
396
 
 
397
    @property
 
398
    def update_where_target_in_subquery(self):
 
399
        """Target must support UPDATE where the same table is present in a
 
400
        subquery in the WHERE clause.
 
401
 
 
402
        This is an ANSI-standard syntax that apparently MySQL can't handle,
 
403
        such as:
 
404
 
 
405
        UPDATE documents SET flag=1 WHERE documents.title IN
 
406
            (SELECT max(documents.title) AS title
 
407
                FROM documents GROUP BY documents.user_id
 
408
            )
 
409
        """
 
410
        return exclusions.open()
 
411
 
 
412
    @property
 
413
    def mod_operator_as_percent_sign(self):
 
414
        """target database must use a plain percent '%' as the 'modulus'
 
415
        operator."""
 
416
        return exclusions.closed()
 
417
 
 
418
    @property
 
419
    def unicode_connections(self):
 
420
        """Target driver must support non-ASCII characters being passed at all."""
 
421
        return exclusions.open()
 
422
 
 
423
    @property
 
424
    def skip_mysql_on_windows(self):
 
425
        """Catchall for a large variety of MySQL on Windows failures"""
 
426
        return exclusions.open()
 
427
 
 
428
    def _has_mysql_on_windows(self):
 
429
        return False
 
430
 
 
431
    def _has_mysql_fully_case_sensitive(self):
 
432
        return False