liminal-orm 3.2.0__tar.gz → 4.0.0__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.2.0 → liminal_orm-4.0.0}/PKG-INFO +2 -2
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/base/name_template_parts.py +1 -1
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/base/properties/base_field_properties.py +19 -0
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/cli/cli.py +42 -7
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/cli/controller.py +26 -6
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/cli/live_test_dropdown_migration.py +4 -2
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/cli/utils.py +1 -1
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/dropdowns/generate_files.py +14 -2
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/entity_schemas/compare.py +56 -34
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/entity_schemas/generate_files.py +62 -18
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/entity_schemas/operations.py +6 -3
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/orm/base_model.py +2 -2
- liminal_orm-4.0.0/liminal/orm/base_results_model.py +207 -0
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/orm/relationship.py +2 -2
- liminal_orm-4.0.0/liminal/orm/results_schema_properties.py +23 -0
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/orm/schema_properties.py +4 -0
- liminal_orm-4.0.0/liminal/results_schemas/generate_files.py +197 -0
- liminal_orm-4.0.0/liminal/results_schemas/models/results_schema_model.py +145 -0
- liminal_orm-4.0.0/liminal/results_schemas/utils.py +48 -0
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/tests/test_entity_schema_compare.py +6 -7
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/pyproject.toml +2 -2
- liminal_orm-3.2.0/liminal/.DS_Store +0 -0
- liminal_orm-3.2.0/liminal/base/__pycache__/__init__.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/base/__pycache__/base.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/base/__pycache__/base_dropdown.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/base/__pycache__/base_operation.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/base/__pycache__/base_validation_filters.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/base/__pycache__/benchling_base_model.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/base/__pycache__/benchling_column.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/base/__pycache__/benchling_dropdown.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/base/__pycache__/benchling_field_properties.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/base/__pycache__/benchling_schema_properties.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/base/__pycache__/callable_operation.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/base/__pycache__/column.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/base/__pycache__/compare_operation.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/base/__pycache__/field_properties.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/base/__pycache__/name_template_components.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/base/__pycache__/name_template_parts.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/base/__pycache__/schema_properties.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/base/__pycache__/str_enum.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/base/__pycache__/unset.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/base/__pycache__/user.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/base/properties/__pycache__/NoDropdown.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/base/properties/__pycache__/__init__.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/base/properties/__pycache__/base_field_properties.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/base/properties/__pycache__/base_name_template.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/base/properties/__pycache__/base_schema_properties.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/base/properties/__pycache__/field_properties.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/base/properties/__pycache__/schema_properties.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/cli/__pycache__/cli.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/cli/__pycache__/controller.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/cli/__pycache__/live_test_dropdown_migration.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/cli/__pycache__/live_test_entity_schema_migration.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/cli/__pycache__/utils.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/connection/__pycache__/__init__.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/connection/__pycache__/benchling_connection.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/connection/__pycache__/benchling_service.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/dropdowns/__pycache__/api.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/dropdowns/__pycache__/compare.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/dropdowns/__pycache__/generate_files.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/dropdowns/__pycache__/operations.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/dropdowns/__pycache__/utils.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/entity_schemas/__pycache__/api.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/entity_schemas/__pycache__/compare.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/entity_schemas/__pycache__/entity_schema_models.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/entity_schemas/__pycache__/generate_files.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/entity_schemas/__pycache__/operations.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/entity_schemas/__pycache__/schemas.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/entity_schemas/__pycache__/tag_schema_models.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/entity_schemas/__pycache__/utils.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/enums/__pycache__/__init__.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/enums/__pycache__/benchling_api_field_type.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/enums/__pycache__/benchling_dropdown.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/enums/__pycache__/benchling_entity_type.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/enums/__pycache__/benchling_enum.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/enums/__pycache__/benchling_field_api_type.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/enums/__pycache__/benchling_field_type.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/enums/__pycache__/benchling_folder_item_type.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/enums/__pycache__/benchling_naming_strategy.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/enums/__pycache__/benchling_report_level.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/enums/__pycache__/benchling_sequence_type.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/enums/__pycache__/name_template_part_type.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/enums/__pycache__/sequence_constraint.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/enums/__pycache__/sequence_constraints.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/enums/__pycache__/str_enum.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/enums/__pycache__/undefined.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/external/__pycache__/__init__.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/migrate/__pycache__/components.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/migrate/__pycache__/revision.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/migrate/__pycache__/revisions_timeline.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/migrate/__pycache__/utils.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/orm/__pycache__/__init__.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/orm/__pycache__/base.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/orm/__pycache__/base_model.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/orm/__pycache__/base_results_schema_model.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/orm/__pycache__/column.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/orm/__pycache__/mixins.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/orm/__pycache__/name_template.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/orm/__pycache__/name_template_parts.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/orm/__pycache__/relationship.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/orm/__pycache__/results_schema_properties.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/orm/__pycache__/schema_properties.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/orm/__pycache__/user.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/orm/base_tables/__pycache__/__init__.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/orm/base_tables/__pycache__/registry_entity.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/orm/base_tables/__pycache__/schema.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/orm/base_tables/__pycache__/user.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/results_schemas/__pycache__/generate_files.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/results_schemas/__pycache__/utils.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/results_schemas/models/__pycache__/results_schema_model.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/tests/.DS_Store +0 -0
- liminal_orm-3.2.0/liminal/tests/__pycache__/__init__.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/tests/__pycache__/conftest.cpython-310-pytest-8.3.3.pyc +0 -0
- liminal_orm-3.2.0/liminal/tests/__pycache__/test_dropdown_compare.cpython-310-pytest-8.3.3.pyc +0 -0
- liminal_orm-3.2.0/liminal/tests/__pycache__/test_entity_schema_compare.cpython-310-pytest-8.3.3.pyc +0 -0
- liminal_orm-3.2.0/liminal/unit_dictionary/__pycache__/utils.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/validation/__pycache__/__init__.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/validation/__pycache__/validation_report_level.cpython-310.pyc +0 -0
- liminal_orm-3.2.0/liminal/validation/__pycache__/validation_severity.cpython-310.pyc +0 -0
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/LICENSE.md +0 -0
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/README.md +0 -0
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/__init__.py +0 -0
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/base/base_dropdown.py +0 -0
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/base/base_operation.py +0 -0
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/base/base_validation_filters.py +0 -0
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/base/compare_operation.py +0 -0
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/base/properties/base_name_template.py +0 -0
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/base/properties/base_schema_properties.py +0 -0
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/base/str_enum.py +0 -0
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/cli/live_test_entity_schema_migration.py +0 -0
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/connection/__init__.py +0 -0
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/connection/benchling_connection.py +0 -0
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/connection/benchling_service.py +0 -0
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/dropdowns/api.py +0 -0
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/dropdowns/compare.py +0 -0
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/dropdowns/operations.py +0 -0
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/dropdowns/utils.py +0 -0
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/entity_schemas/api.py +0 -0
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/entity_schemas/entity_schema_models.py +0 -0
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/entity_schemas/tag_schema_models.py +0 -0
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/entity_schemas/utils.py +0 -0
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/enums/__init__.py +0 -0
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/enums/benchling_api_field_type.py +0 -0
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/enums/benchling_entity_type.py +0 -0
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/enums/benchling_field_type.py +0 -0
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/enums/benchling_folder_item_type.py +0 -0
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/enums/benchling_naming_strategy.py +0 -0
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/enums/benchling_sequence_type.py +0 -0
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/enums/name_template_part_type.py +0 -0
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/enums/sequence_constraint.py +0 -0
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/external/__init__.py +0 -0
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/mappers.py +0 -0
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/migrate/components.py +0 -0
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/migrate/revision.py +0 -0
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/migrate/revisions_timeline.py +0 -0
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/orm/base.py +0 -0
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/orm/base_tables/registry_entity.py +0 -0
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/orm/base_tables/schema.py +0 -0
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/orm/base_tables/user.py +0 -0
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/orm/column.py +0 -0
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/orm/mixins.py +0 -0
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/orm/name_template.py +0 -0
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/orm/name_template_parts.py +0 -0
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/py.typed +0 -0
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/tests/__init__.py +0 -0
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/tests/conftest.py +0 -0
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/tests/from benchling_sdk.py +0 -0
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/tests/test_dropdown_compare.py +0 -0
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/unit_dictionary/utils.py +0 -0
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/utils.py +0 -0
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/liminal/validation/__init__.py +0 -0
- {liminal_orm-3.2.0 → liminal_orm-4.0.0}/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
|
+
Version: 4.0.0
|
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
|
@@ -11,7 +11,7 @@ Classifier: Programming Language :: Python :: 3.9
|
|
11
11
|
Classifier: Programming Language :: Python :: 3.10
|
12
12
|
Classifier: Programming Language :: Python :: 3.11
|
13
13
|
Classifier: Programming Language :: Python :: 3.12
|
14
|
-
Requires-Dist: benchling-sdk (>=1.
|
14
|
+
Requires-Dist: benchling-sdk (>=1.21.2,<2.0.0)
|
15
15
|
Requires-Dist: bs4 (>=0.0.2,<0.0.3)
|
16
16
|
Requires-Dist: lxml (>=5.3.0,<6.0.0)
|
17
17
|
Requires-Dist: numpy (>=1.23.5,<2.0.0)
|
@@ -3,6 +3,6 @@ import warnings
|
|
3
3
|
from liminal.orm.name_template_parts import * # noqa: F403
|
4
4
|
|
5
5
|
warnings.warn(
|
6
|
-
"Importing from 'liminal.base.name_template_parts' is deprecated. Please import from 'liminal.orm.name_template_parts' instead. This will be removed in
|
6
|
+
"Importing from 'liminal.base.name_template_parts' is deprecated. Please import from 'liminal.orm.name_template_parts' instead. This will be removed in v5.",
|
7
7
|
FutureWarning,
|
8
8
|
)
|
@@ -64,12 +64,31 @@ class BaseFieldProperties(BaseModel):
|
|
64
64
|
self.warehouse_name = wh_name
|
65
65
|
return self
|
66
66
|
|
67
|
+
def unset_tooltip(self) -> BaseFieldProperties:
|
68
|
+
if "tooltip" in self.__pydantic_fields_set__:
|
69
|
+
self.__pydantic_fields_set__.remove("tooltip")
|
70
|
+
return self
|
71
|
+
|
67
72
|
def validate_column_definition(self, wh_name: str) -> bool:
|
68
73
|
"""If the Field Properties are meant to represent a column in Benchling,
|
69
74
|
this will validate the properties and ensure that the entity_link and dropdowns are valid names that exist in our code.
|
70
75
|
"""
|
71
76
|
return True
|
72
77
|
|
78
|
+
def column_dump(self) -> dict[str, Any]:
|
79
|
+
"""This function returns a model dump or dictionary of the field properties.
|
80
|
+
However, it removes defaults based on the init in the Column class."""
|
81
|
+
column_props = self.model_dump(exclude_unset=True, exclude_none=True)
|
82
|
+
to_pop = []
|
83
|
+
for k, v in column_props.items():
|
84
|
+
if k == "is_multi" and v is False:
|
85
|
+
to_pop.append(k)
|
86
|
+
elif k == "parent_link" and v is False:
|
87
|
+
to_pop.append(k)
|
88
|
+
for k in to_pop:
|
89
|
+
column_props.pop(k)
|
90
|
+
return column_props
|
91
|
+
|
73
92
|
def merge(self, new_props: BaseFieldProperties) -> dict[str, Any]:
|
74
93
|
"""Returns a diff of the two given Benchling FieldProperties as a dictionary.
|
75
94
|
If the field is different, set it as the new field.
|
@@ -83,7 +83,7 @@ connection = BenchlingConnection(
|
|
83
83
|
|
84
84
|
@app.command(
|
85
85
|
name="generate-files",
|
86
|
-
help="Generates the dropdown and
|
86
|
+
help="Generates the dropdown, entity schema, and results schema files from your Benchling tenant and writes to the given path. By default, this will overwrite any existing files within the {write_path}/dropdowns/, {write_path}/entity_schemas/, and {write_path}/results_schemas/ directories.",
|
87
87
|
)
|
88
88
|
def generate_files(
|
89
89
|
benchling_tenant: str = typer.Argument(
|
@@ -95,13 +95,48 @@ def generate_files(
|
|
95
95
|
"--write-path",
|
96
96
|
help="The path to write the generated files to.",
|
97
97
|
),
|
98
|
+
entity_schemas_flag: bool = typer.Option(
|
99
|
+
False,
|
100
|
+
"-es",
|
101
|
+
"--entity-schemas",
|
102
|
+
help="Generate entity schema files.",
|
103
|
+
),
|
104
|
+
dropdowns_flag: bool = typer.Option(
|
105
|
+
False,
|
106
|
+
"-d",
|
107
|
+
"--dropdowns",
|
108
|
+
help="Generate dropdown files.",
|
109
|
+
),
|
110
|
+
results_schemas_flag: bool = typer.Option(
|
111
|
+
False,
|
112
|
+
"-rs",
|
113
|
+
"--results-schemas",
|
114
|
+
help="Generate results schema files.",
|
115
|
+
),
|
116
|
+
overwrite: bool = typer.Option(
|
117
|
+
False,
|
118
|
+
"-o",
|
119
|
+
"--overwrite",
|
120
|
+
help="Overwrite existing files within the {write_path}/dropdowns/, {write_path}/entity_schemas/, and {write_path}/results_schemas/ directories.",
|
121
|
+
),
|
98
122
|
) -> None:
|
99
123
|
_, benchling_connection = read_local_liminal_dir(LIMINAL_DIR_PATH, benchling_tenant)
|
100
124
|
benchling_service = BenchlingService(benchling_connection, use_internal_api=True)
|
101
125
|
if not write_path.exists():
|
102
126
|
write_path.mkdir()
|
103
127
|
print(f"[green]Created directory: {write_path}")
|
104
|
-
|
128
|
+
if not entity_schemas_flag and not dropdowns_flag and not results_schemas_flag:
|
129
|
+
entity_schemas_flag = True
|
130
|
+
dropdowns_flag = True
|
131
|
+
results_schemas_flag = True
|
132
|
+
generate_all_files(
|
133
|
+
benchling_service,
|
134
|
+
Path(write_path),
|
135
|
+
entity_schemas_flag,
|
136
|
+
dropdowns_flag,
|
137
|
+
results_schemas_flag,
|
138
|
+
overwrite,
|
139
|
+
)
|
105
140
|
|
106
141
|
|
107
142
|
@app.command(
|
@@ -121,7 +156,7 @@ def current(
|
|
121
156
|
remote_revision_id = benchling_service.get_remote_revision_id()
|
122
157
|
if current_revision_id is not None:
|
123
158
|
warnings.warn(
|
124
|
-
f"Accessing and using the revision_id variable in {LIMINAL_DIR_PATH/'env.py'} is deprecated. Delete the variable set in the env.py file, the revision_id is now stored in your Benchling tenant within the '_liminal_remote' schema. Support for reading/writing the local revision_id will end with the
|
159
|
+
f"Accessing and using the revision_id variable in {LIMINAL_DIR_PATH/'env.py'} is deprecated. Delete the variable set in the env.py file, the revision_id is now stored in your Benchling tenant within the '_liminal_remote' schema. Support for reading/writing the local revision_id will end with the v5 release.",
|
125
160
|
FutureWarning,
|
126
161
|
)
|
127
162
|
current_revision_id = remote_revision_id
|
@@ -165,7 +200,7 @@ def revision(
|
|
165
200
|
remote_revision_id = benchling_service.get_remote_revision_id()
|
166
201
|
if current_revision_id is not None:
|
167
202
|
warnings.warn(
|
168
|
-
f"Accessing and using the revision_id variable in {LIMINAL_DIR_PATH/'env.py'} is deprecated. Delete the variable set in the env.py file, the revision_id is now stored in your Benchling tenant within the '_liminal_remote' schema. Support for reading/writing the local revision_id will end with the
|
203
|
+
f"Accessing and using the revision_id variable in {LIMINAL_DIR_PATH/'env.py'} is deprecated. Delete the variable set in the env.py file, the revision_id is now stored in your Benchling tenant within the '_liminal_remote' schema. Support for reading/writing the local revision_id will end with the v5 release.",
|
169
204
|
FutureWarning,
|
170
205
|
)
|
171
206
|
current_revision_id = remote_revision_id
|
@@ -194,7 +229,7 @@ def autogenerate(
|
|
194
229
|
),
|
195
230
|
) -> None:
|
196
231
|
raise DeprecationWarning(
|
197
|
-
"CLI command `liminal autogenerate ...` is deprecated and will be removed in
|
232
|
+
"CLI command `liminal autogenerate ...` is deprecated and will be removed in v5. Please use `liminal revision ...` instead."
|
198
233
|
)
|
199
234
|
|
200
235
|
|
@@ -221,7 +256,7 @@ def upgrade(
|
|
221
256
|
remote_revision_id = benchling_service.get_remote_revision_id()
|
222
257
|
if current_revision_id is not None:
|
223
258
|
warnings.warn(
|
224
|
-
f"Accessing and using the revision_id variable in {LIMINAL_DIR_PATH/'env.py'} is deprecated. Delete the variable set in the env.py file, the revision_id is now stored in your Benchling tenant within the '_liminal_remote' schema. Support for reading/writing the local revision_id will end with the
|
259
|
+
f"Accessing and using the revision_id variable in {LIMINAL_DIR_PATH/'env.py'} is deprecated. Delete the variable set in the env.py file, the revision_id is now stored in your Benchling tenant within the '_liminal_remote' schema. Support for reading/writing the local revision_id will end with the v5 release.",
|
225
260
|
FutureWarning,
|
226
261
|
)
|
227
262
|
current_revision_id = remote_revision_id
|
@@ -265,7 +300,7 @@ def downgrade(
|
|
265
300
|
remote_revision_id = benchling_service.get_remote_revision_id()
|
266
301
|
if current_revision_id is not None:
|
267
302
|
warnings.warn(
|
268
|
-
f"Accessing and using the revision_id variable in {LIMINAL_DIR_PATH/'env.py'} is deprecated. Delete the variable set in the env.py file, the revision_id is now stored in your Benchling tenant within the '_liminal_remote' schema. Support for reading/writing the local revision_id will end with the
|
303
|
+
f"Accessing and using the revision_id variable in {LIMINAL_DIR_PATH/'env.py'} is deprecated. Delete the variable set in the env.py file, the revision_id is now stored in your Benchling tenant within the '_liminal_remote' schema. Support for reading/writing the local revision_id will end with the v5 release.",
|
269
304
|
FutureWarning,
|
270
305
|
)
|
271
306
|
current_revision_id = remote_revision_id
|
@@ -7,12 +7,20 @@ from liminal.dropdowns.generate_files import generate_all_dropdown_files
|
|
7
7
|
from liminal.entity_schemas.generate_files import generate_all_entity_schema_files
|
8
8
|
from liminal.migrate.components import execute_operations, get_full_migration_operations
|
9
9
|
from liminal.migrate.revisions_timeline import RevisionsTimeline
|
10
|
+
from liminal.results_schemas.generate_files import generate_all_results_schema_files
|
10
11
|
|
11
12
|
|
12
|
-
def generate_all_files(
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
def generate_all_files(
|
14
|
+
benchling_service: BenchlingService,
|
15
|
+
write_path: Path,
|
16
|
+
entity_schemas_flag: bool = True,
|
17
|
+
dropdowns_flag: bool = True,
|
18
|
+
results_schemas_flag: bool = True,
|
19
|
+
overwrite: bool = False,
|
20
|
+
) -> None:
|
21
|
+
"""Initializes all the dropdown, entity schema, and results schema files from your Benchling tenant and writes to the given path.
|
22
|
+
Creates and writes to the dropdowns/, entity_schemas/, and results_schemas/ directories.
|
23
|
+
Note: By default, this will overwrite any existing dropdowns, entity schemas, or results schemas that exist in the given path.
|
16
24
|
|
17
25
|
Parameters
|
18
26
|
----------
|
@@ -20,9 +28,21 @@ def generate_all_files(benchling_service: BenchlingService, write_path: Path) ->
|
|
20
28
|
The Benchling service object that is connected to a specified Benchling tenant.
|
21
29
|
write_path : Path
|
22
30
|
The path to write the generated files to.
|
31
|
+
entity_schemas_flag : bool
|
32
|
+
Whether to generate the entity schema files in the entity_schemas/ directory.
|
33
|
+
dropdowns_flag : bool
|
34
|
+
Whether to generate the dropdown files in the dropdowns/ directory.
|
35
|
+
results_schemas_flag : bool
|
36
|
+
Whether to generate the results schema files in the results_schemas/ directory.
|
37
|
+
overwrite : bool
|
38
|
+
Whether to overwrite existing the existing write_path directory.
|
23
39
|
"""
|
24
|
-
|
25
|
-
|
40
|
+
if dropdowns_flag:
|
41
|
+
generate_all_dropdown_files(benchling_service, write_path, overwrite)
|
42
|
+
if entity_schemas_flag:
|
43
|
+
generate_all_entity_schema_files(benchling_service, write_path, overwrite)
|
44
|
+
if results_schemas_flag:
|
45
|
+
generate_all_results_schema_files(benchling_service, write_path, overwrite)
|
26
46
|
|
27
47
|
|
28
48
|
def autogenerate_revision_file(
|
@@ -29,9 +29,11 @@ def mock_dropdown_full_migration(
|
|
29
29
|
dropdown_options = ["Option 1", "Option 2"]
|
30
30
|
create_dropdown_op = CreateDropdown(test_dropdown_name, dropdown_options)
|
31
31
|
|
32
|
-
|
32
|
+
update_dropdown_op = UpdateDropdownName(
|
33
|
+
test_dropdown_name, f"{test_dropdown_name}_arch"
|
34
|
+
)
|
33
35
|
|
34
|
-
|
36
|
+
test_dropdown_name = f"{test_dropdown_name}_arch"
|
35
37
|
|
36
38
|
create_dropdown_option_op = CreateDropdownOption(
|
37
39
|
test_dropdown_name, "Option 3 New", 2
|
@@ -81,7 +81,7 @@ def _read_local_env_file(
|
|
81
81
|
def update_env_revision_id(
|
82
82
|
env_file_path: Path, benchling_env: str, revision_id: str
|
83
83
|
) -> None:
|
84
|
-
"""Updates the CURRENT_REVISION_ID variable in the env.py file to the given revision id. REMOVE WITH
|
84
|
+
"""Updates the CURRENT_REVISION_ID variable in the env.py file to the given revision id. REMOVE WITH v5 release."""
|
85
85
|
env_file_content = env_file_path.read_text().split("\n")
|
86
86
|
for i, line in enumerate(env_file_content):
|
87
87
|
if f"{benchling_env}_CURRENT_REVISION_ID =" in line:
|
@@ -1,3 +1,4 @@
|
|
1
|
+
import shutil
|
1
2
|
from pathlib import Path
|
2
3
|
|
3
4
|
from rich import print
|
@@ -8,13 +9,24 @@ from liminal.utils import to_pascal_case, to_snake_case
|
|
8
9
|
|
9
10
|
|
10
11
|
def generate_all_dropdown_files(
|
11
|
-
benchling_service: BenchlingService, write_path: Path
|
12
|
+
benchling_service: BenchlingService, write_path: Path, overwrite: bool = False
|
12
13
|
) -> None:
|
13
14
|
"""Generate all dropdown files from your Benchling tenant and writes to the given dropdowns/ path.
|
14
15
|
This is used to initialize your code for Liminal and transfer the information from your Benchling tenant to your local codebase.
|
15
|
-
|
16
|
+
|
17
|
+
Parameters
|
18
|
+
----------
|
19
|
+
benchling_service : BenchlingService
|
20
|
+
The Benchling service object that is connected to a specified Benchling tenant.
|
21
|
+
write_path : Path
|
22
|
+
The path to write the generated files to. dropdowns/ directory will be created within this path.
|
23
|
+
overwrite : bool
|
24
|
+
Whether to overwrite existing the existing dropdowns/ directory.
|
16
25
|
"""
|
17
26
|
write_path = write_path / "dropdowns"
|
27
|
+
if write_path.exists() and overwrite:
|
28
|
+
shutil.rmtree(write_path)
|
29
|
+
print(f"[dim]Removed directory: {write_path}")
|
18
30
|
if not write_path.exists():
|
19
31
|
write_path.mkdir(parents=True, exist_ok=True)
|
20
32
|
print(f"[green]Created directory: {write_path}")
|
@@ -272,10 +272,16 @@ def compare_entity_schemas(
|
|
272
272
|
# Benchling api does not allow for setting a custom warehouse_name,
|
273
273
|
# so we need to run another UpdateEntitySchema to set the warehouse_name if it is different from the snakecase version of the model name.
|
274
274
|
else:
|
275
|
-
|
275
|
+
field_props = [
|
276
276
|
col.properties.set_warehouse_name(wh_name)
|
277
277
|
for wh_name, col in model_columns.items()
|
278
278
|
]
|
279
|
+
tooltips_to_update = {
|
280
|
+
p.warehouse_name: p.tooltip
|
281
|
+
for p in field_props
|
282
|
+
if (p.tooltip and p.warehouse_name)
|
283
|
+
}
|
284
|
+
field_props = [f.unset_tooltip() for f in field_props]
|
279
285
|
template_based_naming_strategies = {
|
280
286
|
s
|
281
287
|
for s in model.__schema_properties__.naming_strategies
|
@@ -286,19 +292,61 @@ def compare_entity_schemas(
|
|
286
292
|
for s in model.__schema_properties__.naming_strategies
|
287
293
|
if not BenchlingNamingStrategy.is_template_based(s)
|
288
294
|
}
|
295
|
+
model_wh_name = model.__schema_properties__.warehouse_name
|
296
|
+
benchling_given_wh_name = to_snake_case(model.__schema_properties__.name)
|
289
297
|
ops.append(
|
290
298
|
CompareOperation(
|
291
299
|
op=CreateEntitySchema(
|
292
300
|
BaseSchemaProperties(
|
293
|
-
**model.__schema_properties__.
|
301
|
+
**model.__schema_properties__.set_warehouse_name(
|
302
|
+
benchling_given_wh_name
|
303
|
+
).model_dump()
|
294
304
|
),
|
295
|
-
fields=
|
296
|
-
),
|
297
|
-
reverse_op=ArchiveEntitySchema(
|
298
|
-
model.__schema_properties__.warehouse_name
|
305
|
+
fields=field_props,
|
299
306
|
),
|
307
|
+
reverse_op=ArchiveEntitySchema(benchling_given_wh_name),
|
300
308
|
)
|
301
309
|
)
|
310
|
+
new_schema_props = BaseSchemaProperties()
|
311
|
+
rollback_schema_props = BaseSchemaProperties()
|
312
|
+
if model_wh_name != benchling_given_wh_name:
|
313
|
+
new_schema_props.warehouse_name = model_wh_name
|
314
|
+
rollback_schema_props.warehouse_name = benchling_given_wh_name
|
315
|
+
if template_based_naming_strategies:
|
316
|
+
new_schema_props.naming_strategies = template_based_naming_strategies
|
317
|
+
rollback_schema_props.naming_strategies = (
|
318
|
+
model.__schema_properties__.naming_strategies
|
319
|
+
)
|
320
|
+
if new_schema_props.model_dump(exclude_unset=True) != {}:
|
321
|
+
ops.append(
|
322
|
+
CompareOperation(
|
323
|
+
op=UpdateEntitySchema(
|
324
|
+
benchling_given_wh_name,
|
325
|
+
new_schema_props,
|
326
|
+
),
|
327
|
+
reverse_op=UpdateEntitySchema(
|
328
|
+
model_wh_name,
|
329
|
+
rollback_schema_props,
|
330
|
+
),
|
331
|
+
)
|
332
|
+
)
|
333
|
+
# Benchling api also does not allow for setting of field tooltips
|
334
|
+
# so we need to run another UpdateEntitySchemaField to set the tooltip after the schema is created
|
335
|
+
for wh_field_name, tooltip_value in tooltips_to_update.items():
|
336
|
+
ops.append(
|
337
|
+
CompareOperation(
|
338
|
+
op=UpdateEntitySchemaField(
|
339
|
+
model_wh_name,
|
340
|
+
wh_field_name,
|
341
|
+
BaseFieldProperties(tooltip=tooltip_value),
|
342
|
+
),
|
343
|
+
reverse_op=UpdateEntitySchemaField(
|
344
|
+
model_wh_name,
|
345
|
+
wh_field_name,
|
346
|
+
BaseFieldProperties(tooltip=None),
|
347
|
+
),
|
348
|
+
)
|
349
|
+
)
|
302
350
|
benchling_given_name_template = BaseNameTemplate(
|
303
351
|
parts=[], order_name_parts_by_sequence=False
|
304
352
|
)
|
@@ -306,7 +354,7 @@ def compare_entity_schemas(
|
|
306
354
|
ops.append(
|
307
355
|
CompareOperation(
|
308
356
|
op=UpdateEntitySchemaNameTemplate(
|
309
|
-
|
357
|
+
model_wh_name,
|
310
358
|
BaseNameTemplate(
|
311
359
|
**benchling_given_name_template.merge(
|
312
360
|
model.__name_template__
|
@@ -314,7 +362,7 @@ def compare_entity_schemas(
|
|
314
362
|
),
|
315
363
|
),
|
316
364
|
reverse_op=UpdateEntitySchemaNameTemplate(
|
317
|
-
|
365
|
+
model_wh_name,
|
318
366
|
BaseNameTemplate(
|
319
367
|
**model.__name_template__.merge(
|
320
368
|
benchling_given_name_template
|
@@ -323,32 +371,6 @@ def compare_entity_schemas(
|
|
323
371
|
),
|
324
372
|
)
|
325
373
|
)
|
326
|
-
benchling_given_wh_name = to_snake_case(model.__schema_properties__.name)
|
327
|
-
new_schema_props = BaseSchemaProperties()
|
328
|
-
rollback_schema_props = BaseSchemaProperties()
|
329
|
-
if model.__schema_properties__.warehouse_name != benchling_given_wh_name:
|
330
|
-
new_schema_props.warehouse_name = (
|
331
|
-
model.__schema_properties__.warehouse_name
|
332
|
-
)
|
333
|
-
rollback_schema_props.warehouse_name = benchling_given_wh_name
|
334
|
-
if template_based_naming_strategies:
|
335
|
-
new_schema_props.naming_strategies = template_based_naming_strategies
|
336
|
-
rollback_schema_props.naming_strategies = (
|
337
|
-
model.__schema_properties__.naming_strategies
|
338
|
-
)
|
339
|
-
if new_schema_props.model_dump(exclude_unset=True) != {}:
|
340
|
-
ops.append(
|
341
|
-
CompareOperation(
|
342
|
-
op=UpdateEntitySchema(
|
343
|
-
benchling_given_wh_name,
|
344
|
-
new_schema_props,
|
345
|
-
),
|
346
|
-
reverse_op=UpdateEntitySchema(
|
347
|
-
model.__schema_properties__.warehouse_name,
|
348
|
-
rollback_schema_props,
|
349
|
-
),
|
350
|
-
)
|
351
|
-
)
|
352
374
|
|
353
375
|
model_operations[model.__schema_properties__.warehouse_name] = ops
|
354
376
|
running_benchling_schema_names = [
|
@@ -1,7 +1,9 @@
|
|
1
|
+
import shutil
|
1
2
|
from pathlib import Path
|
2
3
|
|
3
4
|
from rich import print
|
4
5
|
|
6
|
+
from liminal.base.base_dropdown import BaseDropdown
|
5
7
|
from liminal.connection.benchling_service import BenchlingService
|
6
8
|
from liminal.dropdowns.utils import get_benchling_dropdowns_dict
|
7
9
|
from liminal.entity_schemas.utils import get_converted_tag_schemas
|
@@ -45,23 +47,38 @@ def get_file_subdirectory(entity_type: BenchlingEntityType) -> str:
|
|
45
47
|
return type_to_subdir_map[entity_type]
|
46
48
|
|
47
49
|
|
50
|
+
TAB = " "
|
51
|
+
|
52
|
+
|
48
53
|
def generate_all_entity_schema_files(
|
49
|
-
benchling_service: BenchlingService, write_path: Path
|
54
|
+
benchling_service: BenchlingService, write_path: Path, overwrite: bool = False
|
50
55
|
) -> None:
|
56
|
+
"""Generate all entity schema files from your Benchling tenant and writes to the given entity_schemas/ path.
|
57
|
+
This is used to initialize your code for Liminal and transfer the information from your Benchling tenant to your local codebase.
|
58
|
+
|
59
|
+
Parameters
|
60
|
+
----------
|
61
|
+
benchling_service : BenchlingService
|
62
|
+
The Benchling service object that is connected to a specified Benchling tenant.
|
63
|
+
write_path : Path
|
64
|
+
The path to write the generated files to. entity_schemas/ directory will be created within this path.
|
65
|
+
overwrite : bool
|
66
|
+
Whether to overwrite existing the existing entity_schemas/ directory.
|
67
|
+
"""
|
51
68
|
write_path = write_path / "entity_schemas"
|
69
|
+
if write_path.exists() and overwrite:
|
70
|
+
shutil.rmtree(write_path)
|
71
|
+
print(f"[dim]Removed directory: {write_path}")
|
52
72
|
if not write_path.exists():
|
53
73
|
write_path.mkdir(parents=True, exist_ok=True)
|
54
74
|
print(f"[green]Created directory: {write_path}")
|
55
75
|
|
56
76
|
models = get_converted_tag_schemas(benchling_service)
|
57
|
-
tab = " "
|
58
77
|
has_date = False
|
59
78
|
subdirectory_map: dict[str, list[tuple[str, str]]] = {}
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
for dropdown_name in benchling_dropdowns.keys()
|
64
|
-
}
|
79
|
+
dropdown_name_to_classname_map = _get_dropdown_name_to_classname_map(
|
80
|
+
benchling_service
|
81
|
+
)
|
65
82
|
wh_name_to_classname: dict[str, str] = {
|
66
83
|
sp.warehouse_name: to_pascal_case(sp.name) for sp, _, _ in models
|
67
84
|
}
|
@@ -81,21 +98,28 @@ def generate_all_entity_schema_files(
|
|
81
98
|
"from liminal.enums import BenchlingEntityType, BenchlingFieldType, BenchlingNamingStrategy",
|
82
99
|
f"from liminal.orm.mixins import {get_entity_mixin(schema_properties.entity_type)}",
|
83
100
|
]
|
84
|
-
init_strings = [f"{
|
101
|
+
init_strings = [f"{TAB}def __init__(", f"{TAB}self,"]
|
85
102
|
column_strings = []
|
86
103
|
dropdowns = []
|
87
104
|
relationship_strings = []
|
88
105
|
for col_name, col in columns.items():
|
106
|
+
column_props = col.column_dump()
|
89
107
|
dropdown_classname = None
|
90
108
|
if col.dropdown_link:
|
91
109
|
dropdown_classname = dropdown_name_to_classname_map[col.dropdown_link]
|
92
110
|
dropdowns.append(dropdown_classname)
|
93
|
-
|
94
|
-
|
95
|
-
)
|
111
|
+
column_props["dropdown_link"] = dropdown_classname
|
112
|
+
column_props_string = ""
|
113
|
+
for k, v in column_props.items():
|
114
|
+
if k == "dropdown_link":
|
115
|
+
column_props_string += f"""dropdown={v},"""
|
116
|
+
else:
|
117
|
+
column_props_string += f"""{k}={v.__repr__()},"""
|
118
|
+
column_string = f"""{TAB}{col_name}: SqlColumn = Column({column_props_string.rstrip(',')})"""
|
119
|
+
column_strings.append(column_string)
|
96
120
|
if col.required and col.type:
|
97
121
|
init_strings.append(
|
98
|
-
f"""{
|
122
|
+
f"""{TAB}{col_name}: {convert_benchling_type_to_python_type(col.type).__name__},"""
|
99
123
|
)
|
100
124
|
|
101
125
|
if (
|
@@ -110,14 +134,14 @@ def generate_all_entity_schema_files(
|
|
110
134
|
):
|
111
135
|
if not col.is_multi:
|
112
136
|
relationship_strings.append(
|
113
|
-
f"""{
|
137
|
+
f"""{TAB}{col_name}_entity = single_relationship("{wh_name_to_classname[col.entity_link]}", {col_name})"""
|
114
138
|
)
|
115
139
|
import_strings.append(
|
116
140
|
"from liminal.orm.relationship import single_relationship"
|
117
141
|
)
|
118
142
|
else:
|
119
143
|
relationship_strings.append(
|
120
|
-
f"""{
|
144
|
+
f"""{TAB}{col_name}_entities = multi_relationship("{wh_name_to_classname[col.entity_link]}", {col_name})"""
|
121
145
|
)
|
122
146
|
import_strings.append(
|
123
147
|
"from liminal.orm.relationship import multi_relationship"
|
@@ -125,11 +149,11 @@ def generate_all_entity_schema_files(
|
|
125
149
|
for col_name, col in columns.items():
|
126
150
|
if not col.required and col.type:
|
127
151
|
init_strings.append(
|
128
|
-
f"""{
|
152
|
+
f"""{TAB}{col_name}: {convert_benchling_type_to_python_type(col.type).__name__} | None = None,"""
|
129
153
|
)
|
130
154
|
init_strings.append("):")
|
131
155
|
for col_name in columns.keys():
|
132
|
-
init_strings.append(f"{
|
156
|
+
init_strings.append(f"{TAB}self.{col_name} = {col_name}")
|
133
157
|
if len(dropdowns) > 0:
|
134
158
|
import_strings.append(f"from ...dropdowns import {', '.join(dropdowns)}")
|
135
159
|
if name_template != NameTemplate():
|
@@ -141,7 +165,7 @@ def generate_all_entity_schema_files(
|
|
141
165
|
for col_name, col in columns.items():
|
142
166
|
if col.dropdown_link:
|
143
167
|
init_strings.append(
|
144
|
-
|
168
|
+
TAB
|
145
169
|
+ dropdown_name_to_classname_map[col.dropdown_link]
|
146
170
|
+ f".validate({col_name})"
|
147
171
|
)
|
@@ -149,7 +173,7 @@ def generate_all_entity_schema_files(
|
|
149
173
|
columns_string = "\n".join(column_strings)
|
150
174
|
relationship_string = "\n".join(relationship_strings)
|
151
175
|
import_string = "\n".join(list(set(import_strings)))
|
152
|
-
init_string = f"\n{
|
176
|
+
init_string = f"\n{TAB}".join(init_strings) if len(columns) > 0 else ""
|
153
177
|
full_content = f"""{import_string}
|
154
178
|
|
155
179
|
|
@@ -198,3 +222,23 @@ class {classname}(BaseModel, {get_entity_mixin(schema_properties.entity_type)}):
|
|
198
222
|
print(
|
199
223
|
f"[green]Generated {write_path / '__init__.py'} with {len(models)} entity schema imports."
|
200
224
|
)
|
225
|
+
|
226
|
+
|
227
|
+
def _get_dropdown_name_to_classname_map(
|
228
|
+
benchling_service: BenchlingService,
|
229
|
+
) -> dict[str, str]:
|
230
|
+
"""Gets the dropdown name to classname map.
|
231
|
+
If there are dropdowns imported, use BenchlingDropdown.get_all_subclasses()
|
232
|
+
Otherwise, it will query for Benchling dropdowns and use those.
|
233
|
+
"""
|
234
|
+
if len(BaseDropdown.get_all_subclasses()) > 0:
|
235
|
+
return {
|
236
|
+
dropdown.__benchling_name__: dropdown.__name__
|
237
|
+
for dropdown in BaseDropdown.get_all_subclasses()
|
238
|
+
}
|
239
|
+
benchling_dropdowns = get_benchling_dropdowns_dict(benchling_service)
|
240
|
+
if len(benchling_dropdowns) > 0:
|
241
|
+
raise Exception(
|
242
|
+
"No dropdowns found locally. Please ensure your env.py file imports your dropdown classes or generate dropdowns from your Benchling tenant first."
|
243
|
+
)
|
244
|
+
return {}
|
@@ -536,9 +536,12 @@ class UpdateEntitySchemaField(BaseOperation):
|
|
536
536
|
return f"{self.wh_schema_name}: Entity schema field '{self.wh_field_name}' in Benchling is different than in code: {str(self.update_props)}."
|
537
537
|
|
538
538
|
def validate(self, benchling_service: BenchlingService) -> None:
|
539
|
-
|
540
|
-
|
541
|
-
|
539
|
+
try:
|
540
|
+
tag_schema = TagSchemaModel.get_one_cached(
|
541
|
+
benchling_service, self.wh_schema_name
|
542
|
+
)
|
543
|
+
except Exception:
|
544
|
+
return
|
542
545
|
if (
|
543
546
|
benchling_service.connection.config_flags.schemas_enable_change_warehouse_name
|
544
547
|
is False
|
@@ -306,8 +306,8 @@ class BaseModel(Generic[T], Base):
|
|
306
306
|
|
307
307
|
Returns
|
308
308
|
-------
|
309
|
-
|
310
|
-
|
309
|
+
DataFrame
|
310
|
+
A pandas dataframe of all entities from the database.
|
311
311
|
"""
|
312
312
|
query = cls.query(session)
|
313
313
|
return pd.read_sql(query.statement, session.connection())
|