lsst-felis 27.2024.3100__tar.gz → 27.2024.3200__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.

Files changed (34) hide show
  1. {lsst_felis-27.2024.3100/python/lsst_felis.egg-info → lsst_felis-27.2024.3200}/PKG-INFO +1 -1
  2. {lsst_felis-27.2024.3100 → lsst_felis-27.2024.3200}/python/felis/cli.py +8 -4
  3. {lsst_felis-27.2024.3100 → lsst_felis-27.2024.3200}/python/felis/metadata.py +12 -2
  4. lsst_felis-27.2024.3200/python/felis/version.py +2 -0
  5. {lsst_felis-27.2024.3100 → lsst_felis-27.2024.3200/python/lsst_felis.egg-info}/PKG-INFO +1 -1
  6. {lsst_felis-27.2024.3100 → lsst_felis-27.2024.3200}/tests/test_cli.py +19 -0
  7. {lsst_felis-27.2024.3100 → lsst_felis-27.2024.3200}/tests/test_metadata.py +35 -7
  8. lsst_felis-27.2024.3100/python/felis/version.py +0 -2
  9. {lsst_felis-27.2024.3100 → lsst_felis-27.2024.3200}/COPYRIGHT +0 -0
  10. {lsst_felis-27.2024.3100 → lsst_felis-27.2024.3200}/LICENSE +0 -0
  11. {lsst_felis-27.2024.3100 → lsst_felis-27.2024.3200}/README.rst +0 -0
  12. {lsst_felis-27.2024.3100 → lsst_felis-27.2024.3200}/pyproject.toml +0 -0
  13. {lsst_felis-27.2024.3100 → lsst_felis-27.2024.3200}/python/felis/__init__.py +0 -0
  14. {lsst_felis-27.2024.3100 → lsst_felis-27.2024.3200}/python/felis/datamodel.py +0 -0
  15. {lsst_felis-27.2024.3100 → lsst_felis-27.2024.3200}/python/felis/db/__init__.py +0 -0
  16. {lsst_felis-27.2024.3100 → lsst_felis-27.2024.3200}/python/felis/db/dialects.py +0 -0
  17. {lsst_felis-27.2024.3100 → lsst_felis-27.2024.3200}/python/felis/db/sqltypes.py +0 -0
  18. {lsst_felis-27.2024.3100 → lsst_felis-27.2024.3200}/python/felis/db/utils.py +0 -0
  19. {lsst_felis-27.2024.3100 → lsst_felis-27.2024.3200}/python/felis/db/variants.py +0 -0
  20. {lsst_felis-27.2024.3100 → lsst_felis-27.2024.3200}/python/felis/py.typed +0 -0
  21. {lsst_felis-27.2024.3100 → lsst_felis-27.2024.3200}/python/felis/tap.py +0 -0
  22. {lsst_felis-27.2024.3100 → lsst_felis-27.2024.3200}/python/felis/tests/__init__.py +0 -0
  23. {lsst_felis-27.2024.3100 → lsst_felis-27.2024.3200}/python/felis/tests/postgresql.py +0 -0
  24. {lsst_felis-27.2024.3100 → lsst_felis-27.2024.3200}/python/felis/types.py +0 -0
  25. {lsst_felis-27.2024.3100 → lsst_felis-27.2024.3200}/python/lsst_felis.egg-info/SOURCES.txt +0 -0
  26. {lsst_felis-27.2024.3100 → lsst_felis-27.2024.3200}/python/lsst_felis.egg-info/dependency_links.txt +0 -0
  27. {lsst_felis-27.2024.3100 → lsst_felis-27.2024.3200}/python/lsst_felis.egg-info/entry_points.txt +0 -0
  28. {lsst_felis-27.2024.3100 → lsst_felis-27.2024.3200}/python/lsst_felis.egg-info/requires.txt +0 -0
  29. {lsst_felis-27.2024.3100 → lsst_felis-27.2024.3200}/python/lsst_felis.egg-info/top_level.txt +0 -0
  30. {lsst_felis-27.2024.3100 → lsst_felis-27.2024.3200}/python/lsst_felis.egg-info/zip-safe +0 -0
  31. {lsst_felis-27.2024.3100 → lsst_felis-27.2024.3200}/setup.cfg +0 -0
  32. {lsst_felis-27.2024.3100 → lsst_felis-27.2024.3200}/tests/test_datamodel.py +0 -0
  33. {lsst_felis-27.2024.3100 → lsst_felis-27.2024.3200}/tests/test_postgresql.py +0 -0
  34. {lsst_felis-27.2024.3100 → lsst_felis-27.2024.3200}/tests/test_tap.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lsst-felis
