lsst-felis 24.1.6rc1__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.
Potentially problematic release.
This version of lsst-felis might be problematic. Click here for more details.
- felis/__init__.py +22 -0
- felis/cli.py +497 -0
- felis/datamodel.py +1116 -0
- felis/db/__init__.py +0 -0
- felis/db/dialects.py +116 -0
- felis/db/sqltypes.py +436 -0
- felis/db/utils.py +409 -0
- felis/db/variants.py +159 -0
- felis/metadata.py +383 -0
- felis/py.typed +0 -0
- felis/schemas/tap_schema_std.yaml +273 -0
- felis/tap.py +597 -0
- felis/tap_schema.py +644 -0
- felis/tests/__init__.py +0 -0
- felis/tests/postgresql.py +134 -0
- felis/tests/utils.py +122 -0
- felis/types.py +185 -0
- felis/version.py +2 -0
- lsst_felis-24.1.6rc1.dist-info/COPYRIGHT +1 -0
- lsst_felis-24.1.6rc1.dist-info/LICENSE +674 -0
- lsst_felis-24.1.6rc1.dist-info/METADATA +34 -0
- lsst_felis-24.1.6rc1.dist-info/RECORD +26 -0
- lsst_felis-24.1.6rc1.dist-info/WHEEL +5 -0
- lsst_felis-24.1.6rc1.dist-info/entry_points.txt +2 -0
- lsst_felis-24.1.6rc1.dist-info/top_level.txt +1 -0
- lsst_felis-24.1.6rc1.dist-info/zip-safe +1 -0
felis/db/__init__.py
ADDED
|
File without changes
|
felis/db/dialects.py
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"""Get SQLAlchemy dialects and their type modules."""
|
|
2
|
+
|
|
3
|
+
# This file is part of felis.
|
|
4
|
+
#
|
|
5
|
+
# Developed for the LSST Data Management System.
|
|
6
|
+
# This product includes software developed by the LSST Project
|
|
7
|
+
# (https://www.lsst.org).
|
|
8
|
+
# See the COPYRIGHT file at the top-level directory of this distribution
|
|
9
|
+
# for details of code ownership.
|
|
10
|
+
#
|
|
11
|
+
# This program is free software: you can redistribute it and/or modify
|
|
12
|
+
# it under the terms of the GNU General Public License as published by
|
|
13
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
14
|
+
# (at your option) any later version.
|
|
15
|
+
#
|
|
16
|
+
# This program is distributed in the hope that it will be useful,
|
|
17
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
18
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
19
|
+
# GNU General Public License for more details.
|
|
20
|
+
#
|
|
21
|
+
# You should have received a copy of the GNU General Public License
|
|
22
|
+
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
23
|
+
|
|
24
|
+
from __future__ import annotations
|
|
25
|
+
|
|
26
|
+
from collections.abc import Mapping
|
|
27
|
+
from types import MappingProxyType, ModuleType
|
|
28
|
+
|
|
29
|
+
from sqlalchemy import dialects
|
|
30
|
+
from sqlalchemy.engine import Dialect
|
|
31
|
+
from sqlalchemy.engine.mock import create_mock_engine
|
|
32
|
+
|
|
33
|
+
from .sqltypes import MYSQL, POSTGRES, SQLITE
|
|
34
|
+
|
|
35
|
+
__all__ = ["get_supported_dialects", "get_dialect_module"]
|
|
36
|
+
|
|
37
|
+
_DIALECT_NAMES = (MYSQL, POSTGRES, SQLITE)
|
|
38
|
+
"""List of supported dialect names.
|
|
39
|
+
|
|
40
|
+
This list is used to create the dialect and module dictionaries.
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _dialect(dialect_name: str) -> Dialect:
|
|
45
|
+
"""Create the SQLAlchemy dialect for the given name using a mock engine.
|
|
46
|
+
|
|
47
|
+
Parameters
|
|
48
|
+
----------
|
|
49
|
+
dialect_name
|
|
50
|
+
The name of the dialect to create.
|
|
51
|
+
|
|
52
|
+
Returns
|
|
53
|
+
-------
|
|
54
|
+
`~sqlalchemy.engine.Dialect`
|
|
55
|
+
The SQLAlchemy dialect.
|
|
56
|
+
"""
|
|
57
|
+
return create_mock_engine(f"{dialect_name}://", executor=None).dialect
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
_DIALECTS = MappingProxyType({name: _dialect(name) for name in _DIALECT_NAMES})
|
|
61
|
+
"""Dictionary of dialect names to SQLAlchemy dialects."""
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def get_supported_dialects() -> Mapping[str, Dialect]:
|
|
65
|
+
"""Get a dictionary of the supported SQLAlchemy dialects.
|
|
66
|
+
|
|
67
|
+
Returns
|
|
68
|
+
-------
|
|
69
|
+
`dict` [ `str`, `~sqlalchemy.engine.Dialect`]
|
|
70
|
+
A dictionary of the supported SQLAlchemy dialects.
|
|
71
|
+
|
|
72
|
+
Notes
|
|
73
|
+
-----
|
|
74
|
+
The dictionary is keyed by the dialect name and the value is the SQLAlchemy
|
|
75
|
+
dialect object. This function is intended as the primary interface for
|
|
76
|
+
getting the supported dialects.
|
|
77
|
+
"""
|
|
78
|
+
return _DIALECTS
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def _dialect_module(dialect_name: str) -> ModuleType:
|
|
82
|
+
"""Get the SQLAlchemy dialect module for the given name.
|
|
83
|
+
|
|
84
|
+
Parameters
|
|
85
|
+
----------
|
|
86
|
+
dialect_name
|
|
87
|
+
The name of the dialect module to get from the SQLAlchemy package.
|
|
88
|
+
"""
|
|
89
|
+
return getattr(dialects, dialect_name)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
_DIALECT_MODULES = MappingProxyType({name: _dialect_module(name) for name in _DIALECT_NAMES})
|
|
93
|
+
"""Dictionary of dialect names to SQLAlchemy modules."""
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def get_dialect_module(dialect_name: str) -> ModuleType:
|
|
97
|
+
"""Get the SQLAlchemy dialect module for the given name.
|
|
98
|
+
|
|
99
|
+
Parameters
|
|
100
|
+
----------
|
|
101
|
+
dialect_name
|
|
102
|
+
The name of the dialect module to get from the SQLAlchemy package.
|
|
103
|
+
|
|
104
|
+
Returns
|
|
105
|
+
-------
|
|
106
|
+
`~types.ModuleType`
|
|
107
|
+
The SQLAlchemy dialect module.
|
|
108
|
+
|
|
109
|
+
Raises
|
|
110
|
+
------
|
|
111
|
+
ValueError
|
|
112
|
+
Raised if the dialect name is not supported.
|
|
113
|
+
"""
|
|
114
|
+
if dialect_name not in _DIALECT_MODULES:
|
|
115
|
+
raise ValueError(f"Unsupported dialect: {dialect_name}")
|
|
116
|
+
return _DIALECT_MODULES[dialect_name]
|
felis/db/sqltypes.py
ADDED
|
@@ -0,0 +1,436 @@
|
|
|
1
|
+
"""Map Felis types to SQLAlchemy types."""
|
|
2
|
+
|
|
3
|
+
# This file is part of felis.
|
|
4
|
+
#
|
|
5
|
+
# Developed for the LSST Data Management System.
|
|
6
|
+
# This product includes software developed by the LSST Project
|
|
7
|
+
# (https://www.lsst.org).
|
|
8
|
+
# See the COPYRIGHT file at the top-level directory of this distribution
|
|
9
|
+
# for details of code ownership.
|
|
10
|
+
#
|
|
11
|
+
# This program is free software: you can redistribute it and/or modify
|
|
12
|
+
# it under the terms of the GNU General Public License as published by
|
|
13
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
14
|
+
# (at your option) any later version.
|
|
15
|
+
#
|
|
16
|
+
# This program is distributed in the hope that it will be useful,
|
|
17
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
18
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
19
|
+
# GNU General Public License for more details.
|
|
20
|
+
#
|
|
21
|
+
# You should have received a copy of the GNU General Public License
|
|
22
|
+
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
23
|
+
|
|
24
|
+
from __future__ import annotations
|
|
25
|
+
|
|
26
|
+
import builtins
|
|
27
|
+
from collections.abc import Callable, Mapping
|
|
28
|
+
from typing import Any
|
|
29
|
+
|
|
30
|
+
from sqlalchemy import SmallInteger, types
|
|
31
|
+
from sqlalchemy.dialects import mysql, postgresql
|
|
32
|
+
from sqlalchemy.ext.compiler import compiles
|
|
33
|
+
|
|
34
|
+
__all__ = [
|
|
35
|
+
"boolean",
|
|
36
|
+
"byte",
|
|
37
|
+
"short",
|
|
38
|
+
"int",
|
|
39
|
+
"long",
|
|
40
|
+
"float",
|
|
41
|
+
"double",
|
|
42
|
+
"char",
|
|
43
|
+
"string",
|
|
44
|
+
"unicode",
|
|
45
|
+
"text",
|
|
46
|
+
"binary",
|
|
47
|
+
"timestamp",
|
|
48
|
+
"get_type_func",
|
|
49
|
+
]
|
|
50
|
+
|
|
51
|
+
MYSQL = "mysql"
|
|
52
|
+
POSTGRES = "postgresql"
|
|
53
|
+
SQLITE = "sqlite"
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class TINYINT(SmallInteger):
|
|
57
|
+
"""The non-standard TINYINT type."""
|
|
58
|
+
|
|
59
|
+
__visit_name__ = "TINYINT"
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
@compiles(TINYINT)
|
|
63
|
+
def compile_tinyint(type_: Any, compiler: Any, **kwargs: Any) -> str:
|
|
64
|
+
"""Compile the non-standard ``TINYINT`` type to SQL.
|
|
65
|
+
|
|
66
|
+
Parameters
|
|
67
|
+
----------
|
|
68
|
+
type_
|
|
69
|
+
The type object.
|
|
70
|
+
compiler
|
|
71
|
+
The compiler object.
|
|
72
|
+
**kwargs
|
|
73
|
+
Additional keyword arguments.
|
|
74
|
+
|
|
75
|
+
Returns
|
|
76
|
+
-------
|
|
77
|
+
`str`
|
|
78
|
+
The compiled SQL for TINYINT.
|
|
79
|
+
|
|
80
|
+
Notes
|
|
81
|
+
-----
|
|
82
|
+
This function returns the SQL for the the TINYINT type. The function
|
|
83
|
+
signature and parameters are defined by SQLAlchemy.
|
|
84
|
+
"""
|
|
85
|
+
return "TINYINT"
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
_TypeMap = Mapping[str, types.TypeEngine | type[types.TypeEngine]]
|
|
89
|
+
|
|
90
|
+
boolean_map: _TypeMap = {MYSQL: mysql.BOOLEAN, POSTGRES: postgresql.BOOLEAN()}
|
|
91
|
+
|
|
92
|
+
byte_map: _TypeMap = {
|
|
93
|
+
MYSQL: mysql.TINYINT(),
|
|
94
|
+
POSTGRES: postgresql.SMALLINT(),
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
short_map: _TypeMap = {
|
|
98
|
+
MYSQL: mysql.SMALLINT(),
|
|
99
|
+
POSTGRES: postgresql.SMALLINT(),
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
int_map: _TypeMap = {
|
|
103
|
+
MYSQL: mysql.INTEGER(),
|
|
104
|
+
POSTGRES: postgresql.INTEGER(),
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
long_map: _TypeMap = {
|
|
108
|
+
MYSQL: mysql.BIGINT(),
|
|
109
|
+
POSTGRES: postgresql.BIGINT(),
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
float_map: _TypeMap = {
|
|
113
|
+
MYSQL: mysql.FLOAT(),
|
|
114
|
+
POSTGRES: postgresql.FLOAT(),
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
double_map: _TypeMap = {
|
|
118
|
+
MYSQL: mysql.DOUBLE(),
|
|
119
|
+
POSTGRES: postgresql.DOUBLE_PRECISION(),
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
char_map: _TypeMap = {
|
|
123
|
+
MYSQL: mysql.CHAR,
|
|
124
|
+
POSTGRES: postgresql.CHAR,
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
string_map: _TypeMap = {
|
|
128
|
+
MYSQL: mysql.VARCHAR,
|
|
129
|
+
POSTGRES: postgresql.VARCHAR,
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
unicode_map: _TypeMap = {
|
|
133
|
+
MYSQL: mysql.NVARCHAR,
|
|
134
|
+
POSTGRES: postgresql.VARCHAR,
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
text_map: _TypeMap = {
|
|
138
|
+
MYSQL: mysql.LONGTEXT,
|
|
139
|
+
POSTGRES: postgresql.TEXT,
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
binary_map: _TypeMap = {
|
|
143
|
+
MYSQL: mysql.LONGBLOB,
|
|
144
|
+
POSTGRES: postgresql.BYTEA,
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
timestamp_map: _TypeMap = {
|
|
148
|
+
MYSQL: mysql.DATETIME(timezone=False),
|
|
149
|
+
POSTGRES: postgresql.TIMESTAMP(timezone=False),
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def boolean(**kwargs: Any) -> types.TypeEngine:
|
|
154
|
+
"""Get the SQL type for Felis `~felis.types.Boolean` with variants.
|
|
155
|
+
|
|
156
|
+
Parameters
|
|
157
|
+
----------
|
|
158
|
+
**kwargs
|
|
159
|
+
Additional keyword arguments to pass to the type object.
|
|
160
|
+
|
|
161
|
+
Returns
|
|
162
|
+
-------
|
|
163
|
+
`~sqlalchemy.types.TypeEngine`
|
|
164
|
+
The SQL type for a Felis boolean.
|
|
165
|
+
"""
|
|
166
|
+
return _vary(types.BOOLEAN(), boolean_map, kwargs)
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def byte(**kwargs: Any) -> types.TypeEngine:
|
|
170
|
+
"""Get the SQL type for Felis `~felis.types.Byte` with variants.
|
|
171
|
+
|
|
172
|
+
Parameters
|
|
173
|
+
----------
|
|
174
|
+
**kwargs
|
|
175
|
+
Additional keyword arguments to pass to the type object.
|
|
176
|
+
|
|
177
|
+
Returns
|
|
178
|
+
-------
|
|
179
|
+
`~sqlalchemy.types.TypeEngine`
|
|
180
|
+
The SQL type for a Felis byte.
|
|
181
|
+
"""
|
|
182
|
+
return _vary(TINYINT(), byte_map, kwargs)
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
def short(**kwargs: Any) -> types.TypeEngine:
|
|
186
|
+
"""Get the SQL type for Felis `~felis.types.Short` with variants.
|
|
187
|
+
|
|
188
|
+
Parameters
|
|
189
|
+
----------
|
|
190
|
+
**kwargs
|
|
191
|
+
Additional keyword arguments to pass to the type object.
|
|
192
|
+
|
|
193
|
+
Returns
|
|
194
|
+
-------
|
|
195
|
+
`~sqlalchemy.types.TypeEngine`
|
|
196
|
+
The SQL type for a Felis short.
|
|
197
|
+
"""
|
|
198
|
+
return _vary(types.SMALLINT(), short_map, kwargs)
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
def int(**kwargs: Any) -> types.TypeEngine:
|
|
202
|
+
"""Get the SQL type for Felis `~felis.types.Int` with variants.
|
|
203
|
+
|
|
204
|
+
Parameters
|
|
205
|
+
----------
|
|
206
|
+
**kwargs
|
|
207
|
+
Additional keyword arguments to pass to the type object.
|
|
208
|
+
|
|
209
|
+
Returns
|
|
210
|
+
-------
|
|
211
|
+
`~sqlalchemy.types.TypeEngine`
|
|
212
|
+
The SQL type for a Felis int.
|
|
213
|
+
"""
|
|
214
|
+
return _vary(types.INTEGER(), int_map, kwargs)
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
def long(**kwargs: Any) -> types.TypeEngine:
|
|
218
|
+
"""Get the SQL type for Felis `~felis.types.Long` with variants.
|
|
219
|
+
|
|
220
|
+
Parameters
|
|
221
|
+
----------
|
|
222
|
+
**kwargs
|
|
223
|
+
Additional keyword arguments to pass to the type object.
|
|
224
|
+
|
|
225
|
+
Returns
|
|
226
|
+
-------
|
|
227
|
+
`~sqlalchemy.types.TypeEngine`
|
|
228
|
+
The SQL type for a Felis long.
|
|
229
|
+
"""
|
|
230
|
+
return _vary(types.BIGINT(), long_map, kwargs)
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
def float(**kwargs: Any) -> types.TypeEngine:
|
|
234
|
+
"""Get the SQL type for Felis `~felis.types.Float` with variants.
|
|
235
|
+
|
|
236
|
+
Parameters
|
|
237
|
+
----------
|
|
238
|
+
**kwargs
|
|
239
|
+
Additional keyword arguments to pass to the type object.
|
|
240
|
+
|
|
241
|
+
Returns
|
|
242
|
+
-------
|
|
243
|
+
`~sqlalchemy.types.TypeEngine`
|
|
244
|
+
The SQL type for a Felis float.
|
|
245
|
+
"""
|
|
246
|
+
return _vary(types.FLOAT(), float_map, kwargs)
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
def double(**kwargs: Any) -> types.TypeEngine:
|
|
250
|
+
"""Get the SQL type for Felis `~felis.types.Double` with variants.
|
|
251
|
+
|
|
252
|
+
Parameters
|
|
253
|
+
----------
|
|
254
|
+
**kwargs
|
|
255
|
+
Additional keyword arguments to pass to the type object.
|
|
256
|
+
|
|
257
|
+
Returns
|
|
258
|
+
-------
|
|
259
|
+
`~sqlalchemy.types.TypeEngine`
|
|
260
|
+
The SQL type for a Felis double.
|
|
261
|
+
"""
|
|
262
|
+
return _vary(types.DOUBLE(), double_map, kwargs)
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
def char(length: builtins.int, **kwargs: Any) -> types.TypeEngine:
|
|
266
|
+
"""Get the SQL type for Felis `~felis.types.Char` with variants.
|
|
267
|
+
|
|
268
|
+
Parameters
|
|
269
|
+
----------
|
|
270
|
+
length
|
|
271
|
+
The length of the character field.
|
|
272
|
+
**kwargs
|
|
273
|
+
Additional keyword arguments to pass to the type object.
|
|
274
|
+
|
|
275
|
+
Returns
|
|
276
|
+
-------
|
|
277
|
+
`~sqlalchemy.types.TypeEngine`
|
|
278
|
+
The SQL type for a Felis char.
|
|
279
|
+
"""
|
|
280
|
+
return _vary(types.CHAR(length), char_map, kwargs, length)
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
def string(length: builtins.int, **kwargs: Any) -> types.TypeEngine:
|
|
284
|
+
"""Get the SQL type for Felis `~felis.types.String` with variants.
|
|
285
|
+
|
|
286
|
+
Parameters
|
|
287
|
+
----------
|
|
288
|
+
length
|
|
289
|
+
The length of the string field.
|
|
290
|
+
**kwargs
|
|
291
|
+
Additional keyword arguments to pass to the type object.
|
|
292
|
+
|
|
293
|
+
Returns
|
|
294
|
+
-------
|
|
295
|
+
`~sqlalchemy.types.TypeEngine`
|
|
296
|
+
The SQL type for a Felis string.
|
|
297
|
+
"""
|
|
298
|
+
return _vary(types.VARCHAR(length), string_map, kwargs, length)
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
def unicode(length: builtins.int, **kwargs: Any) -> types.TypeEngine:
|
|
302
|
+
"""Get the SQL type for Felis `~felis.types.Unicode` with variants.
|
|
303
|
+
|
|
304
|
+
Parameters
|
|
305
|
+
----------
|
|
306
|
+
length
|
|
307
|
+
The length of the unicode string field.
|
|
308
|
+
**kwargs
|
|
309
|
+
Additional keyword arguments to pass to the type object.
|
|
310
|
+
|
|
311
|
+
Returns
|
|
312
|
+
-------
|
|
313
|
+
`~sqlalchemy.types.TypeEngine`
|
|
314
|
+
The SQL type for a Felis unicode string.
|
|
315
|
+
"""
|
|
316
|
+
return _vary(types.NVARCHAR(length), unicode_map, kwargs, length)
|
|
317
|
+
|
|
318
|
+
|
|
319
|
+
def text(**kwargs: Any) -> types.TypeEngine:
|
|
320
|
+
"""Get the SQL type for Felis `~felis.types.Text` with variants.
|
|
321
|
+
|
|
322
|
+
Parameters
|
|
323
|
+
----------
|
|
324
|
+
**kwargs
|
|
325
|
+
Additional keyword arguments to pass to the type object.
|
|
326
|
+
|
|
327
|
+
Returns
|
|
328
|
+
-------
|
|
329
|
+
`~sqlalchemy.types.TypeEngine`
|
|
330
|
+
The SQL type for Felis text.
|
|
331
|
+
"""
|
|
332
|
+
return _vary(types.TEXT(), text_map, kwargs)
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
def binary(length: builtins.int, **kwargs: Any) -> types.TypeEngine:
|
|
336
|
+
"""Get the SQL type for Felis `~felis.types.Binary` with variants.
|
|
337
|
+
|
|
338
|
+
Parameters
|
|
339
|
+
----------
|
|
340
|
+
length
|
|
341
|
+
The length of the binary field.
|
|
342
|
+
**kwargs
|
|
343
|
+
Additional keyword arguments to pass to the type object.
|
|
344
|
+
|
|
345
|
+
Returns
|
|
346
|
+
-------
|
|
347
|
+
`~sqlalchemy.types.TypeEngine`
|
|
348
|
+
The SQL type for Felis binary.
|
|
349
|
+
"""
|
|
350
|
+
return _vary(types.BLOB(length), binary_map, kwargs, length)
|
|
351
|
+
|
|
352
|
+
|
|
353
|
+
def timestamp(**kwargs: Any) -> types.TypeEngine:
|
|
354
|
+
"""Get the SQL type for Felis `~felis.types.Timestamp` with variants.
|
|
355
|
+
|
|
356
|
+
Parameters
|
|
357
|
+
----------
|
|
358
|
+
**kwargs
|
|
359
|
+
Additional keyword arguments to pass to the type object.
|
|
360
|
+
|
|
361
|
+
Returns
|
|
362
|
+
-------
|
|
363
|
+
`~sqlalchemy.types.TypeEngine`
|
|
364
|
+
The SQL type for a Felis timestamp.
|
|
365
|
+
"""
|
|
366
|
+
return _vary(types.TIMESTAMP(timezone=False), timestamp_map, kwargs)
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
def get_type_func(type_name: str) -> Callable:
|
|
370
|
+
"""Find the function which creates a specific SQL type by its Felis type
|
|
371
|
+
name.
|
|
372
|
+
|
|
373
|
+
Parameters
|
|
374
|
+
----------
|
|
375
|
+
type_name
|
|
376
|
+
The name of the type function to get.
|
|
377
|
+
|
|
378
|
+
Returns
|
|
379
|
+
-------
|
|
380
|
+
`Callable`
|
|
381
|
+
The function for the type.
|
|
382
|
+
|
|
383
|
+
Raises
|
|
384
|
+
------
|
|
385
|
+
ValueError
|
|
386
|
+
Raised if the type name is not recognized.
|
|
387
|
+
|
|
388
|
+
Notes
|
|
389
|
+
-----
|
|
390
|
+
This maps the type name to the function that creates the SQL type. This is
|
|
391
|
+
the main way to get the type functions from the type names.
|
|
392
|
+
"""
|
|
393
|
+
if type_name not in globals():
|
|
394
|
+
raise ValueError(f"Unknown type: {type_name}")
|
|
395
|
+
return globals()[type_name]
|
|
396
|
+
|
|
397
|
+
|
|
398
|
+
def _vary(
|
|
399
|
+
type_: types.TypeEngine,
|
|
400
|
+
variant_map: _TypeMap,
|
|
401
|
+
overrides: _TypeMap,
|
|
402
|
+
*args: Any,
|
|
403
|
+
) -> types.TypeEngine:
|
|
404
|
+
"""Add datatype variants and overrides to a SQLAlchemy type.
|
|
405
|
+
|
|
406
|
+
Parameters
|
|
407
|
+
----------
|
|
408
|
+
type_
|
|
409
|
+
The base SQLAlchemy type object. This is essentially a default
|
|
410
|
+
SQLAlchemy ``TypeEngine`` object, which will apply if there is no
|
|
411
|
+
variant or type override from the schema.
|
|
412
|
+
variant_map
|
|
413
|
+
The dictionary of dialects to types. Each key is a string representing
|
|
414
|
+
a dialect name, and each value is either an instance of
|
|
415
|
+
``TypeEngine`` representing the variant type object or a callable
|
|
416
|
+
reference to its class type that will be instantiated later.
|
|
417
|
+
overrides
|
|
418
|
+
The dictionary of dialects to types to override the defaults. Each key
|
|
419
|
+
is a string representing a dialect name and type with a similar
|
|
420
|
+
structure as the `variant_map`.
|
|
421
|
+
args
|
|
422
|
+
The extra arguments to pass to the type object.
|
|
423
|
+
|
|
424
|
+
Notes
|
|
425
|
+
-----
|
|
426
|
+
This function is intended for internal use only. It builds a SQLAlchemy
|
|
427
|
+
``TypeEngine`` that includes variants and overrides defined by Felis.
|
|
428
|
+
"""
|
|
429
|
+
variants: dict[str, types.TypeEngine | type[types.TypeEngine]] = dict(variant_map)
|
|
430
|
+
variants.update(overrides)
|
|
431
|
+
for dialect, variant in variants.items():
|
|
432
|
+
# If this is a class and not an instance, instantiate
|
|
433
|
+
if callable(variant):
|
|
434
|
+
variant = variant(*args)
|
|
435
|
+
type_ = type_.with_variant(variant, dialect)
|
|
436
|
+
return type_
|