crate 0.29.0__py2.py3-none-any.whl → 0.30.1__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. crate/client/__init__.py +1 -1
  2. crate/client/_pep440.py +501 -0
  3. crate/client/connection.py +3 -3
  4. crate/client/sqlalchemy/__init__.py +24 -0
  5. crate/client/sqlalchemy/compat/__init__.py +0 -0
  6. crate/client/sqlalchemy/compat/api13.py +156 -0
  7. crate/client/sqlalchemy/compat/core10.py +264 -0
  8. crate/client/sqlalchemy/compat/core14.py +359 -0
  9. crate/client/sqlalchemy/compat/core20.py +447 -0
  10. crate/client/sqlalchemy/compiler.py +1 -481
  11. crate/client/sqlalchemy/dialect.py +32 -17
  12. crate/client/sqlalchemy/sa_version.py +4 -3
  13. crate/client/sqlalchemy/tests/__init__.py +17 -6
  14. crate/client/sqlalchemy/tests/array_test.py +6 -3
  15. crate/client/sqlalchemy/tests/bulk_test.py +7 -4
  16. crate/client/sqlalchemy/tests/compiler_test.py +10 -9
  17. crate/client/sqlalchemy/tests/connection_test.py +25 -11
  18. crate/client/sqlalchemy/tests/create_table_test.py +19 -16
  19. crate/client/sqlalchemy/tests/datetime_test.py +6 -3
  20. crate/client/sqlalchemy/tests/dialect_test.py +42 -13
  21. crate/client/sqlalchemy/tests/dict_test.py +17 -13
  22. crate/client/sqlalchemy/tests/function_test.py +6 -3
  23. crate/client/sqlalchemy/tests/insert_from_select_test.py +9 -6
  24. crate/client/sqlalchemy/tests/match_test.py +6 -3
  25. crate/client/sqlalchemy/tests/update_test.py +6 -3
  26. crate/client/sqlalchemy/tests/warnings_test.py +33 -0
  27. crate/client/test_connection.py +25 -0
  28. crate/client/tests.py +98 -119
  29. crate/testing/layer.py +1 -1
  30. crate/testing/settings.py +51 -0
  31. crate/testing/test_layer.py +188 -2
  32. crate/testing/tests.py +2 -38
  33. crate/testing/util.py +20 -0
  34. {crate-0.29.0.dist-info → crate-0.30.1.dist-info}/METADATA +10 -8
  35. crate-0.30.1.dist-info/RECORD +53 -0
  36. crate-0.29.0.dist-info/RECORD +0 -44
  37. /crate-0.29.0-py3.9-nspkg.pth → /crate-0.30.1-py3.9-nspkg.pth +0 -0
  38. {crate-0.29.0.dist-info → crate-0.30.1.dist-info}/LICENSE +0 -0
  39. {crate-0.29.0.dist-info → crate-0.30.1.dist-info}/NOTICE +0 -0
  40. {crate-0.29.0.dist-info → crate-0.30.1.dist-info}/WHEEL +0 -0
  41. {crate-0.29.0.dist-info → crate-0.30.1.dist-info}/entry_points.txt +0 -0
  42. {crate-0.29.0.dist-info → crate-0.30.1.dist-info}/namespace_packages.txt +0 -0
  43. {crate-0.29.0.dist-info → crate-0.30.1.dist-info}/top_level.txt +0 -0
@@ -26,7 +26,10 @@ from unittest.mock import patch, MagicMock
26
26
  import sqlalchemy as sa
27
27
  from sqlalchemy.sql import operators
28
28
  from sqlalchemy.orm import Session
29
- from sqlalchemy.ext.declarative import declarative_base
29
+ try:
30
+ from sqlalchemy.orm import declarative_base
31
+ except ImportError:
32
+ from sqlalchemy.ext.declarative import declarative_base
30
33
 
31
34
  from crate.client.cursor import Cursor
32
35
 
@@ -40,7 +43,7 @@ class SqlAlchemyArrayTypeTest(TestCase):
40
43
 
41
44
  def setUp(self):
42
45
  self.engine = sa.create_engine('crate://')
43
- Base = declarative_base(bind=self.engine)
46
+ Base = declarative_base()
44
47
  self.metadata = sa.MetaData()
45
48
 
46
49
  class User(Base):
@@ -51,7 +54,7 @@ class SqlAlchemyArrayTypeTest(TestCase):
51
54
  scores = sa.Column(sa.ARRAY(sa.Integer))
52
55
 
53
56
  self.User = User
54
- self.session = Session()
57
+ self.session = Session(bind=self.engine)
55
58
 
56
59
  def assertSQL(self, expected_str, actual_expr):
