liminal-orm 4.1.1__py3-none-any.whl → 4.2.0__py3-none-any.whl

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.
@@ -1,6 +1,9 @@
1
1
  from abc import ABC
2
2
  from typing import Any
3
3
 
4
+ from liminal.connection.benchling_service import BenchlingService
5
+ from liminal.dropdowns.utils import get_benchling_dropdown_summaries
6
+
4
7
 
5
8
  class BaseDropdown(ABC):
6
9
  """_summary_
@@ -35,6 +38,30 @@ class BaseDropdown(ABC):
35
38
  cls._existing_benchling_names.add(cls.__benchling_name__)
36
39
  return super().__new__(cls, **kwargs)
37
40
 
41
+ @classmethod
42
+ def get_id(cls, benchling_service: BenchlingService) -> str:
43
+ """Connects to Benchling and returns the id of the dropdown using the __benchling_name__.
44
+
45
+ Parameters
46
+ ----------
47
+ benchling_service : BenchlingService
48
+ The Benchling service to use.
49
+
50
+ Returns
51
+ -------
52
+ str
53
+ The id of the dropdown.
54
+ """
55
+ all_dropdowns = get_benchling_dropdown_summaries(benchling_service)
56
+ dropdowns_found_by_name = [
57
+ d for d in all_dropdowns if d.name == cls.__benchling_name__
58
+ ]
59
+ if len(dropdowns_found_by_name) == 0:
60
+ raise ValueError(f"No dropdowns found with name '{cls.__benchling_name__}'")
61
+ else:
62
+ dropdown = dropdowns_found_by_name[0]
63
+ return dropdown.id
64
+
38
65
  @classmethod
39
66
  def validate(cls, *values: str | None) -> None:
40
67
  err_values = []
liminal/cli/cli.py CHANGED
@@ -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
  )
@@ -1,3 +1,4 @@
1
+ from functools import lru_cache
1
2
  from typing import Any
2
3
 
3
4
  import requests
@@ -6,7 +7,6 @@ from benchling_sdk.models import Dropdown, DropdownOption, DropdownSummary
6
7
  from pydantic import BaseModel
7
8
 
8
9
  from liminal.connection import BenchlingService
9
- from liminal.orm.base_model import BaseModel as BenchlingBaseModel
10
10
 
11
11
 
12
12
  class ArchiveRecord(BaseModel):
@@ -22,6 +22,7 @@ def get_benchling_dropdown_id_name_map(
22
22
  return {d.id: d.name for d in get_benchling_dropdown_summaries(benchling_service)}
23
23
 
24
24
 
25
+ @lru_cache
25
26
  def get_benchling_dropdown_summaries(
26
27
  benchling_service: BenchlingService,
27
28
  ) -> list[DropdownSummary]:
@@ -110,6 +111,8 @@ def dropdown_exists_in_benchling(
110
111
 
111
112
 
112
113
  def get_schemas_with_dropdown(dropdown_name: str) -> list[str]:
114
+ from liminal.orm.base_model import BaseModel as BenchlingBaseModel
115
+
113
116
  schemas_with_dropdown = []
114
117
  for model in BenchlingBaseModel.get_all_subclasses():
115
118
  for props_dict in [
@@ -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
+ }
@@ -1,3 +1,5 @@
1
+ from functools import lru_cache
2
+
1
3
  from benchling_sdk.models import EntitySchema
2
4
 
3
5
  from liminal.base.properties.base_field_properties import BaseFieldProperties
@@ -136,6 +138,7 @@ def convert_tag_schema_field_to_field_properties(
136
138
  )
137
139
 
138
140
 
141
+ @lru_cache
139
142
  def get_benchling_entity_schemas(
140
143
  benchling_service: BenchlingService,
141
144
  ) -> list[EntitySchema]:
liminal/orm/base_model.py CHANGED
@@ -13,6 +13,8 @@ from sqlalchemy.orm.decl_api import declared_attr
13
13
 
14
14
  from liminal.base.base_dropdown import BaseDropdown
15
15
  from liminal.base.base_validation_filters import BaseValidatorFilters
16
+ from liminal.connection.benchling_service import BenchlingService
17
+ from liminal.entity_schemas.utils import get_benchling_entity_schemas
16
18
  from liminal.enums import BenchlingNamingStrategy
17
19
  from liminal.enums.benchling_entity_type import BenchlingEntityType
18
20
  from liminal.enums.sequence_constraint import SequenceConstraint
@@ -279,6 +281,33 @@ class BaseModel(Generic[T], Base):
279
281
  query = query.filter(User.name.in_(base_filters.creator_full_names))
280
282
  return query
281
283
 
284
+ @classmethod
285
+ def get_id(cls, benchling_service: BenchlingService) -> str:
286
+ """Connects to Benchling and returns the id of the schema using the __schema_properties__.name.
287
+
288
+ Parameters
289
+ ----------
290
+ benchling_service : BenchlingService
291
+ The Benchling service to use.
292
+
293
+ Returns
294
+ -------
295
+ str
296
+ The id of the schema.
297
+ """
298
+ all_schemas = get_benchling_entity_schemas(benchling_service)
299
+
300
+ schemas_found_by_name = [
301
+ s for s in all_schemas if s.name == cls.__schema_properties__.name
302
+ ]
303
+ if len(schemas_found_by_name) == 0:
304
+ raise ValueError(
305
+ f"No schema found with name '{cls.__schema_properties__.name}'."
306
+ )
307
+ else:
308
+ schema = schemas_found_by_name[0]
309
+ return schema.id
310
+
282
311
  @classmethod
283
312
  def all(cls, session: Session) -> list[T]:
284
313
  """Uses the get_query method to retrieve all entities from the database.
