Skip to content

Commit 33e6264

Browse files
authored
Clean tests (#94)
1 parent 7982506 commit 33e6264

File tree

7 files changed

+215
-29
lines changed

7 files changed

+215
-29
lines changed

.github/workflows/main.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ jobs:
2929
pip install flake8
3030
- name: Linting
3131
run: |
32-
flake8
32+
flake8 --exclude testapp
3333
3434
build:
3535
runs-on: ${{ matrix.os }}

sql_server/pyodbc/features.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ class DatabaseFeatures(BaseDatabaseFeatures):
3636
uses_savepoints = True
3737
supports_order_by_nulls_modifier = False
3838
supports_order_by_is_nulls = False
39+
order_by_nulls_first = True
3940

4041
@cached_property
4142
def has_bulk_insert(self):

sql_server/pyodbc/functions.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from django import VERSION
22
from django.db.models import BooleanField
33
from django.db.models.functions import Cast
4-
from django.db.models.functions.math import ATan2, Log, Ln, Round
4+
from django.db.models.functions.math import ATan2, Log, Ln, Mod, Round
55
from django.db.models.expressions import Case, Exists, OrderBy, When
66
from django.db.models.lookups import Lookup
77

@@ -54,6 +54,10 @@ def sqlserver_ln(self, compiler, connection, **extra_context):
5454
return self.as_sql(compiler, connection, function='LOG', **extra_context)
5555

5656

57+
def sqlserver_mod(self, compiler, connection, **extra_context):
58+
return self.as_sql(compiler, connection, template='%(expressions)s', arg_joiner='%%', **extra_context)
59+
60+
5761
def sqlserver_round(self, compiler, connection, **extra_context):
5862
return self.as_sql(compiler, connection, template='%(function)s(%(expressions)s, 0)', **extra_context)
5963

@@ -105,6 +109,7 @@ def sqlserver_orderby(self, compiler, connection):
105109
ATan2.as_microsoft = sqlserver_atan2
106110
Log.as_microsoft = sqlserver_log
107111
Ln.as_microsoft = sqlserver_ln
112+
Mod.as_microsoft = sqlserver_mod
108113
Round.as_microsoft = sqlserver_round
109114

110115
if DJANGO3:

sql_server/pyodbc/operations.py

Lines changed: 37 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,8 @@ def date_extract_sql(self, lookup_type, field_name):
114114
return "DATEPART(weekday, %s)" % field_name
115115
elif lookup_type == 'week':
116116
return "DATEPART(iso_week, %s)" % field_name
117+
elif lookup_type == 'iso_year':
118+
return "YEAR(DATEADD(day, 26 - DATEPART(isoww, %s), %s))" % (field_name, field_name)
117119
else:
118120
return "DATEPART(%s, %s)" % (lookup_type, field_name)
119121

@@ -314,7 +316,33 @@ def savepoint_rollback_sql(self, sid):
314316
"""
315317
return "ROLLBACK TRANSACTION %s" % sid
316318

317-
def sql_flush(self, style, tables, *, reset_sequences=False, allow_cascade=False):
319+
def _build_sequences(self, sequences, cursor):
320+
seqs = []
321+
for seq in sequences:
322+
cursor.execute("SELECT COUNT(*) FROM %s" % self.quote_name(seq["table"]))
323+
rowcnt = cursor.fetchone()[0]
324+
elem = {}
325+
if rowcnt:
326+
elem['start_id'] = 0
327+
else:
328+
elem['start_id'] = 1
329+
elem.update(seq)
330+
seqs.append(elem)
331+
return seqs
332+
333+
def _sql_flush_new(self, style, tables, *, reset_sequences=False, allow_cascade=False):
334+
if reset_sequences:
335+
return [
336+
sequence
337+
for sequence in self.connection.introspection.sequence_list()
338+
]
339+
340+
return []
341+
342+
def _sql_flush_old(self, style, tables, sequences, allow_cascade=False):
343+
return sequences
344+
345+
def sql_flush(self, style, tables, *args, **kwargs):
318346
"""
319347
Returns a list of SQL statements required to remove all data from
320348
the given database tables (without actually removing the tables
@@ -329,31 +357,19 @@ def sql_flush(self, style, tables, *, reset_sequences=False, allow_cascade=False
329357
The `allow_cascade` argument determines whether truncation may cascade
330358
to tables with foreign keys pointing the tables being truncated.
331359
"""
360+
332361
if not tables:
333362
return []
334363

335-
# Cannot use TRUNCATE on tables that are referenced by a FOREIGN KEY
336-
# So must use the much slower DELETE
364+
if django.VERSION >= (3, 1):
365+
sequences = self._sql_flush_new(style, tables, *args, **kwargs)
366+
else:
367+
sequences = self._sql_flush_old(style, tables, *args, **kwargs)
368+
337369
from django.db import connections
338370
cursor = connections[self.connection.alias].cursor()
339-
# Try to minimize the risks of the braindeaded inconsistency in
340-
# DBCC CHEKIDENT(table, RESEED, n) behavior.
341-
seqs = []
342-
if reset_sequences:
343-
sequences = [
344-
sequence
345-
for sequence in self.connection.introspection.sequence_list()
346-
]
347-
for seq in sequences:
348-
cursor.execute("SELECT COUNT(*) FROM %s" % self.quote_name(seq["table"]))
349-
rowcnt = cursor.fetchone()[0]
350-
elem = {}
351-
if rowcnt:
352-
elem['start_id'] = 0
353-
else:
354-
elem['start_id'] = 1
355-
elem.update(seq)
356-
seqs.append(elem)
371+
372+
seqs = self._build_sequences(sequences, cursor)
357373

358374
COLUMNS = "TABLE_NAME, CONSTRAINT_NAME"
359375
WHERE = "CONSTRAINT_TYPE not in ('PRIMARY KEY','UNIQUE')"

test.sh

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ set -e
88
DJANGO_VERSION="$(python -m django --version)"
99

1010
cd django
11-
git fetch --depth=1 origin +refs/tags/*:refs/tags/*
12-
git checkout $DJANGO_VERSION
13-
pip install -r tests/requirements/py3.txt
11+
git fetch -q --depth=1 origin +refs/tags/*:refs/tags/*
12+
git checkout -q $DJANGO_VERSION
13+
pip install -q -r tests/requirements/py3.txt
1414

1515
python tests/runtests.py --settings=testapp.settings --noinput --keepdb \
1616
aggregation \
@@ -77,9 +77,6 @@ python tests/runtests.py --settings=testapp.settings --noinput --keepdb \
7777
many_to_one \
7878
max_lengths \
7979
migrate_signals \
80-
migration_test_data_persistence \
81-
migrations \
82-
migrations2 \
8380
model_fields \
8481
model_indexes \
8582
model_options \

testapp/runner.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
from unittest import skip
2+
from django.test.runner import DiscoverRunner
3+
from django.conf import settings
4+
5+
6+
EXCLUDED_TESTS = getattr(settings, 'EXCLUDED_TESTS', [])
7+
8+
9+
class ExcludeTestSuiteRunner(DiscoverRunner):
10+
def build_suite(self, *args, **kwargs):
11+
suite = super().build_suite(*args, **kwargs)
12+
for case in suite:
13+
cls = case.__class__
14+
for attr in dir(cls):
15+
if not attr.startswith('test_'):
16+
continue
17+
fullname = f'{cls.__module__}.{cls.__name__}.{attr}'
18+
if len(list(filter(fullname.startswith, EXCLUDED_TESTS))):
19+
setattr(cls, attr, skip(getattr(cls, attr)))
20+
21+
return suite

testapp/settings.py

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,152 @@
1313
'testapp',
1414
)
1515

16+
17+
TEST_RUNNER = 'testapp.runner.ExcludeTestSuiteRunner'
18+
EXCLUDED_TESTS = (
19+
'aggregation.tests.AggregateTestCase.test_aggregation_subquery_annotation_exists',
20+
'aggregation.tests.AggregateTestCase.test_aggregation_subquery_annotation_values_collision',
21+
'aggregation.tests.AggregateTestCase.test_count_star',
22+
'aggregation.tests.AggregateTestCase.test_distinct_on_aggregate',
23+
'aggregation.tests.AggregateTestCase.test_expression_on_aggregation',
24+
'aggregation_regress.tests.AggregationTests.test_annotated_conditional_aggregate',
25+
'aggregation_regress.tests.AggregationTests.test_annotation_with_value',
26+
'aggregation_regress.tests.AggregationTests.test_more_more',
27+
'aggregation_regress.tests.AggregationTests.test_more_more_more',
28+
'aggregation_regress.tests.AggregationTests.test_ticket_11293',
29+
'aggregation_regress.tests.AggregationTests.test_values_list_annotation_args_ordering',
30+
'annotations.tests.NonAggregateAnnotationTestCase.test_annotate_exists',
31+
'annotations.tests.NonAggregateAnnotationTestCase.test_combined_expression_annotation_with_aggregation',
32+
'backends.tests.BackendTestCase.test_queries',
33+
'backends.tests.BackendTestCase.test_unicode_password',
34+
'backends.tests.FkConstraintsTests.test_disable_constraint_checks_context_manager',
35+
'backends.tests.FkConstraintsTests.test_disable_constraint_checks_manually',
36+
'backends.tests.LastExecutedQueryTest.test_last_executed_query',
37+
'bulk_create.tests.BulkCreateTests.test_bulk_insert_nullable_fields',
38+
'constraints.tests.CheckConstraintTests.test_abstract_name',
39+
'constraints.tests.CheckConstraintTests.test_database_constraint',
40+
'constraints.tests.CheckConstraintTests.test_database_constraint_expression',
41+
'constraints.tests.CheckConstraintTests.test_database_constraint_expressionwrapper',
42+
'constraints.tests.CheckConstraintTests.test_name',
43+
'constraints.tests.UniqueConstraintTests.test_database_constraint',
44+
'constraints.tests.UniqueConstraintTests.test_database_constraint_with_condition',
45+
'constraints.tests.UniqueConstraintTests.test_name',
46+
'custom_lookups.tests.BilateralTransformTests.test_transform_order_by',
47+
'datatypes.tests.DataTypesTestCase.test_error_on_timezone',
48+
'datetimes.tests.DateTimesTests.test_datetimes_ambiguous_and_invalid_times',
49+
'datetimes.tests.DateTimesTests.test_datetimes_returns_available_dates_for_given_scope_and_given_field',
50+
'datetimes.tests.DateTimesTests.test_related_model_traverse',
51+
'db_functions.comparison.test_cast.CastTests.test_cast_to_integer',
52+
'db_functions.datetime.test_extract_trunc.DateFunctionTests.test_extract_func',
53+
'db_functions.datetime.test_extract_trunc.DateFunctionTests.test_extract_iso_weekday_func',
54+
'db_functions.datetime.test_extract_trunc.DateFunctionTests.test_extract_year_exact_lookup',
55+
'db_functions.datetime.test_extract_trunc.DateFunctionTests.test_extract_year_greaterthan_lookup',
56+
'db_functions.datetime.test_extract_trunc.DateFunctionTests.test_extract_year_lessthan_lookup',
57+
'db_functions.datetime.test_extract_trunc.DateFunctionTests.test_trunc_func',
58+
'db_functions.datetime.test_extract_trunc.DateFunctionTests.test_trunc_week_func',
59+
'db_functions.datetime.test_extract_trunc.DateFunctionWithTimeZoneTests.test_extract_func',
60+
'db_functions.datetime.test_extract_trunc.DateFunctionWithTimeZoneTests.test_extract_func_with_timezone',
61+
'db_functions.datetime.test_extract_trunc.DateFunctionWithTimeZoneTests.test_extract_iso_weekday_func',
62+
'db_functions.datetime.test_extract_trunc.DateFunctionWithTimeZoneTests.test_extract_year_exact_lookup',
63+
'db_functions.datetime.test_extract_trunc.DateFunctionWithTimeZoneTests.test_extract_year_greaterthan_lookup',
64+
'db_functions.datetime.test_extract_trunc.DateFunctionWithTimeZoneTests.test_extract_year_lessthan_lookup',
65+
'db_functions.datetime.test_extract_trunc.DateFunctionWithTimeZoneTests.test_trunc_ambiguous_and_invalid_times',
66+
'db_functions.datetime.test_extract_trunc.DateFunctionWithTimeZoneTests.test_trunc_func_with_timezone',
67+
'db_functions.datetime.test_extract_trunc.DateFunctionWithTimeZoneTests.test_trunc_none',
68+
'db_functions.datetime.test_extract_trunc.DateFunctionWithTimeZoneTests.test_trunc_week_func',
69+
'db_functions.math.test_degrees.DegreesTests.test_integer',
70+
'db_functions.math.test_mod.ModTests.test_float',
71+
'db_functions.math.test_power.PowerTests.test_integer',
72+
'db_functions.math.test_radians.RadiansTests.test_integer',
73+
'db_functions.text.test_md5',
74+
'db_functions.text.test_pad.PadTests.test_pad',
75+
'db_functions.text.test_replace.ReplaceTests.test_case_sensitive',
76+
'db_functions.text.test_sha1',
77+
'db_functions.text.test_sha224',
78+
'db_functions.text.test_sha256',
79+
'db_functions.text.test_sha384',
80+
'db_functions.text.test_sha512',
81+
'dbshell.tests.DbshellCommandTestCase.test_command_missing',
82+
'defer_regress.tests.DeferRegressionTest.test_ticket_23270',
83+
'delete.tests.DeletionTests.test_only_referenced_fields_selected',
84+
'expressions.tests.BasicExpressionsTests.test_case_in_filter_if_boolean_output_field',
85+
'expressions.tests.BasicExpressionsTests.test_filtering_on_annotate_that_uses_q',
86+
'expressions.tests.BasicExpressionsTests.test_order_by_exists',
87+
'expressions.tests.BasicExpressionsTests.test_subquery_in_filter',
88+
'expressions.tests.ExpressionOperatorTests.test_lefthand_bitwise_right_shift_operator',
89+
'expressions.tests.ExpressionOperatorTests.test_lefthand_bitwise_xor',
90+
'expressions.tests.ExpressionOperatorTests.test_lefthand_bitwise_xor_null',
91+
'expressions.tests.ExpressionOperatorTests.test_righthand_power',
92+
'expressions.tests.FTimeDeltaTests.test_date_subquery_subtraction',
93+
'expressions.tests.FTimeDeltaTests.test_datetime_subquery_subtraction',
94+
'expressions.tests.FTimeDeltaTests.test_datetime_subtraction_microseconds',
95+
'expressions.tests.FTimeDeltaTests.test_duration_with_datetime_microseconds',
96+
'expressions.tests.FTimeDeltaTests.test_invalid_operator',
97+
'expressions.tests.FTimeDeltaTests.test_time_subquery_subtraction',
98+
'expressions.tests.IterableLookupInnerExpressionsTests.test_expressions_in_lookups_join_choice',
99+
'expressions_case.tests.CaseExpressionTests.test_annotate_with_in_clause',
100+
'fixtures_regress.tests.TestFixtures.test_loaddata_raises_error_when_fixture_has_invalid_foreign_key',
101+
'fixtures_regress.tests.TestFixtures.test_loaddata_with_m2m_to_self',
102+
'fixtures_regress.tests.TestFixtures.test_loaddata_with_valid_fixture_dirs',
103+
'fixtures_regress.tests.TestFixtures.test_loaddata_works_when_fixture_has_forward_refs',
104+
'fixtures_regress.tests.TestFixtures.test_path_containing_dots',
105+
'fixtures_regress.tests.TestFixtures.test_pg_sequence_resetting_checks',
106+
'fixtures_regress.tests.TestFixtures.test_pretty_print_xml',
107+
'fixtures_regress.tests.TestFixtures.test_proxy_model_included',
108+
'fixtures_regress.tests.TestFixtures.test_relative_path',
109+
'fixtures_regress.tests.TestFixtures.test_relative_path_in_fixture_dirs',
110+
'fixtures_regress.tests.TestFixtures.test_ticket_20820',
111+
'fixtures_regress.tests.TestFixtures.test_ticket_22421',
112+
'get_or_create.tests.UpdateOrCreateTransactionTests.test_creation_in_transaction',
113+
'indexes.tests.PartialIndexTests.test_multiple_conditions',
114+
'indexes.tests.SchemaIndexesNotPostgreSQLTests.test_create_index_ignores_opclasses',
115+
'inspectdb.tests.InspectDBTestCase.test_introspection_errors',
116+
'inspectdb.tests.InspectDBTestCase.test_json_field',
117+
'inspectdb.tests.InspectDBTestCase.test_number_field_types',
118+
'introspection.tests.IntrospectionTests.test_get_constraints',
119+
'introspection.tests.IntrospectionTests.test_get_table_description_types',
120+
'introspection.tests.IntrospectionTests.test_smallautofield',
121+
'invalid_models_tests.test_ordinary_fields.TextFieldTests.test_max_length_warning',
122+
'migrate_signals.tests.MigrateSignalTests.test_migrations_only',
123+
'model_fields.test_integerfield.PositiveBigIntegerFieldTests',
124+
'model_fields.test_jsonfield',
125+
'model_indexes.tests.IndexesTests.test_db_tablespace',
126+
'ordering.tests.OrderingTests.test_deprecated_values_annotate',
127+
'ordering.tests.OrderingTests.test_order_by_fk_attname',
128+
'ordering.tests.OrderingTests.test_order_by_pk',
129+
'ordering.tests.OrderingTests.test_orders_nulls_first_on_filtered_subquery',
130+
'prefetch_related.tests.GenericRelationTests.test_prefetch_GFK_nonint_pk',
131+
'queries.test_bulk_update.BulkUpdateNoteTests.test_set_field_to_null',
132+
'queries.test_bulk_update.BulkUpdateTests.test_json_field',
133+
'queries.test_db_returning',
134+
'queries.test_qs_combinators.QuerySetSetOperationTests.test_limits',
135+
'queries.test_qs_combinators.QuerySetSetOperationTests.test_ordering_by_f_expression_and_alias',
136+
'schema.tests.SchemaTests.test_add_foreign_key_quoted_db_table',
137+
'schema.tests.SchemaTests.test_alter_auto_field_quoted_db_column',
138+
'schema.tests.SchemaTests.test_alter_auto_field_to_char_field',
139+
'schema.tests.SchemaTests.test_alter_auto_field_to_integer_field',
140+
'schema.tests.SchemaTests.test_alter_autofield_pk_to_bigautofield_pk_sequence_owner',
141+
'schema.tests.SchemaTests.test_alter_autofield_pk_to_smallautofield_pk_sequence_owner',
142+
'schema.tests.SchemaTests.test_alter_implicit_id_to_explicit',
143+
'schema.tests.SchemaTests.test_alter_int_pk_to_autofield_pk',
144+
'schema.tests.SchemaTests.test_alter_int_pk_to_bigautofield_pk',
145+
'schema.tests.SchemaTests.test_alter_pk_with_self_referential_field',
146+
'schema.tests.SchemaTests.test_alter_primary_key_quoted_db_table',
147+
'schema.tests.SchemaTests.test_alter_smallint_pk_to_smallautofield_pk',
148+
'schema.tests.SchemaTests.test_char_field_pk_to_auto_field',
149+
'schema.tests.SchemaTests.test_inline_fk',
150+
'schema.tests.SchemaTests.test_no_db_constraint_added_during_primary_key_change',
151+
'schema.tests.SchemaTests.test_remove_field_check_does_not_remove_meta_constraints',
152+
'schema.tests.SchemaTests.test_remove_field_unique_does_not_remove_meta_constraints',
153+
'schema.tests.SchemaTests.test_remove_unique_together_does_not_remove_meta_constraints',
154+
'schema.tests.SchemaTests.test_text_field_with_db_index',
155+
'schema.tests.SchemaTests.test_unique_and_reverse_m2m',
156+
'schema.tests.SchemaTests.test_unique_no_unnecessary_fk_drops',
157+
'schema.tests.SchemaTests.test_unique_together_with_fk',
158+
'schema.tests.SchemaTests.test_unique_together_with_fk_with_existing_index',
159+
'select_for_update.tests.SelectForUpdateTests.test_for_update_after_from',
160+
)
161+
16162
SECRET_KEY = "django_tests_secret_key"
17163

18164
# Use a fast hasher to speed up tests.

0 commit comments

Comments
 (0)