ydb-sqlalchemy 0.1.15__tar.gz → 0.1.17__tar.gz
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.
- {ydb_sqlalchemy-0.1.15/ydb_sqlalchemy.egg-info → ydb_sqlalchemy-0.1.17}/PKG-INFO +1 -1
- {ydb_sqlalchemy-0.1.15 → ydb_sqlalchemy-0.1.17}/setup.py +1 -1
- {ydb_sqlalchemy-0.1.15 → ydb_sqlalchemy-0.1.17}/test/test_core.py +61 -14
- ydb_sqlalchemy-0.1.17/ydb_sqlalchemy/_version.py +1 -0
- {ydb_sqlalchemy-0.1.15 → ydb_sqlalchemy-0.1.17}/ydb_sqlalchemy/sqlalchemy/__init__.py +12 -0
- {ydb_sqlalchemy-0.1.15 → ydb_sqlalchemy-0.1.17}/ydb_sqlalchemy/sqlalchemy/compiler/base.py +15 -14
- {ydb_sqlalchemy-0.1.15 → ydb_sqlalchemy-0.1.17}/ydb_sqlalchemy/sqlalchemy/test_sqlalchemy.py +24 -0
- {ydb_sqlalchemy-0.1.15 → ydb_sqlalchemy-0.1.17}/ydb_sqlalchemy/sqlalchemy/types.py +38 -0
- {ydb_sqlalchemy-0.1.15 → ydb_sqlalchemy-0.1.17/ydb_sqlalchemy.egg-info}/PKG-INFO +1 -1
- ydb_sqlalchemy-0.1.15/ydb_sqlalchemy/_version.py +0 -1
- {ydb_sqlalchemy-0.1.15 → ydb_sqlalchemy-0.1.17}/LICENSE +0 -0
- {ydb_sqlalchemy-0.1.15 → ydb_sqlalchemy-0.1.17}/MANIFEST.in +0 -0
- {ydb_sqlalchemy-0.1.15 → ydb_sqlalchemy-0.1.17}/README.md +0 -0
- {ydb_sqlalchemy-0.1.15 → ydb_sqlalchemy-0.1.17}/pyproject.toml +0 -0
- {ydb_sqlalchemy-0.1.15 → ydb_sqlalchemy-0.1.17}/requirements.txt +0 -0
- {ydb_sqlalchemy-0.1.15 → ydb_sqlalchemy-0.1.17}/setup.cfg +0 -0
- {ydb_sqlalchemy-0.1.15 → ydb_sqlalchemy-0.1.17}/test/__init__.py +0 -0
- {ydb_sqlalchemy-0.1.15 → ydb_sqlalchemy-0.1.17}/test/conftest.py +0 -0
- {ydb_sqlalchemy-0.1.15 → ydb_sqlalchemy-0.1.17}/test/test_inspect.py +0 -0
- {ydb_sqlalchemy-0.1.15 → ydb_sqlalchemy-0.1.17}/test/test_orm.py +0 -0
- {ydb_sqlalchemy-0.1.15 → ydb_sqlalchemy-0.1.17}/test/test_suite.py +0 -0
- {ydb_sqlalchemy-0.1.15 → ydb_sqlalchemy-0.1.17}/ydb_sqlalchemy/__init__.py +0 -0
- {ydb_sqlalchemy-0.1.15 → ydb_sqlalchemy-0.1.17}/ydb_sqlalchemy/sqlalchemy/compiler/__init__.py +0 -0
- {ydb_sqlalchemy-0.1.15 → ydb_sqlalchemy-0.1.17}/ydb_sqlalchemy/sqlalchemy/compiler/sa14.py +0 -0
- {ydb_sqlalchemy-0.1.15 → ydb_sqlalchemy-0.1.17}/ydb_sqlalchemy/sqlalchemy/compiler/sa20.py +0 -0
- {ydb_sqlalchemy-0.1.15 → ydb_sqlalchemy-0.1.17}/ydb_sqlalchemy/sqlalchemy/datetime_types.py +0 -0
- {ydb_sqlalchemy-0.1.15 → ydb_sqlalchemy-0.1.17}/ydb_sqlalchemy/sqlalchemy/dbapi_adapter.py +0 -0
- {ydb_sqlalchemy-0.1.15 → ydb_sqlalchemy-0.1.17}/ydb_sqlalchemy/sqlalchemy/dml.py +0 -0
- {ydb_sqlalchemy-0.1.15 → ydb_sqlalchemy-0.1.17}/ydb_sqlalchemy/sqlalchemy/json.py +0 -0
- {ydb_sqlalchemy-0.1.15 → ydb_sqlalchemy-0.1.17}/ydb_sqlalchemy/sqlalchemy/requirements.py +0 -0
- {ydb_sqlalchemy-0.1.15 → ydb_sqlalchemy-0.1.17}/ydb_sqlalchemy.egg-info/SOURCES.txt +0 -0
- {ydb_sqlalchemy-0.1.15 → ydb_sqlalchemy-0.1.17}/ydb_sqlalchemy.egg-info/dependency_links.txt +0 -0
- {ydb_sqlalchemy-0.1.15 → ydb_sqlalchemy-0.1.17}/ydb_sqlalchemy.egg-info/entry_points.txt +0 -0
- {ydb_sqlalchemy-0.1.15 → ydb_sqlalchemy-0.1.17}/ydb_sqlalchemy.egg-info/requires.txt +0 -0
- {ydb_sqlalchemy-0.1.15 → ydb_sqlalchemy-0.1.17}/ydb_sqlalchemy.egg-info/top_level.txt +0 -0
|
@@ -13,7 +13,7 @@ with open("requirements.txt") as f:
|
|
|
13
13
|
|
|
14
14
|
setuptools.setup(
|
|
15
15
|
name="ydb-sqlalchemy",
|
|
16
|
-
version="0.1.
|
|
16
|
+
version="0.1.17", # AUTOVERSION
|
|
17
17
|
description="YDB Dialect for SQLAlchemy",
|
|
18
18
|
author="Yandex LLC",
|
|
19
19
|
author_email="ydb@yandex-team.ru",
|
|
@@ -181,12 +181,19 @@ class TestSimpleSelect(TablesTest):
|
|
|
181
181
|
rows = connection.execute(stm).fetchall()
|
|
182
182
|
assert set(rows) == {(1,), (2,), (3,), (4,), (6,), (7,)}
|
|
183
183
|
|
|
184
|
+
# LIMIT
|
|
185
|
+
rows = connection.execute(tb.select().order_by(tb.c.id).limit(2)).fetchall()
|
|
186
|
+
assert rows == [
|
|
187
|
+
(1, "some text", Decimal("3.141592653")),
|
|
188
|
+
(2, "test text", Decimal("3.14159265")),
|
|
189
|
+
]
|
|
190
|
+
|
|
184
191
|
# LIMIT/OFFSET
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
192
|
+
rows = connection.execute(tb.select().order_by(tb.c.id).limit(2).offset(1)).fetchall()
|
|
193
|
+
assert rows == [
|
|
194
|
+
(2, "test text", Decimal("3.14159265")),
|
|
195
|
+
(3, "test test", Decimal("3.1415926")),
|
|
196
|
+
]
|
|
190
197
|
|
|
191
198
|
# ORDER BY ASC
|
|
192
199
|
rows = connection.execute(sa.select(tb.c.id).order_by(tb.c.id)).fetchall()
|
|
@@ -223,7 +230,7 @@ class TestTypes(TablesTest):
|
|
|
223
230
|
"test_primitive_types",
|
|
224
231
|
metadata,
|
|
225
232
|
Column("int", sa.Integer, primary_key=True),
|
|
226
|
-
|
|
233
|
+
Column("bin", sa.BINARY),
|
|
227
234
|
Column("str", sa.String),
|
|
228
235
|
Column("float", sa.Float),
|
|
229
236
|
Column("bool", sa.Boolean),
|
|
@@ -253,7 +260,7 @@ class TestTypes(TablesTest):
|
|
|
253
260
|
|
|
254
261
|
statement = sa.insert(table).values(
|
|
255
262
|
int=42,
|
|
256
|
-
|
|
263
|
+
bin=b"abc",
|
|
257
264
|
str="Hello World!",
|
|
258
265
|
float=3.5,
|
|
259
266
|
bool=True,
|
|
@@ -262,7 +269,7 @@ class TestTypes(TablesTest):
|
|
|
262
269
|
connection.execute(statement)
|
|
263
270
|
|
|
264
271
|
row = connection.execute(sa.select(table)).fetchone()
|
|
265
|
-
assert row == (42, "Hello World!", 3.5, True)
|
|
272
|
+
assert row == (42, b"abc", "Hello World!", 3.5, True)
|
|
266
273
|
|
|
267
274
|
def test_all_binary_types(self, connection):
|
|
268
275
|
table = self.tables.test_all_binary_types
|
|
@@ -1150,8 +1157,15 @@ class TestAsTable(TablesTest):
|
|
|
1150
1157
|
Column("val_int", Integer, nullable=True),
|
|
1151
1158
|
Column("val_str", String, nullable=True),
|
|
1152
1159
|
)
|
|
1160
|
+
Table(
|
|
1161
|
+
"test_as_table_json",
|
|
1162
|
+
metadata,
|
|
1163
|
+
Column("id", Integer, primary_key=True),
|
|
1164
|
+
Column("data", sa.JSON, nullable=True),
|
|
1165
|
+
)
|
|
1153
1166
|
|
|
1154
|
-
|
|
1167
|
+
@pytest.mark.parametrize("list_cls", [types.ListType, sa.ARRAY])
|
|
1168
|
+
def test_upsert_as_table(self, connection, list_cls):
|
|
1155
1169
|
table = self.tables.test_as_table
|
|
1156
1170
|
|
|
1157
1171
|
input_data = [
|
|
@@ -1167,7 +1181,7 @@ class TestAsTable(TablesTest):
|
|
|
1167
1181
|
"val_str": types.Optional(String),
|
|
1168
1182
|
}
|
|
1169
1183
|
)
|
|
1170
|
-
list_type =
|
|
1184
|
+
list_type = list_cls(struct_type)
|
|
1171
1185
|
|
|
1172
1186
|
bind_param = sa.bindparam("data", type_=list_type)
|
|
1173
1187
|
|
|
@@ -1187,7 +1201,39 @@ class TestAsTable(TablesTest):
|
|
|
1187
1201
|
(3, 30, None),
|
|
1188
1202
|
]
|
|
1189
1203
|
|
|
1190
|
-
|
|
1204
|
+
@pytest.mark.parametrize("list_cls", [types.ListType, sa.ARRAY])
|
|
1205
|
+
def test_upsert_from_table_json(self, connection, list_cls):
|
|
1206
|
+
table = self.tables.test_as_table_json
|
|
1207
|
+
|
|
1208
|
+
input_data = [
|
|
1209
|
+
{"id": 1, "data": {"a": 1}},
|
|
1210
|
+
{"id": 2, "data": [1, 2, 3]},
|
|
1211
|
+
{"id": 3, "data": None},
|
|
1212
|
+
]
|
|
1213
|
+
|
|
1214
|
+
struct_type = types.StructType.from_table(table)
|
|
1215
|
+
list_type = list_cls(struct_type)
|
|
1216
|
+
|
|
1217
|
+
bind_param = sa.bindparam("input_data", type_=list_type)
|
|
1218
|
+
|
|
1219
|
+
cols = [sa.column(c.name, type_=c.type) for c in table.columns]
|
|
1220
|
+
upsert_stm = ydb_sa.upsert(table).from_select(
|
|
1221
|
+
[c.name for c in table.columns],
|
|
1222
|
+
sa.select(*cols).select_from(sa.func.AS_TABLE(bind_param)),
|
|
1223
|
+
)
|
|
1224
|
+
|
|
1225
|
+
connection.execute(upsert_stm, {"input_data": input_data})
|
|
1226
|
+
|
|
1227
|
+
rows = connection.execute(sa.select(table).order_by(table.c.id)).fetchall()
|
|
1228
|
+
|
|
1229
|
+
assert rows == [
|
|
1230
|
+
(1, {"a": 1}),
|
|
1231
|
+
(2, [1, 2, 3]),
|
|
1232
|
+
(3, None),
|
|
1233
|
+
]
|
|
1234
|
+
|
|
1235
|
+
@pytest.mark.parametrize("list_cls", [types.ListType, sa.ARRAY])
|
|
1236
|
+
def test_insert_as_table(self, connection, list_cls):
|
|
1191
1237
|
table = self.tables.test_as_table
|
|
1192
1238
|
|
|
1193
1239
|
input_data = [
|
|
@@ -1202,7 +1248,7 @@ class TestAsTable(TablesTest):
|
|
|
1202
1248
|
"val_str": types.Optional(String),
|
|
1203
1249
|
}
|
|
1204
1250
|
)
|
|
1205
|
-
list_type =
|
|
1251
|
+
list_type = list_cls(struct_type)
|
|
1206
1252
|
|
|
1207
1253
|
bind_param = sa.bindparam("data", type_=list_type)
|
|
1208
1254
|
|
|
@@ -1221,7 +1267,8 @@ class TestAsTable(TablesTest):
|
|
|
1221
1267
|
(5, None, "e"),
|
|
1222
1268
|
]
|
|
1223
1269
|
|
|
1224
|
-
|
|
1270
|
+
@pytest.mark.parametrize("list_cls", [types.ListType, sa.ARRAY])
|
|
1271
|
+
def test_upsert_from_table_reflection(self, connection, list_cls):
|
|
1225
1272
|
table = self.tables.test_as_table
|
|
1226
1273
|
|
|
1227
1274
|
input_data = [
|
|
@@ -1230,7 +1277,7 @@ class TestAsTable(TablesTest):
|
|
|
1230
1277
|
]
|
|
1231
1278
|
|
|
1232
1279
|
struct_type = types.StructType.from_table(table)
|
|
1233
|
-
list_type =
|
|
1280
|
+
list_type = list_cls(struct_type)
|
|
1234
1281
|
|
|
1235
1282
|
bind_param = sa.bindparam("data", type_=list_type)
|
|
1236
1283
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
VERSION = "0.1.17"
|
|
@@ -160,6 +160,7 @@ class YqlDialect(StrCompileDialect):
|
|
|
160
160
|
sa.types.BINARY: types.Binary,
|
|
161
161
|
sa.types.LargeBinary: types.Binary,
|
|
162
162
|
sa.types.BLOB: types.Binary,
|
|
163
|
+
sa.types.ARRAY: types.ListType,
|
|
163
164
|
}
|
|
164
165
|
|
|
165
166
|
connection_characteristics = util.immutabledict(
|
|
@@ -205,6 +206,7 @@ class YqlDialect(StrCompileDialect):
|
|
|
205
206
|
json_serializer=None,
|
|
206
207
|
json_deserializer=None,
|
|
207
208
|
_add_declare_for_yql_stmt_vars=False,
|
|
209
|
+
_statement_prefixes_list=None,
|
|
208
210
|
**kwargs,
|
|
209
211
|
):
|
|
210
212
|
super().__init__(**kwargs)
|
|
@@ -214,6 +216,7 @@ class YqlDialect(StrCompileDialect):
|
|
|
214
216
|
# NOTE: _add_declare_for_yql_stmt_vars is temporary and is soon to be removed.
|
|
215
217
|
# no need in declare in yql statement here since ydb 24-1
|
|
216
218
|
self._add_declare_for_yql_stmt_vars = _add_declare_for_yql_stmt_vars
|
|
219
|
+
self._statement_prefixes = tuple(_statement_prefixes_list) if _statement_prefixes_list else ()
|
|
217
220
|
|
|
218
221
|
def _describe_table(self, connection, table_name, schema=None) -> ydb.TableDescription:
|
|
219
222
|
if schema is not None:
|
|
@@ -404,6 +407,12 @@ class YqlDialect(StrCompileDialect):
|
|
|
404
407
|
)
|
|
405
408
|
return f"{declarations}\n{statement}"
|
|
406
409
|
|
|
410
|
+
def _apply_statement_prefixes_impl(self, statement: str) -> str:
|
|
411
|
+
if not self._statement_prefixes:
|
|
412
|
+
return statement
|
|
413
|
+
prefixes = "\n".join(self._statement_prefixes) + "\n"
|
|
414
|
+
return f"{prefixes}{statement}"
|
|
415
|
+
|
|
407
416
|
def __merge_parameters_values_and_types(
|
|
408
417
|
self, values: Mapping[str, Any], types: Mapping[str, Any], execute_many: bool
|
|
409
418
|
) -> Sequence[Mapping[str, ydb.TypedValue]]:
|
|
@@ -437,9 +446,12 @@ class YqlDialect(StrCompileDialect):
|
|
|
437
446
|
statement, parameters = self._format_variables(statement, parameters, execute_many)
|
|
438
447
|
if self._add_declare_for_yql_stmt_vars:
|
|
439
448
|
statement = self._add_declare_for_yql_stmt_vars_impl(statement, parameters_types)
|
|
449
|
+
statement = self._apply_statement_prefixes_impl(statement)
|
|
440
450
|
return statement, parameters
|
|
441
451
|
|
|
442
452
|
statement, parameters = self._format_variables(statement, parameters, execute_many)
|
|
453
|
+
if not is_ddl:
|
|
454
|
+
statement = self._apply_statement_prefixes_impl(statement)
|
|
443
455
|
return statement, parameters
|
|
444
456
|
|
|
445
457
|
def do_ping(self, dbapi_connection: ydb_dbapi.Connection) -> bool:
|
|
@@ -44,19 +44,6 @@ else:
|
|
|
44
44
|
from sqlalchemy import Cast as _cast
|
|
45
45
|
|
|
46
46
|
|
|
47
|
-
STR_QUOTE_MAP = {
|
|
48
|
-
"'": "\\'",
|
|
49
|
-
"\\": "\\\\",
|
|
50
|
-
"\0": "\\0",
|
|
51
|
-
"\b": "\\b",
|
|
52
|
-
"\f": "\\f",
|
|
53
|
-
"\r": "\\r",
|
|
54
|
-
"\n": "\\n",
|
|
55
|
-
"\t": "\\t",
|
|
56
|
-
"%": "%%",
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
|
|
60
47
|
COMPOUND_KEYWORDS = {
|
|
61
48
|
selectable.CompoundSelect.UNION: "UNION ALL",
|
|
62
49
|
selectable.CompoundSelect.UNION_ALL: "UNION ALL",
|
|
@@ -67,6 +54,19 @@ COMPOUND_KEYWORDS = {
|
|
|
67
54
|
}
|
|
68
55
|
|
|
69
56
|
|
|
57
|
+
ESCAPE_RULES = [
|
|
58
|
+
("\\", "\\\\"), # Must be first to avoid double escaping
|
|
59
|
+
("'", "\\'"),
|
|
60
|
+
("\0", "\\0"),
|
|
61
|
+
("\b", "\\b"),
|
|
62
|
+
("\f", "\\f"),
|
|
63
|
+
("\r", "\\r"),
|
|
64
|
+
("\n", "\\n"),
|
|
65
|
+
("\t", "\\t"),
|
|
66
|
+
("%", "%%"),
|
|
67
|
+
]
|
|
68
|
+
|
|
69
|
+
|
|
70
70
|
class BaseYqlTypeCompiler(StrSQLTypeCompiler):
|
|
71
71
|
def visit_JSON(self, type_: Union[sa.JSON, types.YqlJSON], **kw):
|
|
72
72
|
return "JSON"
|
|
@@ -293,7 +293,8 @@ class BaseYqlCompiler(StrSQLCompiler):
|
|
|
293
293
|
|
|
294
294
|
def render_literal_value(self, value, type_):
|
|
295
295
|
if isinstance(value, str):
|
|
296
|
-
|
|
296
|
+
for pattern, replacement in ESCAPE_RULES:
|
|
297
|
+
value = value.replace(pattern, replacement)
|
|
297
298
|
return f"'{value}'"
|
|
298
299
|
return super().render_literal_value(value, type_)
|
|
299
300
|
|
{ydb_sqlalchemy-0.1.15 → ydb_sqlalchemy-0.1.17}/ydb_sqlalchemy/sqlalchemy/test_sqlalchemy.py
RENAMED
|
@@ -114,6 +114,30 @@ def test_types_compilation():
|
|
|
114
114
|
assert compile_type(struct) == "Struct<a:Int32,b:List<Int32>>"
|
|
115
115
|
|
|
116
116
|
|
|
117
|
+
def test_statement_prefixes_prepended_to_query():
|
|
118
|
+
dialect = YqlDialect(_statement_prefixes_list=["PRAGMA DistinctOverKeys;"])
|
|
119
|
+
result = dialect._apply_statement_prefixes_impl("SELECT 1")
|
|
120
|
+
assert result == "PRAGMA DistinctOverKeys;\nSELECT 1"
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def test_statement_prefixes_empty_list_unchanged():
|
|
124
|
+
dialect = YqlDialect(_statement_prefixes_list=[])
|
|
125
|
+
result = dialect._apply_statement_prefixes_impl("SELECT 1")
|
|
126
|
+
assert result == "SELECT 1"
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def test_statement_prefixes_none_unchanged():
|
|
130
|
+
dialect = YqlDialect()
|
|
131
|
+
result = dialect._apply_statement_prefixes_impl("SELECT 1")
|
|
132
|
+
assert result == "SELECT 1"
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def test_statement_prefixes_multiple():
|
|
136
|
+
dialect = YqlDialect(_statement_prefixes_list=["PRAGMA Foo;", "PRAGMA Bar;"])
|
|
137
|
+
result = dialect._apply_statement_prefixes_impl("SELECT 1")
|
|
138
|
+
assert result == "PRAGMA Foo;\nPRAGMA Bar;\nSELECT 1"
|
|
139
|
+
|
|
140
|
+
|
|
117
141
|
def test_optional_type_compilation():
|
|
118
142
|
dialect = YqlDialect()
|
|
119
143
|
type_compiler = dialect.type_compiler
|
|
@@ -110,6 +110,18 @@ class Decimal(types.DECIMAL):
|
|
|
110
110
|
class ListType(ARRAY):
|
|
111
111
|
__visit_name__ = "list_type"
|
|
112
112
|
|
|
113
|
+
def bind_processor(self, dialect):
|
|
114
|
+
item_proc = self.item_type.bind_processor(dialect)
|
|
115
|
+
|
|
116
|
+
def process(value):
|
|
117
|
+
if value is None:
|
|
118
|
+
return None
|
|
119
|
+
return [item_proc(v) if v is not None else None for v in value]
|
|
120
|
+
|
|
121
|
+
if item_proc:
|
|
122
|
+
return process
|
|
123
|
+
return None
|
|
124
|
+
|
|
113
125
|
|
|
114
126
|
class HashableDict(dict):
|
|
115
127
|
def __hash__(self):
|
|
@@ -173,6 +185,32 @@ class StructType(types.TypeEngine[Mapping[str, Any]]):
|
|
|
173
185
|
def compare_values(self, x, y):
|
|
174
186
|
return x == y
|
|
175
187
|
|
|
188
|
+
def bind_processor(self, dialect):
|
|
189
|
+
processors = {}
|
|
190
|
+
for name, type_ in self.fields_types.items():
|
|
191
|
+
if isinstance(type_, Optional):
|
|
192
|
+
type_ = type_.element_type
|
|
193
|
+
|
|
194
|
+
type_ = type_api.to_instance(type_)
|
|
195
|
+
proc = type_.bind_processor(dialect)
|
|
196
|
+
if proc:
|
|
197
|
+
processors[name] = proc
|
|
198
|
+
|
|
199
|
+
if not processors:
|
|
200
|
+
return None
|
|
201
|
+
|
|
202
|
+
def process(value):
|
|
203
|
+
if value is None:
|
|
204
|
+
return None
|
|
205
|
+
new_value = value.copy()
|
|
206
|
+
for name, proc in processors.items():
|
|
207
|
+
if name in new_value:
|
|
208
|
+
if new_value[name] is not None:
|
|
209
|
+
new_value[name] = proc(new_value[name])
|
|
210
|
+
return new_value
|
|
211
|
+
|
|
212
|
+
return process
|
|
213
|
+
|
|
176
214
|
|
|
177
215
|
class Lambda(ColumnElement):
|
|
178
216
|
__visit_name__ = "lambda"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
VERSION = "0.1.15"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ydb_sqlalchemy-0.1.15 → ydb_sqlalchemy-0.1.17}/ydb_sqlalchemy/sqlalchemy/compiler/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ydb_sqlalchemy-0.1.15 → ydb_sqlalchemy-0.1.17}/ydb_sqlalchemy.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|