liminal-orm 1.1.4__py3-none-any.whl → 2.0.1__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.
Files changed (34) hide show
  1. liminal/base/base_operation.py +4 -3
  2. liminal/base/base_validation_filters.py +15 -0
  3. liminal/base/name_template_parts.py +9 -0
  4. liminal/base/properties/base_field_properties.py +2 -2
  5. liminal/base/properties/base_name_template.py +83 -0
  6. liminal/base/properties/base_schema_properties.py +13 -1
  7. liminal/dropdowns/compare.py +8 -0
  8. liminal/dropdowns/operations.py +1 -1
  9. liminal/entity_schemas/api.py +18 -0
  10. liminal/entity_schemas/compare.py +62 -8
  11. liminal/entity_schemas/entity_schema_models.py +43 -0
  12. liminal/entity_schemas/generate_files.py +13 -11
  13. liminal/entity_schemas/operations.py +43 -18
  14. liminal/entity_schemas/tag_schema_models.py +146 -3
  15. liminal/entity_schemas/utils.py +15 -2
  16. liminal/enums/__init__.py +0 -1
  17. liminal/enums/benchling_entity_type.py +8 -0
  18. liminal/enums/name_template_part_type.py +12 -0
  19. liminal/external/__init__.py +11 -1
  20. liminal/migrate/revisions_timeline.py +2 -1
  21. liminal/orm/base_model.py +90 -29
  22. liminal/orm/name_template.py +39 -0
  23. liminal/orm/name_template_parts.py +96 -0
  24. liminal/orm/schema_properties.py +27 -1
  25. liminal/tests/conftest.py +18 -9
  26. liminal/tests/test_entity_schema_compare.py +61 -12
  27. liminal/utils.py +9 -0
  28. liminal/validation/__init__.py +84 -108
  29. liminal/{enums/benchling_report_level.py → validation/validation_severity.py} +2 -2
  30. {liminal_orm-1.1.4.dist-info → liminal_orm-2.0.1.dist-info}/METADATA +17 -20
  31. {liminal_orm-1.1.4.dist-info → liminal_orm-2.0.1.dist-info}/RECORD +34 -29
  32. {liminal_orm-1.1.4.dist-info → liminal_orm-2.0.1.dist-info}/LICENSE.md +0 -0
  33. {liminal_orm-1.1.4.dist-info → liminal_orm-2.0.1.dist-info}/WHEEL +0 -0
  34. {liminal_orm-1.1.4.dist-info → liminal_orm-2.0.1.dist-info}/entry_points.txt +0 -0
@@ -1,8 +1,8 @@
1
1
  from liminal.base.str_enum import StrEnum
2
2
 
3
3
 
4
- class BenchlingReportLevel(StrEnum):
5
- """This enum represents the different levels of validation that can be returned by Benchling."""
4
+ class ValidationSeverity(StrEnum):
5
+ """This enum represents the different levels of validation that can be returned by Liminal."""
6
6
 
7
7
  LOW = "LOW"
8
8
  MED = "MED"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: liminal-orm
3
- Version: 1.1.4
3
+ Version: 2.0.1
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
@@ -41,13 +41,12 @@ Liminal ORM<sup>1</sup> is an open-source Python package that builds on [Benchli
41
41
  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:
42
42
 
43
43
  - The ability to run migrations to your Benchling tenant(s) through an easy to use CLI.
44
- - One source of truth defined in code for your Benchling schema model that your many Benchling tenants can stay in sync with.
45
44
  - Easy to implement validation rules to reflect business logic for all of your Benchling entities.
46
45
  - Strongly typed queries for all your Benchling entities.
47
46
  - CI/CD integration with GitHub Actions to ensure that your Benchling schemas and code are always in sync.
48
47
  - And more based on community contributions/feedback :)
49
48
 
50
- 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 :)
49
+ 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 [Slack community](https://join.slack.com/t/liminalorm/shared_invite/zt-2ujrp07s3-bctook4e~cAjn1LgOLVY~Q) (preferred method) 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 (info below).
51
50
 
52
51
  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)!
53
52
 
