crate 0.35.1__py2.py3-none-any.whl → 1.0.0.dev0__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 (42) hide show
  1. crate/client/__init__.py +1 -1
  2. crate/testing/test_datetime_old.py +90 -0
  3. crate-1.0.0.dev0-py3.11-nspkg.pth +1 -0
  4. {crate-0.35.1.dist-info → crate-1.0.0.dev0.dist-info}/METADATA +15 -19
  5. crate-1.0.0.dev0.dist-info/RECORD +26 -0
  6. {crate-0.35.1.dist-info → crate-1.0.0.dev0.dist-info}/WHEEL +1 -1
  7. crate/client/sqlalchemy/__init__.py +0 -50
  8. crate/client/sqlalchemy/compat/__init__.py +0 -0
  9. crate/client/sqlalchemy/compat/api13.py +0 -156
  10. crate/client/sqlalchemy/compat/core10.py +0 -264
  11. crate/client/sqlalchemy/compat/core14.py +0 -359
  12. crate/client/sqlalchemy/compat/core20.py +0 -447
  13. crate/client/sqlalchemy/compiler.py +0 -318
  14. crate/client/sqlalchemy/dialect.py +0 -369
  15. crate/client/sqlalchemy/predicates/__init__.py +0 -99
  16. crate/client/sqlalchemy/sa_version.py +0 -28
  17. crate/client/sqlalchemy/support.py +0 -62
  18. crate/client/sqlalchemy/tests/__init__.py +0 -59
  19. crate/client/sqlalchemy/tests/array_test.py +0 -111
  20. crate/client/sqlalchemy/tests/bulk_test.py +0 -256
  21. crate/client/sqlalchemy/tests/compiler_test.py +0 -434
  22. crate/client/sqlalchemy/tests/connection_test.py +0 -129
  23. crate/client/sqlalchemy/tests/create_table_test.py +0 -313
  24. crate/client/sqlalchemy/tests/datetime_test.py +0 -90
  25. crate/client/sqlalchemy/tests/dialect_test.py +0 -156
  26. crate/client/sqlalchemy/tests/dict_test.py +0 -460
  27. crate/client/sqlalchemy/tests/function_test.py +0 -47
  28. crate/client/sqlalchemy/tests/insert_from_select_test.py +0 -85
  29. crate/client/sqlalchemy/tests/match_test.py +0 -137
  30. crate/client/sqlalchemy/tests/query_caching.py +0 -143
  31. crate/client/sqlalchemy/tests/update_test.py +0 -115
  32. crate/client/sqlalchemy/tests/warnings_test.py +0 -64
  33. crate/client/sqlalchemy/types.py +0 -277
  34. crate/client/tests.py +0 -416
  35. crate/testing/tests.py +0 -34
  36. crate-0.35.1-py3.11-nspkg.pth +0 -1
  37. crate-0.35.1.dist-info/RECORD +0 -55
  38. crate-0.35.1.dist-info/entry_points.txt +0 -2
  39. {crate-0.35.1.dist-info → crate-1.0.0.dev0.dist-info}/LICENSE +0 -0
  40. {crate-0.35.1.dist-info → crate-1.0.0.dev0.dist-info}/NOTICE +0 -0
  41. {crate-0.35.1.dist-info → crate-1.0.0.dev0.dist-info}/namespace_packages.txt +0 -0
  42. {crate-0.35.1.dist-info → crate-1.0.0.dev0.dist-info}/top_level.txt +0 -0
