lsst-felis 27.2024.2500__tar.gz → 27.2024.2600__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.
Potentially problematic release.
This version of lsst-felis might be problematic. Click here for more details.
- {lsst_felis-27.2024.2500 → lsst_felis-27.2024.2600}/COPYRIGHT +1 -1
- {lsst_felis-27.2024.2500/python/lsst_felis.egg-info → lsst_felis-27.2024.2600}/PKG-INFO +4 -2
- {lsst_felis-27.2024.2500 → lsst_felis-27.2024.2600}/pyproject.toml +38 -2
- {lsst_felis-27.2024.2500 → lsst_felis-27.2024.2600}/python/felis/cli.py +145 -29
- {lsst_felis-27.2024.2500 → lsst_felis-27.2024.2600}/python/felis/datamodel.py +334 -89
- lsst_felis-27.2024.2600/python/felis/db/dialects.py +116 -0
- lsst_felis-27.2024.2600/python/felis/db/sqltypes.py +443 -0
- {lsst_felis-27.2024.2500 → lsst_felis-27.2024.2600}/python/felis/db/utils.py +108 -52
- {lsst_felis-27.2024.2500 → lsst_felis-27.2024.2600}/python/felis/db/variants.py +66 -8
- {lsst_felis-27.2024.2500 → lsst_felis-27.2024.2600}/python/felis/metadata.py +70 -54
- {lsst_felis-27.2024.2500 → lsst_felis-27.2024.2600}/python/felis/tap.py +180 -18
- {lsst_felis-27.2024.2500 → lsst_felis-27.2024.2600}/python/felis/types.py +56 -8
- lsst_felis-27.2024.2600/python/felis/version.py +2 -0
- {lsst_felis-27.2024.2500 → lsst_felis-27.2024.2600/python/lsst_felis.egg-info}/PKG-INFO +4 -2
- {lsst_felis-27.2024.2500 → lsst_felis-27.2024.2600}/python/lsst_felis.egg-info/SOURCES.txt +0 -1
- {lsst_felis-27.2024.2500 → lsst_felis-27.2024.2600}/python/lsst_felis.egg-info/requires.txt +3 -1
- {lsst_felis-27.2024.2500 → lsst_felis-27.2024.2600}/tests/test_cli.py +7 -5
- {lsst_felis-27.2024.2500 → lsst_felis-27.2024.2600}/tests/test_datamodel.py +141 -61
- {lsst_felis-27.2024.2500 → lsst_felis-27.2024.2600}/tests/test_metadata.py +5 -6
- {lsst_felis-27.2024.2500 → lsst_felis-27.2024.2600}/tests/test_tap.py +4 -3
- lsst_felis-27.2024.2500/python/felis/db/dialects.py +0 -63
- lsst_felis-27.2024.2500/python/felis/db/sqltypes.py +0 -204
- lsst_felis-27.2024.2500/python/felis/version.py +0 -2
- lsst_felis-27.2024.2500/tests/test_datatypes.py +0 -116
- {lsst_felis-27.2024.2500 → lsst_felis-27.2024.2600}/LICENSE +0 -0
- {lsst_felis-27.2024.2500 → lsst_felis-27.2024.2600}/README.rst +0 -0
- {lsst_felis-27.2024.2500 → lsst_felis-27.2024.2600}/python/felis/__init__.py +0 -0
- {lsst_felis-27.2024.2500 → lsst_felis-27.2024.2600}/python/felis/db/__init__.py +0 -0
- {lsst_felis-27.2024.2500 → lsst_felis-27.2024.2600}/python/felis/py.typed +0 -0
- {lsst_felis-27.2024.2500 → lsst_felis-27.2024.2600}/python/lsst_felis.egg-info/dependency_links.txt +0 -0
- {lsst_felis-27.2024.2500 → lsst_felis-27.2024.2600}/python/lsst_felis.egg-info/entry_points.txt +0 -0
- {lsst_felis-27.2024.2500 → lsst_felis-27.2024.2600}/python/lsst_felis.egg-info/top_level.txt +0 -0
- {lsst_felis-27.2024.2500 → lsst_felis-27.2024.2600}/python/lsst_felis.egg-info/zip-safe +0 -0
- {lsst_felis-27.2024.2500 → lsst_felis-27.2024.2600}/setup.cfg +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
Copyright
|
|
1
|
+
Copyright 2018-2024 The Board of Trustees of the Leland Stanford Junior University, through SLAC National Accelerator Laboratory
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: lsst-felis
|
|
3
|
-
Version: 27.2024.
|
|
3
|
+
Version: 27.2024.2600
|
|
4
4
|
Summary: A vocabulary for describing catalogs and acting on those descriptions
|
|
5
5
|
Author-email: Rubin Observatory Data Management <dm-admin@lists.lsst.org>
|
|
6
6
|
License: GNU General Public License v3 or later (GPLv3+)
|
|
@@ -27,4 +27,6 @@ Requires-Dist: lsst-utils
|
|
|
27
27
|
Provides-Extra: test
|
|
28
28
|
Requires-Dist: pytest>=3.2; extra == "test"
|
|
29
29
|
Provides-Extra: dev
|
|
30
|
-
Requires-Dist: documenteer[guide]; extra == "dev"
|
|
30
|
+
Requires-Dist: documenteer[guide]<2; extra == "dev"
|
|
31
|
+
Requires-Dist: autodoc_pydantic; extra == "dev"
|
|
32
|
+
Requires-Dist: sphinx-click; extra == "dev"
|
|
@@ -40,7 +40,9 @@ test = [
|
|
|
40
40
|
"pytest >= 3.2"
|
|
41
41
|
]
|
|
42
42
|
dev = [
|
|
43
|
-
"documenteer[guide]"
|
|
43
|
+
"documenteer[guide] < 2",
|
|
44
|
+
"autodoc_pydantic",
|
|
45
|
+
"sphinx-click",
|
|
44
46
|
]
|
|
45
47
|
|
|
46
48
|
[tool.pytest.ini_options]
|
|
@@ -61,7 +63,6 @@ version = { attr = "lsst_versions.get_lsst_version" }
|
|
|
61
63
|
[project.scripts]
|
|
62
64
|
felis = "felis.cli:cli"
|
|
63
65
|
|
|
64
|
-
|
|
65
66
|
[tool.towncrier]
|
|
66
67
|
package = "felis"
|
|
67
68
|
package_dir = "python"
|
|
@@ -152,6 +153,41 @@ select = [
|
|
|
152
153
|
"UP", # pyupgrade
|
|
153
154
|
]
|
|
154
155
|
|
|
156
|
+
[tool.pydocstyle]
|
|
157
|
+
convention = "numpy"
|
|
158
|
+
# Our coding style does not require docstrings for magic methods (D105)
|
|
159
|
+
# Our docstyle documents __init__ at the class level (D107)
|
|
160
|
+
# We allow methods to inherit docstrings and this is not compatible with D102.
|
|
161
|
+
# Docstring at the very first line is not required
|
|
162
|
+
# D200, D205 and D400 all complain if the first sentence of the docstring does
|
|
163
|
+
# not fit on one line. We do not require docstrings in __init__ files (D104).
|
|
164
|
+
add-ignore = ["D107", "D105", "D102", "D100", "D200", "D205", "D400", "D104"]
|
|
165
|
+
|
|
166
|
+
[tool.ruff.lint.pycodestyle]
|
|
167
|
+
max-doc-length = 79
|
|
168
|
+
|
|
169
|
+
[tool.ruff.lint.pydocstyle]
|
|
170
|
+
convention = "numpy"
|
|
171
|
+
|
|
172
|
+
[tool.numpydoc_validation]
|
|
173
|
+
checks = [
|
|
174
|
+
"all", # All except the rules listed below.
|
|
175
|
+
"SA01", # See Also section.
|
|
176
|
+
"SA04", # We don't use descriptions with See Also.
|
|
177
|
+
"EX01", # Example section.
|
|
178
|
+
"SS06", # Summary can go into second line.
|
|
179
|
+
"GL01", # Summary text can start on same line as """
|
|
180
|
+
"GL08", # Do not require docstring.
|
|
181
|
+
"ES01", # No extended summary required.
|
|
182
|
+
"SS05", # pydocstyle is better at finding infinitive verb.
|
|
183
|
+
"PR04", # Sphinx does not require parameter type.
|
|
184
|
+
]
|
|
185
|
+
exclude = [
|
|
186
|
+
"^test_.*", # Do not test docstrings in test code.
|
|
187
|
+
'^__init__$',
|
|
188
|
+
'\._[a-zA-Z_]+$', # Private methods.
|
|
189
|
+
]
|
|
190
|
+
|
|
155
191
|
[tool.pydeps]
|
|
156
192
|
max_bacon = 2
|
|
157
193
|
no_show = true
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
"""Click command line interface."""
|
|
2
|
+
|
|
1
3
|
# This file is part of felis.
|
|
2
4
|
#
|
|
3
5
|
# Developed for the LSST Data Management System.
|
|
@@ -38,6 +40,8 @@ from .db.utils import DatabaseContext
|
|
|
38
40
|
from .metadata import MetaDataBuilder
|
|
39
41
|
from .tap import Tap11Base, TapLoadingVisitor, init_tables
|
|
40
42
|
|
|
43
|
+
__all__ = ["cli"]
|
|
44
|
+
|
|
41
45
|
logger = logging.getLogger("felis")
|
|
42
46
|
|
|
43
47
|
loglevel_choices = ["CRITICAL", "FATAL", "ERROR", "WARNING", "INFO", "DEBUG"]
|
|
@@ -59,14 +63,14 @@ loglevel_choices = ["CRITICAL", "FATAL", "ERROR", "WARNING", "INFO", "DEBUG"]
|
|
|
59
63
|
help="Felis log file path",
|
|
60
64
|
)
|
|
61
65
|
def cli(log_level: str, log_file: str | None) -> None:
|
|
62
|
-
"""Felis
|
|
66
|
+
"""Felis command line tools"""
|
|
63
67
|
if log_file:
|
|
64
68
|
logging.basicConfig(filename=log_file, level=log_level)
|
|
65
69
|
else:
|
|
66
70
|
logging.basicConfig(level=log_level)
|
|
67
71
|
|
|
68
72
|
|
|
69
|
-
@cli.command("create")
|
|
73
|
+
@cli.command("create", help="Create database objects from the Felis file")
|
|
70
74
|
@click.option("--engine-url", envvar="ENGINE_URL", help="SQLAlchemy Engine URL", default="sqlite://")
|
|
71
75
|
@click.option("--schema-name", help="Alternate schema name to override Felis file")
|
|
72
76
|
@click.option(
|
|
@@ -89,7 +93,34 @@ def create(
|
|
|
89
93
|
output_file: IO[str] | None,
|
|
90
94
|
file: IO,
|
|
91
95
|
) -> None:
|
|
92
|
-
"""Create database objects from the Felis file.
|
|
96
|
+
"""Create database objects from the Felis file.
|
|
97
|
+
|
|
98
|
+
Parameters
|
|
99
|
+
----------
|
|
100
|
+
engine_url
|
|
101
|
+
SQLAlchemy Engine URL.
|
|
102
|
+
schema_name
|
|
103
|
+
Alternate schema name to override Felis file.
|
|
104
|
+
create_if_not_exists
|
|
105
|
+
Create the schema in the database if it does not exist.
|
|
106
|
+
drop_if_exists
|
|
107
|
+
Drop schema if it already exists in the database.
|
|
108
|
+
echo
|
|
109
|
+
Echo database commands as they are executed.
|
|
110
|
+
dry_run
|
|
111
|
+
Dry run only to print out commands instead of executing.
|
|
112
|
+
output_file
|
|
113
|
+
Write SQL commands to a file instead of executing.
|
|
114
|
+
file
|
|
115
|
+
Felis file to read.
|
|
116
|
+
|
|
117
|
+
Notes
|
|
118
|
+
-----
|
|
119
|
+
This command creates database objects from the Felis file. The
|
|
120
|
+
``--create-if-not-exists`` or ``--drop-if-exists`` flags can be used to
|
|
121
|
+
create a new MySQL database or PostgreSQL schema if it does not exist
|
|
122
|
+
already.
|
|
123
|
+
"""
|
|
93
124
|
yaml_data = yaml.safe_load(file)
|
|
94
125
|
schema = Schema.model_validate(yaml_data)
|
|
95
126
|
url = make_url(engine_url)
|
|
@@ -130,13 +161,13 @@ def create(
|
|
|
130
161
|
context.create_all()
|
|
131
162
|
|
|
132
163
|
|
|
133
|
-
@cli.command("init-tap")
|
|
134
|
-
@click.option("--tap-schema-name", help="
|
|
135
|
-
@click.option("--tap-schemas-table", help="
|
|
136
|
-
@click.option("--tap-tables-table", help="
|
|
137
|
-
@click.option("--tap-columns-table", help="
|
|
138
|
-
@click.option("--tap-keys-table", help="
|
|
139
|
-
@click.option("--tap-key-columns-table", help="
|
|
164
|
+
@cli.command("init-tap", help="Initialize TAP_SCHEMA objects in the database")
|
|
165
|
+
@click.option("--tap-schema-name", help="Alternate database schema name for 'TAP_SCHEMA'")
|
|
166
|
+
@click.option("--tap-schemas-table", help="Alternate table name for 'schemas'")
|
|
167
|
+
@click.option("--tap-tables-table", help="Alternate table name for 'tables'")
|
|
168
|
+
@click.option("--tap-columns-table", help="Alternate table name for 'columns'")
|
|
169
|
+
@click.option("--tap-keys-table", help="Alternate table name for 'keys'")
|
|
170
|
+
@click.option("--tap-key-columns-table", help="Alternate table name for 'key_columns'")
|
|
140
171
|
@click.argument("engine-url")
|
|
141
172
|
def init_tap(
|
|
142
173
|
engine_url: str,
|
|
@@ -147,10 +178,31 @@ def init_tap(
|
|
|
147
178
|
tap_keys_table: str,
|
|
148
179
|
tap_key_columns_table: str,
|
|
149
180
|
) -> None:
|
|
150
|
-
"""Initialize
|
|
181
|
+
"""Initialize TAP_SCHEMA objects in the database.
|
|
182
|
+
|
|
183
|
+
Parameters
|
|
184
|
+
----------
|
|
185
|
+
engine_url
|
|
186
|
+
SQLAlchemy Engine URL. The target PostgreSQL schema or MySQL database
|
|
187
|
+
must already exist and be referenced in the URL.
|
|
188
|
+
tap_schema_name
|
|
189
|
+
Alterate name for the database schema ``TAP_SCHEMA``.
|
|
190
|
+
tap_schemas_table
|
|
191
|
+
Alterate table name for ``schemas``.
|
|
192
|
+
tap_tables_table
|
|
193
|
+
Alterate table name for ``tables``.
|
|
194
|
+
tap_columns_table
|
|
195
|
+
Alterate table name for ``columns``.
|
|
196
|
+
tap_keys_table
|
|
197
|
+
Alterate table name for ``keys``.
|
|
198
|
+
tap_key_columns_table
|
|
199
|
+
Alterate table name for ``key_columns``.
|
|
151
200
|
|
|
152
|
-
|
|
153
|
-
|
|
201
|
+
Notes
|
|
202
|
+
-----
|
|
203
|
+
The supported version of TAP_SCHEMA in the SQLAlchemy metadata is 1.1. The
|
|
204
|
+
tables are created in the database schema specified by the engine URL,
|
|
205
|
+
which must be a PostgreSQL schema or MySQL database that already exists.
|
|
154
206
|
"""
|
|
155
207
|
engine = create_engine(engine_url, echo=True)
|
|
156
208
|
init_tables(
|
|
@@ -164,19 +216,19 @@ def init_tap(
|
|
|
164
216
|
Tap11Base.metadata.create_all(engine)
|
|
165
217
|
|
|
166
218
|
|
|
167
|
-
@cli.command("load-tap")
|
|
219
|
+
@cli.command("load-tap", help="Load metadata from a Felis file into a TAP_SCHEMA database")
|
|
168
220
|
@click.option("--engine-url", envvar="ENGINE_URL", help="SQLAlchemy Engine URL to catalog")
|
|
169
221
|
@click.option("--schema-name", help="Alternate Schema Name for Felis file")
|
|
170
222
|
@click.option("--catalog-name", help="Catalog Name for Schema")
|
|
171
223
|
@click.option("--dry-run", is_flag=True, help="Dry Run Only. Prints out the DDL that would be executed")
|
|
172
|
-
@click.option("--tap-schema-name", help="
|
|
173
|
-
@click.option("--tap-tables-postfix", help="Postfix for
|
|
174
|
-
@click.option("--tap-schemas-table", help="
|
|
175
|
-
@click.option("--tap-tables-table", help="
|
|
176
|
-
@click.option("--tap-columns-table", help="
|
|
177
|
-
@click.option("--tap-keys-table", help="
|
|
178
|
-
@click.option("--tap-key-columns-table", help="
|
|
179
|
-
@click.option("--tap-schema-index", type=int, help="TAP_SCHEMA index of the schema")
|
|
224
|
+
@click.option("--tap-schema-name", help="Alternate schema name for 'TAP_SCHEMA'")
|
|
225
|
+
@click.option("--tap-tables-postfix", help="Postfix for TAP_SCHEMA table names")
|
|
226
|
+
@click.option("--tap-schemas-table", help="Alternate table name for 'schemas'")
|
|
227
|
+
@click.option("--tap-tables-table", help="Alternate table name for 'tables'")
|
|
228
|
+
@click.option("--tap-columns-table", help="Alternate table name for 'columns'")
|
|
229
|
+
@click.option("--tap-keys-table", help="Alternate table name for 'keys'")
|
|
230
|
+
@click.option("--tap-key-columns-table", help="Alternate table name for 'key_columns'")
|
|
231
|
+
@click.option("--tap-schema-index", type=int, help="TAP_SCHEMA index of the schema in this environment")
|
|
180
232
|
@click.argument("file", type=click.File())
|
|
181
233
|
def load_tap(
|
|
182
234
|
engine_url: str,
|
|
@@ -193,10 +245,46 @@ def load_tap(
|
|
|
193
245
|
tap_schema_index: int,
|
|
194
246
|
file: io.TextIOBase,
|
|
195
247
|
) -> None:
|
|
196
|
-
"""Load TAP metadata from a Felis
|
|
248
|
+
"""Load TAP metadata from a Felis file.
|
|
249
|
+
|
|
250
|
+
This command loads the associated TAP metadata from a Felis YAML file
|
|
251
|
+
into the TAP_SCHEMA tables.
|
|
197
252
|
|
|
198
|
-
|
|
199
|
-
|
|
253
|
+
Parameters
|
|
254
|
+
----------
|
|
255
|
+
engine_url
|
|
256
|
+
SQLAlchemy Engine URL to catalog.
|
|
257
|
+
schema_name
|
|
258
|
+
Alternate schema name. This overrides the schema name in the
|
|
259
|
+
``catalog`` field of the Felis file.
|
|
260
|
+
catalog_name
|
|
261
|
+
Catalog name for the schema. This possibly duplicates the
|
|
262
|
+
``tap_schema_name`` argument (DM-44870).
|
|
263
|
+
dry_run
|
|
264
|
+
Dry run only to print out commands instead of executing.
|
|
265
|
+
tap_schema_name
|
|
266
|
+
Alternate name for the schema of TAP_SCHEMA in the database.
|
|
267
|
+
tap_tables_postfix
|
|
268
|
+
Postfix for TAP table names that will be automatically appended.
|
|
269
|
+
tap_schemas_table
|
|
270
|
+
Alternate table name for ``schemas``.
|
|
271
|
+
tap_tables_table
|
|
272
|
+
Alternate table name for ``tables``.
|
|
273
|
+
tap_columns_table
|
|
274
|
+
Alternate table name for ``columns``.
|
|
275
|
+
tap_keys_table
|
|
276
|
+
Alternate table name for ``keys``.
|
|
277
|
+
tap_key_columns_table
|
|
278
|
+
Alternate table name for ``key_columns``.
|
|
279
|
+
tap_schema_index
|
|
280
|
+
TAP_SCHEMA index of the schema in this TAP environment.
|
|
281
|
+
file
|
|
282
|
+
Felis file to read.
|
|
283
|
+
|
|
284
|
+
Notes
|
|
285
|
+
-----
|
|
286
|
+
The data will be loaded into the TAP_SCHEMA from the engine URL. The
|
|
287
|
+
tables must have already been initialized or an error will occur.
|
|
200
288
|
"""
|
|
201
289
|
yaml_data = yaml.load(file, Loader=yaml.SafeLoader)
|
|
202
290
|
schema = Schema.model_validate(yaml_data)
|
|
@@ -239,10 +327,12 @@ def load_tap(
|
|
|
239
327
|
tap_visitor.visit_schema(schema)
|
|
240
328
|
|
|
241
329
|
|
|
242
|
-
@cli.command("validate")
|
|
243
|
-
@click.option(
|
|
330
|
+
@cli.command("validate", help="Validate one or more Felis YAML files")
|
|
331
|
+
@click.option(
|
|
332
|
+
"--check-description", is_flag=True, help="Check that all objects have a description", default=False
|
|
333
|
+
)
|
|
244
334
|
@click.option(
|
|
245
|
-
"--check-redundant-datatypes", is_flag=True, help="Check for redundant
|
|
335
|
+
"--check-redundant-datatypes", is_flag=True, help="Check for redundant datatype overrides", default=False
|
|
246
336
|
)
|
|
247
337
|
@click.option(
|
|
248
338
|
"--check-tap-table-indexes",
|
|
@@ -264,7 +354,33 @@ def validate(
|
|
|
264
354
|
check_tap_principal: bool,
|
|
265
355
|
files: Iterable[io.TextIOBase],
|
|
266
356
|
) -> None:
|
|
267
|
-
"""Validate one or more felis YAML files.
|
|
357
|
+
"""Validate one or more felis YAML files.
|
|
358
|
+
|
|
359
|
+
Parameters
|
|
360
|
+
----------
|
|
361
|
+
check_description
|
|
362
|
+
Check that all objects have a valid description.
|
|
363
|
+
check_redundant_datatypes
|
|
364
|
+
Check for redundant type overrides.
|
|
365
|
+
check_tap_table_indexes
|
|
366
|
+
Check that every table has a unique TAP table index.
|
|
367
|
+
check_tap_principal
|
|
368
|
+
Check that at least one column per table is flagged as TAP principal.
|
|
369
|
+
files
|
|
370
|
+
The Felis YAML files to validate.
|
|
371
|
+
|
|
372
|
+
Raises
|
|
373
|
+
------
|
|
374
|
+
click.exceptions.Exit
|
|
375
|
+
If any validation errors are found. The ``ValidationError`` which is
|
|
376
|
+
thrown when a schema fails to validate will be logged as an error
|
|
377
|
+
message.
|
|
378
|
+
|
|
379
|
+
Notes
|
|
380
|
+
-----
|
|
381
|
+
All of the ``check`` flags are turned off by default and represent
|
|
382
|
+
optional validations controlled by the Pydantic context.
|
|
383
|
+
"""
|
|
268
384
|
rc = 0
|
|
269
385
|
for file in files:
|
|
270
386
|
file_name = getattr(file, "name", None)
|