liminal-orm 4.1.1__tar.gz → 4.1.2__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 (74) hide show
  1. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/PKG-INFO +4 -3
  2. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/cli/cli.py +2 -2
  3. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/dropdowns/generate_files.py +14 -6
  4. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/entity_schemas/generate_files.py +39 -33
  5. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/results_schemas/generate_files.py +24 -18
  6. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/pyproject.toml +1 -1
  7. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/LICENSE.md +0 -0
  8. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/README.md +0 -0
  9. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/__init__.py +0 -0
  10. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/base/base_dropdown.py +0 -0
  11. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/base/base_operation.py +0 -0
  12. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/base/base_validation_filters.py +0 -0
  13. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/base/compare_operation.py +0 -0
  14. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/base/name_template_parts.py +0 -0
  15. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/base/properties/base_field_properties.py +0 -0
  16. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/base/properties/base_name_template.py +0 -0
  17. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/base/properties/base_schema_properties.py +0 -0
  18. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/base/str_enum.py +0 -0
  19. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/cli/controller.py +0 -0
  20. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/cli/live_test_dropdown_migration.py +0 -0
  21. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/cli/live_test_entity_schema_migration.py +0 -0
  22. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/cli/utils.py +0 -0
  23. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/connection/__init__.py +0 -0
  24. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/connection/benchling_connection.py +0 -0
  25. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/connection/benchling_service.py +0 -0
  26. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/dropdowns/api.py +0 -0
  27. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/dropdowns/compare.py +0 -0
  28. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/dropdowns/operations.py +0 -0
  29. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/dropdowns/utils.py +0 -0
  30. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/entity_schemas/api.py +0 -0
  31. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/entity_schemas/compare.py +0 -0
  32. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/entity_schemas/entity_schema_models.py +0 -0
  33. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/entity_schemas/operations.py +0 -0
  34. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/entity_schemas/tag_schema_models.py +0 -0
  35. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/entity_schemas/utils.py +0 -0
  36. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/enums/__init__.py +0 -0
  37. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/enums/benchling_api_field_type.py +0 -0
  38. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/enums/benchling_entity_type.py +0 -0
  39. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/enums/benchling_field_type.py +0 -0
  40. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/enums/benchling_folder_item_type.py +0 -0
  41. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/enums/benchling_naming_strategy.py +0 -0
  42. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/enums/benchling_sequence_type.py +0 -0
  43. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/enums/name_template_part_type.py +0 -0
  44. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/enums/sequence_constraint.py +0 -0
  45. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/external/__init__.py +0 -0
  46. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/mappers.py +0 -0
  47. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/migrate/components.py +0 -0
  48. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/migrate/revision.py +0 -0
  49. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/migrate/revisions_timeline.py +0 -0
  50. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/orm/base.py +0 -0
  51. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/orm/base_model.py +0 -0
  52. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/orm/base_results_model.py +0 -0
  53. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/orm/base_tables/registry_entity.py +0 -0
  54. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/orm/base_tables/schema.py +0 -0
  55. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/orm/base_tables/user.py +0 -0
  56. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/orm/column.py +0 -0
  57. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/orm/mixins.py +0 -0
  58. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/orm/name_template.py +0 -0
  59. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/orm/name_template_parts.py +0 -0
  60. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/orm/relationship.py +0 -0
  61. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/orm/results_schema_properties.py +0 -0
  62. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/orm/schema_properties.py +0 -0
  63. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/py.typed +0 -0
  64. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/results_schemas/models/results_schema_model.py +0 -0
  65. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/results_schemas/utils.py +0 -0
  66. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/tests/__init__.py +0 -0
  67. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/tests/conftest.py +0 -0
  68. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/tests/from benchling_sdk.py +0 -0
  69. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/tests/test_dropdown_compare.py +0 -0
  70. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/tests/test_entity_schema_compare.py +0 -0
  71. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/unit_dictionary/utils.py +0 -0
  72. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/utils.py +0 -0
  73. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/validation/__init__.py +0 -0
  74. {liminal_orm-4.1.1 → liminal_orm-4.1.2}/liminal/validation/validation_severity.py +0 -0
@@ -1,8 +1,7 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.3
2
2
  Name: liminal-orm
