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
@@ -0,0 +1,156 @@
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
+ # https://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
+ """
23
+ Compatibility module for running a subset of SQLAlchemy 2.0 programs on
24
+ SQLAlchemy 1.3. By using monkey-patching, it can do two things:
25
+
26
+ 1. Add the `exec_driver_sql` method to SA's `Connection` and `Engine`.
27
+ 2. Amend the `sql.select` function to accept the calling semantics of
28
+ the modern variant.
29
+
30
+ Reason: `exec_driver_sql` gets used within the CrateDB dialect already,
31
+ and the new calling semantics of `sql.select` already get used within
32
+ many of the test cases already. Please note that the patch for
33
+ `sql.select` is only applied when running the test suite.
34
+ """
35
+
36
+ import collections.abc as collections_abc
37
+
38
+ from sqlalchemy import exc
39
+ from sqlalchemy.sql import Select
40
+ from sqlalchemy.sql import select as original_select
41
+ from sqlalchemy.util import immutabledict
42
+
43
+
44
+ # `_distill_params_20` copied from SA14's `sqlalchemy.engine.{base,util}`.
45
+ _no_tuple = ()
46
+ _no_kw = immutabledict()
47
+
48
+
49
+ def _distill_params_20(params):
50
+ if params is None:
51
+ return _no_tuple, _no_kw
52
+ elif isinstance(params, list):
53
+ # collections_abc.MutableSequence): # avoid abc.__instancecheck__
54
+ if params and not isinstance(params[0], (collections_abc.Mapping, tuple)):
55
+ raise exc.ArgumentError(
56
+ "List argument must consist only of tuples or dictionaries"
57
+ )
58
+
59
+ return (params,), _no_kw
60
+ elif isinstance(
61
+ params,
62
+ (tuple, dict, immutabledict),
63
+ # only do abc.__instancecheck__ for Mapping after we've checked
64
+ # for plain dictionaries and would otherwise raise
65
+ ) or isinstance(params, collections_abc.Mapping):
66
+ return (params,), _no_kw
67
+ else:
68
+ raise exc.ArgumentError("mapping or sequence expected for parameters")
69
+
70
+
71
+ def exec_driver_sql(self, statement, parameters=None, execution_options=None):
72
+ """
73
+ Adapter for `exec_driver_sql`, which is available since SA14, for SA13.
74
+ """
75
+ if execution_options is not None:
76
+ raise ValueError(
77
+ "SA13 backward-compatibility: "
78
+ "`exec_driver_sql` does not support `execution_options`"
79
+ )
80
+ args_10style, kwargs_10style = _distill_params_20(parameters)
81
+ return self.execute(statement, *args_10style, **kwargs_10style)
82
+
83
+
84
+ def monkeypatch_add_exec_driver_sql():
85
+ """
86
+ Transparently add SA14's `exec_driver_sql()` method to SA13.
87
+
88
+ AttributeError: 'Connection' object has no attribute 'exec_driver_sql'
89
+ AttributeError: 'Engine' object has no attribute 'exec_driver_sql'
90
+ """
91
+ from sqlalchemy.engine.base import Connection, Engine
92
+
93
+ # Add `exec_driver_sql` method to SA's `Connection` and `Engine` classes.
94
+ Connection.exec_driver_sql = exec_driver_sql
95
+ Engine.exec_driver_sql = exec_driver_sql
96
+
97
+
98
+ def select_sa14(*columns, **kw) -> Select:
99
+ """
100
+ Adapt SA14/SA20's calling semantics of `sql.select()` to SA13.
101
+
102
+ With SA20, `select()` no longer accepts varied constructor arguments, only
103
+ the "generative" style of `select()` will be supported. The list of columns
104
+ / tables to select from should be passed positionally.
105
+
106
+ Derived from https://github.com/sqlalchemy/alembic/blob/b1fad6b6/alembic/util/sqla_compat.py#L557-L558
107
+
108
+ sqlalchemy.exc.ArgumentError: columns argument to select() must be a Python list or other iterable
109
+ """
110
+ if isinstance(columns, tuple) and isinstance(columns[0], list):
111
+ if "whereclause" in kw:
112
+ raise ValueError(
113
+ "SA13 backward-compatibility: "
114
+ "`whereclause` is both in kwargs and columns tuple"
115
+ )
116
+ columns, whereclause = columns
117
+ kw["whereclause"] = whereclause
118
+ return original_select(columns, **kw)
119
+
120
+
121
+ def monkeypatch_amend_select_sa14():
122
+ """
123
+ Make SA13's `sql.select()` transparently accept calling semantics of SA14
124
+ and SA20, by swapping in the newer variant of `select_sa14()`.
125
+
126
+ This supports the test suite of `crate-python`, because it already uses the
127
+ modern calling semantics.
128
+ """
129
+ import sqlalchemy
130
+
131
+ sqlalchemy.select = select_sa14
132
+ sqlalchemy.sql.select = select_sa14
133
+ sqlalchemy.sql.expression.select = select_sa14
134
+
135
+
136
+ @property
137
+ def connectionfairy_driver_connection_sa14(self):
138
+ """The connection object as returned by the driver after a connect.
139
+
140
+ .. versionadded:: 1.4.24
141
+
142
+ .. seealso::
143
+
144
+ :attr:`._ConnectionFairy.dbapi_connection`
145
+
146
+ :attr:`._ConnectionRecord.driver_connection`
147
+
148
+ :ref:`faq_dbapi_connection`
149
+
150
+ """
151
+ return self.connection
152
+
153
+
154
+ def monkeypatch_add_connectionfairy_driver_connection():
155
+ import sqlalchemy.pool.base
156
+ sqlalchemy.pool.base._ConnectionFairy.driver_connection = connectionfairy_driver_connection_sa14
@@ -0,0 +1,264 @@
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
+ import sqlalchemy as sa
23
+ from sqlalchemy.dialects.postgresql.base import PGCompiler
24
+ from sqlalchemy.sql.crud import (REQUIRED, _create_bind_param,
25
+ _extend_values_for_multiparams,
26
+ _get_multitable_params,
27
+ _get_stmt_parameters_params,
28
+ _key_getters_for_crud_column, _scan_cols,
29
+ _scan_insert_from_select_cols)
30
+
31
+ from crate.client.sqlalchemy.compiler import CrateCompiler
32
+
33
+
34
+ class CrateCompilerSA10(CrateCompiler):
35
+
36
+ def returning_clause(self, stmt, returning_cols):
37
+ """
38
+ Generate RETURNING clause, PostgreSQL-compatible.
39
+ """
40
+ return PGCompiler.returning_clause(self, stmt, returning_cols)
41
+
42
+ def visit_update(self, update_stmt, **kw):
43
+ """
44
+ used to compile <sql.expression.Update> expressions
45
+ Parts are taken from the SQLCompiler base class.
46
+ """
47
+
48
+ # [10] CrateDB patch.
49
+ if not update_stmt.parameters and \
50
+ not hasattr(update_stmt, '_crate_specific'):
51
+ return super().visit_update(update_stmt, **kw)
52
+
53
+ self.isupdate = True
54
+
55
+ extra_froms = update_stmt._extra_froms
56
+
57
+ text = 'UPDATE '
58
+
59
+ if update_stmt._prefixes:
60
+ text += self._generate_prefixes(update_stmt,
61
+ update_stmt._prefixes, **kw)
62
+
63
+ table_text = self.update_tables_clause(update_stmt, update_stmt.table,
64
+ extra_froms, **kw)
65
+
66
+ dialect_hints = None
67
+ if update_stmt._hints:
68
+ dialect_hints, table_text = self._setup_crud_hints(
69
+ update_stmt, table_text
70
+ )
71
+
72
+ # [10] CrateDB patch.
73
+ crud_params = _get_crud_params(self, update_stmt, **kw)
74
+
75
+ text += table_text
76
+
77
+ text += ' SET '
78
+
79
+ # [10] CrateDB patch begin.
80
+ include_table = \
81
+ extra_froms and self.render_table_with_column_in_update_from
82
+
83
+ set_clauses = []
84
+
85
+ for k, v in crud_params:
86
+ clause = k._compiler_dispatch(self,
87
+ include_table=include_table) + \
88
+ ' = ' + v
89
+ set_clauses.append(clause)
90
+
91
+ for k, v in update_stmt.parameters.items():
92
+ if isinstance(k, str) and '[' in k:
93
+ bindparam = sa.sql.bindparam(k, v)
94
+ set_clauses.append(k + ' = ' + self.process(bindparam))
95
+
96
+ text += ', '.join(set_clauses)
97
+ # [10] CrateDB patch end.
98
+
99
+ if self.returning or update_stmt._returning:
100
+ if not self.returning:
101
+ self.returning = update_stmt._returning
102
+ if self.returning_precedes_values:
103
+ text += " " + self.returning_clause(
104
+ update_stmt, self.returning)
105
+
106
+ if extra_froms:
107
+ extra_from_text = self.update_from_clause(
108
+ update_stmt,
109
+ update_stmt.table,
110
+ extra_froms,
111
+ dialect_hints,
112
+ **kw)
113
+ if extra_from_text:
114
+ text += " " + extra_from_text
115
+
116
+ if update_stmt._whereclause is not None:
117
+ t = self.process(update_stmt._whereclause)
118
+ if t:
119
+ text += " WHERE " + t
120
+
121
+ limit_clause = self.update_limit_clause(update_stmt)
122
+ if limit_clause:
123
+ text += " " + limit_clause
124
+
125
+ if self.returning and not self.returning_precedes_values:
126
+ text += " " + self.returning_clause(
127
+ update_stmt, self.returning)
128
+
129
+ return text
130
+
131
+
132
+ def _get_crud_params(compiler, stmt, **kw):
133
+ """create a set of tuples representing column/string pairs for use
134
+ in an INSERT or UPDATE statement.
135
+
136
+ Also generates the Compiled object's postfetch, prefetch, and
137
+ returning column collections, used for default handling and ultimately
138
+ populating the ResultProxy's prefetch_cols() and postfetch_cols()
139
+ collections.
140
+
141
+ """
142
+
143
+ compiler.postfetch = []
144
+ compiler.insert_prefetch = []
145
+ compiler.update_prefetch = []
146
+ compiler.returning = []
147
+
148
+ # no parameters in the statement, no parameters in the
149
+ # compiled params - return binds for all columns
150
+ if compiler.column_keys is None and stmt.parameters is None:
151
+ return [
152
+ (c, _create_bind_param(compiler, c, None, required=True))
153
+ for c in stmt.table.columns
154
+ ]
155
+
156
+ if stmt._has_multi_parameters:
157
+ stmt_parameters = stmt.parameters[0]
158
+ else:
159
+ stmt_parameters = stmt.parameters
160
+
161
+ # getters - these are normally just column.key,
162
+ # but in the case of mysql multi-table update, the rules for
163
+ # .key must conditionally take tablename into account
164
+ (
165
+ _column_as_key,
166
+ _getattr_col_key,
167
+ _col_bind_name,
168
+ ) = _key_getters_for_crud_column(compiler, stmt)
169
+
170
+ # if we have statement parameters - set defaults in the
171
+ # compiled params
172
+ if compiler.column_keys is None:
173
+ parameters = {}
174
+ else:
175
+ parameters = dict(
176
+ (_column_as_key(key), REQUIRED)
177
+ for key in compiler.column_keys
178
+ if not stmt_parameters or key not in stmt_parameters
179
+ )
180
+
181
+ # create a list of column assignment clauses as tuples
182
+ values = []
183
+
184
+ if stmt_parameters is not None:
185
+ _get_stmt_parameters_params(
186
+ compiler, parameters, stmt_parameters, _column_as_key, values, kw
187
+ )
188
+
189
+ check_columns = {}
190
+
191
+ # special logic that only occurs for multi-table UPDATE
192
+ # statements
193
+ if compiler.isupdate and stmt._extra_froms and stmt_parameters:
194
+ _get_multitable_params(
195
+ compiler,
196
+ stmt,
197
+ stmt_parameters,
198
+ check_columns,
199
+ _col_bind_name,
200
+ _getattr_col_key,
201
+ values,
202
+ kw,
203
+ )
204
+
205
+ if compiler.isinsert and stmt.select_names:
206
+ _scan_insert_from_select_cols(
207
+ compiler,
208
+ stmt,
209
+ parameters,
210
+ _getattr_col_key,
211
+ _column_as_key,
212
+ _col_bind_name,
213
+ check_columns,
214
+ values,
215
+ kw,
216
+ )
217
+ else:
218
+ _scan_cols(
219
+ compiler,
220
+ stmt,
221
+ parameters,
222
+ _getattr_col_key,
223
+ _column_as_key,
224
+ _col_bind_name,
225
+ check_columns,
226
+ values,
227
+ kw,
228
+ )
229
+
230
+ # [10] CrateDB patch.
231
+ #
232
+ # This sanity check performed by SQLAlchemy currently needs to be
233
+ # deactivated in order to satisfy the rewriting logic of the CrateDB
234
+ # dialect in `rewrite_update` and `visit_update`.
235
+ #
236
+ # It can be quickly reproduced by activating this section and running the
237
+ # test cases::
238
+ #
239
+ # ./bin/test -vvvv -t dict_test
240
+ #
241
+ # That croaks like::
242
+ #
243
+ # sqlalchemy.exc.CompileError: Unconsumed column names: characters_name, data['nested']
244
+ #
245
+ # TODO: Investigate why this is actually happening and eventually mitigate
246
+ # the root cause.
247
+ """
248
+ if parameters and stmt_parameters:
249
+ check = (
250
+ set(parameters)
251
+ .intersection(_column_as_key(k) for k in stmt_parameters)
252
+ .difference(check_columns)
253
+ )
254
+ if check:
255
+ raise exc.CompileError(
256
+ "Unconsumed column names: %s"
257
+ % (", ".join("%s" % c for c in check))
258
+ )
259
+ """
260
+
261
+ if stmt._has_multi_parameters:
262
+ values = _extend_values_for_multiparams(compiler, stmt, values, kw)
263
+
264
+ return values