@@ -1,434 +0,0 @@
1
- # -*- coding: utf-8; -*-
2
- #
3
- # Licensed to CRATE Technology GmbH ("Crate") under one or more contributor
4
- # license agreements. See the NOTICE file distributed with this work for
5
- # additional information regarding copyright ownership. Crate licenses
6
- # this file to you under the Apache License, Version 2.0 (the "License");
7
- # you may not use this file except in compliance with the License. You may
8
- # obtain a copy of the License at
9
- #
10
- # http://www.apache.org/licenses/LICENSE-2.0
11
- #
12
- # Unless required by applicable law or agreed to in writing, software
13
- # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14
- # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15
- # License for the specific language governing permissions and limitations
16
- # under the License.
17
- #
18
- # However, if you have executed another commercial license agreement
19
- # with Crate these terms will supersede the license and you may use the
20
- # software solely pursuant to the terms of the relevant commercial agreement.
21
- import warnings
22
- from textwrap import dedent
23
- from unittest import mock, skipIf, TestCase
24
- from unittest.mock import MagicMock, patch
25
-
26
- from crate.client.cursor import Cursor
27
- from crate.client.sqlalchemy.compiler import crate_before_execute
28
-
29
- import sqlalchemy as sa
30
- from sqlalchemy.sql import text, Update
31
-
32
- from crate.testing.util import ExtraAssertions
33
-
34
- try:
35
- from sqlalchemy.orm import declarative_base
36
- except ImportError:
37
- from sqlalchemy.ext.declarative import declarative_base
38
-
39
- from crate.client.sqlalchemy.sa_version import SA_VERSION, SA_1_4, SA_2_0
40
- from crate.client.sqlalchemy.types import ObjectType
41
- from crate.client.test_util import ParametrizedTestCase
42
-
43
- from crate.testing.settings import crate_host
44
-
45
-
46
- class SqlAlchemyCompilerTest(ParametrizedTestCase, ExtraAssertions):
47
-
48
- def setUp(self):
49
- self.crate_engine = sa.create_engine('crate://')
50
- if isinstance(self.param, dict) and "server_version_info" in self.param:
51
- server_version_info = self.param["server_version_info"]
52
- self.crate_engine.dialect.server_version_info = server_version_info
53
- self.sqlite_engine = sa.create_engine('sqlite://')
54
- self.metadata = sa.MetaData()
55
- self.mytable = sa.Table('mytable', self.metadata,
56
- sa.Column('name', sa.String),
57
- sa.Column('data', ObjectType))
58
-
59
- self.update = Update(self.mytable).where(text('name=:name'))
60
- self.values = [{'name': 'crate'}]
61
- self.values = (self.values, )
62
-
63
- def test_sqlite_update_not_rewritten(self):
64
- clauseelement, multiparams, params = crate_before_execute(
65
- self.sqlite_engine, self.update, self.values, {}
66
- )
67
-
68
- self.assertFalse(hasattr(clauseelement, '_crate_specific'))
69
-
70
- def test_crate_update_rewritten(self):
71
- clauseelement, multiparams, params = crate_before_execute(
72
- self.crate_engine, self.update, self.values, {}
73
- )
74
-
75
- self.assertTrue(hasattr(clauseelement, '_crate_specific'))
76
-
77
- def test_bulk_update_on_builtin_type(self):
78
- """
79
- The "before_execute" hook in the compiler doesn't get
80
- access to the parameters in case of a bulk update. It
81
- should not try to optimize any parameters.
82
- """
83
- data = ({},)
84
- clauseelement, multiparams, params = crate_before_execute(
85
- self.crate_engine, self.update, data, None
86
- )
87
-
88
- self.assertFalse(hasattr(clauseelement, '_crate_specific'))
89
-
90
- def test_select_with_ilike_no_escape(self):
91
- """
92
- Verify the compiler uses CrateDB's native `ILIKE` method.
93
- """
94
- selectable = self.mytable.select().where(self.mytable.c.name.ilike("%foo%"))
95
- statement = str(selectable.compile(bind=self.crate_engine))
96
- if self.crate_engine.dialect.has_ilike_operator():
97
- self.assertEqual(statement, dedent("""
98
- SELECT mytable.name, mytable.data
99
- FROM mytable
100
- WHERE mytable.name ILIKE ?
101
- """).strip()) # noqa: W291
102
- else:
103
- self.assertEqual(statement, dedent("""
104
- SELECT mytable.name, mytable.data
105
- FROM mytable
106
- WHERE lower(mytable.name) LIKE lower(?)
107
- """).strip()) # noqa: W291
108
-
109
- def test_select_with_not_ilike_no_escape(self):
110
- """
111
- Verify the compiler uses CrateDB's native `ILIKE` method.
112
- """
113
- selectable = self.mytable.select().where(self.mytable.c.name.notilike("%foo%"))
114
- statement = str(selectable.compile(bind=self.crate_engine))
115
- if SA_VERSION < SA_1_4 or not self.crate_engine.dialect.has_ilike_operator():
116
- self.assertEqual(statement, dedent("""
117
- SELECT mytable.name, mytable.data
118
- FROM mytable
119
- WHERE lower(mytable.name) NOT LIKE lower(?)
120
- """).strip()) # noqa: W291
121
- else:
122
- self.assertEqual(statement, dedent("""
123
- SELECT mytable.name, mytable.data
124
- FROM mytable
125
- WHERE mytable.name NOT ILIKE ?
126
- """).strip()) # noqa: W291
127
-
128
- def test_select_with_ilike_and_escape(self):
129
- """
130
- Verify the compiler fails when using CrateDB's native `ILIKE` method together with `ESCAPE`.
131
- """
132
-
133
- selectable = self.mytable.select().where(self.mytable.c.name.ilike("%foo%", escape='\\'))
134
- with self.assertRaises(NotImplementedError) as cmex:
135
- selectable.compile(bind=self.crate_engine)
136
- self.assertEqual(str(cmex.exception), "Unsupported feature: ESCAPE is not supported")
137
-
138
- @skipIf(SA_VERSION < SA_1_4, "SQLAlchemy 1.3 and earlier do not support native `NOT ILIKE` compilation")
139
- def test_select_with_not_ilike_and_escape(self):
140
- """
141
- Verify the compiler fails when using CrateDB's native `ILIKE` method together with `ESCAPE`.
142
- """
143
-
144
- selectable = self.mytable.select().where(self.mytable.c.name.notilike("%foo%", escape='\\'))
145
- with self.assertRaises(NotImplementedError) as cmex:
146
- selectable.compile(bind=self.crate_engine)
147
- self.assertEqual(str(cmex.exception), "Unsupported feature: ESCAPE is not supported")
148
-
149
- def test_select_with_offset(self):
150
- """
151
- Verify the `CrateCompiler.limit_clause` method, with offset.
152
- """
153
- selectable = self.mytable.select().offset(5)
154
- statement = str(selectable.compile(bind=self.crate_engine))
155
- if SA_VERSION >= SA_1_4:
156
- self.assertEqual(statement, "SELECT mytable.name, mytable.data \nFROM mytable\n LIMIT ALL OFFSET ?")
157
- else:
158
- self.assertEqual(statement, "SELECT mytable.name, mytable.data \nFROM mytable \n LIMIT ALL OFFSET ?")
159
-
160
- def test_select_with_limit(self):
161
- """
162
- Verify the `CrateCompiler.limit_clause` method, with limit.
163
- """
164
- selectable = self.mytable.select().limit(42)
165
- statement = str(selectable.compile(bind=self.crate_engine))
166
- self.assertEqual(statement, "SELECT mytable.name, mytable.data \nFROM mytable \n LIMIT ?")
167
-
168
- def test_select_with_offset_and_limit(self):
169
- """
170
- Verify the `CrateCompiler.limit_clause` method, with offset and limit.
171
- """
172
- selectable = self.mytable.select().offset(5).limit(42)
173
- statement = str(selectable.compile(bind=self.crate_engine))
174
- self.assertEqual(statement, "SELECT mytable.name, mytable.data \nFROM mytable \n LIMIT ? OFFSET ?")
175
-
176
- def test_insert_multivalues(self):
177
- """
178
- Verify that "in-place multirow inserts" aka. "multivalues inserts" aka.
179
- the `supports_multivalues_insert` dialect feature works.
180
-
181
- When this feature is not enabled, using it will raise an error:
182
-
183
- CompileError: The 'crate' dialect with current database version
184
- settings does not support in-place multirow inserts
185
-
186
- > The Insert construct also supports being passed a list of dictionaries
187
- > or full-table-tuples, which on the server will render the less common
188
- > SQL syntax of "multiple values" - this syntax is supported on backends
189
- > such as SQLite, PostgreSQL, MySQL, but not necessarily others.
190
-
191
- > It is essential to note that passing multiple values is NOT the same
192
- > as using traditional `executemany()` form. The above syntax is a special
193
- > syntax not typically used. To emit an INSERT statement against
194
- > multiple rows, the normal method is to pass a multiple values list to
195
- > the `Connection.execute()` method, which is supported by all database
196
- > backends and is generally more efficient for a very large number of
197
- > parameters.
198
-
199
- - https://docs.sqlalchemy.org/core/dml.html#sqlalchemy.sql.expression.Insert.values.params.*args
200
- """
201
- records = [{"name": f"foo_{i}"} for i in range(3)]
202
- insertable = self.mytable.insert().values(records)
203
- statement = str(insertable.compile(bind=self.crate_engine))
204
- self.assertEqual(statement, "INSERT INTO mytable (name) VALUES (?), (?), (?)")
205
-
206
- @skipIf(SA_VERSION < SA_2_0, "SQLAlchemy 1.x does not support the 'insertmanyvalues' dialect feature")
207
- def test_insert_manyvalues(self):
208
- """
209
- Verify the `use_insertmanyvalues` and `use_insertmanyvalues_wo_returning` dialect features.
210
-
211
- > For DML statements such as "INSERT", "UPDATE" and "DELETE", we can
212
- > send multiple parameter sets to the `Connection.execute()` method by
213
- > passing a list of dictionaries instead of a single dictionary, which
214
- > indicates that the single SQL statement should be invoked multiple
215
- > times, once for each parameter set. This style of execution is known
216
- > as "executemany".
217
-
218
- > A key characteristic of "insertmanyvalues" is that the size of the INSERT
219
- > statement is limited on a fixed max number of "values" clauses as well as
220
- > a dialect-specific fixed total number of bound parameters that may be
221
- > represented in one INSERT statement at a time.
222
- > When the number of parameter dictionaries given exceeds a fixed limit [...],
223
- > multiple INSERT statements will be invoked within the scope of a single
224
- > `Connection.execute()` call, each of which accommodate for a portion of the
225
- > parameter dictionaries, referred towards as a "batch".
226
-
227
- - https://docs.sqlalchemy.org/tutorial/dbapi_transactions.html#tutorial-multiple-parameters
228
- - https://docs.sqlalchemy.org/glossary.html#term-executemany
229
- - https://docs.sqlalchemy.org/core/connections.html#engine-insertmanyvalues
230
- - https://docs.sqlalchemy.org/core/connections.html#controlling-the-batch-size
231
- """
232
-
233
- # Don't truncate unittest's diff output on `assertListEqual`.
234
- self.maxDiff = None
235
-
236
- # Five records with a batch size of two should produce three `INSERT` statements.
237
- record_count = 5
238
- batch_size = 2
239
-
240
- # Prepare input data and verify insert statement.
241
- records = [{"name": f"foo_{i}"} for i in range(record_count)]
242
- insertable = self.mytable.insert()
243
- statement = str(insertable.compile(bind=self.crate_engine))
244
- self.assertEqual(statement, "INSERT INTO mytable (name, data) VALUES (?, ?)")
245
-
246
- with mock.patch("crate.client.http.Client.sql", autospec=True, return_value={"cols": []}) as client_mock:
247
-
248
- with self.crate_engine.begin() as conn:
249
- # Adjust page size on a per-connection level.
250
- conn.execution_options(insertmanyvalues_page_size=batch_size)
251
- conn.execute(insertable, parameters=records)
252
-
253
- # Verify that input data has been batched correctly.
254
- self.assertListEqual(client_mock.mock_calls, [
255
- mock.call(mock.ANY, 'INSERT INTO mytable (name) VALUES (?), (?)', ('foo_0', 'foo_1'), None),
256
- mock.call(mock.ANY, 'INSERT INTO mytable (name) VALUES (?), (?)', ('foo_2', 'foo_3'), None),
257
- mock.call(mock.ANY, 'INSERT INTO mytable (name) VALUES (?)', ('foo_4', ), None),
258
- ])
259
-
260
- def test_for_update(self):
261
- """
262
- Verify the `CrateCompiler.for_update_clause` method to
263
- omit the clause, since CrateDB does not support it.
264
- """
265
-
266
- with warnings.catch_warnings(record=True) as w:
267
-
268
- # By default, warnings from a loop will only be emitted once.
269
- # This scenario tests exactly this behaviour, to verify logs
270
- # don't get flooded.
271
- warnings.simplefilter("once")
272
-
273
- selectable = self.mytable.select().with_for_update()
274
- _ = str(selectable.compile(bind=self.crate_engine))
275
-
276
- selectable = self.mytable.select().with_for_update()
277
- statement = str(selectable.compile(bind=self.crate_engine))
278
-
279
- # Verify SQL statement.
280
- self.assertEqual(statement, "SELECT mytable.name, mytable.data \nFROM mytable")
281
-
282
- # Verify if corresponding warning is emitted, once.
283
- self.assertEqual(len(w), 1)
284
- self.assertIsSubclass(w[-1].category, UserWarning)
285
- self.assertIn("CrateDB does not support the 'INSERT ... FOR UPDATE' clause, "
286
- "it will be omitted when generating SQL statements.", str(w[-1].message))
287
-
288
-
289
- FakeCursor = MagicMock(name='FakeCursor', spec=Cursor)
290
-
291
-
292
- class CompilerTestCase(TestCase):
293
- """
294
- A base class for providing mocking infrastructure to validate the DDL compiler.
295
- """
296
-
297
- def setUp(self):
298
- self.engine = sa.create_engine(f"crate://{crate_host}")
299
- self.metadata = sa.MetaData(schema="testdrive")
300
- self.session = sa.orm.Session(bind=self.engine)
301
- self.setup_mock()
302
-
303
- def setup_mock(self):
304
- """
305
- Set up a fake cursor, in order to intercept query execution.
306
- """
307
-
308
- self.fake_cursor = MagicMock(name="fake_cursor")
309
- FakeCursor.return_value = self.fake_cursor
310
-
311
- self.executed_statement = None
312
- self.fake_cursor.execute = self.execute_wrapper
313
-
314
- def execute_wrapper(self, query, *args, **kwargs):
315
- """
316
- Receive the SQL query expression, and store it.
317
- """
318
- self.executed_statement = query
319
- return self.fake_cursor
320
-
321
-
322
- @patch('crate.client.connection.Cursor', FakeCursor)
323
- class SqlAlchemyDDLCompilerTest(CompilerTestCase, ExtraAssertions):
324
- """
325
- Verify a few scenarios regarding the DDL compiler.
326
- """
327
-
328
- def test_ddl_with_foreign_keys(self):
329
- """
330
- Verify the CrateDB dialect properly ignores foreign key constraints.
331
- """
332
-
333
- Base = declarative_base(metadata=self.metadata)
334
-
335
- class RootStore(Base):
336
- """The main store."""
337
-
338
- __tablename__ = "root"
339
-
340
- id = sa.Column(sa.Integer, primary_key=True)
341
- name = sa.Column(sa.String)
342
-
343
- items = sa.orm.relationship(
344
- "ItemStore",
345
- back_populates="root",
346
- passive_deletes=True,
347
- )
348
-
349
- class ItemStore(Base):
350
- """The auxiliary store."""
351
-
352
- __tablename__ = "item"
353
-
354
- id = sa.Column(sa.Integer, primary_key=True)
355
- name = sa.Column(sa.String)
356
- root_id = sa.Column(
357
- sa.Integer,
358
- sa.ForeignKey(
359
- f"{RootStore.__tablename__}.id",
360
- ondelete="CASCADE",
361
- ),
362
- )
363
- root = sa.orm.relationship(RootStore, back_populates="items")
364
-
365
- with warnings.catch_warnings(record=True) as w:
366
-
367
- # Cause all warnings to always be triggered.
368
- warnings.simplefilter("always")
369
-
370
- # Verify SQL DDL statement.
371
- self.metadata.create_all(self.engine, tables=[RootStore.__table__], checkfirst=False)
372
- self.assertEqual(self.executed_statement, dedent("""
373
- CREATE TABLE testdrive.root (
374
- \tid INT NOT NULL,
375
- \tname STRING,
376
- \tPRIMARY KEY (id)
377
- )
378
-
379
- """)) # noqa: W291, W293
380
-
381
- # Verify SQL DDL statement.
382
- self.metadata.create_all(self.engine, tables=[ItemStore.__table__], checkfirst=False)
383
- self.assertEqual(self.executed_statement, dedent("""
384
- CREATE TABLE testdrive.item (
385
- \tid INT NOT NULL,
386
- \tname STRING,
387
- \troot_id INT,
388
- \tPRIMARY KEY (id)
389
- )
390
-
391
- """)) # noqa: W291, W293
392
-
393
- # Verify if corresponding warning is emitted.
394
- self.assertEqual(len(w), 1)
395
- self.assertIsSubclass(w[-1].category, UserWarning)
396
- self.assertIn("CrateDB does not support foreign key constraints, "
397
- "they will be omitted when generating DDL statements.", str(w[-1].message))
398
-
399
- def test_ddl_with_unique_key(self):
400
- """
401
- Verify the CrateDB dialect properly ignores unique key constraints.
402
- """
403
-
404
- Base = declarative_base(metadata=self.metadata)
405
-
406
- class FooBar(Base):
407
- """The entity."""
408
-
409
- __tablename__ = "foobar"
410
-
411
- id = sa.Column(sa.Integer, primary_key=True)
412
- name = sa.Column(sa.String, unique=True)
413
-
414
- with warnings.catch_warnings(record=True) as w:
415
-
416
- # Cause all warnings to always be triggered.
417
- warnings.simplefilter("always")
418
-
419
- # Verify SQL DDL statement.
420
- self.metadata.create_all(self.engine, tables=[FooBar.__table__], checkfirst=False)
421
- self.assertEqual(self.executed_statement, dedent("""
422
- CREATE TABLE testdrive.foobar (
423
- \tid INT NOT NULL,
424
- \tname STRING,
425
- \tPRIMARY KEY (id)
426
- )
427
-
428
- """)) # noqa: W291, W293
429
-
430
- # Verify if corresponding warning is emitted.
431
- self.assertEqual(len(w), 1)
432
- self.assertIsSubclass(w[-1].category, UserWarning)
433
- self.assertIn("CrateDB does not support unique constraints, "
434
- "they will be omitted when generating DDL statements.", str(w[-1].message))
@@ -1,129 +0,0 @@
1
- # -*- coding: utf-8; -*-
2
- #
3
- # Licensed to CRATE Technology GmbH ("Crate") under one or more contributor
4
- # license agreements. See the NOTICE file distributed with this work for
5
- # additional information regarding copyright ownership. Crate licenses
6
- # this file to you under the Apache License, Version 2.0 (the "License");
7
- # you may not use this file except in compliance with the License. You may
8
- # obtain a copy of the License at
9
- #
10
- # http://www.apache.org/licenses/LICENSE-2.0
11
- #
12
- # Unless required by applicable law or agreed to in writing, software
13
- # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14
- # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15
- # License for the specific language governing permissions and limitations
16
- # under the License.
17
- #
18
- # However, if you have executed another commercial license agreement
19
- # with Crate these terms will supersede the license and you may use the
20
- # software solely pursuant to the terms of the relevant commercial agreement.
21
-
22
- from unittest import TestCase
23
- import sqlalchemy as sa
24
- from sqlalchemy.exc import NoSuchModuleError
25
-
26
-
27
- class SqlAlchemyConnectionTest(TestCase):
28
-
29
- def test_connection_server_uri_unknown_sa_plugin(self):
30
- with self.assertRaises(NoSuchModuleError):
31
- sa.create_engine("foobar://otherhost:19201")
32
-
33
- def test_default_connection(self):
34
- engine = sa.create_engine('crate://')
35
- conn = engine.raw_connection()
36
- self.assertEqual("<Connection <Client ['http://127.0.0.1:4200']>>",
37
- repr(conn.driver_connection))
38
- conn.close()
39
- engine.dispose()
40
-
41
- def test_connection_server_uri_http(self):
42
- engine = sa.create_engine(
43
- "crate://otherhost:19201")
44
- conn = engine.raw_connection()
45
- self.assertEqual("<Connection <Client ['http://otherhost:19201']>>",
46
- repr(conn.driver_connection))
47
- conn.close()
48
- engine.dispose()
49
-
50
- def test_connection_server_uri_https(self):
51
- engine = sa.create_engine(
52
- "crate://otherhost:19201/?ssl=true")
53
- conn = engine.raw_connection()
54
- self.assertEqual("<Connection <Client ['https://otherhost:19201']>>",
55
- repr(conn.driver_connection))
56
- conn.close()
57
- engine.dispose()
58
-
59
- def test_connection_server_uri_invalid_port(self):
60
- with self.assertRaises(ValueError) as context:
61
- sa.create_engine("crate://foo:bar")
62
- self.assertIn("invalid literal for int() with base 10: 'bar'", str(context.exception))
63
-
64
- def test_connection_server_uri_https_with_trusted_user(self):
65
- engine = sa.create_engine(
66
- "crate://foo@otherhost:19201/?ssl=true")
67
- conn = engine.raw_connection()
68
- self.assertEqual("<Connection <Client ['https://otherhost:19201']>>",
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()
74
-
75
- def test_connection_server_uri_https_with_credentials(self):
76
- engine = sa.create_engine(
77
- "crate://foo:bar@otherhost:19201/?ssl=true")
78
- conn = engine.raw_connection()
79
- self.assertEqual("<Connection <Client ['https://otherhost:19201']>>",
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()
85
-
86
- def test_connection_server_uri_parameter_timeout(self):
87
- engine = sa.create_engine(
88
- "crate://otherhost:19201/?timeout=42.42")
89
- conn = engine.raw_connection()
90
- self.assertEqual(conn.driver_connection.client._pool_kw["timeout"], 42.42)
91
- conn.close()
92
- engine.dispose()
93
-
94
- def test_connection_server_uri_parameter_pool_size(self):
95
- engine = sa.create_engine(
96
- "crate://otherhost:19201/?pool_size=20")
97
- conn = engine.raw_connection()
98
- self.assertEqual(conn.driver_connection.client._pool_kw["maxsize"], 20)
99
- conn.close()
100
- engine.dispose()
101
-
102
- def test_connection_multiple_server_http(self):
103
- engine = sa.create_engine(
104
- "crate://", connect_args={
105
- 'servers': ['localhost:4201', 'localhost:4202']
106
- }
107
- )
108
- conn = engine.raw_connection()
109
- self.assertEqual(
110
- "<Connection <Client ['http://localhost:4201', " +
111
- "'http://localhost:4202']>>",
112
- repr(conn.driver_connection))
113
- conn.close()
114
- engine.dispose()
115
-
116
- def test_connection_multiple_server_https(self):
117
- engine = sa.create_engine(
118
- "crate://", connect_args={
119
- 'servers': ['localhost:4201', 'localhost:4202'],
120
- 'ssl': True,
121
- }
122
- )
123
- conn = engine.raw_connection()
124
- self.assertEqual(
125
- "<Connection <Client ['https://localhost:4201', " +
126
- "'https://localhost:4202']>>",
127
- repr(conn.driver_connection))
128
- conn.close()
129
- engine.dispose()