57
60
  self.assertEqual(expected_str, str(actual_expr).replace('\n', ''))
@@ -24,7 +24,10 @@ from unittest.mock import patch, MagicMock
24
24
 
25
25
  import sqlalchemy as sa
26
26
  from sqlalchemy.orm import Session
27
- from sqlalchemy.ext.declarative import declarative_base
27
+ try:
28
+ from sqlalchemy.orm import declarative_base
29
+ except ImportError:
30
+ from sqlalchemy.ext.declarative import declarative_base
28
31
 
29
32
  from crate.client.cursor import Cursor
30
33
 
@@ -38,7 +41,7 @@ class SqlAlchemyBulkTest(TestCase):
38
41
 
39
42
  def setUp(self):
40
43
  self.engine = sa.create_engine('crate://')
41
- Base = declarative_base(bind=self.engine)
44
+ Base = declarative_base()
42
45
 
43
46
  class Character(Base):
44
47
  __tablename__ = 'characters'
@@ -47,7 +50,7 @@ class SqlAlchemyBulkTest(TestCase):
47
50
  age = sa.Column(sa.Integer)
48
51
 
49
52
  self.character = Character
50
- self.session = Session()
53
+ self.session = Session(bind=self.engine)
51
54
 
52
55
  @patch('crate.client.connection.Cursor', FakeCursor)
53
56
  def test_bulk_save(self):
@@ -75,4 +78,4 @@ class SqlAlchemyBulkTest(TestCase):
75
78
  ('Banshee', 26),
76
79
  ('Callisto', 37)
77
80
  )
78
- self.assertEqual(expected_bulk_args, bulk_args)
81
+ self.assertSequenceEqual(expected_bulk_args, bulk_args)
@@ -24,8 +24,9 @@ from unittest import TestCase
24
24
  from crate.client.sqlalchemy.compiler import crate_before_execute
25
25
 
26
26
  import sqlalchemy as sa
27
- from sqlalchemy.sql import update, text
27
+ from sqlalchemy.sql import text, Update
28
28
 
29
+ from crate.client.sqlalchemy.sa_version import SA_VERSION, SA_1_4
29
30
  from crate.client.sqlalchemy.types import Craty
30
31
 
31
32
 
@@ -39,7 +40,7 @@ class SqlAlchemyCompilerTest(TestCase):
39
40
  sa.Column('name', sa.String),
40
41
  sa.Column('data', Craty))
41
42
 
42
- self.update = update(self.mytable, text('where name=:name'))
43
+ self.update = Update(self.mytable).where(text('name=:name'))
43
44
  self.values = [{'name': 'crate'}]
44
45
  self.values = (self.values, )
45
46
 
@@ -74,25 +75,25 @@ class SqlAlchemyCompilerTest(TestCase):
74
75
  """
75
76
  Verify the `CrateCompiler.limit_clause` method, with offset.
76
77
  """
77
- self.metadata.bind = self.crate_engine
78
78
  selectable = self.mytable.select().offset(5)
79
- statement = str(selectable.compile())
80
- self.assertEqual(statement, "SELECT mytable.name, mytable.data \nFROM mytable\n LIMIT ALL OFFSET ?")
79
+ statement = str(selectable.compile(bind=self.crate_engine))
80
+ if SA_VERSION >= SA_1_4:
81
+ self.assertEqual(statement, "SELECT mytable.name, mytable.data \nFROM mytable\n LIMIT ALL OFFSET ?")
82
+ else:
83
+ self.assertEqual(statement, "SELECT mytable.name, mytable.data \nFROM mytable \n LIMIT ALL OFFSET ?")
81
84
 
82
85
  def test_select_with_limit(self):
83
86
  """
84
87
  Verify the `CrateCompiler.limit_clause` method, with limit.
85
88
  """
86
- self.metadata.bind = self.crate_engine
87
89
  selectable = self.mytable.select().limit(42)
88
- statement = str(selectable.compile())
90
+ statement = str(selectable.compile(bind=self.crate_engine))
89
91
  self.assertEqual(statement, "SELECT mytable.name, mytable.data \nFROM mytable \n LIMIT ?")
90
92
 
91
93
  def test_select_with_offset_and_limit(self):
92
94
  """
93
95
  Verify the `CrateCompiler.limit_clause` method, with offset and limit.
94
96
  """
95
- self.metadata.bind = self.crate_engine
96
97
  selectable = self.mytable.select().offset(5).limit(42)
97
- statement = str(selectable.compile())
98
+ statement = str(selectable.compile(bind=self.crate_engine))
98
99
  self.assertEqual(statement, "SELECT mytable.name, mytable.data \nFROM mytable \n LIMIT ? OFFSET ?")
