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

Sign up to get free protection for your applications and to get access to all the features.
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
  )