@@ -12,9 +12,11 @@ from sqlalchemy.orm import Query, RelationshipProperty, Session, relationship
12
12
  from sqlalchemy.orm.decl_api import declared_attr
13
13
 
14
14
  from liminal.base.base_validation_filters import BaseValidatorFilters
15
+ from liminal.connection.benchling_service import BenchlingService
15
16
  from liminal.orm.base import Base
16
17
  from liminal.orm.base_tables.user import User
17
18
  from liminal.orm.results_schema_properties import ResultsSchemaProperties
19
+ from liminal.results_schemas.utils import get_benchling_results_schemas
18
20
  from liminal.validation import BenchlingValidatorReport
19
21
 
20
22
  T = TypeVar("T")
@@ -83,6 +85,33 @@ class BaseResultsModel(Generic[T], Base):
83
85
  query = query.filter(User.name.in_(base_filters.creator_full_names))
84
86
  return query
85
87
 
88
+ @classmethod
89
+ def get_id(cls, benchling_service: BenchlingService) -> str:
90
+ """Connects to Benchling and returns the id of the results schema using the __schema_properties__.name.
91
+
92
+ Parameters
93
+ ----------
94
+ benchling_service : BenchlingService
95
+ The Benchling service to use.
96
+
97
+ Returns
98
+ -------
99
+ str
100
+ The id of the results schema.
101
+ """
102
+ all_schemas = get_benchling_results_schemas(benchling_service)
103
+
104
+ schemas_found_by_name = [
105
+ s for s in all_schemas if s.name == cls.__schema_properties__.name
106
+ ]
107
+ if len(schemas_found_by_name) == 0:
108
+ raise ValueError(
109
+ f"No results schema found with name '{cls.__schema_properties__.name}'."
110
+ )
111
+ else:
112
+ schema = schemas_found_by_name[0]
113
+ return schema.id
114
+
86
115
  @classmethod
87
116
  def all(cls, session: Session) -> list[T]:
