liminal-orm 1.0.5__tar.gz → 1.0.6__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 (60) hide show
  1. {liminal_orm-1.0.5 → liminal_orm-1.0.6}/PKG-INFO +10 -4
  2. {liminal_orm-1.0.5 → liminal_orm-1.0.6}/README.md +8 -3
  3. {liminal_orm-1.0.5 → liminal_orm-1.0.6}/liminal/base/properties/base_schema_properties.py +9 -0
  4. {liminal_orm-1.0.5 → liminal_orm-1.0.6}/liminal/cli/cli.py +4 -1
  5. {liminal_orm-1.0.5 → liminal_orm-1.0.6}/liminal/connection/benchling_service.py +7 -1
  6. {liminal_orm-1.0.5 → liminal_orm-1.0.6}/liminal/entity_schemas/generate_files.py +2 -2
  7. {liminal_orm-1.0.5 → liminal_orm-1.0.6}/liminal/entity_schemas/operations.py +3 -7
  8. {liminal_orm-1.0.5 → liminal_orm-1.0.6}/liminal/entity_schemas/tag_schema_models.py +2 -0
  9. {liminal_orm-1.0.5 → liminal_orm-1.0.6}/liminal/orm/column.py +5 -1
  10. {liminal_orm-1.0.5 → liminal_orm-1.0.6}/pyproject.toml +2 -1
  11. {liminal_orm-1.0.5 → liminal_orm-1.0.6}/LICENSE.md +0 -0
  12. {liminal_orm-1.0.5 → liminal_orm-1.0.6}/liminal/__init__.py +0 -0
  13. {liminal_orm-1.0.5 → liminal_orm-1.0.6}/liminal/base/base_dropdown.py +0 -0
  14. {liminal_orm-1.0.5 → liminal_orm-1.0.6}/liminal/base/base_operation.py +0 -0
  15. {liminal_orm-1.0.5 → liminal_orm-1.0.6}/liminal/base/base_validation_filters.py +0 -0
  16. {liminal_orm-1.0.5 → liminal_orm-1.0.6}/liminal/base/compare_operation.py +0 -0
  17. {liminal_orm-1.0.5 → liminal_orm-1.0.6}/liminal/base/properties/base_field_properties.py +0 -0
  18. {liminal_orm-1.0.5 → liminal_orm-1.0.6}/liminal/base/str_enum.py +0 -0
  19. {liminal_orm-1.0.5 → liminal_orm-1.0.6}/liminal/cli/controller.py +0 -0
  20. {liminal_orm-1.0.5 → liminal_orm-1.0.6}/liminal/cli/live_test_dropdown_migration.py +0 -0
  21. {liminal_orm-1.0.5 → liminal_orm-1.0.6}/liminal/cli/live_test_entity_schema_migration.py +0 -0
  22. {liminal_orm-1.0.5 → liminal_orm-1.0.6}/liminal/connection/__init__.py +0 -0
  23. {liminal_orm-1.0.5 → liminal_orm-1.0.6}/liminal/connection/benchling_connection.py +0 -0
  24. {liminal_orm-1.0.5 → liminal_orm-1.0.6}/liminal/dropdowns/api.py +0 -0
  25. {liminal_orm-1.0.5 → liminal_orm-1.0.6}/liminal/dropdowns/compare.py +0 -0
  26. {liminal_orm-1.0.5 → liminal_orm-1.0.6}/liminal/dropdowns/generate_files.py +0 -0
  27. {liminal_orm-1.0.5 → liminal_orm-1.0.6}/liminal/dropdowns/operations.py +0 -0
  28. {liminal_orm-1.0.5 → liminal_orm-1.0.6}/liminal/dropdowns/utils.py +0 -0
  29. {liminal_orm-1.0.5 → liminal_orm-1.0.6}/liminal/entity_schemas/api.py +0 -0
  30. {liminal_orm-1.0.5 → liminal_orm-1.0.6}/liminal/entity_schemas/compare.py +0 -0
  31. {liminal_orm-1.0.5 → liminal_orm-1.0.6}/liminal/entity_schemas/entity_schema_models.py +0 -0
  32. {liminal_orm-1.0.5 → liminal_orm-1.0.6}/liminal/entity_schemas/utils.py +0 -0
  33. {liminal_orm-1.0.5 → liminal_orm-1.0.6}/liminal/enums/__init__.py +0 -0
  34. {liminal_orm-1.0.5 → liminal_orm-1.0.6}/liminal/enums/benchling_api_field_type.py +0 -0
  35. {liminal_orm-1.0.5 → liminal_orm-1.0.6}/liminal/enums/benchling_entity_type.py +0 -0
  36. {liminal_orm-1.0.5 → liminal_orm-1.0.6}/liminal/enums/benchling_field_type.py +0 -0
  37. {liminal_orm-1.0.5 → liminal_orm-1.0.6}/liminal/enums/benchling_folder_item_type.py +0 -0
  38. {liminal_orm-1.0.5 → liminal_orm-1.0.6}/liminal/enums/benchling_naming_strategy.py +0 -0
  39. {liminal_orm-1.0.5 → liminal_orm-1.0.6}/liminal/enums/benchling_report_level.py +0 -0
  40. {liminal_orm-1.0.5 → liminal_orm-1.0.6}/liminal/enums/benchling_sequence_type.py +0 -0
  41. {liminal_orm-1.0.5 → liminal_orm-1.0.6}/liminal/external/__init__.py +0 -0
  42. {liminal_orm-1.0.5 → liminal_orm-1.0.6}/liminal/mappers.py +0 -0
  43. {liminal_orm-1.0.5 → liminal_orm-1.0.6}/liminal/migrate/components.py +0 -0
  44. {liminal_orm-1.0.5 → liminal_orm-1.0.6}/liminal/migrate/revision.py +0 -0
  45. {liminal_orm-1.0.5 → liminal_orm-1.0.6}/liminal/migrate/revisions_timeline.py +0 -0
  46. {liminal_orm-1.0.5 → liminal_orm-1.0.6}/liminal/migrate/utils.py +0 -0
  47. {liminal_orm-1.0.5 → liminal_orm-1.0.6}/liminal/orm/base.py +0 -0
  48. {liminal_orm-1.0.5 → liminal_orm-1.0.6}/liminal/orm/base_model.py +0 -0
  49. {liminal_orm-1.0.5 → liminal_orm-1.0.6}/liminal/orm/mixins.py +0 -0
  50. {liminal_orm-1.0.5 → liminal_orm-1.0.6}/liminal/orm/relationship.py +0 -0
  51. {liminal_orm-1.0.5 → liminal_orm-1.0.6}/liminal/orm/schema_properties.py +0 -0
  52. {liminal_orm-1.0.5 → liminal_orm-1.0.6}/liminal/orm/user.py +0 -0
  53. {liminal_orm-1.0.5 → liminal_orm-1.0.6}/liminal/py.typed +0 -0
  54. {liminal_orm-1.0.5 → liminal_orm-1.0.6}/liminal/tests/__init__.py +0 -0
  55. {liminal_orm-1.0.5 → liminal_orm-1.0.6}/liminal/tests/conftest.py +0 -0
  56. {liminal_orm-1.0.5 → liminal_orm-1.0.6}/liminal/tests/from benchling_sdk.py +0 -0
  57. {liminal_orm-1.0.5 → liminal_orm-1.0.6}/liminal/tests/test_dropdown_compare.py +0 -0
  58. {liminal_orm-1.0.5 → liminal_orm-1.0.6}/liminal/tests/test_entity_schema_compare.py +0 -0
  59. {liminal_orm-1.0.5 → liminal_orm-1.0.6}/liminal/utils.py +0 -0
  60. {liminal_orm-1.0.5 → liminal_orm-1.0.6}/liminal/validation/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: liminal-orm