3
- Version: 4.1.1
3
+ Version: 4.1.2
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
- Home-page: https://github.com/dynotx/liminal-orm
6
5
  Author: DynoTx Open Source
7
6
  Author-email: opensource@dynotx.com
8
7
  Requires-Python: >=3.9,<4
@@ -11,6 +10,7 @@ Classifier: Programming Language :: Python :: 3.9
11
10
  Classifier: Programming Language :: Python :: 3.10
12
11
  Classifier: Programming Language :: Python :: 3.11
13
12
  Classifier: Programming Language :: Python :: 3.12
13
+ Classifier: Programming Language :: Python :: 3.13
14
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)
@@ -26,6 +26,7 @@ Requires-Dist: tornado (==6.5.0)
26
26
  Requires-Dist: typer (>=0.12.5,<0.13.0)
27
27
  Project-URL: Bug Tracker, https://github.com/dynotx/liminal-orm/issues
28
28
  Project-URL: Documentation, https://dynotx.github.io/liminal-orm/
29
+ Project-URL: Homepage, https://github.com/dynotx/liminal-orm
29
30
  Project-URL: Repository, https://github.com/dynotx/liminal-orm
30
31
  Description-Content-Type: text/markdown
31
32
 
@@ -83,7 +83,7 @@ connection = BenchlingConnection(
83
83
 
84
84
  @app.command(
85
85
  name="generate-files",
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.",
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 not overwrite existing files.",
87
87
  )
88
88
  def generate_files(
89
89
  benchling_tenant: str = typer.Argument(
@@ -117,7 +117,7 @@ def generate_files(
117
117
  False,
118
118
  "-o",
119
119
  "--overwrite",
120
- help="Overwrite existing files within the {write_path}/dropdowns/, {write_path}/entity_schemas/, and {write_path}/results_schemas/ directories.",
120
+ help="Overwrite the whole write directory at the given path.",
121
121
  ),
122
122
  ) -> None:
123
123
  _, benchling_connection = read_local_liminal_dir(LIMINAL_DIR_PATH, benchling_tenant)
@@ -21,7 +21,7 @@ def generate_all_dropdown_files(
21
21
  write_path : Path
22
22
  The path to write the generated files to. dropdowns/ directory will be created within this path.
23
23
  overwrite : bool
24
- Whether to overwrite existing the existing dropdowns/ directory.
24
+ Whether to overwrite existing files in the dropdowns/ directory.
25
25
  """
26
26
  write_path = write_path / "dropdowns"
27
27
  if write_path.exists() and overwrite:
@@ -33,6 +33,7 @@ def generate_all_dropdown_files(
33
33
 
34
34
  dropdowns = get_benchling_dropdowns_dict(benchling_service)
35
35
  file_names_to_classname = []
36
+ num_files_written = 0
36
37
  for dropdown_name, dropdown_options in dropdowns.items():
37
38
  dropdown_values = [option.name for option in dropdown_options.options]
38
39
  options_list = str(dropdown_values).replace("'", '"')
@@ -46,8 +47,10 @@ class {classname}(BaseDropdown):
46
47
  __allowed_values__ = {options_list}
47
48
  """
48
49
  filename = to_snake_case(dropdown_name) + ".py"
49
- with open(write_path / filename, "w") as file:
50
- file.write(dropdown_content)
50
+ if overwrite or not (write_path / filename).exists():
51
+ with open(write_path / filename, "w") as file:
52
+ file.write(dropdown_content)
53
+ num_files_written += 1
51
54
  file_names_to_classname.append((filename, classname))
52
55
 
53
56
  file_names_to_classname.sort(key=lambda x: x[0])
@@ -55,8 +58,13 @@ class {classname}(BaseDropdown):
55
58
  f"from .{filename[:-3]} import {classname}"
56
59
  for filename, classname in file_names_to_classname
57
60
  )
58
- with open(write_path / "__init__.py", "w") as file:
59
- file.write(import_statements)
61
+ if num_files_written > 0:
62
+ with open(write_path / "__init__.py", "w") as file:
63
+ file.write(import_statements)
60
64
  print(
61
- f"[green]Generated {write_path / '__init__.py'} with {len(file_names_to_classname)} dropdown imports."
65
+ f"[green]Generated {write_path / '__init__.py'} with {len(file_names_to_classname)} dropdown imports. {num_files_written} dropdown files written."
66
+ )
67
+ else:
68
+ print(
69
+ "[green dim]No new dropdown files to be written. If you want to overwrite existing files, run with -o flag."
62
70
  )
@@ -63,7 +63,7 @@ def generate_all_entity_schema_files(
63
63
  write_path : Path
64
64
  The path to write the generated files to. entity_schemas/ directory will be created within this path.
65
65
  overwrite : bool
66
- Whether to overwrite existing the existing entity_schemas/ directory.
66
+ Whether to overwrite existing files in the entity_schemas/ directory.
67
67
  """
68
68
  write_path = write_path / "entity_schemas"
69
69
  if write_path.exists() and overwrite:
@@ -76,6 +76,7 @@ def generate_all_entity_schema_files(
76
76
  models = get_converted_tag_schemas(benchling_service)
77
77
  has_date = False
78
78
  subdirectory_map: dict[str, list[tuple[str, str]]] = {}
79
+ subdirectory_num_files_written: dict[str, int] = {}
79
80
  dropdown_name_to_classname_map = _get_dropdown_name_to_classname_map(
80
81
  benchling_service
81
82
  )
@@ -188,39 +189,45 @@ class {classname}(BaseModel, {get_entity_mixin(schema_properties.entity_type)}):
188
189
  {init_string}
189
190
 
190
191
  """
191
- write_directory_path = write_path / get_file_subdirectory(
192
- schema_properties.entity_type
193
- )
194
- subdirectory_map[get_file_subdirectory(schema_properties.entity_type)] = (
195
- subdirectory_map.get(
196
- get_file_subdirectory(schema_properties.entity_type), []
197
- )
198
- + [(filename, classname)]
199
- )
192
+ subdirectory_name = get_file_subdirectory(schema_properties.entity_type)
193
+ write_directory_path = write_path / subdirectory_name
194
+ if not subdirectory_map.get(subdirectory_name):
195
+ subdirectory_map[subdirectory_name] = []
196
+ subdirectory_num_files_written[subdirectory_name] = 0
197
+ subdirectory_map[subdirectory_name].append((filename, classname))
200
198
  write_directory_path.mkdir(exist_ok=True)
201
- with open(write_directory_path / filename, "w") as file:
202
- file.write(full_content)
199
+ if overwrite or not (write_directory_path / filename).exists():
200
+ with open(write_directory_path / filename, "w") as file:
201
+ file.write(full_content)
202
+ subdirectory_num_files_written[subdirectory_name] += 1
203
203
 
204
204
  for subdir, names in subdirectory_map.items():
205
- init_content = (
206
- "\n".join(
207
- f"from .{filename[:-3]} import {classname}"
208
- for filename, classname in names
205
+ if subdirectory_num_files_written[subdir] > 0:
206
+ init_content = (
207
+ "\n".join(
208
+ f"from .{filename[:-3]} import {classname}"
209
+ for filename, classname in names
210
+ )
211
+ + "\n"
209
212
  )
210
- + "\n"
211
- )
212
- with open(write_path / subdir / "__init__.py", "w") as file:
213
- file.write(init_content)
214
-
215
- with open(write_path / "__init__.py", "w") as file:
216
- file.write(
217
- "\n".join(
218
- f"from .{subdir} import * # noqa" for subdir in subdirectory_map.keys()
213
+ with open(write_path / subdir / "__init__.py", "w") as file:
214
+ file.write(init_content)
215
+
216
+ if sum(subdirectory_num_files_written.values()) > 0:
217
+ with open(write_path / "__init__.py", "w") as file:
218
+ file.write(
219
+ "\n".join(
220
+ f"from .{subdir} import * # noqa"
221
+ for subdir in subdirectory_map.keys()
222
+ )
223
+ + "\n"
219
224
  )
220
- + "\n"
221
- )
225
+ print(
226
+ f"[green]Generated {write_path / '__init__.py'} with {sum(subdirectory_num_files_written.values())} entity schema files written."
227
+ )
228
+ else:
222
229
  print(
223
- f"[green]Generated {write_path / '__init__.py'} with {len(models)} entity schema imports."
230
+ "[green dim]No new entity schema files to be written. If you want to overwrite existing files, run with -o flag."
224
231
  )
225
232
 
226
233
 
@@ -237,8 +244,7 @@ def _get_dropdown_name_to_classname_map(
237
244
  for dropdown in BaseDropdown.get_all_subclasses()
238
245
  }
239
246
  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 {}
247
+ return {
248
+ dropdown_name: to_pascal_case(dropdown_name)
249
+ for dropdown_name in benchling_dropdowns.keys()
250
+ }
@@ -29,7 +29,7 @@ def generate_all_results_schema_files(
29
29
  write_path : Path
30
30
  The path to write the generated files to. results_schemas/ directory will be created within this path.
31
31
  overwrite : bool
32
- Whether to overwrite existing the existing results_schemas/ directory.
32
+ Whether to overwrite existing files in the results_schemas/ directory.
33
33
  """
34
34
  write_path = write_path / "results_schemas"
35
35
  if write_path.exists() and overwrite:
@@ -47,6 +47,7 @@ def generate_all_results_schema_files(
47
47
  benchling_service
48
48
  )
49
49
  init_file_imports = []
50
+ num_files_written = 0
50
51
 
51
52
  for schema_properties, field_properties_dict in results_schemas:
52
53
  has_date = False
@@ -147,14 +148,21 @@ class {schema_name}(BaseResultsModel):
147
148
  {init_string}
148
149
  """
149
150
 
150
- with open(write_path / file_name, "w") as file:
151
- file.write(schema_content)
151
+ if overwrite or not (write_path / file_name).exists():
152
+ with open(write_path / file_name, "w") as file:
153
+ file.write(schema_content)
154
+ num_files_written += 1
152
155
 
153
- with open(write_path / "__init__.py", "w") as file:
154
- file.write("\n".join(init_file_imports))
155
- print(
156
- f"[green]Generated {write_path / '__init__.py'} with {len(results_schemas)} entity schema imports."
157
- )
156
+ if num_files_written > 0:
157
+ with open(write_path / "__init__.py", "w") as file:
158
+ file.write("\n".join(init_file_imports))
159
+ print(
160
+ f"[green]Generated {write_path / '__init__.py'} with {len(results_schemas)} entity schema imports. {num_files_written} results schema files written."
161
+ )
162
+ else:
163
+ print(
164
+ "[green dim]No new results schema files to be written. If you want to overwrite existing files, run with -o flag."
165
+ )
158
166
 
159
167
 
160
168
  def _get_dropdown_name_to_classname_map(
@@ -170,11 +178,10 @@ def _get_dropdown_name_to_classname_map(
170
178
  for dropdown in BaseDropdown.get_all_subclasses()
171
179
  }
172
180
  benchling_dropdowns = get_benchling_dropdowns_dict(benchling_service)
173
- if len(benchling_dropdowns) > 0:
174
- raise Exception(
175
- "No dropdowns found locally. Please ensure your env.py file imports your dropdown classes or generate dropdowns from your Benchling tenant first."
176
- )
177
- return {}
181
+ return {
182
+ dropdown_name: to_pascal_case(dropdown_name)
183
+ for dropdown_name in benchling_dropdowns.keys()
184
+ }
178
185
 
179
186
 
180
187
  def _get_entity_schemas_wh_name_to_classname(
@@ -190,8 +197,7 @@ def _get_entity_schemas_wh_name_to_classname(
190
197
  for s in BaseModel.get_all_subclasses()
191
198
  }
192
199
  tag_schemas = get_converted_tag_schemas(benchling_service)
193
- if len(tag_schemas) > 0:
194
- raise Exception(
195
- "No entity schemas found locally. Please ensure your env.py file imports your entity schema classes or generate entity schemas from your Benchling tenant first."
196
- )
197
- return {}
200
+ return {
201
+ schema_props.warehouse_name: to_pascal_case(schema_props.warehouse_name)
202
+ for schema_props, _, _ in tag_schemas
203
+ }
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "liminal-orm"
3
- version = "4.1.1"
3
+ version = "4.1.2"
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"
File without changes
File without changes