liminal-orm 3.0.0__tar.gz → 3.1.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.
Files changed (161) hide show
  1. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/PKG-INFO +1 -1
  2. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/liminal/base/properties/base_field_properties.py +3 -3
  3. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/liminal/cli/cli.py +18 -17
  4. {liminal_orm-3.0.0/liminal/migrate → liminal_orm-3.1.0/liminal/cli}/utils.py +25 -6
  5. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/liminal/connection/benchling_connection.py +16 -6
  6. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/liminal/entity_schemas/operations.py +14 -18
  7. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/liminal/entity_schemas/tag_schema_models.py +6 -2
  8. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/liminal/enums/name_template_part_type.py +2 -0
  9. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/liminal/external/__init__.py +3 -0
  10. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/liminal/orm/base_model.py +1 -1
  11. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/liminal/orm/name_template_parts.py +15 -0
  12. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/pyproject.toml +1 -1
  13. liminal_orm-3.0.0/liminal/.DS_Store +0 -0
  14. liminal_orm-3.0.0/liminal/base/__pycache__/__init__.cpython-310.pyc +0 -0
  15. liminal_orm-3.0.0/liminal/base/__pycache__/base.cpython-310.pyc +0 -0
  16. liminal_orm-3.0.0/liminal/base/__pycache__/base_dropdown.cpython-310.pyc +0 -0
  17. liminal_orm-3.0.0/liminal/base/__pycache__/base_operation.cpython-310.pyc +0 -0
  18. liminal_orm-3.0.0/liminal/base/__pycache__/base_validation_filters.cpython-310.pyc +0 -0
  19. liminal_orm-3.0.0/liminal/base/__pycache__/benchling_base_model.cpython-310.pyc +0 -0
  20. liminal_orm-3.0.0/liminal/base/__pycache__/benchling_column.cpython-310.pyc +0 -0
  21. liminal_orm-3.0.0/liminal/base/__pycache__/benchling_dropdown.cpython-310.pyc +0 -0
  22. liminal_orm-3.0.0/liminal/base/__pycache__/benchling_field_properties.cpython-310.pyc +0 -0
  23. liminal_orm-3.0.0/liminal/base/__pycache__/benchling_schema_properties.cpython-310.pyc +0 -0
  24. liminal_orm-3.0.0/liminal/base/__pycache__/callable_operation.cpython-310.pyc +0 -0
  25. liminal_orm-3.0.0/liminal/base/__pycache__/column.cpython-310.pyc +0 -0
  26. liminal_orm-3.0.0/liminal/base/__pycache__/compare_operation.cpython-310.pyc +0 -0
  27. liminal_orm-3.0.0/liminal/base/__pycache__/field_properties.cpython-310.pyc +0 -0
  28. liminal_orm-3.0.0/liminal/base/__pycache__/name_template_components.cpython-310.pyc +0 -0
  29. liminal_orm-3.0.0/liminal/base/__pycache__/name_template_parts.cpython-310.pyc +0 -0
  30. liminal_orm-3.0.0/liminal/base/__pycache__/schema_properties.cpython-310.pyc +0 -0
  31. liminal_orm-3.0.0/liminal/base/__pycache__/str_enum.cpython-310.pyc +0 -0
  32. liminal_orm-3.0.0/liminal/base/__pycache__/unset.cpython-310.pyc +0 -0
  33. liminal_orm-3.0.0/liminal/base/__pycache__/user.cpython-310.pyc +0 -0
  34. liminal_orm-3.0.0/liminal/base/properties/__pycache__/NoDropdown.cpython-310.pyc +0 -0
  35. liminal_orm-3.0.0/liminal/base/properties/__pycache__/__init__.cpython-310.pyc +0 -0
  36. liminal_orm-3.0.0/liminal/base/properties/__pycache__/base_field_properties.cpython-310.pyc +0 -0
  37. liminal_orm-3.0.0/liminal/base/properties/__pycache__/base_name_template.cpython-310.pyc +0 -0
  38. liminal_orm-3.0.0/liminal/base/properties/__pycache__/base_schema_properties.cpython-310.pyc +0 -0
  39. liminal_orm-3.0.0/liminal/base/properties/__pycache__/field_properties.cpython-310.pyc +0 -0
  40. liminal_orm-3.0.0/liminal/base/properties/__pycache__/schema_properties.cpython-310.pyc +0 -0
  41. liminal_orm-3.0.0/liminal/cli/__pycache__/cli.cpython-310.pyc +0 -0
  42. liminal_orm-3.0.0/liminal/cli/__pycache__/controller.cpython-310.pyc +0 -0
  43. liminal_orm-3.0.0/liminal/cli/__pycache__/live_test_dropdown_migration.cpython-310.pyc +0 -0
  44. liminal_orm-3.0.0/liminal/cli/__pycache__/live_test_entity_schema_migration.cpython-310.pyc +0 -0
  45. liminal_orm-3.0.0/liminal/connection/__pycache__/__init__.cpython-310.pyc +0 -0
  46. liminal_orm-3.0.0/liminal/connection/__pycache__/benchling_connection.cpython-310.pyc +0 -0
  47. liminal_orm-3.0.0/liminal/connection/__pycache__/benchling_service.cpython-310.pyc +0 -0
  48. liminal_orm-3.0.0/liminal/dropdowns/__pycache__/api.cpython-310.pyc +0 -0
  49. liminal_orm-3.0.0/liminal/dropdowns/__pycache__/compare.cpython-310.pyc +0 -0
  50. liminal_orm-3.0.0/liminal/dropdowns/__pycache__/generate_files.cpython-310.pyc +0 -0
  51. liminal_orm-3.0.0/liminal/dropdowns/__pycache__/operations.cpython-310.pyc +0 -0
  52. liminal_orm-3.0.0/liminal/dropdowns/__pycache__/utils.cpython-310.pyc +0 -0
  53. liminal_orm-3.0.0/liminal/entity_schemas/__pycache__/api.cpython-310.pyc +0 -0
  54. liminal_orm-3.0.0/liminal/entity_schemas/__pycache__/compare.cpython-310.pyc +0 -0
  55. liminal_orm-3.0.0/liminal/entity_schemas/__pycache__/entity_schema_models.cpython-310.pyc +0 -0
  56. liminal_orm-3.0.0/liminal/entity_schemas/__pycache__/generate_files.cpython-310.pyc +0 -0
  57. liminal_orm-3.0.0/liminal/entity_schemas/__pycache__/operations.cpython-310.pyc +0 -0
  58. liminal_orm-3.0.0/liminal/entity_schemas/__pycache__/schemas.cpython-310.pyc +0 -0
  59. liminal_orm-3.0.0/liminal/entity_schemas/__pycache__/tag_schema_models.cpython-310.pyc +0 -0
  60. liminal_orm-3.0.0/liminal/entity_schemas/__pycache__/utils.cpython-310.pyc +0 -0
  61. liminal_orm-3.0.0/liminal/enums/__pycache__/__init__.cpython-310.pyc +0 -0
  62. liminal_orm-3.0.0/liminal/enums/__pycache__/benchling_api_field_type.cpython-310.pyc +0 -0
  63. liminal_orm-3.0.0/liminal/enums/__pycache__/benchling_dropdown.cpython-310.pyc +0 -0
  64. liminal_orm-3.0.0/liminal/enums/__pycache__/benchling_entity_type.cpython-310.pyc +0 -0
  65. liminal_orm-3.0.0/liminal/enums/__pycache__/benchling_enum.cpython-310.pyc +0 -0
  66. liminal_orm-3.0.0/liminal/enums/__pycache__/benchling_field_api_type.cpython-310.pyc +0 -0
  67. liminal_orm-3.0.0/liminal/enums/__pycache__/benchling_field_type.cpython-310.pyc +0 -0
  68. liminal_orm-3.0.0/liminal/enums/__pycache__/benchling_folder_item_type.cpython-310.pyc +0 -0
  69. liminal_orm-3.0.0/liminal/enums/__pycache__/benchling_naming_strategy.cpython-310.pyc +0 -0
  70. liminal_orm-3.0.0/liminal/enums/__pycache__/benchling_report_level.cpython-310.pyc +0 -0
  71. liminal_orm-3.0.0/liminal/enums/__pycache__/benchling_sequence_type.cpython-310.pyc +0 -0
  72. liminal_orm-3.0.0/liminal/enums/__pycache__/name_template_part_type.cpython-310.pyc +0 -0
  73. liminal_orm-3.0.0/liminal/enums/__pycache__/sequence_constraint.cpython-310.pyc +0 -0
  74. liminal_orm-3.0.0/liminal/enums/__pycache__/sequence_constraints.cpython-310.pyc +0 -0
  75. liminal_orm-3.0.0/liminal/enums/__pycache__/str_enum.cpython-310.pyc +0 -0
  76. liminal_orm-3.0.0/liminal/enums/__pycache__/undefined.cpython-310.pyc +0 -0
  77. liminal_orm-3.0.0/liminal/external/__pycache__/__init__.cpython-310.pyc +0 -0
  78. liminal_orm-3.0.0/liminal/migrate/__pycache__/components.cpython-310.pyc +0 -0
  79. liminal_orm-3.0.0/liminal/migrate/__pycache__/revision.cpython-310.pyc +0 -0
  80. liminal_orm-3.0.0/liminal/migrate/__pycache__/revisions_timeline.cpython-310.pyc +0 -0
  81. liminal_orm-3.0.0/liminal/migrate/__pycache__/utils.cpython-310.pyc +0 -0
  82. liminal_orm-3.0.0/liminal/orm/__pycache__/__init__.cpython-310.pyc +0 -0
  83. liminal_orm-3.0.0/liminal/orm/__pycache__/base.cpython-310.pyc +0 -0
  84. liminal_orm-3.0.0/liminal/orm/__pycache__/base_model.cpython-310.pyc +0 -0
  85. liminal_orm-3.0.0/liminal/orm/__pycache__/column.cpython-310.pyc +0 -0
  86. liminal_orm-3.0.0/liminal/orm/__pycache__/mixins.cpython-310.pyc +0 -0
  87. liminal_orm-3.0.0/liminal/orm/__pycache__/name_template.cpython-310.pyc +0 -0
  88. liminal_orm-3.0.0/liminal/orm/__pycache__/name_template_parts.cpython-310.pyc +0 -0
  89. liminal_orm-3.0.0/liminal/orm/__pycache__/relationship.cpython-310.pyc +0 -0
  90. liminal_orm-3.0.0/liminal/orm/__pycache__/schema_properties.cpython-310.pyc +0 -0
  91. liminal_orm-3.0.0/liminal/orm/__pycache__/user.cpython-310.pyc +0 -0
  92. liminal_orm-3.0.0/liminal/orm/base_tables/__pycache__/__init__.cpython-310.pyc +0 -0
  93. liminal_orm-3.0.0/liminal/orm/base_tables/__pycache__/registry_entity.cpython-310.pyc +0 -0
  94. liminal_orm-3.0.0/liminal/orm/base_tables/__pycache__/schema.cpython-310.pyc +0 -0
  95. liminal_orm-3.0.0/liminal/orm/base_tables/__pycache__/user.cpython-310.pyc +0 -0
  96. liminal_orm-3.0.0/liminal/tests/.DS_Store +0 -0
  97. liminal_orm-3.0.0/liminal/tests/__pycache__/__init__.cpython-310.pyc +0 -0
  98. liminal_orm-3.0.0/liminal/tests/__pycache__/conftest.cpython-310-pytest-8.3.3.pyc +0 -0
  99. liminal_orm-3.0.0/liminal/tests/__pycache__/test_dropdown_compare.cpython-310-pytest-8.3.3.pyc +0 -0
  100. liminal_orm-3.0.0/liminal/tests/__pycache__/test_entity_schema_compare.cpython-310-pytest-8.3.3.pyc +0 -0
  101. liminal_orm-3.0.0/liminal/unit_dictionary/__pycache__/utils.cpython-310.pyc +0 -0
  102. liminal_orm-3.0.0/liminal/validation/__pycache__/__init__.cpython-310.pyc +0 -0
  103. liminal_orm-3.0.0/liminal/validation/__pycache__/validation_report_level.cpython-310.pyc +0 -0
  104. liminal_orm-3.0.0/liminal/validation/__pycache__/validation_severity.cpython-310.pyc +0 -0
  105. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/LICENSE.md +0 -0
  106. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/README.md +0 -0
  107. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/liminal/__init__.py +0 -0
  108. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/liminal/base/base_dropdown.py +0 -0
  109. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/liminal/base/base_operation.py +0 -0
  110. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/liminal/base/base_validation_filters.py +0 -0
  111. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/liminal/base/compare_operation.py +0 -0
  112. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/liminal/base/name_template_parts.py +0 -0
  113. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/liminal/base/properties/base_name_template.py +0 -0
  114. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/liminal/base/properties/base_schema_properties.py +0 -0
  115. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/liminal/base/str_enum.py +0 -0
  116. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/liminal/cli/controller.py +0 -0
  117. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/liminal/cli/live_test_dropdown_migration.py +0 -0
  118. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/liminal/cli/live_test_entity_schema_migration.py +0 -0
  119. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/liminal/connection/__init__.py +0 -0
  120. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/liminal/connection/benchling_service.py +0 -0
  121. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/liminal/dropdowns/api.py +0 -0
  122. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/liminal/dropdowns/compare.py +0 -0
  123. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/liminal/dropdowns/generate_files.py +0 -0
  124. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/liminal/dropdowns/operations.py +0 -0
  125. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/liminal/dropdowns/utils.py +0 -0
  126. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/liminal/entity_schemas/api.py +0 -0
  127. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/liminal/entity_schemas/compare.py +0 -0
  128. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/liminal/entity_schemas/entity_schema_models.py +0 -0
  129. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/liminal/entity_schemas/generate_files.py +0 -0
  130. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/liminal/entity_schemas/utils.py +0 -0
  131. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/liminal/enums/__init__.py +0 -0
  132. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/liminal/enums/benchling_api_field_type.py +0 -0
  133. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/liminal/enums/benchling_entity_type.py +0 -0
  134. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/liminal/enums/benchling_field_type.py +0 -0
  135. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/liminal/enums/benchling_folder_item_type.py +0 -0
  136. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/liminal/enums/benchling_naming_strategy.py +0 -0
  137. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/liminal/enums/benchling_sequence_type.py +0 -0
  138. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/liminal/enums/sequence_constraint.py +0 -0
  139. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/liminal/mappers.py +0 -0
  140. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/liminal/migrate/components.py +0 -0
  141. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/liminal/migrate/revision.py +0 -0
  142. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/liminal/migrate/revisions_timeline.py +0 -0
  143. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/liminal/orm/base.py +0 -0
  144. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/liminal/orm/base_tables/registry_entity.py +0 -0
  145. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/liminal/orm/base_tables/schema.py +0 -0
  146. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/liminal/orm/base_tables/user.py +0 -0
  147. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/liminal/orm/column.py +0 -0
  148. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/liminal/orm/mixins.py +0 -0
  149. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/liminal/orm/name_template.py +0 -0
  150. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/liminal/orm/relationship.py +0 -0
  151. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/liminal/orm/schema_properties.py +0 -0
  152. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/liminal/py.typed +0 -0
  153. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/liminal/tests/__init__.py +0 -0
  154. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/liminal/tests/conftest.py +0 -0
  155. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/liminal/tests/from benchling_sdk.py +0 -0
  156. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/liminal/tests/test_dropdown_compare.py +0 -0
  157. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/liminal/tests/test_entity_schema_compare.py +0 -0
  158. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/liminal/unit_dictionary/utils.py +0 -0
  159. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/liminal/utils.py +0 -0
  160. {liminal_orm-3.0.0 → liminal_orm-3.1.0}/liminal/validation/__init__.py +0 -0
  161. {liminal_orm-3.0.0 → liminal_orm-3.1.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.0.0
3
+ Version: 3.1.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
@@ -77,18 +77,18 @@ class BaseFieldProperties(BaseModel):
77
77
  for s in BenchlingBaseModel.get_all_subclasses()
78
78
  ]:
