Skip to content

Commit ebb0472

Browse files
authored
Merge 2.2 into master (#7)
1 parent a902a95 commit ebb0472

File tree

15 files changed

+359
-120
lines changed

15 files changed

+359
-120
lines changed

.editorconfig

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# https://editorconfig.org/
2+
3+
root = true
4+
5+
[*]
6+
indent_style = space
7+
indent_size = 4
8+
insert_final_newline = true
9+
trim_trailing_whitespace = true
10+
end_of_line = lf
11+
charset = utf-8
12+
max_line_length = 119
13+
14+
[*.{yml,yaml}]
15+
indent_size = 2

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,7 @@ Thumbs.db
88
*.egg-info
99

1010
tests/local_settings.py
11+
12+
# Virtual Env
13+
/venv/
14+
.idea/

.travis.yml

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
sudo: required
2+
language: python
3+
cache: pip
4+
5+
branches:
6+
only:
7+
- azure-2.1
8+
9+
templates:
10+
mssql: &mssql DB_PACKAGES="" DATABASE_URL="mssql://SA:MyPassword42@localhost:1433/default?isolation_level=read committed&driver=ODBC Driver 17 for SQL Server" DATABASE_URL_OTHER="mssql://SA:MyPassword42@localhost:1433/other?isolation_level=read committed&driver=ODBC Driver 17 for SQL Server"
11+
12+
matrix:
13+
include:
14+
- env: FLAKE8
15+
python: "3.6"
16+
install: pip install flake8==3.7.1
17+
script: flake8
18+
19+
- python: "3.6"
20+
dist: trusty
21+
services: docker
22+
before_install:
23+
- docker pull mcr.microsoft.com/mssql/server:2017-latest-ubuntu
24+
- docker run -e 'ACCEPT_EULA=Y' -e 'SA_PASSWORD=MyPassword42' -p 1433:1433 -d mcr.microsoft.com/mssql/server:2017-latest-ubuntu
25+
- curl https://packages.microsoft.com/keys/microsoft.asc | sudo apt-key add -
26+
- curl https://packages.microsoft.com/config/ubuntu/14.04/prod.list | sudo tee /etc/apt/sources.list.d/mssql-release.list
27+
- sudo apt-get update
28+
- sudo ACCEPT_EULA=Y apt-get install msodbcsql17
29+
env:
30+
- *mssql
31+
32+
- os: windows
33+
language: sh
34+
python: "3.6"
35+
services: docker
36+
before_install:
37+
- docker pull christianacca/mssql-server-windows-express:1803
38+
- docker run -e 'ACCEPT_EULA=Y' -e 'SA_PASSWORD=MyPassword42' -p 1433:1433 -d christianacca/mssql-server-windows-express:1803
39+
- wget https://download.microsoft.com/download/E/6/B/E6BFDC7A-5BCD-4C51-9912-635646DA801E/en-US/msodbcsql_17.3.1.1_x64.msi
40+
- powershell "Start-Process msiexec.exe -Wait -ArgumentList '/I msodbcsql_17.3.1.1_x64.msi /qn /norestart IACCEPTMSODBCSQLLICENSETERMS=YES'"
41+
- choco install python3 --version 3.6.6
42+
- export PATH="/c/Python36:/c/Python36/Scripts:$PATH"
43+
env:
44+
- *mssql
45+
46+
install:
47+
- python -m pip install --upgrade pip wheel setuptools
48+
- pip install -e .["tests$DB_PACKAGES"]
49+
- git clone --branch=stable/2.1.x https://github.com/django/django.git "$TRAVIS_BUILD_DIR/../django" --depth=1
50+
- export PYTHONPATH=$PYTHONPATH:$TRAVIS_BUILD_DIR
51+
52+
script:
53+
- cd "$TRAVIS_BUILD_DIR/../django/tests"
54+
- pip install -r requirements/py3.txt
55+
- ./runtests.py --settings=testapp.settings \
56+
aggregation
57+
aggregation_regress
58+
annotations
59+
backends basic
60+
bulk_create constraints
61+
custom_columns
62+
custom_lookups
63+
custom_managers
64+
custom_methods
65+
custom_migration_operations
66+
custom_pk
67+
datatypes
68+
dates
69+
datetimes
70+
db_functions
71+
db_typecasts
72+
db_utils
73+
dbshell
74+
defer
75+
defer_regress
76+
delete
77+
delete_regress
78+
distinct_on_fields
79+
empty
80+
empty_models
81+
expressions
82+
expressions_case
83+
expressions_window
84+
extra_regress
85+
field_deconstruction
86+
field_defaults
87+
field_subclassing
88+
filtered_relation
89+
fixtures
90+
fixtures_model_package
91+
fixtures_regress
92+
force_insert_update
93+
foreign_object
94+
from_db_value
95+
generic_relations
96+
generic_relations_regress
97+
get_earliest_or_latest
98+
get_object_or_404
99+
get_or_create
100+
indexes
101+
inspectdb
102+
introspection
103+
invalid_model_tests
104+
known_related_objects
105+
lookup
106+
m2m_and_m2o
107+
m2m_intermediary
108+
m2m_multiple
109+
m2m_recursive
110+
m2m_regress
111+
m2m_signals
112+
m2m_through
113+
m2m_through_regress
114+
m2o_recursive
115+
managers_regress
116+
many_to_many
117+
many_to_one
118+
many_to_one_null
119+
max_lengths
120+
migrate_signals
121+
migration_test_data_persistance
122+
migrations
123+
migrations2
124+
model_fields
125+
model_indexes
126+
model_options
127+
mutually_referential
128+
nested_foreign_keys
129+
null_fk
130+
null_fk_ordering
131+
null_queries
132+
one_to_one
133+
or_lookups
134+
order_with_respect_to
135+
ordering
136+
pagination
137+
prefetch_related
138+
queries
139+
queryset_pickle
140+
raw_query
141+
reverse_lookup
142+
save_delete_hooks
143+
schema
144+
select_for_update
145+
select_related
146+
select_related_onetoone
147+
select_related_regress
148+
transaction_hooks
149+
transactions
150+
update
151+
update_only_fields

setup.cfg

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[flake8]
2+
exclude = .git,__pycache__,
3+
# W504 is mutually exclusive with W503
4+
ignore = W504
5+
max-line-length = 119

setup.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
except ImportError:
44
from distutils.core import setup
55

6-
CLASSIFIERS=[
6+
CLASSIFIERS = [
77
'Development Status :: 4 - Beta',
88
'License :: OSI Approved :: BSD License',
99
'Framework :: Django',
@@ -29,6 +29,9 @@
2929
'Django>=2.1.0,<2.2',
3030
'pyodbc>=3.0',
3131
],
32+
extras_require={
33+
'tests': ['dj-database-url==0.5.0'],
34+
},
3235
classifiers=CLASSIFIERS,
3336
keywords='azure django',
3437
)

sql_server/pyodbc/base.py

Lines changed: 43 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -8,38 +8,36 @@
88
from django.core.exceptions import ImproperlyConfigured
99
from django import VERSION
1010

11-
if VERSION[:3] < (2,1,0) or VERSION[:2] >= (2,2):
11+
if VERSION[:3] < (2, 1, 0) or VERSION[:2] >= (2, 2):
1212
raise ImproperlyConfigured("Django %d.%d.%d is not supported." % VERSION[:3])
1313

1414
try:
1515
import pyodbc as Database
1616
except ImportError as e:
1717
raise ImproperlyConfigured("Error loading pyodbc module: %s" % e)
1818

19-
from django.utils.version import get_version_tuple
19+
from django.utils.version import get_version_tuple # noqa
2020

2121
pyodbc_ver = get_version_tuple(Database.version)
22-
if pyodbc_ver < (3,0):
22+
if pyodbc_ver < (3, 0):
2323
raise ImproperlyConfigured("pyodbc 3.0 or newer is required; you have %s" % Database.version)
2424

25-
from django.conf import settings
26-
from django.db import NotSupportedError
27-
from django.db.backends.base.base import BaseDatabaseWrapper
28-
from django.db.backends.base.validation import BaseDatabaseValidation
29-
from django.utils.encoding import smart_str
30-
from django.utils.functional import cached_property
31-
from django.utils.timezone import utc
25+
from django.conf import settings # noqa
26+
from django.db import NotSupportedError # noqa
27+
from django.db.backends.base.base import BaseDatabaseWrapper # noqa
28+
from django.utils.encoding import smart_str # noqa
29+
from django.utils.functional import cached_property # noqa
3230

3331
if hasattr(settings, 'DATABASE_CONNECTION_POOLING'):
3432
if not settings.DATABASE_CONNECTION_POOLING:
3533
Database.pooling = False
3634

37-
from .client import DatabaseClient
38-
from .creation import DatabaseCreation
39-
from .features import DatabaseFeatures
40-
from .introspection import DatabaseIntrospection
41-
from .operations import DatabaseOperations
42-
from .schema import DatabaseSchemaEditor
35+
from .client import DatabaseClient # noqa
36+
from .creation import DatabaseCreation # noqa
37+
from .features import DatabaseFeatures # noqa
38+
from .introspection import DatabaseIntrospection # noqa
39+
from .operations import DatabaseOperations # noqa
40+
from .schema import DatabaseSchemaEditor # noqa
4341

4442
EDITION_AZURE_SQL_DB = 5
4543

@@ -57,6 +55,7 @@ def encode_connection_string(fields):
5755
for k, v in fields.items()
5856
)
5957