88
117
  """Uses the get_query method to retrieve all results schema rows from the database.
@@ -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,3 +1,5 @@
1
+ from functools import lru_cache
2
+
1
3
  from benchling_api_client.v2.stable.models.assay_result_schema import AssayResultSchema
2
4
 
3
5
  from liminal.base.properties.base_field_properties import BaseFieldProperties
@@ -35,14 +37,10 @@ def get_converted_results_schemas(
35
37
  return results_schemas_list
36
38
 
37
39
 
38
- def get_results_schemas_dict(
40
+ @lru_cache
41
+ def get_benchling_results_schemas(
39
42
  benchling_service: BenchlingService,
40
- ) -> dict[str, AssayResultSchema]:
41
- """This function gets all Results Schema schemas using the Benchling API and returns a dictionary of the schemas by their system name."""
42
- flattened_schemas = [
43
- s
44
- for schemas in list(benchling_service.schemas.list_assay_result_schemas())
45
- for s in schemas
43
+ ) -> list[AssayResultSchema]:
44
+ return [
45
+ s for loe in benchling_service.schemas.list_assay_result_schemas() for s in loe
46
46
  ]
47
- schemas_dict = {s.system_name: s for s in flattened_schemas}
48
- return schemas_dict
@@ -1,32 +1,27 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: liminal-orm
3
- Version: 4.1.1
3
+ Version: 4.2.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
- Home-page: https://github.com/dynotx/liminal-orm
6
- Author: DynoTx Open Source
7
- Author-email: opensource@dynotx.com
8
- Requires-Python: >=3.9,<4
9
- Classifier: Programming Language :: Python :: 3
10
- Classifier: Programming Language :: Python :: 3.9
11
- Classifier: Programming Language :: Python :: 3.10
12
- Classifier: Programming Language :: Python :: 3.11
13
- Classifier: Programming Language :: Python :: 3.12
14
- Requires-Dist: benchling-sdk (>=1.21.2,<2.0.0)
15
- Requires-Dist: bs4 (>=0.0.2,<0.0.3)
16
- Requires-Dist: lxml (>=5.3.0,<6.0.0)
17
- Requires-Dist: numpy (>=1.23.5,<2.0.0)
18
- Requires-Dist: pandas (>=1.5.3,<2.0.0)
19
- Requires-Dist: psycopg2-binary (>=2.9.10,<3.0.0)
20
- Requires-Dist: pydantic (>=2,<=2.7)
21
- Requires-Dist: requests (>=2.32.3,<3.0.0)
22
- Requires-Dist: rich (>=13.9.2,<14.0.0)
23
- Requires-Dist: sqlalchemy (<2)
24
- Requires-Dist: tenacity (>=8,<10)
25
- Requires-Dist: tornado (==6.5.0)
26
- Requires-Dist: typer (>=0.12.5,<0.13.0)
27
- Project-URL: Bug Tracker, https://github.com/dynotx/liminal-orm/issues
28
- Project-URL: Documentation, https://dynotx.github.io/liminal-orm/
5
+ Project-URL: Homepage, https://github.com/dynotx/liminal-orm
29
6
  Project-URL: Repository, https://github.com/dynotx/liminal-orm
7
+ Project-URL: Documentation, https://dynotx.github.io/liminal-orm/
8
+ Project-URL: Bug Tracker, https://github.com/dynotx/liminal-orm/issues
9
+ Author-email: DynoTx Open Source <opensource@dynotx.com>
10
+ License-File: LICENSE.md
11
+ Requires-Python: <4,>=3.9
12
+ Requires-Dist: benchling-sdk<2,>=1.21.2
13
+ Requires-Dist: bs4<0.0.3,>=0.0.2
14
+ Requires-Dist: lxml<6,>=5.3.0
15
+ Requires-Dist: numpy<2,>=1.23.5
16
+ Requires-Dist: pandas<2,>=1.5.3
17
+ Requires-Dist: psycopg2-binary<3,>=2.9.10
18
+ Requires-Dist: pydantic<=2.7,>=2
19
+ Requires-Dist: requests<3,>=2.32.3
20
+ Requires-Dist: rich<14,>=13.9.2
21
+ Requires-Dist: sqlalchemy<2
22
+ Requires-Dist: tenacity<10,>=8
23
+ Requires-Dist: tornado==6.5.0
24
+ Requires-Dist: typer<0.13,>=0.12.5
30
25
  Description-Content-Type: text/markdown
31
26
 
32
27
  # [Liminal ORM](#liminal-orm)
@@ -152,4 +147,3 @@ ORM<sup>1</sup>: Object-Relational Mapper. An ORM is a piece of software designe
152
147
  LIMS<sup>2</sup>: Laboratory Information Management System. A LIMS is a piece of software that allows you to effectively manage samples and associated data. [Benchling](https://www.benchling.com/) is an industry-leading LIMS software.
153
148
 
154
149
  CLI<sup>3</sup>: Command Line Interface. A CLI is a piece of software that allows you to interact with a software program via the command line. Liminal provides a CLI that allows you to interact with your Liminal environment. This project uses [Typer](https://github.com/fastapi/typer) to construct the CLI
155
-
@@ -1,14 +1,17 @@
1
1
  liminal/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- liminal/base/base_dropdown.py,sha256=Unk4l_5Y8rj_eSWYqzFi2BAFSQToQDWW2qdXwiCHTg8,2523
2
+ liminal/mappers.py,sha256=UYj8xqse1wXXkGedaqnGo6hkbOT9lntbQmju105MfaM,10059
3
+ liminal/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ liminal/utils.py,sha256=Eu_o5qfx1Thy26UaDOL-QnrB67FeJf3kOrTavGNRSo0,3248
5
+ liminal/base/base_dropdown.py,sha256=phowgjP5C2GPaOFoeJJs2hJ1oBzss6z41Fg6nN0vUXs,3484
3
6
  liminal/base/base_operation.py,sha256=opQfFZeC49YAFkg5ahE6CFpeSUNPh1ootWZxXyEXfFI,3128
4
7
  liminal/base/base_validation_filters.py,sha256=kHG3G5gXkuNHQosMTrxRc57OTmczcaoSx0DmkrScIr4,1043
5
8
  liminal/base/compare_operation.py,sha256=hkpv4ewHhxy4dlTPKgJuzBjsAqO6Km7OrrKB44pRA_o,352
6
9
  liminal/base/name_template_parts.py,sha256=EqQEkZjYePzSdWQkbojzBXpviXx4QpajqXr0z22zAO0,276
10
+ liminal/base/str_enum.py,sha256=jF3d-Lo8zsHUe6GsctX2L-TSj92Y3qCYDrTD-saeJoc,210
7
11
  liminal/base/properties/base_field_properties.py,sha256=2I3L8mhoxOD1nzEAzwWJzUFemxNYFeAFiIgzvpfyY-M,4704
8
12
  liminal/base/properties/base_name_template.py,sha256=AOtaW4QEDRC-mjZOZk6jgc_mopUMsHS2Fj6VVsO07WY,3150
9
13
  liminal/base/properties/base_schema_properties.py,sha256=jm7dG218gzHITOPdnILY4BUnOCW-KA8yiQjgz5FgQUI,5906
10
- liminal/base/str_enum.py,sha256=jF3d-Lo8zsHUe6GsctX2L-TSj92Y3qCYDrTD-saeJoc,210
11
- liminal/cli/cli.py,sha256=mh86uHRL7pidrtxHVzxgdcvRCVZjPYumLbkDc_aJXYM,14578
14
+ liminal/cli/cli.py,sha256=N1wTOpmfIFG1zCOyAKteSRTmKAdvZUUck-0pgCDSMUw,14383
12
15
  liminal/cli/controller.py,sha256=2eRP-SDapjDsTYaipxhQyXwBYKtoJcbKNbd4rZCQNlk,11501
13
16
  liminal/cli/live_test_dropdown_migration.py,sha256=XLeFZaR4acLOQ6LmTMWjZHIIUnB6ysZMUu6kaSRcQiA,2913
14
17
  liminal/cli/live_test_entity_schema_migration.py,sha256=_JawaiJNHkAjIrtwe9_K15OoJSFq_4vaTK5vrmz-b6s,5576
@@ -18,16 +21,16 @@ liminal/connection/benchling_connection.py,sha256=PLiaI4v9EcJDNBEO5ZF3jERuI6AYo8
18
21
  liminal/connection/benchling_service.py,sha256=gpZLGd7SwqyddWHLSoAd6PBxGqjdfQKYWhtVdpFnMeU,12425
19
22
  liminal/dropdowns/api.py,sha256=n5oxi1EhkmpmPpNi1LOI4xcIQmk1C069XFaGP5XSBx8,6959
20
23
  liminal/dropdowns/compare.py,sha256=-UbCkeTKx3THwvjMTUubyYVXBkhmvyhEKzwrIzBkthY,7141
21
- liminal/dropdowns/generate_files.py,sha256=zErD1jbbQxc5MpCPhgMnlXapyZ90S_0epE7FZD-sx4s,2519
24
+ liminal/dropdowns/generate_files.py,sha256=_t1daFAWcYL292xsniYFhFp06OO9BosqVlzHlbT4L0M,2888
22
25
  liminal/dropdowns/operations.py,sha256=-TRIsxqnUtrIUjhrt5k_PdiBCDUXsXDzsOUmznJE-6Q,13516
23
- liminal/dropdowns/utils.py,sha256=1-H7bTszCUeqeRBpiYXjRjreDzhn1Fd1MFwIsrEI-o4,4109
26
+ liminal/dropdowns/utils.py,sha256=HcLylGhk0WUCZjJC7Qzp0sAhO4We2vIYCoPpAOAsZx8,4157
24
27
  liminal/entity_schemas/api.py,sha256=Emn_Y95cAG9Wis6tpchw6QBVKQh4If86LOdgKk0Ndjw,3575
25
28
  liminal/entity_schemas/compare.py,sha256=JPnQVUy9w0IOBRn-VCWFa1JYhTYqzlEtdCgKNWw1e74,18569
26
29
  liminal/entity_schemas/entity_schema_models.py,sha256=v5A1ELaiuBnUSl1HkUNAeMuIRQeQnIKzfpFxmsiKWh0,8349
27
- liminal/entity_schemas/generate_files.py,sha256=j8JcGzbERCFdL85Xd5ljeH1O7S7l2ffsRxMwoaobzM4,10548
30
+ liminal/entity_schemas/generate_files.py,sha256=mjmBo6hHGoerPT6OI41JTUy8xsjX-6rEpi4p3rJavEo,11063
28
31
  liminal/entity_schemas/operations.py,sha256=mIMPvr9-eFaM603eOGn4PHfl7RblDpOzRtktBwqd5vQ,27189
29
32
  liminal/entity_schemas/tag_schema_models.py,sha256=HCtiJPMsPksX3wOBpfDdyIElNH3XybM7w25OUpIYoWM,24242
30
- liminal/entity_schemas/utils.py,sha256=voy5_dTvjdLO6K3c5ACr3ayUEL3BsUbZImIgLfIk9fs,6243
33
+ liminal/entity_schemas/utils.py,sha256=_-JI24Z6M0vhcEpQea_irLQbT36Sc4YyAecucIl4csM,6287
31
34
  liminal/enums/__init__.py,sha256=-szuqAwMED4ai0NaPVUfgihQJAJ27wPu_nDnj4cEgTk,518
32
35
  liminal/enums/benchling_api_field_type.py,sha256=jwp6txwPo_n1AU8oyl7vR7LnakVpxPPicGS1krwsvVE,681
33
36
  liminal/enums/benchling_entity_type.py,sha256=H_6ZlHJsiVNMpezPBrNKo2eP0pDrt--HU-P7PgznaMA,846
@@ -38,16 +41,12 @@ liminal/enums/benchling_sequence_type.py,sha256=TBI4C5c1XKE4ZXqsz1ApDUzy2wR-04u-
38
41
  liminal/enums/name_template_part_type.py,sha256=Z3Zv5PpzoUrIj_EvwPVgDDkY2G0kO-wE3-ZvEvnv86M,507
39
42
  liminal/enums/sequence_constraint.py,sha256=CT3msm8qzJpcivfbQZ3NOWNRsedH4mSlfhzvQBLrHWA,407
40
43
  liminal/external/__init__.py,sha256=EundQBe68_ZIhcsuSOhc-CznzYauNDYlNG1CjRDui_Y,1348
41
- liminal/mappers.py,sha256=UYj8xqse1wXXkGedaqnGo6hkbOT9lntbQmju105MfaM,10059
42
44
  liminal/migrate/components.py,sha256=bzt-5eJbhWVNs_zk9WieKmTkGgQrn58sm9GOuHUlM3Q,3526
43
45
  liminal/migrate/revision.py,sha256=KppU0u-d0JsfPsXsmncxy9Q_XBJyf-o4e16wNZAJODM,7774
44
46
  liminal/migrate/revisions_timeline.py,sha256=FSKzjUnZwnD3v2o7qoilBUkmKmJVvLVqozo25WnTo-w,14456
45
47
  liminal/orm/base.py,sha256=fFSpiNRYgK5UG7lbXdQGV8KgO8pwjMqt0pycM3rWJ2o,615
46
- liminal/orm/base_model.py,sha256=2B_hAie0ynjUx_EAMPl4RZp65WjHrzAbRvZUm7t542Q,16913
47
- liminal/orm/base_results_model.py,sha256=0z5O10Td165u4JVqmMHl68QvGRIhbFnGJB_fFV5Ln08,7669
48
- liminal/orm/base_tables/registry_entity.py,sha256=4ET1cepTGjZ3AMFI5q-iMYxMObzXwuUDBD0jNNqCipE,2126
49
- liminal/orm/base_tables/schema.py,sha256=7_btCVSUJxjVdGcKVRKL8sKcNw7-_gazTpfEh1jru3o,921
50
- liminal/orm/base_tables/user.py,sha256=elRAHj7HgO3iVLK_pNCIwf_9Rl_9k6vkBgaYazoJSQc,818
48
+ liminal/orm/base_model.py,sha256=xPyKRGNE95-UMRYIMigbDHahcCUcn2_HMXn-XGMVdD8,17905
49
+ liminal/orm/base_results_model.py,sha256=nAPIhrcYEyYAr04OuKNGhn9lewAcV0mkP8MoQ2-D9sM,8688
51
50
  liminal/orm/column.py,sha256=aK-MrKabOK5tf3UFPpRACq83YVVrjXITZF_rcOU-wPQ,6207
52
51
  liminal/orm/mixins.py,sha256=yEeUDF1qEBLP523q8bZra4KtNVK0gwZN9mXJSNe3GEE,4802
53
52
  liminal/orm/name_template.py,sha256=ftXZOiRR6gGGvGaZkFVDXKOboIHFWauhQENRguBGWMI,1739
@@ -55,21 +54,22 @@ liminal/orm/name_template_parts.py,sha256=iI4S9ZGvckQbYjhgFdn6xeJ3rS90lzCvjH0863
55
54
  liminal/orm/relationship.py,sha256=4FwMr_B008zjqp6J84rvb-CUReIlZtNCh-Ls1ippQYM,4324
56
55
  liminal/orm/results_schema_properties.py,sha256=o0rHHa5dCzBynEBkF6uLuEHALumR-G2FGSJkPeVRqRc,701
57
56
  liminal/orm/schema_properties.py,sha256=Xs8ptsEUxVvuxPDenYmZByL7Bwemyjdm6IvBAdIYq5Y,4290
58
- liminal/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
59
- liminal/results_schemas/generate_files.py,sha256=aBbt0_P_IUUpaDRWA2g5wTDoWa_GPUREyZ9O-BkOwns,8500
57
+ liminal/orm/base_tables/registry_entity.py,sha256=4ET1cepTGjZ3AMFI5q-iMYxMObzXwuUDBD0jNNqCipE,2126
58
+ liminal/orm/base_tables/schema.py,sha256=7_btCVSUJxjVdGcKVRKL8sKcNw7-_gazTpfEh1jru3o,921
59
+ liminal/orm/base_tables/user.py,sha256=elRAHj7HgO3iVLK_pNCIwf_9Rl_9k6vkBgaYazoJSQc,818
60
+ liminal/results_schemas/generate_files.py,sha256=Z_Z83UScKNJHPa1H3k_R9r5dCMuC9zXfZRmXlhbetLA,8671
61
+ liminal/results_schemas/utils.py,sha256=H8tsj6fHVtAQ_LIETPDdipGi4hUcEW8tlX0bpYQ8ZlE,2103
60
62
  liminal/results_schemas/models/results_schema_model.py,sha256=qZsCT_y327FnX1zBaUHQL2bXWSbuVokKTn0dnH3BRPA,5341
61
- liminal/results_schemas/utils.py,sha256=3oo7ZB34OXt8wAdxTrqRtauu9AHTfh-Ze0IGCDtC2Tw,2333
62
63
  liminal/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
63
64
  liminal/tests/conftest.py,sha256=B463eOfe1uCHDJsUNvG-6tY8Qx8FJMByGDOtuyM87lA,17669
64
65
  liminal/tests/from benchling_sdk.py,sha256=CjRUHFB3iaa4rUPLGOqDiBq5EPKldm-Fd8aQQr92zF4,147
65
66
  liminal/tests/test_dropdown_compare.py,sha256=yHB0ovQlBLRu8-qYkqIPd8VtYEOmOft_93FQM86g_z8,8198
66
67
  liminal/tests/test_entity_schema_compare.py,sha256=asKDU4uO1PFdWCKU-78xqSzNN90L6QBDYeH_QxwDbSs,18918
67
68
  liminal/unit_dictionary/utils.py,sha256=o3K06Yyt33iIUSMHPT8f1vSuUSgWjZLf51p78lx4SZs,1817
68
- liminal/utils.py,sha256=Eu_o5qfx1Thy26UaDOL-QnrB67FeJf3kOrTavGNRSo0,3248
69
69
  liminal/validation/__init__.py,sha256=NsjzmivSRwGki1k9ykJgjtcYNcILR_PHSf6RkI1w2n0,5290
70
70
  liminal/validation/validation_severity.py,sha256=ib03PTZCQHcbBDc01v4gJF53YtA-ANY6QSFnhTV-FbU,259
71
- liminal_orm-4.1.1.dist-info/LICENSE.md,sha256=oVA877F_D1AV44dpjsv4f-4k690uNGApX1EtzOo3T8U,11353
72
- liminal_orm-4.1.1.dist-info/METADATA,sha256=7F7jyDarAmuFxvDubwp9Yi_o-173IChnG5-zWRojW_0,11022
73
- liminal_orm-4.1.1.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
74
- liminal_orm-4.1.1.dist-info/entry_points.txt,sha256=atIrU63rrzH81dWC2sjUbFLlc5FWMmYRdMxXEWexIZA,47
75
- liminal_orm-4.1.1.dist-info/RECORD,,
71
+ liminal_orm-4.2.0.dist-info/METADATA,sha256=t4o0NkOnZmD-TumpaX7cmbcWpW1dfj6PHAHRu_Hm5OM,10732
72
+ liminal_orm-4.2.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
73
+ liminal_orm-4.2.0.dist-info/entry_points.txt,sha256=M9yndBmBWcZvlHQpZc1sEp-rRTXjsLFiz-pnsI4jy0g,48
74
+ liminal_orm-4.2.0.dist-info/licenses/LICENSE.md,sha256=oVA877F_D1AV44dpjsv4f-4k690uNGApX1EtzOo3T8U,11353
75
+ liminal_orm-4.2.0.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 1.9.0
2
+ Generator: hatchling 1.27.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ liminal = liminal.cli.cli:app
@@ -1,3 +0,0 @@
1
- [console_scripts]
2
- liminal=liminal.cli.cli:app
3
-