@@ -34,21 +34,27 @@ class SqlAlchemyConnectionTest(TestCase):
34
34
  engine = sa.create_engine('crate://')
35
35
  conn = engine.raw_connection()
36
36
  self.assertEqual("<Connection <Client ['http://127.0.0.1:4200']>>",
37
- repr(conn.connection))
37
+ repr(conn.driver_connection))
38
+ conn.close()
39
+ engine.dispose()
38
40
 
39
41
  def test_connection_server_uri_http(self):
40
42
  engine = sa.create_engine(
41
43
  "crate://otherhost:19201")
42
44
  conn = engine.raw_connection()
43
45
  self.assertEqual("<Connection <Client ['http://otherhost:19201']>>",
44
- repr(conn.connection))
46
+ repr(conn.driver_connection))
47
+ conn.close()
48
+ engine.dispose()
45
49
 
46
50
  def test_connection_server_uri_https(self):
47
51
  engine = sa.create_engine(
48
52
  "crate://otherhost:19201/?ssl=true")
49
53
  conn = engine.raw_connection()
50
54
  self.assertEqual("<Connection <Client ['https://otherhost:19201']>>",
51
- repr(conn.connection))
55
+ repr(conn.driver_connection))
56
+ conn.close()
57
+ engine.dispose()
52
58
 
53
59
  def test_connection_server_uri_invalid_port(self):
54
60
  with self.assertRaises(ValueError) as context:
@@ -60,18 +66,22 @@ class SqlAlchemyConnectionTest(TestCase):
60
66
  "crate://foo@otherhost:19201/?ssl=true")
61
67
  conn = engine.raw_connection()
62
68
  self.assertEqual("<Connection <Client ['https://otherhost:19201']>>",
63
- repr(conn.connection))
64
- self.assertEqual(conn.connection.client.username, "foo")
65
- self.assertEqual(conn.connection.client.password, None)
69
+ repr(conn.driver_connection))
70
+ self.assertEqual(conn.driver_connection.client.username, "foo")
71
+ self.assertEqual(conn.driver_connection.client.password, None)
72
+ conn.close()
73
+ engine.dispose()
66
74
 
67
75
  def test_connection_server_uri_https_with_credentials(self):
68
76
  engine = sa.create_engine(
69
77
  "crate://foo:bar@otherhost:19201/?ssl=true")
70
78
  conn = engine.raw_connection()
71
79
  self.assertEqual("<Connection <Client ['https://otherhost:19201']>>",
72
- repr(conn.connection))
73
- self.assertEqual(conn.connection.client.username, "foo")
74
- self.assertEqual(conn.connection.client.password, "bar")
80
+ repr(conn.driver_connection))
81
+ self.assertEqual(conn.driver_connection.client.username, "foo")
82
+ self.assertEqual(conn.driver_connection.client.password, "bar")
83
+ conn.close()
84
+ engine.dispose()
75
85
 
76
86
  def test_connection_multiple_server_http(self):
77
87
  engine = sa.create_engine(
@@ -83,7 +93,9 @@ class SqlAlchemyConnectionTest(TestCase):
83
93
  self.assertEqual(
84
94
  "<Connection <Client ['http://localhost:4201', " +
85
95
  "'http://localhost:4202']>>",
86
- repr(conn.connection))
96
+ repr(conn.driver_connection))
97
+ conn.close()
98
+ engine.dispose()
87
99
 
88
100
  def test_connection_multiple_server_https(self):
89
101
  engine = sa.create_engine(
@@ -96,4 +108,6 @@ class SqlAlchemyConnectionTest(TestCase):
96
108
  self.assertEqual(
97
109
  "<Connection <Client ['https://localhost:4201', " +
98
110
  "'https://localhost:4202']>>",
99
- repr(conn.connection))
111
+ repr(conn.driver_connection))
112
+ conn.close()
113
+ engine.dispose()
@@ -20,7 +20,10 @@
20
20
  # software solely pursuant to the terms of the relevant commercial agreement.
21
21
 
22
22
  import sqlalchemy as sa
23
- from sqlalchemy.ext.declarative import declarative_base
23
+ try:
24
+ from sqlalchemy.orm import declarative_base
25
+ except ImportError:
26
+ from sqlalchemy.ext.declarative import declarative_base
24
27
 
25
28
  from crate.client.sqlalchemy.types import Object, ObjectArray, Geopoint
26
29
  from crate.client.cursor import Cursor
@@ -35,11 +38,11 @@ FakeCursor.return_value = fake_cursor
35
38
 
36
39
 
