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.
- liminal/base/base_dropdown.py +27 -0
- liminal/cli/cli.py +2 -2
- liminal/dropdowns/generate_files.py +14 -6
- liminal/dropdowns/utils.py +4 -1
- liminal/entity_schemas/generate_files.py +39 -33
- liminal/entity_schemas/utils.py +3 -0
- liminal/orm/base_model.py +29 -0
- liminal/orm/base_results_model.py +29 -0
- liminal/results_schemas/generate_files.py +24 -18
- liminal/results_schemas/utils.py +7 -9
- {liminal_orm-4.1.1.dist-info → liminal_orm-4.2.0.dist-info}/METADATA +21 -27
- {liminal_orm-4.1.1.dist-info → liminal_orm-4.2.0.dist-info}/RECORD +22 -22
- {liminal_orm-4.1.1.dist-info → liminal_orm-4.2.0.dist-info}/WHEEL +1 -1
- liminal_orm-4.2.0.dist-info/entry_points.txt +2 -0
- liminal_orm-4.1.1.dist-info/entry_points.txt +0 -3
- {liminal_orm-4.1.1.dist-info → liminal_orm-4.2.0.dist-info/licenses}/LICENSE.md +0 -0
liminal/base/base_dropdown.py
CHANGED
@@ -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
|
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
|
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
|
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
|
-
|
50
|
-
|
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
|
-
|
59
|
-
|
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
|
)
|
liminal/dropdowns/utils.py
CHANGED
@@ -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
|
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
|
-
|
192
|
-
|
193
|
-
)
|
194
|
-
|
195
|
-
|
196
|
-
|
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
|
-
|
202
|
-
|
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
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
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
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
return {}
|
247
|
+
return {
|
248
|
+
dropdown_name: to_pascal_case(dropdown_name)
|
249
|
+
for dropdown_name in benchling_dropdowns.keys()
|
250
|
+
}
|
liminal/entity_schemas/utils.py
CHANGED
@@ -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
|
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
|
-
|
151
|
-
|
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
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
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
|
-
|
174
|
-
|
175
|
-
|
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
|
-
|
194
|
-
|
195
|
-
|
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
|
+
}
|
liminal/results_schemas/utils.py
CHANGED
@@ -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
|
-
|
40
|
+
@lru_cache
|
41
|
+
def get_benchling_results_schemas(
|
39
42
|
benchling_service: BenchlingService,
|
40
|
-
) ->
|
41
|
-
|
42
|
-
|
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
|
+
Metadata-Version: 2.4
|
2
2
|
Name: liminal-orm
|
3
|
-
Version: 4.
|
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
|
-
|
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/
|
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/
|
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=
|
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=
|
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=
|
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=
|
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=
|
47
|
-
liminal/orm/base_results_model.py,sha256=
|
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
|
59
|
-
liminal/
|
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.
|
72
|
-
liminal_orm-4.
|
73
|
-
liminal_orm-4.
|
74
|
-
liminal_orm-4.
|
75
|
-
liminal_orm-4.
|
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,,
|
File without changes
|