@@ -67,6 +66,7 @@ If you or your organization use Liminal, please consider adding yourself or your
67
66
  - [Community](#community)
68
67
  - [Contributing](#contributing)
69
68
  - [License](#license)
69
+ - [Direct Contact](#direct-contact)
70
70
  - [Acknowledgements](#acknowledgements)
71
71
  - [Footnotes](#footnotes)
72
72
 
@@ -83,22 +83,19 @@ With your schemas defined in code, you can now take advantage of the additional
83
83
  1. Entity validation: Easily create custom validation rules for your Benchling entities.
84
84
 
85
85
  ```python
86
- from liminal.validation import BenchlingValidator, BenchlingValidatorReport, BenchlingReportLevel
87
- from liminal.orm.base_model import BaseModel
88
-
89
- class CookTempValidator(BenchlingValidator):
90
- """Validates that a field value is a valid enum value for a Benchling entity"""
91
-
92
- def validate(self, entity: type[BaseModel]) -> BenchlingValidatorReport:
93
- valid = True
94
- message = None
95
- if entity.cook_time is not None and entity.cook_temp is None:
96
- valid = False
97
- message = "Cook temp is required if cook time is set"
98
- if entity.cook_time is None and entity.cook_temp is not None:
99
- valid = False
100
- message = "Cook time is required if cook temp is set"
101
- return self.create_report(valid, BenchlingReportLevel.MED, entity, message)
86
+ from liminal.validation import ValidationSeverity, liminal_validator
87
+
88
+ class Pizza(BaseModel, CustomEntityMixin):
89
+ ...
90
+
91
+ @liminal_validator(ValidationSeverity.MED)
92
+ def cook_time_and_temp_validator(self) -> None:
93
+ if self.cook_time is not None and self.cook_temp is None:
94
+ raise ValueError("Cook temp is required if cook time is set")
95
+ if self.cook_time is None and self.cook_temp is not None:
96
+ raise ValueError("Cook time is required if cook temp is set")
97
+
98
+ validation_reports = Pizza.validate(session)
102
99
  ```
103
100
 
104
101
  2. Strongly typed queries: Write type-safe queries using SQLAlchemy to access your Benchling entities.
@@ -106,7 +103,6 @@ With your schemas defined in code, you can now take advantage of the additional
106
103
  ```python
107
104
  with BenchlingSession(benchling_connection, with_db=True) as session:
108
105
  pizza = session.query(Pizza).filter(Pizza.name == "Margherita").first()
109
- print(pizza)
110
106
  ```
111
107
 
112
108
  3. CI/CD integration: Use Liminal to automatically generate and apply your revision files to your Benchling tenant(s) as part of your CI/CD pipeline.
@@ -136,6 +132,7 @@ Liminal ORM is distributed under the [Apache License, Version 2.0](./LICENSE.md)
136
132
 
137
133
  ## [Direct Contact](#direct-contact)
138
134
 
135
+ - Liminal Community Slack group: [Join here](https://join.slack.com/t/liminalorm/shared_invite/zt-2ujrp07s3-bctook4e~cAjn1LgOLVY~Q)
139
136
  - Email: <opensource@dynotx.com>
140
137
  - LinkedIn: [Nirmit Damania](https://www.linkedin.com/in/nirmit-damania/)
141
138
 
@@ -1,10 +1,12 @@
1
1
  liminal/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  liminal/base/base_dropdown.py,sha256=Unk4l_5Y8rj_eSWYqzFi2BAFSQToQDWW2qdXwiCHTg8,2523
3
- liminal/base/base_operation.py,sha256=t16LqSPKQPkh1oJtJU1Wr8TPyflILfHqfrRa4Y8ohAM,3089
4
- liminal/base/base_validation_filters.py,sha256=2Q4QhqDSloZqc313p_fc8dnSw0uMhk_iMtsEtsC_5LQ,536
3
+ liminal/base/base_operation.py,sha256=RjGRaCTNQ5oVI4PAQ5D3svymw_HAcGvzBXWWrMRo29k,3128
4
+ liminal/base/base_validation_filters.py,sha256=kHG3G5gXkuNHQosMTrxRc57OTmczcaoSx0DmkrScIr4,1043
5
5
  liminal/base/compare_operation.py,sha256=hkpv4ewHhxy4dlTPKgJuzBjsAqO6Km7OrrKB44pRA_o,352
6
- liminal/base/properties/base_field_properties.py,sha256=wSEZI3YlQw2jEAOCE0yemcwYZJJhcfnBXhXZR9YAz6o,4891
7
- liminal/base/properties/base_schema_properties.py,sha256=IHfSEdghuLtRJvUDCl-Axgf0wgoCj71J134vVTxKWHQ,4425
6
+ liminal/base/name_template_parts.py,sha256=dJeyrhhhZHDwKXe_p7AtgDlbZlzsnYQ8FoM8FXVF7q0,271
7
+ liminal/base/properties/base_field_properties.py,sha256=NvuQjYZ5U_2363P2c8FXmmLfOtdzUqTuZTjDDfXnO-E,4922
8
+ liminal/base/properties/base_name_template.py,sha256=AOtaW4QEDRC-mjZOZk6jgc_mopUMsHS2Fj6VVsO07WY,3150
9
+ liminal/base/properties/base_schema_properties.py,sha256=pVeIVHea-3Wt0fde9CsOvluwVmYMbsMhGeSncRL2Ats,5351
8
10
  liminal/base/str_enum.py,sha256=jF3d-Lo8zsHUe6GsctX2L-TSj92Y3qCYDrTD-saeJoc,210
9
11
  liminal/cli/cli.py,sha256=JxWHLO9KMeMaOnOYwzdH0w71l0477ScFOkWNtTlc97Y,9045
10
12
  liminal/cli/controller.py,sha256=QNj3QO9TMb9hfc6U-VhLuFa0_aohOHZUmvY4XkATPhw,10118
@@ -14,50 +16,53 @@ liminal/connection/__init__.py,sha256=3z4pSANIOkc9mh1Xp763oYQuJZDEh4lauN901PU4vq
14
16
  liminal/connection/benchling_connection.py,sha256=nALLAA-hPIO2Eb_KhUL-nU3jOlMDSIrPMUgUyDKGRRw,2862
15
17
  liminal/connection/benchling_service.py,sha256=lEYCHF1U8nII8Rn3rMBPTffTFiVFjoFeNmX2Kq36-qE,7170
16
18
  liminal/dropdowns/api.py,sha256=n5oxi1EhkmpmPpNi1LOI4xcIQmk1C069XFaGP5XSBx8,6959
17
- liminal/dropdowns/compare.py,sha256=5cz8djtaStozUun_Cp8t_5PVjq-aovme2Qq5J8FXFg4,6829
19
+ liminal/dropdowns/compare.py,sha256=-UbCkeTKx3THwvjMTUubyYVXBkhmvyhEKzwrIzBkthY,7141
18
20
  liminal/dropdowns/generate_files.py,sha256=IqnBs-IyLsIZE0NUkdB99zd5EAF-1f9CPBeblz-GzJE,2041
19
- liminal/dropdowns/operations.py,sha256=RKXgwO6NQacao6dqzk6__T1B9s-B2YHLPPUyM-0wf0U,13516
21
+ liminal/dropdowns/operations.py,sha256=-TRIsxqnUtrIUjhrt5k_PdiBCDUXsXDzsOUmznJE-6Q,13516
20
22
  liminal/dropdowns/utils.py,sha256=1-H7bTszCUeqeRBpiYXjRjreDzhn1Fd1MFwIsrEI-o4,4109
21
- liminal/entity_schemas/api.py,sha256=Dkd44NGJ4JqRTJLJtPsZ8Qan2owbEYf446A6EuP8iL0,2786
22
- liminal/entity_schemas/compare.py,sha256=C5qr9amGCKvkV61pa29obN883vSdFzSoiebD7hKEHY4,14128
23
- liminal/entity_schemas/entity_schema_models.py,sha256=SNScXY3SeF0lhdAXwqKXrrgpCphpLg6s5tU9fO3juB4,5239
24
- liminal/entity_schemas/generate_files.py,sha256=SW0EccfODptNkZUVwJxa8-8ssd1RWdBqzrCGph4_vSI,8515
25
- liminal/entity_schemas/operations.py,sha256=E12U-F0PtViBApbkoXbEtOlIEcOSSYn_gBx-2Z-vGGM,23164
26
- liminal/entity_schemas/tag_schema_models.py,sha256=rRCAvpjx7iAiIxOh9MRBrpH603zHbFxKOY7sLgOutnE,16260
27
- liminal/entity_schemas/utils.py,sha256=X53KNfguWtu7z-tAliBHuCYpSwTqBGgRSGsdR_BU9Vc,4206
28
- liminal/enums/__init__.py,sha256=jz_c-B_fifatvrYoESlHZ9ljYdz-3rNl0sBazoESiHI,523
23
+ liminal/entity_schemas/api.py,sha256=Emn_Y95cAG9Wis6tpchw6QBVKQh4If86LOdgKk0Ndjw,3575
24
+ liminal/entity_schemas/compare.py,sha256=CIYglq1F-g9jGc1eRRD4LnNErrH2n__pPIJc4EB1hkM,16570
25
+ liminal/entity_schemas/entity_schema_models.py,sha256=YDpz1XkNc9e51zah8Z6qCk30gAuXP6xLEYv1Lb3ECpA,6838
26
+ liminal/entity_schemas/generate_files.py,sha256=oYx0t76oRa36gWwVl1W5jHryh-POIyZPDMbGNjT5bfY,8877
27
+ liminal/entity_schemas/operations.py,sha256=rs9EXmHDgnUad2SSfZ3tnDPFA6L-2wvllAGqBwBurMs,24020
28
+ liminal/entity_schemas/tag_schema_models.py,sha256=h6Zf_zXYG_gTh2eQh_lEGZKUAmvzdnnArlmAhIeX1bM,22016
29
+ liminal/entity_schemas/utils.py,sha256=iZ1_M2r8zKOCFj9QSMdrv-_4XznDn_znAOfoP4Mh1jA,4943
30
+ liminal/enums/__init__.py,sha256=Ue_3QtElW-JMSWtu4vGsAOFQbYnzHHZUdkWpdkzkKA4,453
29
31
  liminal/enums/benchling_api_field_type.py,sha256=0QamSWEMnxZtedZXlh6zNhSRogS9ZqvWskdHHN19xJo,633
30
- liminal/enums/benchling_entity_type.py,sha256=CXCxJzboEbABLMwxrGIoc8hC73LxoSJXHwJWfPjrjvY,435
32
+ liminal/enums/benchling_entity_type.py,sha256=BS6U8qnRM3I3xTTqp9BbInV7yjPh9gC3ULvN6-zLaCM,624
31
33
  liminal/enums/benchling_field_type.py,sha256=uinDm5Mn_yGK1jlmlRH3NlAlXUzA1guNk8wF6lbUKD4,947
32
34
  liminal/enums/benchling_folder_item_type.py,sha256=Jb-YxCvB8O86_qTsfwtLQOkKGjTWGKHFwIKf24eemYk,248
33
35
  liminal/enums/benchling_naming_strategy.py,sha256=wG3AfnPOui5Qfc0Fihszm5uKWjuc7gdpI8jptNB5A-w,1201
34
- liminal/enums/benchling_report_level.py,sha256=HtnSW_yNuRpJ_iQHhzcZudb1Me4QubVg3n9sPSnJiNI,263
35
36
  liminal/enums/benchling_sequence_type.py,sha256=TBI4C5c1XKE4ZXqsz1ApDUzy2wR-04u-M3VO_zLikjM,202
36
- liminal/external/__init__.py,sha256=fXA-WM8eD4q8D0bhnGvRCV-eOzvppnd8d9w6xcH0iLA,991
37
+ liminal/enums/name_template_part_type.py,sha256=Kv0phZIO_dPN3tLHM0lT2tjUd3zBGqpJQGahEpGjNcU,365
38
+ liminal/external/__init__.py,sha256=nMpyzpBXpYhTvN3R3HQEiYb24_U2AYjz_20seAUUK9s,1264
37
39
  liminal/mappers.py,sha256=O9gc95b7JvfaR8xVrn0X1d0Tcs6Iwh-yhBHXhWSX8i0,9616
38
40
  liminal/migrate/components.py,sha256=2HuFp5KDNhofROMRI-BioUoA4CCjhQ_v_F0QmGJzUBU,3480
39
41
  liminal/migrate/revision.py,sha256=KppU0u-d0JsfPsXsmncxy9Q_XBJyf-o4e16wNZAJODM,7774
40
- liminal/migrate/revisions_timeline.py,sha256=06qf_7E1Hecucfczpm85rV3ATLDjpCf7y6TUfah5aLM,14450
42
+ liminal/migrate/revisions_timeline.py,sha256=G9VwxPrLhLqKOrIXyxrXyHpujc-72m7omsZjI5-0D0M,14520
41
43
  liminal/migrate/utils.py,sha256=HdSr3N2WN_1S-PLRGVWSMYl-4gIcP-Ph2wPycGi2cGg,3404
42
44
  liminal/orm/base.py,sha256=fFSpiNRYgK5UG7lbXdQGV8KgO8pwjMqt0pycM3rWJ2o,615
43
- liminal/orm/base_model.py,sha256=QoOmA3S_9nLgPiyboleh-WvJRXcfn4VeDSrWmvyx8aA,11064
45
+ liminal/orm/base_model.py,sha256=Nf4gSEwvORRdnY5ODW79ddJWxnshLLvrPo8xcimHH6c,13891
44
46
  liminal/orm/base_tables/registry_entity.py,sha256=4ET1cepTGjZ3AMFI5q-iMYxMObzXwuUDBD0jNNqCipE,2126
45
47
  liminal/orm/base_tables/schema.py,sha256=7_btCVSUJxjVdGcKVRKL8sKcNw7-_gazTpfEh1jru3o,921
46
48
  liminal/orm/base_tables/user.py,sha256=elRAHj7HgO3iVLK_pNCIwf_9Rl_9k6vkBgaYazoJSQc,818
47
49
  liminal/orm/column.py,sha256=e4JWn97s_4EVJ1LOO5l6iucHQUd39Vl0stqMEj0uet8,5114
48
50
  liminal/orm/mixins.py,sha256=yEeUDF1qEBLP523q8bZra4KtNVK0gwZN9mXJSNe3GEE,4802
51
+ liminal/orm/name_template.py,sha256=ftXZOiRR6gGGvGaZkFVDXKOboIHFWauhQENRguBGWMI,1739
52
+ liminal/orm/name_template_parts.py,sha256=KCGXAcCuOqCjlgYn-mw1K7fwDI92D20l-FnlpEVrbM8,2771
49
53
  liminal/orm/relationship.py,sha256=Zl4bMHbtDSPx1psGHYnojGGJpA8B8hwcPJdgjB1lmW0,2490
50
- liminal/orm/schema_properties.py,sha256=UEIIayhiwHw7YexSGoKU9Z7gj57d7_C1CMUv51-HcGk,2158
54
+ liminal/orm/schema_properties.py,sha256=yv6MOsE_16OWJnGDh2K8wI_054PJwafYmHgY_Awr3XA,3420
51
55
  liminal/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
52
56
  liminal/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
53
- liminal/tests/conftest.py,sha256=1RGiI_h8izLjT9txJ1IkRHYf8yrN_r6yjUn5SI2bxr8,17311
57
+ liminal/tests/conftest.py,sha256=B463eOfe1uCHDJsUNvG-6tY8Qx8FJMByGDOtuyM87lA,17669
54
58
  liminal/tests/from benchling_sdk.py,sha256=CjRUHFB3iaa4rUPLGOqDiBq5EPKldm-Fd8aQQr92zF4,147
55
59
  liminal/tests/test_dropdown_compare.py,sha256=yHB0ovQlBLRu8-qYkqIPd8VtYEOmOft_93FQM86g_z8,8198
56
- liminal/tests/test_entity_schema_compare.py,sha256=p-9inAZM4GOm4e1cadO191LNsnqceUGGyy0YVIXXxVw,16440
57
- liminal/utils.py,sha256=vMjSasDnEghwqULDo14joxxJ56G4-9cBsw719nQ8C7g,2798
58
- liminal/validation/__init__.py,sha256=SBd48xxBMJrBzI48G2RcK056EMlevt5YjmZMkfCWN1I,6924
59
- liminal_orm-1.1.4.dist-info/LICENSE.md,sha256=oVA877F_D1AV44dpjsv4f-4k690uNGApX1EtzOo3T8U,11353
60
- liminal_orm-1.1.4.dist-info/METADATA,sha256=824ba_KuKxfRginOGqJiZYHKPu3yMzsxk7N32CuZzwI,11313
61
- liminal_orm-1.1.4.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
62
- liminal_orm-1.1.4.dist-info/entry_points.txt,sha256=atIrU63rrzH81dWC2sjUbFLlc5FWMmYRdMxXEWexIZA,47
63
- liminal_orm-1.1.4.dist-info/RECORD,,
60
+ liminal/tests/test_entity_schema_compare.py,sha256=-26Bu5eYIuHRswB5kYjGDo5Wed5LUWjm1e6IRI1Q-lE,18952
61
+ liminal/utils.py,sha256=radRtRsZmCiNblMvxOX1DH0rcO5TR09kFlp6OONIPBU,2951
62
+ liminal/validation/__init__.py,sha256=HOjBHCwxvQao6SN_Q5B-JbabG7Z6ff44JIDKLeK96l8,5458
63
+ liminal/validation/validation_severity.py,sha256=ib03PTZCQHcbBDc01v4gJF53YtA-ANY6QSFnhTV-FbU,259
64
+ liminal_orm-2.0.1.dist-info/LICENSE.md,sha256=oVA877F_D1AV44dpjsv4f-4k690uNGApX1EtzOo3T8U,11353
65
+ liminal_orm-2.0.1.dist-info/METADATA,sha256=axM6tXYgSWVWjPGQ_dYDOhNkPEtECVvcB6UHPaB_h8o,11056
66
+ liminal_orm-2.0.1.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
67
+ liminal_orm-2.0.1.dist-info/entry_points.txt,sha256=atIrU63rrzH81dWC2sjUbFLlc5FWMmYRdMxXEWexIZA,47
68
+ liminal_orm-2.0.1.dist-info/RECORD,,