37
40
  @patch('crate.client.connection.Cursor', FakeCursor)
38
- class CreateTableTest(TestCase):
41
+ class SqlAlchemyCreateTableTest(TestCase):
39
42
 
40
43
  def setUp(self):
41
44
  self.engine = sa.create_engine('crate://')
42
- self.Base = declarative_base(bind=self.engine)
45
+ self.Base = declarative_base()
43
46
 
44
47
  def test_table_basic_types(self):
45
48
  class User(self.Base):
@@ -57,7 +60,7 @@ class CreateTableTest(TestCase):
57
60
  float_col = sa.Column(sa.Float)
58
61
  double_col = sa.Column(sa.DECIMAL)
59
62
 
60
- self.Base.metadata.create_all()
63
+ self.Base.metadata.create_all(bind=self.engine)
61
64
  fake_cursor.execute.assert_called_with(
62
65
  ('\nCREATE TABLE users (\n\tstring_col STRING NOT NULL, '
63
66
  '\n\tunicode_col STRING, \n\ttext_col STRING, \n\tint_col INT, '
@@ -74,7 +77,7 @@ class CreateTableTest(TestCase):
74
77
  __tablename__ = 'dummy'
75
78
  pk = sa.Column(sa.String, primary_key=True)
76
79
  obj_col = sa.Column(Object)
77
- self.Base.metadata.create_all()
80
+ self.Base.metadata.create_all(bind=self.engine)
78
81
  fake_cursor.execute.assert_called_with(
79
82
  ('\nCREATE TABLE dummy (\n\tpk STRING NOT NULL, \n\tobj_col OBJECT, '
80
83
  '\n\tPRIMARY KEY (pk)\n)\n\n'),
@@ -88,7 +91,7 @@ class CreateTableTest(TestCase):
88
91
  }
89
92
  pk = sa.Column(sa.String, primary_key=True)
90
93
  p = sa.Column(sa.String)
91
- self.Base.metadata.create_all()
94
+ self.Base.metadata.create_all(bind=self.engine)
92
95
  fake_cursor.execute.assert_called_with(
93
96
  ('\nCREATE TABLE t (\n\t'
94
97
  'pk STRING NOT NULL, \n\t'
@@ -102,7 +105,7 @@ class CreateTableTest(TestCase):
102
105
  __tablename__ = 't'
103
106
  ts = sa.Column(sa.BigInteger, primary_key=True)
104
107
  p = sa.Column(sa.BigInteger, sa.Computed("date_trunc('day', ts)"))
105
- self.Base.metadata.create_all()
108
+ self.Base.metadata.create_all(bind=self.engine)
106
109
  fake_cursor.execute.assert_called_with(
107
110
  ('\nCREATE TABLE t (\n\t'
108
111
  'ts LONG NOT NULL, \n\t'
@@ -117,7 +120,7 @@ class CreateTableTest(TestCase):
117
120
  ts = sa.Column(sa.BigInteger, primary_key=True)
118
121
  p = sa.Column(sa.BigInteger, sa.Computed("date_trunc('day', ts)", persisted=False))
119
122
  with self.assertRaises(sa.exc.CompileError):
120
- self.Base.metadata.create_all()
123
+ self.Base.metadata.create_all(bind=self.engine)
121
124
 
122
125
  def test_table_partitioned_by(self):
123
126
  class DummyTable(self.Base):
@@ -128,7 +131,7 @@ class CreateTableTest(TestCase):
128
131
  }
129
132
  pk = sa.Column(sa.String, primary_key=True)
130
133
  p = sa.Column(sa.String)
131
- self.Base.metadata.create_all()
134
+ self.Base.metadata.create_all(bind=self.engine)
132
135
  fake_cursor.execute.assert_called_with(
133
136
  ('\nCREATE TABLE t (\n\t'
134
137
  'pk STRING NOT NULL, \n\t'
@@ -146,7 +149,7 @@ class CreateTableTest(TestCase):
146
149
  }
147
150
  pk = sa.Column(sa.String, primary_key=True)
148
151
 
149
- self.Base.metadata.create_all()
152
+ self.Base.metadata.create_all(bind=self.engine)
150
153
  fake_cursor.execute.assert_called_with(
151
154
  ('\nCREATE TABLE t (\n\t'
152
155
  'pk STRING NOT NULL, \n\t'
@@ -163,7 +166,7 @@ class CreateTableTest(TestCase):
163
166
  }
164
167
  pk = sa.Column(sa.String, primary_key=True)
165
168
  p = sa.Column(sa.String, primary_key=True)
166
- self.Base.metadata.create_all()
169
+ self.Base.metadata.create_all(bind=self.engine)
167
170
  fake_cursor.execute.assert_called_with(
168
171
  ('\nCREATE TABLE t (\n\t'
169
172
  'pk STRING NOT NULL, \n\t'
@@ -178,7 +181,7 @@ class CreateTableTest(TestCase):
178
181
  pk = sa.Column(sa.String, primary_key=True)
179
182
  tags = sa.Column(ObjectArray)
180
183
 
181
- self.Base.metadata.create_all()
184
+ self.Base.metadata.create_all(bind=self.engine)
182
185
  fake_cursor.execute.assert_called_with(
183
186
  ('\nCREATE TABLE t (\n\t'
184
187
  'pk STRING NOT NULL, \n\t'
@@ -192,7 +195,7 @@ class CreateTableTest(TestCase):
192
195
  a = sa.Column(sa.Integer, nullable=True)
193
196
  b = sa.Column(sa.Integer, nullable=False)
194
197
 
195
- self.Base.metadata.create_all()
198
+ self.Base.metadata.create_all(bind=self.engine)
196
199
  fake_cursor.execute.assert_called_with(
197
200
  ('\nCREATE TABLE t (\n\t'
198
201
  'pk STRING NOT NULL, \n\t'
@@ -205,7 +208,7 @@ class CreateTableTest(TestCase):
205
208
  __tablename__ = 't'
206
209
  pk = sa.Column(sa.String, primary_key=True, nullable=True)
207
210
  with self.assertRaises(sa.exc.CompileError):
208
- self.Base.metadata.create_all()
211
+ self.Base.metadata.create_all(bind=self.engine)
209
212
 
210
213
  def test_column_crate_index(self):
211
214
  class DummyTable(self.Base):
@@ -214,7 +217,7 @@ class CreateTableTest(TestCase):
214
217
  a = sa.Column(sa.Integer, crate_index=False)
215
218
  b = sa.Column(sa.Integer, crate_index=True)
216
219
 
217
- self.Base.metadata.create_all()
220
+ self.Base.metadata.create_all(bind=self.engine)
218
221
  fake_cursor.execute.assert_called_with(
219
222
  ('\nCREATE TABLE t (\n\t'
220
223
  'pk STRING NOT NULL, \n\t'
@@ -228,4 +231,4 @@ class CreateTableTest(TestCase):
228
231
  pk = sa.Column(sa.String, primary_key=True)
229
232
  a = sa.Column(Geopoint, crate_index=False)
230
233
  with self.assertRaises(sa.exc.CompileError):
231
- self.Base.metadata.create_all()
234
+ self.Base.metadata.create_all(bind=self.engine)
@@ -27,7 +27,10 @@ from unittest.mock import patch, MagicMock
27
27
  import sqlalchemy as sa
28
28
  from sqlalchemy.exc import DBAPIError
29
29
  from sqlalchemy.orm import Session
30
- from sqlalchemy.ext.declarative import declarative_base
30
+ try:
31
+ from sqlalchemy.orm import declarative_base
32
+ except ImportError:
33
+ from sqlalchemy.ext.declarative import declarative_base
31
34
 
32
35
  from crate.client.cursor import Cursor
33
36
 
@@ -54,7 +57,7 @@ class SqlAlchemyDateAndDateTimeTest(TestCase):
54
57
 
55
58
  def setUp(self):
56
59
  self.engine = sa.create_engine('crate://')
57
- Base = declarative_base(bind=self.engine)
60
+ Base = declarative_base()
58
61
 
59
62
  class Character(Base):
60
63
  __tablename__ = 'characters'
@@ -66,7 +69,7 @@ class SqlAlchemyDateAndDateTimeTest(TestCase):
66
69
  ('characters_name', None, None, None, None, None, None),
67
70
  ('characters_date', None, None, None, None, None, None)
68
71
  )
69
- self.session = Session()
72
+ self.session = Session(bind=self.engine)
70
73
  self.Character = Character
71
74
 
72
75
  def test_date_can_handle_datetime(self):
@@ -20,23 +20,28 @@
20
20
  # software solely pursuant to the terms of the relevant commercial agreement.
21
21
 
22
22
  from datetime import datetime
23
- from unittest import TestCase
23
+ from unittest import TestCase, skipIf
24
24
  from unittest.mock import MagicMock, patch
25
25
 
26
26
  import sqlalchemy as sa
27
27
 
28
28
  from crate.client.cursor import Cursor
29
+ from crate.client.sqlalchemy import SA_VERSION
30
+ from crate.client.sqlalchemy.sa_version import SA_1_4, SA_2_0
29
31
  from crate.client.sqlalchemy.types import Object
30
32
  from sqlalchemy import inspect
31
- from sqlalchemy.ext.declarative import declarative_base
32
33
  from sqlalchemy.orm import Session
33
- from sqlalchemy.testing import eq_, in_
34
+ try:
35
+ from sqlalchemy.orm import declarative_base
36
+ except ImportError:
37
+ from sqlalchemy.ext.declarative import declarative_base
38
+ from sqlalchemy.testing import eq_, in_, is_true
34
39
 
35
40
  FakeCursor = MagicMock(name='FakeCursor', spec=Cursor)
36
41
 
37
42
 
38
43
  @patch('crate.client.connection.Cursor', FakeCursor)
39
- class DialectTest(TestCase):
44
+ class SqlAlchemyDialectTest(TestCase):
40
45
 
41
46
  def execute_wrapper(self, query, *args, **kwargs):
42
47
  self.executed_statement = query
@@ -48,13 +53,14 @@ class DialectTest(TestCase):
48
53
  FakeCursor.return_value = self.fake_cursor
49
54
 
50
55
  self.engine = sa.create_engine('crate://')
56
+
51
57
  self.executed_statement = None
52
58
 
53
59
  self.connection = self.engine.connect()
54
60
 
55
61
  self.fake_cursor.execute = self.execute_wrapper
56
62
 
57
- self.base = declarative_base(bind=self.engine)
63
+ self.base = declarative_base()
58
64
 
59
65
  class Character(self.base):
60
66
  __tablename__ = 'characters'
@@ -64,12 +70,17 @@ class DialectTest(TestCase):
64
70
  obj = sa.Column(Object)
65
71
  ts = sa.Column(sa.DateTime, onupdate=datetime.utcnow)
66
72
 
67
- self.character = Character
68
- self.session = Session()
73
+ self.session = Session(bind=self.engine)
74
+
75
+ def init_mock(self, return_value=None):
76
+ self.fake_cursor.rowcount = 1
77
+ self.fake_cursor.description = (
78
+ ('foo', None, None, None, None, None, None),
79
+ )
80
+ self.fake_cursor.fetchall = MagicMock(return_value=return_value)
69
81
 
70
82
  def test_primary_keys_2_3_0(self):
71
- meta = self.character.metadata
72
- insp = inspect(meta.bind)
83
+ insp = inspect(self.session.bind)
73
84
  self.engine.dialect.server_version_info = (2, 3, 0)
74
85
 
75
86
  self.fake_cursor.rowcount = 3
@@ -84,8 +95,7 @@ class DialectTest(TestCase):
84
95
  in_("table_catalog = ?", self.executed_statement)
85
96
 
86
97
  def test_primary_keys_3_0_0(self):
87
- meta = self.character.metadata
88
- insp = inspect(meta.bind)
98
+ insp = inspect(self.session.bind)
89
99
  self.engine.dialect.server_version_info = (3, 0, 0)
90
100
 
91
101
  self.fake_cursor.rowcount = 3
@@ -106,7 +116,7 @@ class DialectTest(TestCase):
106
116
  )
107
117
  self.fake_cursor.fetchall = MagicMock(return_value=[["t1"], ["t2"]])
108
118
 
109
- insp = inspect(self.character.metadata.bind)
119
+ insp = inspect(self.session.bind)
110
120
  self.engine.dialect.server_version_info = (2, 0, 0)
111
121
  eq_(insp.get_table_names(schema="doc"),
112
122
  ['t1', 't2'])
@@ -119,9 +129,28 @@ class DialectTest(TestCase):
119
129
  )
120
130
  self.fake_cursor.fetchall = MagicMock(return_value=[["v1"], ["v2"]])
121
131
 
122
- insp = inspect(self.character.metadata.bind)
132
+ insp = inspect(self.session.bind)
123
133
  self.engine.dialect.server_version_info = (2, 0, 0)
124
134
  eq_(insp.get_view_names(schema="doc"),
125
135
  ['v1', 'v2'])
126
136
  eq_(self.executed_statement, "SELECT table_name FROM information_schema.views "
127
137
  "ORDER BY table_name ASC, table_schema ASC")
138
+
139
+ @skipIf(SA_VERSION < SA_1_4, "Inspector.has_table only available on SQLAlchemy>=1.4")
140
+ def test_has_table(self):
141
+ self.init_mock(return_value=[["foo"], ["bar"]])
142
+ insp = inspect(self.session.bind)
143
+ is_true(insp.has_table("bar"))
144
+ eq_(self.executed_statement,
145
+ "SELECT table_name FROM information_schema.tables "
146
+ "WHERE table_schema = ? AND table_type = 'BASE TABLE' "
147
+ "ORDER BY table_name ASC, table_schema ASC")
148
+
149
+ @skipIf(SA_VERSION < SA_2_0, "Inspector.has_schema only available on SQLAlchemy>=2.0")
150
+ def test_has_schema(self):
151
+ self.init_mock(
152
+ return_value=[["blob"], ["doc"], ["information_schema"], ["pg_catalog"], ["sys"]])
153
+ insp = inspect(self.session.bind)
154
+ is_true(insp.has_schema("doc"))
155
+ eq_(self.executed_statement,
156
+ "select schema_name from information_schema.schemata order by schema_name asc")
@@ -26,7 +26,10 @@ from unittest.mock import patch, MagicMock
26
26
  import sqlalchemy as sa
27
27
  from sqlalchemy.sql import select
28
28
  from sqlalchemy.orm import Session
29
- from sqlalchemy.ext.declarative import declarative_base
29
+ try:
30
+ from sqlalchemy.orm import declarative_base
31
+ except ImportError:
32
+ from sqlalchemy.ext.declarative import declarative_base
30
33
 
31
34
  from crate.client.sqlalchemy.types import Craty, ObjectArray
32
35
  from crate.client.cursor import Cursor
@@ -46,19 +49,20 @@ class SqlAlchemyDictTypeTest(TestCase):
46
49
  sa.Column('name', sa.String),
47
50
  sa.Column('data', Craty))
48
51
 
49
- def assertSQL(self, expected_str, actual_expr):
52
+ def assertSQL(self, expected_str, selectable):
53
+ actual_expr = selectable.compile(bind=self.engine)
50
54
  self.assertEqual(expected_str, str(actual_expr).replace('\n', ''))
51
55
 
52
56
  def test_select_with_dict_column(self):
53
57
  mytable = self.mytable
54
58
  self.assertSQL(
55
59
  "SELECT mytable.data['x'] AS anon_1 FROM mytable",
56
- select([mytable.c.data['x']], bind=self.engine)
60
+ select(mytable.c.data['x'])
57
61
  )
58
62
 
59
63
  def test_select_with_dict_column_where_clause(self):
60
64
  mytable = self.mytable
61
- s = select([mytable.c.data], bind=self.engine).\
65
+ s = select(mytable.c.data).\
62
66
  where(mytable.c.data['x'] == 1)
63
67
  self.assertSQL(
64
68
  "SELECT mytable.data FROM mytable WHERE mytable.data['x'] = ?",
@@ -67,7 +71,7 @@ class SqlAlchemyDictTypeTest(TestCase):
67
71
 
68
72
  def test_select_with_dict_column_nested_where(self):
69
73
  mytable = self.mytable
70
- s = select([mytable.c.name], bind=self.engine)
74
+ s = select(mytable.c.name)
71
75
  s = s.where(mytable.c.data['x']['y'] == 1)
72
76
  self.assertSQL(
73
77
  "SELECT mytable.name FROM mytable " +
@@ -77,7 +81,7 @@ class SqlAlchemyDictTypeTest(TestCase):
77
81
 
78
82
  def test_select_with_dict_column_where_clause_gt(self):
79
83
  mytable = self.mytable
80
- s = select([mytable.c.data], bind=self.engine).\
84
+ s = select(mytable.c.data).\
81
85
  where(mytable.c.data['x'] > 1)
82
86
  self.assertSQL(
83
87
  "SELECT mytable.data FROM mytable WHERE mytable.data['x'] > ?",
@@ -86,7 +90,7 @@ class SqlAlchemyDictTypeTest(TestCase):
86
90
 
87
91
  def test_select_with_dict_column_where_clause_other_col(self):
88
92
  mytable = self.mytable
89
- s = select([mytable.c.name], bind=self.engine)
93
+ s = select(mytable.c.name)
90
94
  s = s.where(mytable.c.data['x'] == mytable.c.name)
91
95
  self.assertSQL(
92
96
  "SELECT mytable.name FROM mytable " +
@@ -96,7 +100,7 @@ class SqlAlchemyDictTypeTest(TestCase):
96
100
 
97
101
  def test_update_with_dict_column(self):
98
102
  mytable = self.mytable
99
- stmt = mytable.update(bind=self.engine).\
103
+ stmt = mytable.update().\
100
104
  where(mytable.c.name == 'Arthur Dent').\
101
105
  values({
102
106
  "data['x']": "Trillian"
@@ -114,7 +118,7 @@ class SqlAlchemyDictTypeTest(TestCase):
114
118
  ('characters_data', None, None, None, None, None, None)
115
119
  )
116
120
  fake_cursor.rowcount = 1
117
- Base = declarative_base(bind=self.engine)
121
+ Base = declarative_base()
118
122
 
119
123
  class Character(Base):
120
124
  __tablename__ = 'characters'
@@ -123,7 +127,7 @@ class SqlAlchemyDictTypeTest(TestCase):
123
127
  data = sa.Column(Craty)
124
128
  data_list = sa.Column(ObjectArray)
125
129
 
126
- session = Session()
130
+ session = Session(bind=self.engine)
127
131
  return session, Character
128
132
 
129
133
  def test_assign_null_to_object_array(self):
@@ -266,7 +270,7 @@ class SqlAlchemyDictTypeTest(TestCase):
266
270
  return_value=[('Trillian', {'x': 1})]
267
271
  )
268
272
 
269
- session = Session()
273
+ session = Session(bind=self.engine)
270
274
  char = Character(name='Trillian')
271
275
  char.data = {'x': 1}
272
276
  session.add(char)
@@ -339,14 +343,14 @@ class SqlAlchemyDictTypeTest(TestCase):
339
343
 
340
344
  )
341
345
  fake_cursor.rowcount = 1
342
- Base = declarative_base(bind=self.engine)
346
+ Base = declarative_base()
343
347
 
344
348
  class Character(Base):
345
349
  __tablename__ = 'characters'
346
350
  name = sa.Column(sa.String, primary_key=True)
347
351
  data_list = sa.Column(ObjectArray)
348
352
 
349
- session = Session()
353
+ session = Session(bind=self.engine)
350
354
  return session, Character
351
355
 
352
356
  def _setup_object_array_char(self):
@@ -23,12 +23,15 @@ from unittest import TestCase
23
23
 
24
24
  import sqlalchemy as sa
25
25
  from sqlalchemy.sql.sqltypes import TIMESTAMP
26
- from sqlalchemy.ext.declarative import declarative_base
26
+ try:
27
+ from sqlalchemy.orm import declarative_base
28
+ except ImportError:
29
+ from sqlalchemy.ext.declarative import declarative_base
27
30
 
28
31
 
29
- class FunctionTest(TestCase):
32
+ class SqlAlchemyFunctionTest(TestCase):
30
33
  def setUp(self):
31
- Base = declarative_base(bind=sa.create_engine("crate://"))
34
+ Base = declarative_base()
32
35
 
33
36
  class Character(Base):
34
37
  __tablename__ = "characters"
@@ -24,9 +24,12 @@ from unittest import TestCase
24
24
  from unittest.mock import patch, MagicMock
25
25
 
26
26
  import sqlalchemy as sa
27
- from sqlalchemy.orm import Session
28
- from sqlalchemy.ext.declarative import declarative_base
29
27
  from sqlalchemy import select, insert
28
+ from sqlalchemy.orm import Session
29
+ try:
30
+ from sqlalchemy.orm import declarative_base
31
+ except ImportError:
32
+ from sqlalchemy.ext.declarative import declarative_base
30
33
 
31
34
  from crate.client.cursor import Cursor
32
35
 
@@ -44,7 +47,7 @@ class SqlAlchemyInsertFromSelectTest(TestCase):
44
47
 
45
48
  def setUp(self):
46
49
  self.engine = sa.create_engine('crate://')
47
- Base = declarative_base(bind=self.engine)
50
+ Base = declarative_base()
48
51
 
49
52
  class Character(Base):
50
53
  __tablename__ = 'characters'
@@ -64,7 +67,7 @@ class SqlAlchemyInsertFromSelectTest(TestCase):
64
67
 
65
68
  self.character = Character
66
69
  self.character_archived = CharacterArchive
67
- self.session = Session()
70
+ self.session = Session(bind=self.engine)
68
71
 
69
72
  @patch('crate.client.connection.Cursor', FakeCursor)
70
73
  def test_insert_from_select_triggered(self):
@@ -72,11 +75,11 @@ class SqlAlchemyInsertFromSelectTest(TestCase):
72
75
  self.session.add(char)
73
76
  self.session.commit()
74
77
 
75
- sel = select([self.character.name, self.character.age]).where(self.character.status == "Archived")
78
+ sel = select(self.character.name, self.character.age).where(self.character.status == "Archived")
76
79
  ins = insert(self.character_archived).from_select(['name', 'age'], sel)
77
80
  self.session.execute(ins)
78
81
  self.session.commit()
79
82
  self.assertSQL(
80
83
  "INSERT INTO characters_archive (name, age) SELECT characters.name, characters.age FROM characters WHERE characters.status = ?",
81
- ins
84
+ ins.compile(bind=self.engine)
82
85
  )