3
- Version: 27.2024.3100
3
+ Version: 27.2024.3200
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+)
@@ -71,7 +71,7 @@ def cli(log_level: str, log_file: str | None) -> None:
71
71
 
72
72
 
73
73
  @cli.command("create", help="Create database objects from the Felis file")
74
- @click.option("--engine-url", envvar="ENGINE_URL", help="SQLAlchemy Engine URL", default="sqlite://")
74
+ @click.option("--engine-url", envvar="FELIS_ENGINE_URL", help="SQLAlchemy Engine URL", default="sqlite://")
75
75
  @click.option("--schema-name", help="Alternate schema name to override Felis file")
76
76
  @click.option(
77
77
  "--initialize",
@@ -86,6 +86,7 @@ def cli(log_level: str, log_file: str | None) -> None:
86
86
  @click.option(
87
87
  "--output-file", "-o", type=click.File(mode="w"), help="Write SQL commands to a file instead of executing"
88
88
  )
89
+ @click.option("--ignore-constraints", is_flag=True, help="Ignore constraints when creating tables")
89
90
  @click.argument("file", type=click.File())
90
91
  def create(
91
92
  engine_url: str,
@@ -95,6 +96,7 @@ def create(
95
96
  echo: bool,
96
97
  dry_run: bool,
97
98
  output_file: IO[str] | None,
99
+ ignore_constraints: bool,
98
100
  file: IO,
99
101
  ) -> None:
100
102
  """Create database objects from the Felis file.
@@ -115,6 +117,8 @@ def create(
115
117
  Dry run only to print out commands instead of executing.
116
118
  output_file
117
119
  Write SQL commands to a file instead of executing.
120
+ ignore_constraints
121
+ Ignore constraints when creating tables.
118
122
  file
119
123
  Felis file to read.
120
124
  """
@@ -132,7 +136,7 @@ def create(
132
136
  dry_run = True
133
137
  logger.info("Forcing dry run for non-sqlite engine URL with no host")
134
138
 
135
- metadata = MetaDataBuilder(schema).build()
139
+ metadata = MetaDataBuilder(schema, ignore_constraints=ignore_constraints).build()
136
140
  logger.debug(f"Created metadata with schema name: {metadata.schema}")
137
141
 
138
142
  engine: Engine | MockConnection
@@ -208,7 +212,7 @@ def init_tap(
208
212
  tables are created in the database schema specified by the engine URL,
209
213
  which must be a PostgreSQL schema or MySQL database that already exists.
210
214
  """
211
- engine = create_engine(engine_url, echo=True)
215
+ engine = create_engine(engine_url)
212
216
  init_tables(
213
217
  tap_schema_name,
214
218
  tap_schemas_table,
@@ -221,7 +225,7 @@ def init_tap(
221
225
 
222
226
 
223
227
  @cli.command("load-tap", help="Load metadata from a Felis file into a TAP_SCHEMA database")
224
- @click.option("--engine-url", envvar="ENGINE_URL", help="SQLAlchemy Engine URL to catalog")
228
+ @click.option("--engine-url", envvar="FELIS_ENGINE_URL", help="SQLAlchemy Engine URL")
225
229
  @click.option("--schema-name", help="Alternate Schema Name for Felis file")
226
230
  @click.option("--catalog-name", help="Catalog Name for Schema")
227
231
  @click.option("--dry-run", is_flag=True, help="Dry Run Only. Prints out the DDL that would be executed")
@@ -127,10 +127,16 @@ class MetaDataBuilder:
127
127
  Whether to apply the schema name to the metadata object.
128
128
  apply_schema_to_tables
129
129
  Whether to apply the schema name to the tables.
130
+ ignore_constraints
131
+ Whether to ignore constraints when building the metadata.
130
132
  """
131
133
 
132
134
  def __init__(
133
- self, schema: Schema, apply_schema_to_metadata: bool = True, apply_schema_to_tables: bool = True
135
+ self,
136
+ schema: Schema,
137
+ apply_schema_to_metadata: bool = True,
138
+ apply_schema_to_tables: bool = True,
139
+ ignore_constraints: bool = False,
134
140
  ) -> None:
135
141
  """Initialize the metadata builder."""
136
142
  self.schema = schema
@@ -141,6 +147,7 @@ class MetaDataBuilder:
141
147
  self.metadata = MetaData(schema=schema.name if apply_schema_to_metadata else None)
142
148
  self._objects: dict[str, Any] = {}
143
149
  self.apply_schema_to_tables = apply_schema_to_tables
150
+ self.ignore_constraints = ignore_constraints
144
151
 
145
152
  def build(self) -> MetaData:
146
153
  """Build the SQLAlchemy tables and constraints from the schema.
@@ -157,7 +164,10 @@ class MetaDataBuilder:
157
164
  The SQLAlchemy metadata object.
158
165
  """
159
166
  self.build_tables()
160
- self.build_constraints()
167
+ if not self.ignore_constraints:
168
+ self.build_constraints()
169
+ else:
170
+ logger.warning("Ignoring constraints")
161
171
  return self.metadata
162
172
 
163
173
  def build_tables(self) -> None:
@@ -0,0 +1,2 @@
1
+ __all__ = ["__version__"]
2
+ __version__ = "27.2024.3200"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lsst-felis
3
- Version: 27.2024.3100
3
+ Version: 27.2024.3200
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+)
@@ -69,6 +69,25 @@ class CliTestCase(unittest.TestCase):
69
69
  )
70
70
  self.assertEqual(result.exit_code, 0)
71
71
 
72
+ def test_ignore_constraints(self) -> None:
73
+ """Test ``--ignore-constraints`` flag of ``create`` command."""
74
+ url = f"sqlite:///{self.tmpdir}/tap.sqlite3"
75
+
76
+ runner = CliRunner()
77
+ result = runner.invoke(
78
+ cli,
79
+ [
80
+ "create",
81
+ "--schema-name=main",
82
+ "--ignore-constraints",
83
+ f"--engine-url={url}",
84
+ "--dry-run",
85
+ TEST_YAML,
86
+ ],
87
+ catch_exceptions=False,
88
+ )
89
+ self.assertEqual(result.exit_code, 0)
90
+
72
91
  def test_init_tap(self) -> None:
73
92
  """Test for ``init-tap`` command."""
74
93
  url = f"sqlite:///{self.tmpdir}/tap.sqlite3"
@@ -25,6 +25,7 @@ import unittest
25
25
  import yaml
26
26
  from sqlalchemy import (
27
27
  CheckConstraint,
28
+ Connection,
28
29
  Constraint,
29
30
  ForeignKeyConstraint,
30
31
  Index,
@@ -52,11 +53,11 @@ class MetaDataTestCase(unittest.TestCase):
52
53
  with open(TEST_YAML) as data:
53
54
  self.yaml_data = yaml.safe_load(data)
54
55
 
55
- def connection(self):
56
+ def connection(self) -> Connection:
56
57
  """Return a connection to the database."""
57
58
  return self.engine.connect()
58
59
 
59
- def test_create_all(self):
60
+ def test_create_all(self) -> None:
60
61
  """Create all tables in the schema using the metadata object and a
61
62
  SQLite connection.
62
63
 
@@ -113,16 +114,25 @@ class MetaDataTestCase(unittest.TestCase):
113
114
  self.assertEqual(md_constraint.name, md_db_constraint.name)
114
115
  self.assertEqual(md_constraint.deferrable, md_db_constraint.deferrable)
115
116
  self.assertEqual(md_constraint.initially, md_db_constraint.initially)
116
- if isinstance(md_constraint, ForeignKeyConstraint):
117
+ self.assertEqual(
118
+ type(md_constraint), type(md_db_constraint), "Constraint types do not match"
119
+ )
120
+ if isinstance(md_constraint, ForeignKeyConstraint) and isinstance(
121
+ md_db_constraint, ForeignKeyConstraint
122
+ ):
117
123
  md_fk: ForeignKeyConstraint = md_constraint
118
124
  md_db_fk: ForeignKeyConstraint = md_db_constraint
119
125
  self.assertEqual(md_fk.referred_table.name, md_db_fk.referred_table.name)
120
126
  self.assertEqual(md_fk.column_keys, md_db_fk.column_keys)
121
- elif isinstance(md_constraint, UniqueConstraint):
127
+ elif isinstance(md_constraint, UniqueConstraint) and isinstance(
128
+ md_db_constraint, UniqueConstraint
129
+ ):
122
130
  md_uniq: UniqueConstraint = md_constraint
123
131
  md_db_uniq: UniqueConstraint = md_db_constraint
124
132
  self.assertEqual(md_uniq.columns.keys(), md_db_uniq.columns.keys())
125
- elif isinstance(md_constraint, CheckConstraint):
133
+ elif isinstance(md_constraint, CheckConstraint) and isinstance(
134
+ md_db_constraint, CheckConstraint
135
+ ):
126
136
  md_check: CheckConstraint = md_constraint
127
137
  md_db_check: CheckConstraint = md_db_constraint
128
138
  self.assertEqual(str(md_check.sqltext), str(md_db_check.sqltext))
@@ -139,7 +149,7 @@ class MetaDataTestCase(unittest.TestCase):
139
149
  self.assertEqual(md_index.name, md_db_index.name)
140
150
  self.assertEqual(md_index.columns.keys(), md_db_index.columns.keys())
141
151
 
142
- def test_builder(self):
152
+ def test_builder(self) -> None:
143
153
  """Test that the information in the metadata object created by the
144
154
  builder matches the data in the Felis schema used to create it.
145
155
  """
@@ -188,7 +198,7 @@ class MetaDataTestCase(unittest.TestCase):
188
198
  for primary_key in primary_keys:
189
199
  self.assertTrue(md_table.columns[primary_key].primary_key)
190
200
 
191
- def test_timestamp(self):
201
+ def test_timestamp(self) -> None:
192
202
  """Test that the `timestamp` datatype is created correctly."""
193
203
  for precision in [None, 6]:
194
204
  col = dm.Column(
@@ -210,6 +220,24 @@ class MetaDataTestCase(unittest.TestCase):
210
220
  self.assertEqual(mysql_timestamp.timezone, False)
211
221
  self.assertEqual(mysql_timestamp.fsp, precision)
212
222
 
223
+ def test_ignore_constraints(self) -> None:
224
+ """Test that constraints are not created when the
225
+ ``ignore_constraints`` flag is set on the metadata builder.
226
+ """
227
+ schema = Schema.model_validate(self.yaml_data)
228
+ schema.name = "main"
229
+ builder = MetaDataBuilder(schema, ignore_constraints=True)
230
+ md = builder.build()
231
+ for table in md.tables.values():
232
+ non_primary_key_constraints = [
233
+ c for c in table.constraints if not isinstance(c, PrimaryKeyConstraint)
234
+ ]
235
+ self.assertEqual(
236
+ len(non_primary_key_constraints),
237
+ 0,
238
+ msg=f"Table {table.name} has non-primary key constraints defined",
239
+ )
240
+
213
241
 
214
242
  if __name__ == "__main__":
215
243
  unittest.main()
@@ -1,2 +0,0 @@
1
- __all__ = ["__version__"]
2
- __version__ = "27.2024.3100"