79
79
  raise ValueError(
80
- f"Could not find {self.entity_link} as a warehouse name for any currently defined schemas."
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"Could not find {self.dropdown_link} as a name to any defined dropdowns."
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"Invalid warehouse name '{wh_name}'. It should only contain alphanumeric characters and underscores."
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
- ENV_FILE_PATH = Path("liminal/env.py")
38
- VERSIONS_DIR_PATH = Path("liminal/versions")
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
- Path("liminal").mkdir()
48
- Path("liminal/versions").mkdir()
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 = read_local_env_file(
89
- ENV_FILE_PATH, benchling_tenant
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 = read_local_env_file(
108
- ENV_FILE_PATH, benchling_tenant
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 = read_local_env_file(
129
- ENV_FILE_PATH, benchling_tenant
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 = read_local_env_file(
152
- ENV_FILE_PATH, benchling_tenant
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 = read_local_env_file(
180
- ENV_FILE_PATH, benchling_tenant
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 = read_local_env_file(
220
- ENV_FILE_PATH, benchling_tenant
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 _check_env_file(env_file_path: Path) -> None:
8
- """Raises an exception if the env.py file does not exist at the given path."""
9
- if not env_file_path.exists():
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
- f"No {env_file_path} file found. Run `liminal init` or check your current working directory for liminal/env.py."
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 read_local_env_file(
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")
@@ -81,14 +81,13 @@ class CreateEntitySchema(BaseOperation):
81
81
 
82
82
  def validate(self, benchling_service: BenchlingService) -> None:
83
83
  if (
84
- not benchling_service.connection.warehouse_access
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"Warehouse access is required to set a custom field warehouse name. \
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"Updating properties for entity schema {self.wh_schema_name}: {str(self.update_props)}."
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"Schema properties for {self.wh_schema_name} are different in code versus Benchling: {str(self.update_props)}."
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.warehouse_access
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
- "Warehouse access is required to change the schema warehouse name. \
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:
@@ -385,13 +383,12 @@ class CreateEntitySchemaField(BaseOperation):
385
383
 
386
384
  def validate(self, benchling_service: BenchlingService) -> None:
387
385
  if (
388
- not benchling_service.connection.warehouse_access
386
+ benchling_service.connection.config_flags.schemas_enable_change_warehouse_name
387
+ is False
389
388
  and self.field_props.warehouse_name != to_snake_case(self.field_props.name)
390
389
  ):
391
390
  raise ValueError(
392
- f"Warehouse access is required to set a custom field warehouse name. \
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."
391
+ 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_props.name)}."
395
392
  )
396
393
  if (
397
394
  self.field_props.unit_name
@@ -538,13 +535,12 @@ class UpdateEntitySchemaField(BaseOperation):
538
535
  benchling_service, self.wh_schema_name
539
536
  )
540
537
  if (
541
- not benchling_service.connection.warehouse_access
538
+ benchling_service.connection.config_flags.schemas_enable_change_warehouse_name
539
+ is False
542
540
  and self.update_props.warehouse_name is not None
543
541
  ):
544
542
  raise ValueError(
545
- "Warehouse access is required to change the field warehouse name. \
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."
543
+ 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
544
  )
549
545
  if "unit_name" in self.update_props.model_dump(exclude_unset=True):
550
546
  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."
@@ -58,8 +58,12 @@ class NameTemplatePartModel(BaseModel):
58
58
  field = next((f for f in fields if f.systemName == wh_field_name), None)
59
59
  if field is None:
60
60
  raise ValueError(f"Field {wh_field_name} not found in fields")
61
- field_id = field.id
62
- if part.component_type == NameTemplatePartType.CHILD_ENTITY_LOT_NUMBER:
61
+ field_id = field.apiId
62
+ if (
63
+ part.component_type == NameTemplatePartType.CHILD_ENTITY_LOT_NUMBER
64
+ or part.component_type
65
+ == NameTemplatePartType.LINKED_BIOENTITY_REGISTRY_IDENTIFIER
66
+ ):
63
67
  if not field.isParentLink:
64
68
  raise ValueError(
65
69
  f"Field {wh_field_name} is not a parent link field. The field for type {part.component_type} must be a parent link field."
@@ -8,5 +8,7 @@ class NameTemplatePartType(StrEnum):
8
8
  CREATION_DATE = "CREATED_AT_DATE"
9
9
  FIELD = "FIELD"
10
10
  REGISTRY_IDENTIFIER_NUMBER = "REGISTRY_IDENTIFIER_NUMBER"
11
+ LINKED_BIOENTITY_REGISTRY_IDENTIFIER = "LINKED_BIOENTITY_REGISTRY_IDENTIFIER"
11
12
  PROJECT = "PROJECT"
12
13
  CHILD_ENTITY_LOT_NUMBER = "CHILD_ENTITY_LOT_NUMBER"
14
+ COMPLEX_POLYMER_COMPONENT = "COMPLEX_POLYMER_COMPONENT"
@@ -34,9 +34,12 @@ from liminal.enums import (
34
34
  BenchlingSequenceType,
35
35
  )
36
36
  from liminal.orm.name_template_parts import (
37
+ ComplexPolymerComponentPart,
37
38
  CreationDatePart,
38
39
  CreationYearPart,
39
40
  FieldPart,
41
+ ParentLotNumberPart,
42
+ ParentRegistryIdPart,
40
43
  ProjectPart,
41
44
  RegistryIdentifierNumberPart,
42
45
  SeparatorPart,
@@ -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 schema {cls.__schema_properties__.name}."
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)
@@ -74,6 +74,13 @@ class ParentLotNumberPart(NameTemplatePart):
74
74
  wh_field_name: str
75
75
 
76
76
 
77
+ class ParentRegistryIdPart(NameTemplatePart):
78
+ component_type: ClassVar[NameTemplatePartType] = (
79
+ NameTemplatePartType.LINKED_BIOENTITY_REGISTRY_IDENTIFIER
80
+ )
81
+ wh_field_name: str
82
+
83
+
77
84
  class RegistryIdentifierNumberPart(NameTemplatePart):
78
85
  component_type: ClassVar[NameTemplatePartType] = (
79
86
  NameTemplatePartType.REGISTRY_IDENTIFIER_NUMBER
@@ -84,6 +91,12 @@ class ProjectPart(NameTemplatePart):
84
91
  component_type: ClassVar[NameTemplatePartType] = NameTemplatePartType.PROJECT
85
92
 
86
93
 
94
+ class ComplexPolymerComponentPart(NameTemplatePart):
95
+ component_type: ClassVar[NameTemplatePartType] = (
96
+ NameTemplatePartType.COMPLEX_POLYMER_COMPONENT
97
+ )
98
+
99
+
87
100
  NameTemplateParts = (
88
101
  SeparatorPart
89
102
  | TextPart
@@ -93,4 +106,6 @@ NameTemplateParts = (
93
106
  | RegistryIdentifierNumberPart
94
107
  | ProjectPart
95
108
  | ParentLotNumberPart
109
+ | ParentRegistryIdPart
110
+ | ComplexPolymerComponentPart
96
111
  )
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "liminal-orm"
3
- version = "3.0.0"
3
+ version = "3.1.0"
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
File without changes
File without changes