58+
6059
def encode_value(v):
6160
"""If the value contains a semicolon, or starts with a left curly brace,
6261
then enclose it in curly braces and escape all right curly braces.
@@ -65,6 +64,7 @@ def encode_value(v):
6564
return '{%s}' % (v.replace('}', '}}'),)
6665
return v
6766

67+
6868
class DatabaseWrapper(BaseDatabaseWrapper):
6969
vendor = 'microsoft'
7070
display_name = 'SQL Server'
@@ -73,31 +73,31 @@ class DatabaseWrapper(BaseDatabaseWrapper):
7373
# be interpolated against the values of Field.__dict__ before being output.
7474
# If a column type is set to None, it won't be included in the output.
7575
data_types = {
76-
'AutoField': 'int IDENTITY (1, 1)',
77-
'BigAutoField': 'bigint IDENTITY (1, 1)',
78-
'BigIntegerField': 'bigint',
79-
'BinaryField': 'varbinary(max)',
80-
'BooleanField': 'bit',
81-
'CharField': 'nvarchar(%(max_length)s)',
82-
'DateField': 'date',
83-
'DateTimeField': 'datetime2',
84-
'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)',
85-
'DurationField': 'bigint',
86-
'FileField': 'nvarchar(%(max_length)s)',
87-
'FilePathField': 'nvarchar(%(max_length)s)',
88-
'FloatField': 'double precision',
89-
'IntegerField': 'int',
90-
'IPAddressField': 'nvarchar(15)',
76+
'AutoField': 'int IDENTITY (1, 1)',
77+
'BigAutoField': 'bigint IDENTITY (1, 1)',
78+
'BigIntegerField': 'bigint',
79+
'BinaryField': 'varbinary(max)',
80+
'BooleanField': 'bit',
81+
'CharField': 'nvarchar(%(max_length)s)',
82+
'DateField': 'date',
83+
'DateTimeField': 'datetime2',
84+
'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)',
85+
'DurationField': 'bigint',
86+
'FileField': 'nvarchar(%(max_length)s)',
87+
'FilePathField': 'nvarchar(%(max_length)s)',
88+
'FloatField': 'double precision',
89+
'IntegerField': 'int',
90+
'IPAddressField': 'nvarchar(15)',
9191
'GenericIPAddressField': 'nvarchar(39)',
92-
'NullBooleanField': 'bit',
93-
'OneToOneField': 'int',
92+
'NullBooleanField': 'bit',
93+
'OneToOneField': 'int',
9494
'PositiveIntegerField': 'int',
9595
'PositiveSmallIntegerField': 'smallint',
96-
'SlugField': 'nvarchar(%(max_length)s)',
96+
'SlugField': 'nvarchar(%(max_length)s)',
9797
'SmallIntegerField': 'smallint',
98-
'TextField': 'nvarchar(max)',
99-
'TimeField': 'time',
100-
'UUIDField': 'char(32)',
98+
'TextField': 'nvarchar(max)',
99+
'TimeField': 'time',
100+
'UUIDField': 'char(32)',
101101
}
102102
data_type_check_constraints = {
103103
'PositiveIntegerField': '[%(column)s] >= 0',
@@ -324,7 +324,7 @@ def init_connection_state(self):
324324
if ver < (0, 95):
325325
raise ImproperlyConfigured(
326326
"FreeTDS 0.95 or newer is required.")
327-
except:
327+
except Exception:
328328
# unknown driver version
329329
pass
330330

@@ -380,7 +380,7 @@ def sql_server_version(self, _known_versions={}):
380380
cursor.execute("SELECT CAST(SERVERPROPERTY('ProductVersion') AS varchar)")
381381
ver = cursor.fetchone()[0]
382382
ver = int(ver.split('.')[0])
383-
if not ver in self._sql_server_versions:
383+
if ver not in self._sql_server_versions:
384384
raise NotSupportedError('SQL Server v%d is not supported.' % ver)
385385
_known_versions[self.alias] = self._sql_server_versions[ver]
386386
return _known_versions[self.alias]
@@ -419,7 +419,7 @@ def _on_error(self, e):
419419
self.close()
420420
# wait a moment for recovery from network error
421421
time.sleep(self.connection_recovery_interval_msec)
422-
except:
422+
except Exception:
423423
pass
424424
self.connection = None
425425

@@ -458,14 +458,14 @@ def check_constraints(self, table_names=None):
458458

459459
def disable_constraint_checking(self):
460460
# Azure SQL Database doesn't support sp_msforeachtable
461-
#cursor.execute('EXEC sp_msforeachtable "ALTER TABLE ? NOCHECK CONSTRAINT ALL"')
461+
# cursor.execute('EXEC sp_msforeachtable "ALTER TABLE ? NOCHECK CONSTRAINT ALL"')
462462
if not self.needs_rollback:
463463
self._execute_foreach('ALTER TABLE %s NOCHECK CONSTRAINT ALL')
464464
return not self.needs_rollback
465465

466466
def enable_constraint_checking(self):
467467
# Azure SQL Database doesn't support sp_msforeachtable
468-
#cursor.execute('EXEC sp_msforeachtable "ALTER TABLE ? WITH CHECK CHECK CONSTRAINT ALL"')
468+
# cursor.execute('EXEC sp_msforeachtable "ALTER TABLE ? WITH CHECK CHECK CONSTRAINT ALL"')
469469
if not self.needs_rollback:
470470
self.check_constraints()
471471

@@ -475,6 +475,7 @@ class CursorWrapper(object):
475475
A wrapper around the pyodbc's cursor that takes in account a) some pyodbc
476476
DB-API 2.0 implementation and b) some common ODBC driver particularities.
477477
"""
478+
478479
def __init__(self, cursor, connection):
479480
self.active = True
480481
self.cursor = cursor

sql_server/pyodbc/client.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
from django.db.backends.base.client import BaseDatabaseClient
55

6+
67
class DatabaseClient(BaseDatabaseClient):
78
executable_name = 'sqlcmd'
89

@@ -33,7 +34,7 @@ def runshell(self):
3334
if password:
3435
args += ["-P", password]
3536
else:
36-
args += ["-E"] # Try trusted connection instead
37+
args += ["-E"] # Try trusted connection instead
3738
if db:
3839
args += ["-d", db]
3940
if defaults_file:

0 commit comments

Comments
 (0)