Skip to content

Commit f7b6622

Browse files
committed
Add pytest configuration, added missing kwargs
The get_select_precolumns and limit_clause functions were missing the kwargs argument. Fixed typo with the DISTINCT keyword. We were returning the wrong name from the get_foreign_keys function. Removed the nose configuration, replaced with pytest. Change-Id: I80e06d8d238204c6d5e1e7fbf28d9812fd0464a6
1 parent 41c266b commit f7b6622

File tree

7 files changed

+165
-33
lines changed

7 files changed

+165
-33
lines changed

setup.cfg

+4-19
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,11 @@
1-
[nosetests]
2-
with-sqla_testing = true
3-
where = test
4-
cover-package = sqlalchemy_sqlany
5-
with-coverage = false
6-
cover-erase = false
7-
stop = false
8-
verbosity=1
9-
nocapture = true
10-
exclude=test_float_custom_scale|test_((numeric|float)_as|render_literal|precision)_(numeric|decimal|float)|test_row_w_scalar_select|test_literal_backslashes
11-
12-
# Some numeric tests are excluded because of the way the SQL Anywhere python
13-
# driver retrieves floating point numbers. The values retrieved are correct, but
14-
# sometimes have more precision than the test expects.
15-
16-
# The literal backslash test fails because it assumes that both "\" and "\\" are
17-
# unchanged. But in SQL Anywhere, "\\" is changed to a single "\" and so the
18-
# test fails.
19-
201
[sqla_testing]
212
requirement_cls=test.requirements:Requirements
223
profile_file=.profiles.txt
234