3
- Version: 1.0.5
3
+ Version: 1.0.6
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
@@ -14,6 +14,7 @@ Requires-Dist: benchling-sdk (>=1.8.0)
14
14
  Requires-Dist: bs4 (>=0.0.2,<0.0.3)
15
15
  Requires-Dist: lxml (>=5.3.0,<6.0.0)
16
16
  Requires-Dist: pandas (>=1.5.3)
17
+ Requires-Dist: psycopg2-binary (>=2.9.10,<3.0.0)
17
18
  Requires-Dist: pydantic (>=2,<=2.7)
18
19
  Requires-Dist: requests (>=2.32.3,<3.0.0)
19
20
  Requires-Dist: rich (>=13.9.2,<14.0.0)
@@ -27,7 +28,12 @@ Description-Content-Type: text/markdown
27
28
 
28
29
  # [Liminal ORM](#liminal-orm)
29
30
 
30
- Liminal ORM<sup>1</sup> is an open-source Python package that builds on [Benchling's](https://www.benchling.com/) LIMS<sup>2</sup> platform and provides a simple, code-first approach for synchronizing and managing your Benchling schemas. Check out the [**full documentation here**](https://dynotx.github.io/liminal-orm/)!
31
+ [![PyPI version](https://img.shields.io/pypi/v/liminal-orm.svg)](https://pypi.org/project/liminal-orm/)
32
+ [![License](https://img.shields.io/github/license/dynotx/liminal-orm)](https://github.com/dynotx/liminal-orm/blob/main/LICENSE.md)
33
+ [![CI](https://github.com/dynotx/liminal-orm/actions/workflows/liminal.yml/badge.svg)](https://github.com/dynotx/liminal-orm/actions/workflows/liminal.yml)
34
+ [![Downloads](https://static.pepy.tech/personalized-badge/liminal-orm?period=total&units=international_system&left_color=grey&right_color=blue&left_text=Downloads)](https://pepy.tech/project/liminal-orm)
35
+
36
+ Liminal ORM<sup>1</sup> is an open-source Python package that builds on [Benchling's](https://www.benchling.com/) LIMS<sup>2</sup> platform and provides a simple, code-first approach for synchronizing and managing your Benchling schemas. Check out the [**full documentation here**](https://dynotx.github.io/liminal-orm/) and join our [**Slack community here**](https://join.slack.com/t/liminalorm/shared_invite/zt-2ujrp07s3-bctook4e~cAjn1LgOLVY~Q)!
31
37
 
32
38
  Liminal provides an ORM framework using [SQLAlchemy](https://github.com/sqlalchemy/sqlalchemy) along with a schema migration service inspired by [Alembic](https://alembic.sqlalchemy.org/en/latest/). This allows you to define your Benchling schemas in code and create a *single source of truth* that synchronizes between your upstream Benchling tenant(s) and downstream dependencies. By creating a standard interface and through using one-line CLI<sup>3</sup> commands, Liminal enables a code-first approach for managing Benchling tenants and accessing Benchling data. With the schemas defined in code, you can also take advantage of the additional capabilities that the Liminal toolkit provides. This includes:
33
39
 
@@ -38,10 +44,10 @@ Liminal provides an ORM framework using [SQLAlchemy](https://github.com/sqlalche
38
44
  - CI/CD integration with GitHub Actions to ensure that your Benchling schemas and code are always in sync.
39
45
  - And more based on community contributions/feedback :)
40
46
 
41
- Benchling is an industry standard cloud platform for life sciences R&D. Liminal builds on top of Benchling's platform and assumes that you already have a Benchling tenant set up and have (or have access to) an admin user account. If not, learn more about getting started with Benchling [here](https://www.benchling.com/explore-benchling)!
42
-
43
47
  If you are a Benchling user, try out Liminal by following the [**Quick Start Guide**](https://dynotx.github.io/liminal-orm/getting-started/prerequisites/)! Reach out in the [Discussions](https://github.com/dynotx/liminal-orm/discussions) forum with any questions or to simply introduce yourself! If there is something blocking you from using Liminal or you're having trouble setting Liminal up, please share in [Issues](https://github.com/dynotx/liminal-orm/issues) or reach out directly (contact information below). You can expect responses within 48 hours :)
44
48
 
49
+ Benchling is an industry standard cloud platform for life sciences R&D. Liminal builds on top of Benchling's platform and assumes that you already have a Benchling tenant set up and have (or have access to) an admin user account. If not, learn more about getting started with Benchling [here](https://www.benchling.com/explore-benchling)!
50
+
45
51
  Nirmit Damania is the creator and current maintainer of Liminal (I post Liminal updates to [Discussions](https://github.com/dynotx/liminal-orm/discussions) and my [LinkedIn](https://www.linkedin.com/in/nirmit-damania/)). Most importantly, **you** have the ability to influence the future of Liminal! Any feedback, positive or negative, is highly encouraged and will be used to steer the direction of Liminal. Refer to the [Contributing guide](https://github.com/dynotx/liminal-orm/blob/main/CONTRIBUTING.md) to learn more about how you can contribute to Liminal.
46
52
 
47
53
  ⭐️ Leave a star on the repo to spread the word!
@@ -1,6 +1,11 @@
1
1
  # [Liminal ORM](#liminal-orm)
2
2
 
3
- Liminal ORM<sup>1</sup> is an open-source Python package that builds on [Benchling's](https://www.benchling.com/) LIMS<sup>2</sup> platform and provides a simple, code-first approach for synchronizing and managing your Benchling schemas. Check out the [**full documentation here**](https://dynotx.github.io/liminal-orm/)!
3
+ [![PyPI version](https://img.shields.io/pypi/v/liminal-orm.svg)](https://pypi.org/project/liminal-orm/)
4
+ [![License](https://img.shields.io/github/license/dynotx/liminal-orm)](https://github.com/dynotx/liminal-orm/blob/main/LICENSE.md)
5
+ [![CI](https://github.com/dynotx/liminal-orm/actions/workflows/liminal.yml/badge.svg)](https://github.com/dynotx/liminal-orm/actions/workflows/liminal.yml)
6
+ [![Downloads](https://static.pepy.tech/personalized-badge/liminal-orm?period=total&units=international_system&left_color=grey&right_color=blue&left_text=Downloads)](https://pepy.tech/project/liminal-orm)
7
+
8
+ Liminal ORM<sup>1</sup> is an open-source Python package that builds on [Benchling's](https://www.benchling.com/) LIMS<sup>2</sup> platform and provides a simple, code-first approach for synchronizing and managing your Benchling schemas. Check out the [**full documentation here**](https://dynotx.github.io/liminal-orm/) and join our [**Slack community here**](https://join.slack.com/t/liminalorm/shared_invite/zt-2ujrp07s3-bctook4e~cAjn1LgOLVY~Q)!
4
9
 
5
10
  Liminal provides an ORM framework using [SQLAlchemy](https://github.com/sqlalchemy/sqlalchemy) along with a schema migration service inspired by [Alembic](https://alembic.sqlalchemy.org/en/latest/). This allows you to define your Benchling schemas in code and create a *single source of truth* that synchronizes between your upstream Benchling tenant(s) and downstream dependencies. By creating a standard interface and through using one-line CLI<sup>3</sup> commands, Liminal enables a code-first approach for managing Benchling tenants and accessing Benchling data. With the schemas defined in code, you can also take advantage of the additional capabilities that the Liminal toolkit provides. This includes:
6
11
 
@@ -11,10 +16,10 @@ Liminal provides an ORM framework using [SQLAlchemy](https://github.com/sqlalche
11
16
  - CI/CD integration with GitHub Actions to ensure that your Benchling schemas and code are always in sync.
12
17
  - And more based on community contributions/feedback :)
13
18
 
14
- Benchling is an industry standard cloud platform for life sciences R&D. Liminal builds on top of Benchling's platform and assumes that you already have a Benchling tenant set up and have (or have access to) an admin user account. If not, learn more about getting started with Benchling [here](https://www.benchling.com/explore-benchling)!
15
-
16
19
  If you are a Benchling user, try out Liminal by following the [**Quick Start Guide**](https://dynotx.github.io/liminal-orm/getting-started/prerequisites/)! Reach out in the [Discussions](https://github.com/dynotx/liminal-orm/discussions) forum with any questions or to simply introduce yourself! If there is something blocking you from using Liminal or you're having trouble setting Liminal up, please share in [Issues](https://github.com/dynotx/liminal-orm/issues) or reach out directly (contact information below). You can expect responses within 48 hours :)
17
20
 
21
+ Benchling is an industry standard cloud platform for life sciences R&D. Liminal builds on top of Benchling's platform and assumes that you already have a Benchling tenant set up and have (or have access to) an admin user account. If not, learn more about getting started with Benchling [here](https://www.benchling.com/explore-benchling)!
22
+
18
23
  Nirmit Damania is the creator and current maintainer of Liminal (I post Liminal updates to [Discussions](https://github.com/dynotx/liminal-orm/discussions) and my [LinkedIn](https://www.linkedin.com/in/nirmit-damania/)). Most importantly, **you** have the ability to influence the future of Liminal! Any feedback, positive or negative, is highly encouraged and will be used to steer the direction of Liminal. Refer to the [Contributing guide](https://github.com/dynotx/liminal-orm/blob/main/CONTRIBUTING.md) to learn more about how you can contribute to Liminal.
19
24
 
20
25
  ⭐️ Leave a star on the repo to spread the word!
@@ -97,3 +97,12 @@ class BaseSchemaProperties(BaseModel):
97
97
  if not isinstance(other, BaseSchemaProperties):
98
98
  return False
99
99
  return self.model_dump() == other.model_dump()
100
+
101
+ def __str__(self) -> str:
102
+ return ", ".join(
103
+ [f"{k}={v}" for k, v in self.model_dump(exclude_unset=True).items()]
104
+ )
105
+
106
+ def __repr__(self) -> str:
107
+ """Generates a string representation of the class so that it can be executed."""
108
+ return f"{self.__class__.__name__}({', '.join([f'{k}={v.__repr__()}' for k, v in self.model_dump(exclude_defaults=True).items()])})"
@@ -79,7 +79,10 @@ def generate_files(
79
79
  ..., help="Benchling tenant (or alias) to connect to."
80
80
  ),
81
81
  write_path: Path = typer.Option(
82
- Path("."), help="The path to write the generated files to."
82
+ Path("."),
83
+ "-p",
84
+ "--write-path",
85
+ help="The path to write the generated files to.",
83
86
  ),
84
87
  ) -> None:
85
88
  current_revision_id, benchling_connection = read_local_env_file(
@@ -9,7 +9,12 @@ from bs4 import BeautifulSoup
9
9
  from sqlalchemy import create_engine
10
10
  from sqlalchemy.engine import Engine
11
11
  from sqlalchemy.orm import Session, configure_mappers
12
- from tenacity import retry, retry_if_exception_type, stop_after_attempt
12
+ from tenacity import (
13
+ retry,
14
+ retry_if_exception_type,
15
+ stop_after_attempt,
16
+ wait_exponential,
17
+ )
13
18
 
14
19
  from liminal.connection.benchling_connection import BenchlingConnection
15
20
 
@@ -144,6 +149,7 @@ class BenchlingService(Benchling):
144
149
  @retry(
145
150
  stop=stop_after_attempt(3),
146
151
  retry=retry_if_exception_type(ValueError),
152
+ wait=wait_exponential(multiplier=1, min=1, max=8),
147
153
  reraise=True,
148
154
  )
149
155
  def autogenerate_auth(
@@ -106,14 +106,14 @@ def generate_all_entity_schema_files(
106
106
  ):
107
107
  if not col.is_multi:
108
108
  relationship_strings.append(
109
- f"""{tab}single_relationship("{wh_name_to_classname[col.entity_link]}", {col_name})"""
109
+ f"""{tab}{col_name}_entity = single_relationship("{wh_name_to_classname[col.entity_link]}", {col_name})"""
110
110
  )
111
111
  import_strings.append(
112
112
  "from liminal.orm.relationship import single_relationship"
113
113
  )
114
114
  else:
115
115
  relationship_strings.append(
116
- f"""{tab}multi_relationship("{wh_name_to_classname[col.entity_link]}", "{classname}", "{col_name}")"""
116
+ f"""{tab}{col_name}_entities = multi_relationship("{wh_name_to_classname[col.entity_link]}", "{classname}", "{col_name}")"""
117
117
  )
118
118
  import_strings.append(
119
119
  "from liminal.orm.relationship import multi_relationship"
@@ -195,10 +195,10 @@ class UpdateEntitySchema(BaseOperation):
195
195
  return update_tag_schema(benchling_service, tag_schema.id, update.model_dump())
196
196
 
197
197
  def describe_operation(self) -> str:
198
- return f"Updating properties for entity schema {self.wh_schema_name}: {repr(self.update_props)}."
198
+ return f"Updating properties for entity schema {self.wh_schema_name}: {str(self.update_props)}."
199
199
 
200
200
  def describe(self) -> str:
201
- return f"Schema properties for {self.wh_schema_name} are different in code versus Benchling: {repr(self.update_props)}."
201
+ return f"Schema properties for {self.wh_schema_name} are different in code versus Benchling: {str(self.update_props)}."
202
202
 
203
203
  def _validate(self, benchling_service: BenchlingService) -> TagSchemaModel:
204
204
  all_schemas = TagSchemaModel.get_all_json(benchling_service)
@@ -485,11 +485,7 @@ class UpdateEntitySchemaField(BaseOperation):
485
485
  # Only if changing name of field
486
486
  if self.update_props.name:
487
487
  existing_new_field = next(
488
- (
489
- f
490
- for f in tag_schema.allFields
491
- if f.systemName == self.update_props.name
492
- ),
488
+ (f for f in tag_schema.allFields if f.name == self.update_props.name),
493
489
  None,
494
490
  )
495
491
  if existing_new_field:
@@ -59,6 +59,7 @@ class CreateTagSchemaFieldModel(BaseModel):
59
59
  systemName: str
60
60
  name: str
61
61
  requiredLink: FieldRequiredLinkShortModel | None = None
62
+ tooltipText: str | None = None
62
63
 
63
64
  @classmethod
64
65
  def from_props(
@@ -121,6 +122,7 @@ class CreateTagSchemaFieldModel(BaseModel):
121
122
  folderItemType=folder_item_type,
122
123
  tagSchema=tagSchema,
123
124
  ),
125
+ tooltipText=new_props.tooltip,
124
126
  )
125
127
 
126
128
 
@@ -82,7 +82,7 @@ class Column(SqlColumn):
82
82
  super().__init__(
83
83
  self.sqlalchemy_type,
84
84
  foreign_key,
85
- nullable=not properties.required,
85
+ nullable=not required,
86
86
  info={"benchling_properties": properties},
87
87
  **kwargs,
88
88
  )
@@ -107,3 +107,7 @@ class Column(SqlColumn):
107
107
  f"Could not set benchling properties for column {column.name}. Please check that the column has a valid benchling properties set."
108
108
  )
109
109
  return Column(**properties.model_dump())
110
+
111
+ def _constructor(self, *args: Any, **kwargs: Any) -> SqlColumn:
112
+ """Returns a new instance of the SqlAlchemy Column class."""
113
+ return SqlColumn(*args, **kwargs)
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "liminal-orm"
3
- version = "1.0.5"
3
+ version = "1.0.6"
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"
@@ -24,6 +24,7 @@ sqlalchemy = "<2" # TODO: We need to assess this upgrade
24
24
  tenacity = ">=8,<10"
25
25
  typer = "^0.12.5"
26
26
  lxml = "^5.3.0"
27
+ psycopg2-binary = "^2.9.10"
27
28
 
28
29
  [tool.poetry.group.dev.dependencies]
29
30
  ipykernel = "^6.29.5"
File without changes