liminal-orm 3.0.1__tar.gz → 3.1.1__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.
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/PKG-INFO +1 -1
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/base/properties/base_field_properties.py +3 -3
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/cli/cli.py +18 -17
- {liminal_orm-3.0.1/liminal/migrate → liminal_orm-3.1.1/liminal/cli}/utils.py +25 -6
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/connection/benchling_connection.py +16 -6
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/dropdowns/generate_files.py +2 -2
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/entity_schemas/generate_files.py +5 -5
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/entity_schemas/operations.py +20 -19
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/orm/base_model.py +1 -1
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/utils.py +10 -15
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/validation/__init__.py +3 -3
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/pyproject.toml +1 -1
- liminal_orm-3.0.1/liminal/.DS_Store +0 -0
- liminal_orm-3.0.1/liminal/base/__pycache__/__init__.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/base/__pycache__/base.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/base/__pycache__/base_dropdown.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/base/__pycache__/base_operation.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/base/__pycache__/base_validation_filters.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/base/__pycache__/benchling_base_model.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/base/__pycache__/benchling_column.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/base/__pycache__/benchling_dropdown.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/base/__pycache__/benchling_field_properties.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/base/__pycache__/benchling_schema_properties.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/base/__pycache__/callable_operation.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/base/__pycache__/column.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/base/__pycache__/compare_operation.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/base/__pycache__/field_properties.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/base/__pycache__/name_template_components.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/base/__pycache__/name_template_parts.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/base/__pycache__/schema_properties.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/base/__pycache__/str_enum.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/base/__pycache__/unset.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/base/__pycache__/user.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/base/properties/__pycache__/NoDropdown.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/base/properties/__pycache__/__init__.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/base/properties/__pycache__/base_field_properties.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/base/properties/__pycache__/base_name_template.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/base/properties/__pycache__/base_schema_properties.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/base/properties/__pycache__/field_properties.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/base/properties/__pycache__/schema_properties.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/cli/__pycache__/cli.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/cli/__pycache__/controller.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/cli/__pycache__/live_test_dropdown_migration.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/cli/__pycache__/live_test_entity_schema_migration.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/cli/__pycache__/utils.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/connection/__pycache__/__init__.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/connection/__pycache__/benchling_connection.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/connection/__pycache__/benchling_service.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/dropdowns/__pycache__/api.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/dropdowns/__pycache__/compare.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/dropdowns/__pycache__/generate_files.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/dropdowns/__pycache__/operations.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/dropdowns/__pycache__/utils.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/entity_schemas/__pycache__/api.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/entity_schemas/__pycache__/compare.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/entity_schemas/__pycache__/entity_schema_models.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/entity_schemas/__pycache__/generate_files.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/entity_schemas/__pycache__/operations.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/entity_schemas/__pycache__/schemas.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/entity_schemas/__pycache__/tag_schema_models.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/entity_schemas/__pycache__/utils.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/enums/__pycache__/__init__.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/enums/__pycache__/benchling_api_field_type.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/enums/__pycache__/benchling_dropdown.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/enums/__pycache__/benchling_entity_type.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/enums/__pycache__/benchling_enum.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/enums/__pycache__/benchling_field_api_type.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/enums/__pycache__/benchling_field_type.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/enums/__pycache__/benchling_folder_item_type.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/enums/__pycache__/benchling_naming_strategy.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/enums/__pycache__/benchling_report_level.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/enums/__pycache__/benchling_sequence_type.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/enums/__pycache__/name_template_part_type.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/enums/__pycache__/sequence_constraint.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/enums/__pycache__/sequence_constraints.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/enums/__pycache__/str_enum.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/enums/__pycache__/undefined.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/external/__pycache__/__init__.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/migrate/__pycache__/components.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/migrate/__pycache__/revision.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/migrate/__pycache__/revisions_timeline.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/migrate/__pycache__/utils.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/orm/__pycache__/__init__.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/orm/__pycache__/base.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/orm/__pycache__/base_model.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/orm/__pycache__/column.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/orm/__pycache__/mixins.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/orm/__pycache__/name_template.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/orm/__pycache__/name_template_parts.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/orm/__pycache__/relationship.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/orm/__pycache__/schema_properties.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/orm/__pycache__/user.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/orm/base_tables/__pycache__/__init__.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/orm/base_tables/__pycache__/registry_entity.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/orm/base_tables/__pycache__/schema.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/orm/base_tables/__pycache__/user.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/tests/.DS_Store +0 -0
- liminal_orm-3.0.1/liminal/tests/__pycache__/__init__.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/tests/__pycache__/conftest.cpython-310-pytest-8.3.3.pyc +0 -0
- liminal_orm-3.0.1/liminal/tests/__pycache__/test_dropdown_compare.cpython-310-pytest-8.3.3.pyc +0 -0
- liminal_orm-3.0.1/liminal/tests/__pycache__/test_entity_schema_compare.cpython-310-pytest-8.3.3.pyc +0 -0
- liminal_orm-3.0.1/liminal/unit_dictionary/__pycache__/utils.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/validation/__pycache__/__init__.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/validation/__pycache__/validation_report_level.cpython-310.pyc +0 -0
- liminal_orm-3.0.1/liminal/validation/__pycache__/validation_severity.cpython-310.pyc +0 -0
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/LICENSE.md +0 -0
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/README.md +0 -0
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/__init__.py +0 -0
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/base/base_dropdown.py +0 -0
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/base/base_operation.py +0 -0
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/base/base_validation_filters.py +0 -0
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/base/compare_operation.py +0 -0
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/base/name_template_parts.py +0 -0
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/base/properties/base_name_template.py +0 -0
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/base/properties/base_schema_properties.py +0 -0
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/base/str_enum.py +0 -0
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/cli/controller.py +0 -0
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/cli/live_test_dropdown_migration.py +0 -0
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/cli/live_test_entity_schema_migration.py +0 -0
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/connection/__init__.py +0 -0
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/connection/benchling_service.py +0 -0
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/dropdowns/api.py +0 -0
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/dropdowns/compare.py +0 -0
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/dropdowns/operations.py +0 -0
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/dropdowns/utils.py +0 -0
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/entity_schemas/api.py +0 -0
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/entity_schemas/compare.py +0 -0
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/entity_schemas/entity_schema_models.py +0 -0
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/entity_schemas/tag_schema_models.py +0 -0
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/entity_schemas/utils.py +0 -0
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/enums/__init__.py +0 -0
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/enums/benchling_api_field_type.py +0 -0
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/enums/benchling_entity_type.py +0 -0
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/enums/benchling_field_type.py +0 -0
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/enums/benchling_folder_item_type.py +0 -0
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/enums/benchling_naming_strategy.py +0 -0
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/enums/benchling_sequence_type.py +0 -0
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/enums/name_template_part_type.py +0 -0
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/enums/sequence_constraint.py +0 -0
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/external/__init__.py +0 -0
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/mappers.py +0 -0
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/migrate/components.py +0 -0
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/migrate/revision.py +0 -0
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/migrate/revisions_timeline.py +0 -0
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/orm/base.py +0 -0
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/orm/base_tables/registry_entity.py +0 -0
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/orm/base_tables/schema.py +0 -0
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/orm/base_tables/user.py +0 -0
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/orm/column.py +0 -0
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/orm/mixins.py +0 -0
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/orm/name_template.py +0 -0
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/orm/name_template_parts.py +0 -0
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/orm/relationship.py +0 -0
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/orm/schema_properties.py +0 -0
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/py.typed +0 -0
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/tests/__init__.py +0 -0
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/tests/conftest.py +0 -0
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/tests/from benchling_sdk.py +0 -0
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/tests/test_dropdown_compare.py +0 -0
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/tests/test_entity_schema_compare.py +0 -0
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/unit_dictionary/utils.py +0 -0
- {liminal_orm-3.0.1 → liminal_orm-3.1.1}/liminal/validation/validation_severity.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: liminal-orm
|
3
|
-
Version: 3.
|
3
|
+
Version: 3.1.1
|
4
4
|
Summary: An ORM and toolkit that builds on top of Benchling's platform to keep your schemas and downstream code dependencies in sync.
|
5
5
|
Home-page: https://github.com/dynotx/liminal-orm
|
6
6
|
Author: DynoTx Open Source
|
@@ -77,18 +77,18 @@ class BaseFieldProperties(BaseModel):
|
|
77
77
|
for s in BenchlingBaseModel.get_all_subclasses()
|
78
78
|
]:
|
79
79
|
raise ValueError(
|
80
|
-
f"
|
80
|
+
f"Field {wh_name}: could not find entity link {self.entity_link} as a warehouse name for any currently defined schemas."
|
81
81
|
)
|
82
82
|
if self.dropdown_link:
|
83
83
|
if self.dropdown_link not in [
|
84
84
|
d.__benchling_name__ for d in BaseDropdown.get_all_subclasses()
|
85
85
|
]:
|
86
86
|
raise ValueError(
|
87
|
-
f"
|
87
|
+
f"Field {wh_name}: could not find dropdown link {self.dropdown_link} as a name to any defined dropdowns."
|
88
88
|
)
|
89
89
|
if not is_valid_wh_name(wh_name):
|
90
90
|
raise ValueError(
|
91
|
-
f"
|
91
|
+
f"Field {wh_name}: invalid warehouse name '{wh_name}'. It should only contain alphanumeric characters and underscores."
|
92
92
|
)
|
93
93
|
return True
|
94
94
|
|
@@ -16,9 +16,9 @@ from liminal.cli.live_test_dropdown_migration import mock_dropdown_full_migratio
|
|
16
16
|
from liminal.cli.live_test_entity_schema_migration import (
|
17
17
|
mock_entity_schema_full_migration,
|
18
18
|
)
|
19
|
+
from liminal.cli.utils import read_local_liminal_dir, update_env_revision_id
|
19
20
|
from liminal.connection.benchling_service import BenchlingService
|
20
21
|
from liminal.migrate.revisions_timeline import RevisionsTimeline
|
21
|
-
from liminal.migrate.utils import read_local_env_file, update_env_revision_id
|
22
22
|
|
23
23
|
|
24
24
|
class OrderCommands(TyperGroup):
|
@@ -34,8 +34,9 @@ app = typer.Typer(
|
|
34
34
|
help="The Liminal CLI allows you to run revisions against different Benchling tenants and keep tenants in sync with dropdowns and schemas defined in code.",
|
35
35
|
)
|
36
36
|
|
37
|
-
|
38
|
-
|
37
|
+
LIMINAL_DIR_PATH = Path("liminal")
|
38
|
+
ENV_FILE_PATH = LIMINAL_DIR_PATH / "env.py"
|
39
|
+
VERSIONS_DIR_PATH = LIMINAL_DIR_PATH / "versions"
|
39
40
|
|
40
41
|
|
41
42
|
@app.command(
|
@@ -44,8 +45,8 @@ VERSIONS_DIR_PATH = Path("liminal/versions")
|
|
44
45
|
)
|
45
46
|
def init() -> None:
|
46
47
|
try:
|
47
|
-
|
48
|
-
|
48
|
+
LIMINAL_DIR_PATH.mkdir()
|
49
|
+
VERSIONS_DIR_PATH.mkdir()
|
49
50
|
except Exception:
|
50
51
|
raise Exception(
|
51
52
|
"Liminal CLI already initialized. liminal/ already exists. Please delete it before running init."
|
@@ -85,8 +86,8 @@ def generate_files(
|
|
85
86
|
help="The path to write the generated files to.",
|
86
87
|
),
|
87
88
|
) -> None:
|
88
|
-
current_revision_id, benchling_connection =
|
89
|
-
|
89
|
+
current_revision_id, benchling_connection = read_local_liminal_dir(
|
90
|
+
LIMINAL_DIR_PATH, benchling_tenant
|
90
91
|
)
|
91
92
|
benchling_service = BenchlingService(benchling_connection, use_internal_api=True)
|
92
93
|
if not write_path.exists():
|
@@ -104,8 +105,8 @@ def current(
|
|
104
105
|
..., help="Benchling tenant (or alias) to connect to."
|
105
106
|
),
|
106
107
|
) -> None:
|
107
|
-
current_revision_id, benchling_connection =
|
108
|
-
|
108
|
+
current_revision_id, benchling_connection = read_local_liminal_dir(
|
109
|
+
LIMINAL_DIR_PATH, benchling_tenant
|
109
110
|
)
|
110
111
|
print(
|
111
112
|
f"[blue]{benchling_connection.current_revision_id_var_name}: {current_revision_id}[/blue]"
|
@@ -125,8 +126,8 @@ def autogenerate(
|
|
125
126
|
help="A description of the revision being generated. This will also be included in the file name.",
|
126
127
|
),
|
127
128
|
) -> None:
|
128
|
-
current_revision_id, benchling_connection =
|
129
|
-
|
129
|
+
current_revision_id, benchling_connection = read_local_liminal_dir(
|
130
|
+
LIMINAL_DIR_PATH, benchling_tenant
|
130
131
|
)
|
131
132
|
benchling_service = BenchlingService(benchling_connection, use_internal_api=True)
|
132
133
|
autogenerate_revision_file(
|
@@ -148,8 +149,8 @@ def upgrade(
|
|
148
149
|
help="Determines the revision files that get run. Pass in the 'revision_id' to upgrade to that revision. Pass in 'head' to upgrade to the latest revision. Pass in '+n' to make a relative revision based on the current revision id.",
|
149
150
|
),
|
150
151
|
) -> None:
|
151
|
-
current_revision_id, benchling_connection =
|
152
|
-
|
152
|
+
current_revision_id, benchling_connection = read_local_liminal_dir(
|
153
|
+
LIMINAL_DIR_PATH, benchling_tenant
|
153
154
|
)
|
154
155
|
benchling_service = BenchlingService(benchling_connection, use_internal_api=True)
|
155
156
|
upgrade_revision_id = upgrade_benchling_tenant(
|
@@ -176,8 +177,8 @@ def downgrade(
|
|
176
177
|
help="Determines the revision files that get run. Pass in the 'revision_id' to downgrade to that revision. Pass in '-n' to make a relative revision based on the current revision id.",
|
177
178
|
),
|
178
179
|
) -> None:
|
179
|
-
current_revision_id, benchling_connection =
|
180
|
-
|
180
|
+
current_revision_id, benchling_connection = read_local_liminal_dir(
|
181
|
+
LIMINAL_DIR_PATH, benchling_tenant
|
181
182
|
)
|
182
183
|
benchling_service = BenchlingService(benchling_connection, use_internal_api=True)
|
183
184
|
downgrade_revision_id = downgrade_benchling_tenant(
|
@@ -216,8 +217,8 @@ def live_test(
|
|
216
217
|
raise ValueError(
|
217
218
|
"Only one of --entity-schema-migration or --dropdown-migration can be set."
|
218
219
|
)
|
219
|
-
current_revision_id, benchling_connection =
|
220
|
-
|
220
|
+
current_revision_id, benchling_connection = read_local_liminal_dir(
|
221
|
+
LIMINAL_DIR_PATH, benchling_tenant
|
221
222
|
)
|
222
223
|
benchling_service = BenchlingService(benchling_connection, use_internal_api=True)
|
223
224
|
if test_entity_schema_migration:
|
@@ -4,22 +4,41 @@ from pathlib import Path
|
|
4
4
|
from liminal.connection.benchling_connection import BenchlingConnection
|
5
5
|
|
6
6
|
|
7
|
-
def
|
8
|
-
"""Raises an exception if the
|
9
|
-
if not
|
7
|
+
def _check_liminal_directory_initialized(liminal_dir_path: Path) -> None:
|
8
|
+
"""Raises an exception if the liminal directory does not exist at the given path."""
|
9
|
+
if not liminal_dir_path.exists() or not liminal_dir_path.is_dir():
|
10
10
|
raise Exception(
|
11
|
-
|
11
|
+
"Liminal directory not found at current working directory. Run `liminal init` or check your current working directory."
|
12
12
|
)
|
13
|
+
else:
|
14
|
+
if not (liminal_dir_path / "env.py").exists():
|
15
|
+
raise Exception(
|
16
|
+
"No liminal/env.py file found. Run `liminal init` or check your current working directory for liminal/env.py."
|
17
|
+
)
|
18
|
+
|
19
|
+
|
20
|
+
def read_local_liminal_dir(
|
21
|
+
liminal_dir_path: Path, benchling_tenant: str
|
22
|
+
) -> tuple[str, BenchlingConnection]:
|
23
|
+
"""Imports the env.py file from /liminal/env.py and returns the CURRENT_REVISION_ID variable along with the BenchlingConnection object.
|
24
|
+
The env.py file is expected to have the CURRENT_REVISION_ID variable set to the revision id you are currently on.
|
25
|
+
The BenchlingConnection object is expected to be defined and have connection information for the Benchling API client and internal API.
|
26
|
+
"""
|
27
|
+
_check_liminal_directory_initialized(liminal_dir_path)
|
28
|
+
env_file_path = liminal_dir_path / "env.py"
|
29
|
+
current_revision_id, benchling_connection = _read_local_env_file(
|
30
|
+
env_file_path, benchling_tenant
|
31
|
+
)
|
32
|
+
return current_revision_id, benchling_connection
|
13
33
|
|
14
34
|
|
15
|
-
def
|
35
|
+
def _read_local_env_file(
|
16
36
|
env_file_path: Path, benchling_tenant: str
|
17
37
|
) -> tuple[str, BenchlingConnection]:
|
18
38
|
"""Imports the env.py file from the current working directory and returns the CURRENT_REVISION_ID variable along with the BenchlingConnection object.
|
19
39
|
The env.py file is expected to have the CURRENT_REVISION_ID variable set to the revision id you are currently on.
|
20
40
|
The BenchlingConnection object is expected to be defined and have connection information for the Benchling API client and internal API.
|
21
41
|
"""
|
22
|
-
_check_env_file(env_file_path)
|
23
42
|
module_path = Path.cwd() / env_file_path
|
24
43
|
spec = importlib.util.spec_from_file_location(env_file_path.stem, module_path)
|
25
44
|
if spec is None or spec.loader is None:
|
@@ -4,6 +4,19 @@ import re
|
|
4
4
|
from pydantic import BaseModel, model_validator
|
5
5
|
|
6
6
|
|
7
|
+
class TenantConfigFlags(BaseModel):
|
8
|
+
"""Set of config flags that are configured on the tenant level. These can be updated on Benchling's end by contacting their support team.
|
9
|
+
Ask Benchling support to give you the full export of these flags.
|
10
|
+
|
11
|
+
Parameters
|
12
|
+
----------
|
13
|
+
schemas_enable_change_warehouse_name: bool = False
|
14
|
+
If enabled, allows renaming schema and field warehouse names for all schema admins. Default value is False for Benchling
|
15
|
+
"""
|
16
|
+
|
17
|
+
schemas_enable_change_warehouse_name: bool = False
|
18
|
+
|
19
|
+
|
7
20
|
class BenchlingConnection(BaseModel):
|
8
21
|
"""Class that contains the connection information for a Benchling tenant.
|
9
22
|
|
@@ -27,11 +40,10 @@ class BenchlingConnection(BaseModel):
|
|
27
40
|
The email of the internal API admin.
|
28
41
|
internal_api_admin_password: str | None = None
|
29
42
|
The password of the internal API admin.
|
30
|
-
warehouse_access: bool = False
|
31
|
-
Whether your Benchling tenant has access to the warehouse. If warehouse_connection_string is provided, this will default to True.
|
32
|
-
warehouse_access is required to set a custom warehouse names on entity schemas and their fields.
|
33
43
|
fieldsets: bool = False
|
34
44
|
Whether your Benchling tenant has access to fieldsets.
|
45
|
+
config_flags: TenantConfigFlags = TenantConfigFlags()
|
46
|
+
Set of config flags that are configured on the tenant level. These can be updated on Benchling's end by contacting their support team.
|
35
47
|
"""
|
36
48
|
|
37
49
|
tenant_name: str
|
@@ -42,14 +54,12 @@ class BenchlingConnection(BaseModel):
|
|
42
54
|
warehouse_connection_string: str | None = None
|
43
55
|
internal_api_admin_email: str | None = None
|
44
56
|
internal_api_admin_password: str | None = None
|
45
|
-
warehouse_access: bool = False
|
46
57
|
fieldsets: bool = False
|
58
|
+
config_flags: TenantConfigFlags = TenantConfigFlags()
|
47
59
|
|
48
60
|
@model_validator(mode="before")
|
49
61
|
@classmethod
|
50
62
|
def set_current_revision_id_var_name(cls, values: dict) -> dict:
|
51
|
-
if values.get("warehouse_connection_string"):
|
52
|
-
values["warehouse_access"] = True
|
53
63
|
if not values.get("current_revision_id_var_name"):
|
54
64
|
tenant_alias = values.get("tenant_alias")
|
55
65
|
tenant_name = values.get("tenant_name")
|
@@ -4,7 +4,7 @@ from rich import print
|
|
4
4
|
|
5
5
|
from liminal.connection import BenchlingService
|
6
6
|
from liminal.dropdowns.utils import get_benchling_dropdowns_dict
|
7
|
-
from liminal.utils import
|
7
|
+
from liminal.utils import to_pascal_case, to_snake_case
|
8
8
|
|
9
9
|
|
10
10
|
def generate_all_dropdown_files(
|
@@ -24,7 +24,7 @@ def generate_all_dropdown_files(
|
|
24
24
|
for dropdown_name, dropdown_options in dropdowns.items():
|
25
25
|
dropdown_values = [option.name for option in dropdown_options.options]
|
26
26
|
options_list = str(dropdown_values).replace("'", '"')
|
27
|
-
classname =
|
27
|
+
classname = to_pascal_case(dropdown_name)
|
28
28
|
dropdown_content = f"""
|
29
29
|
from liminal.base.base_dropdown import BaseDropdown
|
30
30
|
|
@@ -8,7 +8,7 @@ from liminal.entity_schemas.utils import get_converted_tag_schemas
|
|
8
8
|
from liminal.enums import BenchlingEntityType, BenchlingFieldType
|
9
9
|
from liminal.mappers import convert_benchling_type_to_python_type
|
10
10
|
from liminal.orm.name_template import NameTemplate
|
11
|
-
from liminal.utils import
|
11
|
+
from liminal.utils import to_pascal_case, to_snake_case
|
12
12
|
|
13
13
|
|
14
14
|
def get_entity_mixin(entity_type: BenchlingEntityType) -> str:
|
@@ -59,18 +59,18 @@ def generate_all_entity_schema_files(
|
|
59
59
|
subdirectory_map: dict[str, list[tuple[str, str]]] = {}
|
60
60
|
benchling_dropdowns = get_benchling_dropdowns_dict(benchling_service)
|
61
61
|
dropdown_name_to_classname_map: dict[str, str] = {
|
62
|
-
dropdown_name:
|
62
|
+
dropdown_name: to_pascal_case(dropdown_name)
|
63
63
|
for dropdown_name in benchling_dropdowns.keys()
|
64
64
|
}
|
65
65
|
wh_name_to_classname: dict[str, str] = {
|
66
|
-
sp.warehouse_name:
|
66
|
+
sp.warehouse_name: to_pascal_case(sp.name) for sp, _, _ in models
|
67
67
|
}
|
68
68
|
|
69
69
|
for schema_properties, name_template, columns in models:
|
70
|
-
classname =
|
70
|
+
classname = to_pascal_case(schema_properties.name)
|
71
71
|
|
72
72
|
for schema_properties, name_template, columns in models:
|
73
|
-
classname =
|
73
|
+
classname = to_pascal_case(schema_properties.name)
|
74
74
|
filename = to_snake_case(schema_properties.name) + ".py"
|
75
75
|
columns = {key: columns[key] for key in columns}
|
76
76
|
import_strings = [
|
@@ -81,14 +81,13 @@ class CreateEntitySchema(BaseOperation):
|
|
81
81
|
|
82
82
|
def validate(self, benchling_service: BenchlingService) -> None:
|
83
83
|
if (
|
84
|
-
|
84
|
+
benchling_service.connection.config_flags.schemas_enable_change_warehouse_name
|
85
|
+
is False
|
85
86
|
and self._validated_schema_properties.warehouse_name
|
86
87
|
!= to_snake_case(self._validated_schema_properties.name)
|
87
88
|
):
|
88
89
|
raise ValueError(
|
89
|
-
f"
|
90
|
-
Either set warehouse_access to True in BenchlingConnection or set the schema warehouse_name to the given Benchling warehouse name: {to_snake_case(self._validated_schema_properties.name)}. \
|
91
|
-
Reach out to Benchling support if you need help setting up warehouse access."
|
90
|
+
f"{self._validated_schema_properties.name}: Tenant config flag SCHEMAS_ENABLE_CHANGE_WAREHOUSE_NAME is required to set a custom schema warehouse name. Reach out to Benchling support to turn this config flag to True and then set the flag to True in BenchlingConnection.config_flags. Otherwise, define the schema warehouse_name in code to be the given Benchling warehouse name: {to_snake_case(self._validated_schema_properties.name)}."
|
92
91
|
)
|
93
92
|
for field in self.fields:
|
94
93
|
if (
|
@@ -225,20 +224,19 @@ class UpdateEntitySchema(BaseOperation):
|
|
225
224
|
return update_tag_schema(benchling_service, tag_schema.id, update.model_dump())
|
226
225
|
|
227
226
|
def describe_operation(self) -> str:
|
228
|
-
return f"
|
227
|
+
return f"{self.wh_schema_name}: Updating schema properties to: {str(self.update_props)}."
|
229
228
|
|
230
229
|
def describe(self) -> str:
|
231
|
-
return f"
|
230
|
+
return f"{self.wh_schema_name}: Schema properties are different in code versus Benchling: {str(self.update_props)}."
|
232
231
|
|
233
232
|
def validate(self, benchling_service: BenchlingService) -> None:
|
234
233
|
if (
|
235
|
-
benchling_service.connection.
|
234
|
+
benchling_service.connection.config_flags.schemas_enable_change_warehouse_name
|
235
|
+
is False
|
236
236
|
and self.update_props.warehouse_name is not None
|
237
237
|
):
|
238
238
|
raise ValueError(
|
239
|
-
"
|
240
|
-
Either set warehouse_access to True in BenchlingConnection or do not change the warehouse name. \
|
241
|
-
Reach out to Benchling support if you need help setting up warehouse access."
|
239
|
+
f"{self.wh_schema_name}: Tenant config flag SCHEMAS_ENABLE_CHANGE_WAREHOUSE_NAME is required to update the schema warehouse_name to a custom name. Reach out to Benchling support to turn this config flag to True and then set the flag to True in BenchlingConnection.config_flags."
|
242
240
|
)
|
243
241
|
|
244
242
|
def _validate(self, benchling_service: BenchlingService) -> TagSchemaModel:
|
@@ -315,10 +313,15 @@ class CreateEntitySchemaField(BaseOperation):
|
|
315
313
|
self.index = index
|
316
314
|
|
317
315
|
self._wh_field_name: str
|
316
|
+
self._field_name: str
|
318
317
|
if field_props.warehouse_name:
|
319
318
|
self._wh_field_name = field_props.warehouse_name
|
320
319
|
else:
|
321
320
|
raise ValueError("Field warehouse name is required.")
|
321
|
+
if field_props.name:
|
322
|
+
self._field_name = field_props.name
|
323
|
+
else:
|
324
|
+
raise ValueError("Field name is required.")
|
322
325
|
|
323
326
|
def execute(self, benchling_service: BenchlingService) -> dict[str, Any]:
|
324
327
|
try:
|
@@ -385,13 +388,12 @@ class CreateEntitySchemaField(BaseOperation):
|
|
385
388
|
|
386
389
|
def validate(self, benchling_service: BenchlingService) -> None:
|
387
390
|
if (
|
388
|
-
|
389
|
-
|
391
|
+
benchling_service.connection.config_flags.schemas_enable_change_warehouse_name
|
392
|
+
is False
|
393
|
+
and self.field_props.warehouse_name != to_snake_case(self._field_name)
|
390
394
|
):
|
391
395
|
raise ValueError(
|
392
|
-
f"
|
393
|
-
Either set warehouse_access to True in BenchlingConnection or set the column variable name to the given Benchling field warehouse name: {to_snake_case(self.field_props.name)}. \
|
394
|
-
Reach out to Benchling support if you need help setting up warehouse access."
|
396
|
+
f"{self.wh_schema_name}: Tenant config flag SCHEMAS_ENABLE_CHANGE_WAREHOUSE_NAME is required to set a custom field warehouse name. Reach out to Benchling support to turn this config flag to True and then set the flag to True in BenchlingConnection.config_flags. Otherwise, define the field warehouse_name in code to be the given Benchling warehouse name: {to_snake_case(self._field_name)}."
|
395
397
|
)
|
396
398
|
if (
|
397
399
|
self.field_props.unit_name
|
@@ -538,13 +540,12 @@ class UpdateEntitySchemaField(BaseOperation):
|
|
538
540
|
benchling_service, self.wh_schema_name
|
539
541
|
)
|
540
542
|
if (
|
541
|
-
|
543
|
+
benchling_service.connection.config_flags.schemas_enable_change_warehouse_name
|
544
|
+
is False
|
542
545
|
and self.update_props.warehouse_name is not None
|
543
546
|
):
|
544
547
|
raise ValueError(
|
545
|
-
"
|
546
|
-
Either set warehouse_access to True in BenchlingConnection or do not change the warehouse name. \
|
547
|
-
Reach out to Benchling support if you need help setting up warehouse access."
|
548
|
+
f"{self.wh_schema_name}: Tenant config flag SCHEMAS_ENABLE_CHANGE_WAREHOUSE_NAME is required to update the field warehouse_name to a custom name. Reach out to Benchling support to turn this config flag to True and then set the flag to True in BenchlingConnection.config_flags."
|
548
549
|
)
|
549
550
|
if "unit_name" in self.update_props.model_dump(exclude_unset=True):
|
550
551
|
no_change_message = f"{self.wh_schema_name}: On field {self.wh_field_name}, updating unit name to {self.update_props.unit_name}. The unit of this field CANNOT be changed once it's been set."
|
@@ -131,7 +131,7 @@ class BaseModel(Generic[T], Base):
|
|
131
131
|
for field_part in field_parts:
|
132
132
|
if field_part.wh_field_name not in column_wh_names:
|
133
133
|
raise ValueError(
|
134
|
-
f"Field part {field_part.wh_field_name} is not a column on
|
134
|
+
f"{cls.__schema_properties__.warehouse_name}: Field name template part {field_part.wh_field_name} is not a column on field warehouse name on schema."
|
135
135
|
)
|
136
136
|
cls._existing_schema_warehouse_names.add(warehouse_name)
|
137
137
|
cls._existing_schema_names.add(cls.__schema_properties__.name)
|
@@ -10,30 +10,25 @@ from liminal.connection.benchling_service import BenchlingService
|
|
10
10
|
|
11
11
|
|
12
12
|
def generate_random_id(length: int = 8) -> str:
|
13
|
-
"""Generate a random ID with only lowercase letters."""
|
13
|
+
"""Generate a pseudo-random ID with only lowercase letters."""
|
14
14
|
return "".join(random.choices(string.ascii_lowercase, k=length))
|
15
15
|
|
16
16
|
|
17
|
-
def
|
17
|
+
def to_pascal_case(input_string: str) -> str:
|
18
18
|
"""
|
19
|
-
Convert a string to PascalCase.
|
19
|
+
Convert a string to PascalCase. Filters out any non-alphanumeric characters.
|
20
20
|
"""
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
)
|
21
|
+
words = re.split(r"[ /_\-]", input_string)
|
22
|
+
# Then remove any non-alphanumeric characters and capitalize each word
|
23
|
+
return "".join(re.sub(r"[^a-zA-Z0-9]", "", word).capitalize() for word in words)
|
25
24
|
|
26
25
|
|
27
|
-
def to_snake_case(input_string: str
|
26
|
+
def to_snake_case(input_string: str) -> str:
|
28
27
|
"""
|
29
|
-
Convert a string to snake_case.
|
28
|
+
Convert a string to snake_case. Filters out any non-alphanumeric characters.
|
30
29
|
"""
|
31
|
-
|
32
|
-
|
33
|
-
return "_".join(
|
34
|
-
re.sub(r"[\[\]{}():]", "", word).lower()
|
35
|
-
for word in re.split(r"[ /_\-]", input_string)
|
36
|
-
)
|
30
|
+
words = re.split(r"[ /_\-]", input_string)
|
31
|
+
return "_".join(re.sub(r"[^a-zA-Z0-9]", "", word).lower() for word in words)
|
37
32
|
|
38
33
|
|
39
34
|
def to_string_val(input_val: Any) -> str:
|
@@ -4,7 +4,7 @@ from typing import TYPE_CHECKING, Any, Callable
|
|
4
4
|
|
5
5
|
from pydantic import BaseModel, ConfigDict
|
6
6
|
|
7
|
-
from liminal.utils import
|
7
|
+
from liminal.utils import to_pascal_case
|
8
8
|
from liminal.validation.validation_severity import ValidationSeverity
|
9
9
|
|
10
10
|
if TYPE_CHECKING:
|
@@ -137,14 +137,14 @@ def liminal_validator(
|
|
137
137
|
valid=False,
|
138
138
|
level=validator_level,
|
139
139
|
entity=self,
|
140
|
-
validator_name=validator_name or
|
140
|
+
validator_name=validator_name or to_pascal_case(func.__name__),
|
141
141
|
message=str(e),
|
142
142
|
)
|
143
143
|
return BenchlingValidatorReport.create_validation_report(
|
144
144
|
valid=True,
|
145
145
|
level=validator_level,
|
146
146
|
entity=self,
|
147
|
-
validator_name=validator_name or
|
147
|
+
validator_name=validator_name or to_pascal_case(func.__name__),
|
148
148
|
)
|
149
149
|
|
150
150
|
setattr(wrapper, "_is_liminal_validator", True)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
[tool.poetry]
|
2
2
|
name = "liminal-orm"
|
3
|
-
version = "3.
|
3
|
+
version = "3.1.1"
|
4
4
|
description = "An ORM and toolkit that builds on top of Benchling's platform to keep your schemas and downstream code dependencies in sync."
|
5
5
|
authors = ["DynoTx Open Source <opensource@dynotx.com>"]
|
6
6
|
readme = "README.md"
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
liminal_orm-3.0.1/liminal/base/properties/__pycache__/base_schema_properties.cpython-310.pyc
DELETED
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
liminal_orm-3.0.1/liminal/tests/__pycache__/test_dropdown_compare.cpython-310-pytest-8.3.3.pyc
DELETED
Binary file
|
liminal_orm-3.0.1/liminal/tests/__pycache__/test_entity_schema_compare.cpython-310-pytest-8.3.3.pyc
DELETED
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
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
|
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
|
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
|
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
|
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
|