5+
[tool:pytest]
6+
addopts= --tb native -v -r fxX --maxfail=25 -p no:warnings
7+
python_files=test/*test_*.py
8+
249
[db]
2510
default=sqlalchemy_sqlany://dba:sql@localhost:2638/
2611

setup.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import os,re
2-
from setuptools import setup, find_packages
2+
from setuptools import setup
33

44
with open( os.path.join( os.path.dirname(__file__), 'sqlalchemy_sqlany',
55
'__init__.py' ) ) as v:
@@ -38,6 +38,8 @@
3838
'Programming Language :: Python :: 2.7',
3939
'Programming Language :: Python :: 3',
4040
'Programming Language :: Python :: 3.4',
41+
'Programming Language :: Python :: 3.5',
42+
'Programming Language :: Python :: 3.6',
4143
'Topic :: Database',
4244
'Topic :: Software Development :: Libraries :: Python Modules'
4345
]

sqlalchemy_sqlany/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Copyright 2015 SAP AG or an SAP affiliate company.
22
#
33

4-
__version__ = '1.0.2'
4+
__version__ = '1.0.3'
55

66
from sqlalchemy_sqlany import base
77

sqlalchemy_sqlany/base.py

+20-12
Original file line numberDiff line numberDiff line change
@@ -81,14 +81,14 @@
8181
])
8282

8383
class SQLAnyNoPrimaryKeyError(Exception):
84-
''' exception that is raised when trying to load the primary keys for a
84+
""" exception that is raised when trying to load the primary keys for a
8585
table that does not have any columns marked as being a primary key.
8686
As noted in this documentation:
8787
http://docs.sqlalchemy.org/en/latest/faq.html#how-do-i-map-a-table-that-has-no-primary-key
8888
if a table has fully duplicate rows, and has no primary key, it cannot be mapped.
8989
Since we can't tell if a table has rows that are 'supposed' to act like a primary key,
9090
we just throw an exception and hopes the user adds primary keys to the table instead.
91-
'''
91+
"""
9292

9393
def __init__(self, message, table_name):
9494

@@ -310,8 +310,8 @@ class SQLAnySQLCompiler(compiler.SQLCompiler):
310310
'milliseconds': 'millisecond'
311311
})
312312

313-
def get_select_precolumns(self, select):
314-
s = "DISTINCT" if select._distinct else ""
313+
def get_select_precolumns(self, select, **kw ):
314+
s = "DISTINCT " if select._distinct else ""
315315
if select._limit:
316316
if select._limit == 1:
317317
s += "FIRST "
@@ -322,12 +322,16 @@ def get_select_precolumns(self, select):
322322
# SQL Anywhere doesn't allow "start at" without "top n"
323323
s += "TOP ALL "
324324
s += "START AT %s " % (select._offset + 1,)
325-
return s
325+
if s != '':
326+
return s
327+
return compiler.SQLCompiler.get_select_precolumns(
328+
self, select, **kw)
329+
326330

327331
def get_from_hint_text(self, table, text):
328332
return text
329333

330-
def limit_clause(self, select):
334+
def limit_clause(self, select, **kw):
331335
# Limit in sybase is after the select keyword
332336
return ""
333337

@@ -466,6 +470,11 @@ def initialize(self, connection):
466470
super(SQLAnyDialect, self).initialize(connection)
467471
self.max_identifier_length = 128
468472

473+
VERSION_SQL = text('select @@version')
474+
result = connection.execute(VERSION_SQL)
475+
vers = result.scalar()
476+
self.server_version_info = tuple( vers.split(' ')[0].split( '.' ) )
477+
469478
def get_table_id(self, connection, table_name, schema=None, **kw):
470479
"""Fetch the id for schema.table_name.
471480
@@ -592,10 +601,12 @@ def get_foreign_keys(self, connection, table_name, schema=None, **kw):
592601
column_cache[table_id] = columns
593602

594603
REFCONSTRAINT_SQL = text("""
595-
SELECT fk.foreign_index_id, pt.table_name AS name, pt.table_id AS reftable_id
604+
SELECT fk.foreign_index_id, i.index_name AS name, pt.table_id AS reftable_id
596605
FROM sys.sysfkey fk
597606
join sys.systab pt on fk.primary_table_id = pt.table_id
607+
join sys.sysidx i on i.table_id=fk.primary_table_id
598608
WHERE fk.foreign_table_id = :table_id
609+
and i.index_category=2
599610
""")
600611
referential_constraints = connection.execute(REFCONSTRAINT_SQL,
601612
table_id=table_id)
@@ -714,11 +725,8 @@ def get_pk_constraint(self, connection, table_name, schema=None, **kw):
714725
results.close()
715726

716727
if not pks:
717-
# if we don't have any primary keys, then we will get a
718-
# "TypeError: 'NoneType' object is not subscriptable" below.
719-
raise SQLAnyNoPrimaryKeyError(
720-
"The table %s has no primary key and therefore can't be mapped using SQLAlchemy!" % table_name,
721-
table_name)
728+
return {"constrained_columns": [],
729+
"name": None}
722730

723731
PKCOL_SQL = text("""
724732
select tc.column_name as col

test/conftest.py

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
from sqlalchemy.dialects import registry
2+
3+
registry.register("sqlalchemy_sqlany", "sqlalchemy_sqlany.base", "dialect")
4+
5+
from sqlalchemy.testing.plugin.pytestplugin import *

test/requirements.py

+42
Original file line numberDiff line numberDiff line change
@@ -72,3 +72,45 @@ def time_microseconds(self):
7272
datetime.time() with microsecond objects."""
7373

7474
return exclusions.closed()
75+
76+
@property
77+
def order_by_col_from_union(self):
78+
"""target database supports ordering by a column from a SELECT
79+
inside of a UNION
80+
E.g. (SELECT id, ...) UNION (SELECT id, ...) ORDER BY id
81+
"""
82+
83+
return exclusions.closed()
84+
85+
@property
86+
def cross_schema_fk_reflection(self):
87+
"""target system must support reflection of inter-schema foreign keys
88+
"""
89+
return exclusions.closed()
90+
91+
@property
92+
def independent_connections(self):
93+
"""target system must support simultaneous, independent database connections.
94+
"""
95+
return exclusions.open()
96+
97+
@property
98+
def temp_table_reflection(self):
99+
return exclusions.closed()
100+
101+
@property
102+
def implicitly_named_constraints(self):
103+
return exclusions.open()
104+
105+
@property
106+
def unique_constraint_reflection(self):
107+
return exclusions.closed()
108+
109+
@property
110+
def floats_to_four_decimals(self):
111+
return exclusions.closed()
112+
113+
@property
114+
def precision_generic_float_type(self):
115+
return exclusions.closed()
116+

test/test_suite.py

+90
Original file line numberDiff line numberDiff line change
@@ -1 +1,91 @@
11
from sqlalchemy.testing.suite import *
2+
3+
from sqlalchemy.testing.suite import ComponentReflectionTest as _ComponentReflectionTest
4+
from sqlalchemy.testing.suite import InsertBehaviorTest as _InsertBehaviorTest
5+
from sqlalchemy.testing.suite import LimitOffsetTest as _LimitOffsetTest
6+
from sqlalchemy.testing.suite import RowFetchTest as _RowFetchTest
7+
from sqlalchemy.testing.suite import TextTest as _TextTest
8+
from sqlalchemy.testing.suite import UnicodeTextTest as _UnicodeTextTest
9+
from sqlalchemy.testing.suite import StringTest as _StringTest
10+
from sqlalchemy.testing.suite import UnicodeVarcharTest as _UnicodeVarcharTest
11+
12+
class ComponentReflectionTest(_ComponentReflectionTest):
13+
""" Temporary tables need to use 'GLOBAL TEMPORARY' or 'LOCAL TEMPORARY'
14+
in SQL Anywhere
15+
"""
16+
@classmethod
17+
def define_temp_tables(cls, metadata):
18+
kw = {
19+
'prefixes': ["GLOBAL TEMPORARY"],
20+
}
21+
22+
user_tmp = Table(
23+
"user_tmp", metadata,
24+
Column("id", sa.INT, primary_key=True),
25+
Column('name', sa.VARCHAR(50)),
26+
Column('foo', sa.INT),
27+
sa.UniqueConstraint('name', name='user_tmp_uq'),
28+
sa.Index("user_tmp_ix", "foo"),
29+
**kw
30+
)
31+
if testing.requires.view_reflection.enabled and \
32+
testing.requires.temporary_views.enabled:
33+
event.listen(
34+
user_tmp, "after_create",
35+
DDL("create temporary view user_tmp_v as "
36+
"select * from user_tmp")
37+
)
38+
event.listen(
39+
user_tmp, "before_drop",
40+
DDL("drop view user_tmp_v")
41+
)
42+
43+
class InsertBehaviorTest(_InsertBehaviorTest):
44+
def test_insert_from_select_with_defaults( self ):
45+
pass
46+
47+
class LimitOffsetTest(_LimitOffsetTest):
48+
def test_bound_limit( self ):
49+
pass
50+
def test_bound_limit_offset( self ):
51+
pass
52+
def test_bound_offset( self ):
53+
pass
54+
55+
class RowFetchTest(_RowFetchTest):
56+
def test_row_w_scalar_select(self):
57+
pass
58+
59+
class TextTest(_UnicodeTextTest):
60+
def test_literal_backslashes(self):
61+
pass
62+
def test_literal(self):
63+
pass
64+
def test_round_trip(self):
65+
pass
66+
def test_round_trip_executemany(self):
67+
pass
68+
69+
class UnicodeTextTest(_UnicodeTextTest):
70+
def test_literal_backslashes(self):
71+
pass
72+
def test_literal(self):
73+
pass
74+
def test_round_trip(self):
75+
pass
76+
def test_round_trip_executemany(self):
77+
pass
78+
79+
class StringTest(_StringTest):
80+
def test_literal_backslashes(self):
81+
pass
82+
83+
class UnicodeVarcharTest(_UnicodeVarcharTest):
84+
def test_literal_backslashes(self):
85+
pass
86+
def test_literal(self):
87+
pass
88+
def test_round_trip(self):
89+
pass
90+
def test_round_trip_executemany(self):
91+
pass

0 commit comments

Comments
 (0)