pymetadata 0.5.4__tar.gz → 0.5.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.
Potentially problematic release.
This version of pymetadata might be problematic. Click here for more details.
- {pymetadata-0.5.4 → pymetadata-0.5.6}/.bumpversion.toml +1 -1
- {pymetadata-0.5.4 → pymetadata-0.5.6}/.gitignore +1 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/PKG-INFO +9 -24
- {pymetadata-0.5.4 → pymetadata-0.5.6}/README.md +2 -17
- {pymetadata-0.5.4 → pymetadata-0.5.6}/docs/composite_annotations.md +1 -1
- {pymetadata-0.5.4 → pymetadata-0.5.6}/pyproject.toml +6 -6
- pymetadata-0.5.6/release-notes/0.5.5.md +13 -0
- pymetadata-0.5.6/release-notes/0.5.6.md +10 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/src/pymetadata/__init__.py +1 -1
- {pymetadata-0.5.4 → pymetadata-0.5.6}/src/pymetadata/core/annotation.py +114 -52
- pymetadata-0.5.6/src/pymetadata/identifiers/registry.py +173 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/src/pymetadata/metadata/eco.py +882 -301
- {pymetadata-0.5.4 → pymetadata-0.5.6}/tests/core/test_annotation.py +49 -24
- pymetadata-0.5.4/.github/CONTRIBUTING.rst +0 -141
- pymetadata-0.5.4/.github/ISSUE_TEMPLATE/01-bug-report.md +0 -49
- pymetadata-0.5.4/.github/ISSUE_TEMPLATE/02-question.md +0 -15
- pymetadata-0.5.4/.github/ISSUE_TEMPLATE/03-feature-request.md +0 -36
- pymetadata-0.5.4/.github/ISSUE_TEMPLATE/config.yml +0 -2
- pymetadata-0.5.4/.github/PULL_REQUEST_TEMPLATE.md +0 -4
- pymetadata-0.5.4/.github/SUPPORT.rst +0 -6
- pymetadata-0.5.4/src/pymetadata/identifiers/registry.py +0 -375
- pymetadata-0.5.4/uv.lock +0 -1410
- {pymetadata-0.5.4 → pymetadata-0.5.6}/.github/workflows/main.yml +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/.github/workflows/mypy.yml +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/.github/workflows/ruff.yml +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/.pre-commit-config.yaml +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/.python-version +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/.ruff.toml +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/.zenodo.json +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/LICENSE +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/RELEASE.md +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/docs/images/favicon/about.txt +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/docs/images/favicon/android-chrome-192x192.png +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/docs/images/favicon/android-chrome-512x512.png +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/docs/images/favicon/apple-touch-icon.png +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/docs/images/favicon/favicon-16x16.png +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/docs/images/favicon/favicon-32x32.png +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/docs/images/favicon/favicon.ico +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/docs/images/favicon/favicon_io.zip +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/docs/images/favicon/pymetadata-100x100-300dpi.png +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/docs/images/favicon/site.webmanifest +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/release-notes/0.0.10.md +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/release-notes/0.0.11.md +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/release-notes/0.0.12.md +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/release-notes/0.0.13.md +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/release-notes/0.0.14.md +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/release-notes/0.0.15.md +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/release-notes/0.0.16.md +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/release-notes/0.0.17.md +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/release-notes/0.0.18.md +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/release-notes/0.0.19.md +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/release-notes/0.0.2.md +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/release-notes/0.0.20.md +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/release-notes/0.0.21.md +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/release-notes/0.0.22.md +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/release-notes/0.0.3.md +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/release-notes/0.0.4.md +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/release-notes/0.0.5.md +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/release-notes/0.0.6.md +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/release-notes/0.0.7.md +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/release-notes/0.0.8.md +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/release-notes/0.0.9.md +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/release-notes/0.1.0.md +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/release-notes/0.2.1.md +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/release-notes/0.2.10.md +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/release-notes/0.2.2.md +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/release-notes/0.2.3.md +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/release-notes/0.2.4.md +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/release-notes/0.2.5.md +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/release-notes/0.2.6.md +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/release-notes/0.2.7.md +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/release-notes/0.2.8.md +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/release-notes/0.2.9.md +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/release-notes/0.3.0.md +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/release-notes/0.3.1.md +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/release-notes/0.3.10.md +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/release-notes/0.3.11.md +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/release-notes/0.3.2.md +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/release-notes/0.3.3.md +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/release-notes/0.3.4.md +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/release-notes/0.3.5.md +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/release-notes/0.3.6.md +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/release-notes/0.3.7.md +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/release-notes/0.3.8.md +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/release-notes/0.3.9.md +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/release-notes/0.4.0.md +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/release-notes/0.4.1.md +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/release-notes/0.4.2.md +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/release-notes/0.4.3.md +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/release-notes/0.4.4.md +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/release-notes/0.5.0.md +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/release-notes/0.5.1.md +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/release-notes/0.5.2.md +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/release-notes/0.5.3.md +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/release-notes/0.5.4.md +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/src/pymetadata/cache.py +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/src/pymetadata/chebi.py +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/src/pymetadata/console.py +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/src/pymetadata/core/__init__.py +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/src/pymetadata/core/creator.py +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/src/pymetadata/core/synonym.py +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/src/pymetadata/core/xref.py +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/src/pymetadata/examples/__init__.py +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/src/pymetadata/examples/cache_path_example.py +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/src/pymetadata/examples/omex_example.py +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/src/pymetadata/examples/results/test_from_files.omex +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/src/pymetadata/examples/results/test_from_omex.omex +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/src/pymetadata/examples/results/testomex/README.md +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/src/pymetadata/examples/results/testomex/manifest.xml +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/src/pymetadata/examples/results/testomex/models/omex_comp.xml +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/src/pymetadata/examples/results/testomex/models/omex_comp_flat.xml +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/src/pymetadata/examples/results/testomex/models/omex_minimal.xml +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/src/pymetadata/examples/test.omex +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/src/pymetadata/identifiers/__init__.py +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/src/pymetadata/identifiers/miriam.py +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/src/pymetadata/log.py +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/src/pymetadata/metadata/__init__.py +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/src/pymetadata/metadata/kisao.py +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/src/pymetadata/metadata/sbo.py +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/src/pymetadata/omex.py +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/src/pymetadata/omex_v2.py +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/src/pymetadata/ontologies/__init__.py +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/src/pymetadata/ontologies/ols.py +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/src/pymetadata/ontologies/ontology.py +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/src/pymetadata/py.typed +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/src/pymetadata/resources/ontologies/README.md +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/src/pymetadata/resources/templates/ontology_enum.pytemplate +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/src/pymetadata/unichem.py +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/tests/core/test_creator.py +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/tests/data/omex/BIOMD0000000001.omex +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/tests/data/omex/CombineArchiveShowCase.omex +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/tests/data/omex/CombineArchiveShowCase_manifest.xml +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/tests/data/omex/CompModels.omex +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/tests/data/omex/CompModels_manifest.xml +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/tests/data/omex/iCGB21FR.omex +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/tests/test_chebi.py +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/tests/test_ols.py +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/tests/test_omex.py +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/tests/test_ontology.py +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/tests/test_registry.py +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/tests/test_sbo_kisao.py +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/tests/test_unichem.py +0 -0
- {pymetadata-0.5.4 → pymetadata-0.5.6}/tox.ini +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pymetadata
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.6
|
|
4
4
|
Summary: pymetadata are python utilities for working with metadata.
|
|
5
5
|
Author-email: Matthias König <konigmatt@googlemail.com>
|
|
6
6
|
Maintainer-email: Matthias König <konigmatt@googlemail.com>
|
|
@@ -28,14 +28,14 @@ Requires-Dist: requests>=2.32.3
|
|
|
28
28
|
Requires-Dist: rich>=13.9.4
|
|
29
29
|
Requires-Dist: xmltodict>=0.14.2
|
|
30
30
|
Provides-Extra: dev
|
|
31
|
-
Requires-Dist: bump-my-version>=
|
|
32
|
-
Requires-Dist: mypy>=1.
|
|
31
|
+
Requires-Dist: bump-my-version>=1.2.4; extra == 'dev'
|
|
32
|
+
Requires-Dist: mypy>=1.18.2; extra == 'dev'
|
|
33
33
|
Requires-Dist: pre-commit>=4.0.1; extra == 'dev'
|
|
34
|
-
Requires-Dist: ruff>=0.
|
|
34
|
+
Requires-Dist: ruff>=0.14.0; extra == 'dev'
|
|
35
35
|
Provides-Extra: test
|
|
36
|
-
Requires-Dist: pytest-cov>=
|
|
37
|
-
Requires-Dist: pytest>=8.
|
|
38
|
-
Requires-Dist: tox>=4.
|
|
36
|
+
Requires-Dist: pytest-cov>=7.0.0; extra == 'test'
|
|
37
|
+
Requires-Dist: pytest>=8.4.2; extra == 'test'
|
|
38
|
+
Requires-Dist: tox>=4.31.0; extra == 'test'
|
|
39
39
|
Description-Content-Type: text/markdown
|
|
40
40
|
|
|
41
41
|

|
|
@@ -53,9 +53,9 @@ metadata in the context of COMBINE standards with source code available from
|
|
|
53
53
|
|
|
54
54
|
Features include among others
|
|
55
55
|
|
|
56
|
-
-
|
|
56
|
+
- COMBINE archive version 1 support (OMEX)
|
|
57
57
|
- annotation classes and helpers
|
|
58
|
-
- SBO and
|
|
58
|
+
- SBO, KISAO and ECO ontology enums
|
|
59
59
|
|
|
60
60
|
If you have any questions or issues please [open an issue](https://github.com/matthiaskoenig/pymetadata/issues).
|
|
61
61
|
|
|
@@ -66,8 +66,6 @@ see [omex_example.py](src/pymetadata/examples/omex_example.py).
|
|
|
66
66
|
# How to cite
|
|
67
67
|
[](https://doi.org/10.5281/zenodo.5308801)
|
|
68
68
|
|
|
69
|
-
# Contributing
|
|
70
|
-
Contributions are always welcome! Please read the [contributing guidelines](https://github.com/matthiaskoenig/pymetadata/blob/develop/.github/CONTRIBUTING.rst) to get started.
|
|
71
69
|
|
|
72
70
|
# License
|
|
73
71
|
- Source Code: [MIT](https://opensource.org/license/MIT)
|
|
@@ -84,19 +82,6 @@ can be installed via
|
|
|
84
82
|
pip install pymetadata
|
|
85
83
|
```
|
|
86
84
|
|
|
87
|
-
## Develop version
|
|
88
|
-
The latest develop version can be installed via
|
|
89
|
-
```bash
|
|
90
|
-
pip install git+https://github.com/matthiaskoenig/pymetadata.git@develop
|
|
91
|
-
```
|
|
92
|
-
|
|
93
|
-
Or via cloning the repository and installing via
|
|
94
|
-
```bash
|
|
95
|
-
git clone https://github.com/matthiaskoenig/pymetadata.git
|
|
96
|
-
cd pymetadata
|
|
97
|
-
pip install -e .
|
|
98
|
-
```
|
|
99
|
-
|
|
100
85
|
# Cache path
|
|
101
86
|
`pymetadata` caches some information for faster retrieval. The cache path is set to
|
|
102
87
|
|
|
@@ -13,9 +13,9 @@ metadata in the context of COMBINE standards with source code available from
|
|
|
13
13
|
|
|
14
14
|
Features include among others
|
|
15
15
|
|
|
16
|
-
-
|
|
16
|
+
- COMBINE archive version 1 support (OMEX)
|
|
17
17
|
- annotation classes and helpers
|
|
18
|
-
- SBO and
|
|
18
|
+
- SBO, KISAO and ECO ontology enums
|
|
19
19
|
|
|
20
20
|
If you have any questions or issues please [open an issue](https://github.com/matthiaskoenig/pymetadata/issues).
|
|
21
21
|
|
|
@@ -26,8 +26,6 @@ see [omex_example.py](src/pymetadata/examples/omex_example.py).
|
|
|
26
26
|
# How to cite
|
|
27
27
|
[](https://doi.org/10.5281/zenodo.5308801)
|
|
28
28
|
|
|
29
|
-
# Contributing
|
|
30
|
-
Contributions are always welcome! Please read the [contributing guidelines](https://github.com/matthiaskoenig/pymetadata/blob/develop/.github/CONTRIBUTING.rst) to get started.
|
|
31
29
|
|
|
32
30
|
# License
|
|
33
31
|
- Source Code: [MIT](https://opensource.org/license/MIT)
|
|
@@ -44,19 +42,6 @@ can be installed via
|
|
|
44
42
|
pip install pymetadata
|
|
45
43
|
```
|
|
46
44
|
|
|
47
|
-
## Develop version
|
|
48
|
-
The latest develop version can be installed via
|
|
49
|
-
```bash
|
|
50
|
-
pip install git+https://github.com/matthiaskoenig/pymetadata.git@develop
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
Or via cloning the repository and installing via
|
|
54
|
-
```bash
|
|
55
|
-
git clone https://github.com/matthiaskoenig/pymetadata.git
|
|
56
|
-
cd pymetadata
|
|
57
|
-
pip install -e .
|
|
58
|
-
```
|
|
59
|
-
|
|
60
45
|
# Cache path
|
|
61
46
|
`pymetadata` caches some information for faster retrieval. The cache path is set to
|
|
62
47
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Composite annotations are semantic annotations that are comprised of multiple annotation
|
|
4
4
|
terms linked using standard qualifiers (also known as “relations” or “predicates”)
|
|
5
|
-
to indicate the meaning of
|
|
5
|
+
to indicate the meaning of annotation.
|
|
6
6
|
Composite annotations are used when a single knowledge resource term is not available to
|
|
7
7
|
sufficiently define a model or data element. For model-component annotations,
|
|
8
8
|
composite annotations have two primary components:
|
|
@@ -49,15 +49,15 @@ dependencies = [
|
|
|
49
49
|
|
|
50
50
|
[project.optional-dependencies]
|
|
51
51
|
dev = [
|
|
52
|
-
"bump-my-version>=
|
|
53
|
-
"ruff>=0.
|
|
52
|
+
"bump-my-version>=1.2.4",
|
|
53
|
+
"ruff>=0.14.0",
|
|
54
54
|
"pre-commit>=4.0.1",
|
|
55
|
-
"mypy>=1.
|
|
55
|
+
"mypy>=1.18.2",
|
|
56
56
|
]
|
|
57
57
|
test = [
|
|
58
|
-
"tox>=4.
|
|
59
|
-
"pytest>=8.
|
|
60
|
-
"pytest-cov>=
|
|
58
|
+
"tox>=4.31.0",
|
|
59
|
+
"pytest>=8.4.2",
|
|
60
|
+
"pytest-cov>=7.0.0",
|
|
61
61
|
]
|
|
62
62
|
|
|
63
63
|
[project_urls]
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Release notes for pymetadata 0.5.5
|
|
2
|
+

|
|
3
|
+
|
|
4
|
+
We are pleased to release the next version of pymetadata including the
|
|
5
|
+
following changes:
|
|
6
|
+
|
|
7
|
+
## Features & fixes
|
|
8
|
+
- remove custom namespaces (#62)
|
|
9
|
+
- better support of compact identifiers.org identifiers (#63)
|
|
10
|
+
- support of bioregistry.io as provider (#40)
|
|
11
|
+
- updated ECO ontology
|
|
12
|
+
|
|
13
|
+
Your pymetadata team
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Release notes for pymetadata 0.5.6
|
|
2
|
+

|
|
3
|
+
|
|
4
|
+
We are pleased to release the next version of pymetadata including the
|
|
5
|
+
following changes:
|
|
6
|
+
|
|
7
|
+
## Features & fixes
|
|
8
|
+
- bugfix compact ids when id starts with namespace
|
|
9
|
+
|
|
10
|
+
Your pymetadata team
|
|
@@ -5,12 +5,14 @@ Core data structure to store annotations.
|
|
|
5
5
|
|
|
6
6
|
import re
|
|
7
7
|
import urllib
|
|
8
|
+
from enum import Enum
|
|
8
9
|
from pprint import pprint
|
|
9
10
|
from typing import Any, Dict, Final, List, Optional, Tuple, Union
|
|
10
11
|
|
|
11
12
|
import requests
|
|
12
13
|
|
|
13
14
|
from pymetadata import log
|
|
15
|
+
from pymetadata.console import console
|
|
14
16
|
from pymetadata.core.xref import CrossReference, is_url
|
|
15
17
|
from pymetadata.identifiers.miriam import BQB, BQM
|
|
16
18
|
from pymetadata.identifiers.registry import REGISTRY
|
|
@@ -19,19 +21,31 @@ from pymetadata.ontologies.ols import ONTOLOGIES, OLSQuery
|
|
|
19
21
|
|
|
20
22
|
OLS_QUERY = OLSQuery(ontologies=ONTOLOGIES)
|
|
21
23
|
|
|
22
|
-
IDENTIFIERS_ORG_PREFIX: Final = "
|
|
24
|
+
IDENTIFIERS_ORG_PREFIX: Final = "https://identifiers.org"
|
|
23
25
|
IDENTIFIERS_ORG_PATTERN1: Final = re.compile(r"^https?://identifiers.org/(.+?)/(.+)")
|
|
24
26
|
IDENTIFIERS_ORG_PATTERN2: Final = re.compile(r"^https?://identifiers.org/(.+)")
|
|
27
|
+
|
|
28
|
+
BIOREGISTRY_PREFIX: Final = "https://bioregistry.io"
|
|
29
|
+
BIOREGISTRY_PATTERN: Final = re.compile(r"^https?://bioregistry.io/(.+)")
|
|
30
|
+
|
|
25
31
|
MIRIAM_URN_PATTERN: Final = re.compile(r"^urn:miriam:(.+)")
|
|
26
32
|
|
|
27
33
|
logger = log.get_logger(__name__)
|
|
28
34
|
|
|
29
35
|
|
|
36
|
+
class ProviderType(str, Enum):
|
|
37
|
+
"""Provider type."""
|
|
38
|
+
|
|
39
|
+
IDENTIFIERS_ORG = "identifiers.org"
|
|
40
|
+
BIOREGISTRY_IO = "bioregistry.io"
|
|
41
|
+
NONE = "none"
|
|
42
|
+
|
|
43
|
+
|
|
30
44
|
class RDFAnnotation:
|
|
31
45
|
"""RDFAnnotation class.
|
|
32
46
|
|
|
33
47
|
Basic storage of annotation information. This consists of the relation
|
|
34
|
-
and the
|
|
48
|
+
and the resource.
|
|
35
49
|
The annotations can be attached to other objects thereby forming
|
|
36
50
|
triples which can be converted to RDF.
|
|
37
51
|
|
|
@@ -40,6 +54,7 @@ class RDFAnnotation:
|
|
|
40
54
|
- `collection/term`, i.e., the combination of collection and term
|
|
41
55
|
- `http(s)://arbitrary.url`, an arbitrary URL
|
|
42
56
|
- urn:miriam:uniprot:P03023
|
|
57
|
+
- https://bioregistry.io/chebi:15996 urls via the bioregistry provider
|
|
43
58
|
"""
|
|
44
59
|
|
|
45
60
|
replaced_collections: Dict[str, str] = {
|
|
@@ -53,6 +68,7 @@ class RDFAnnotation:
|
|
|
53
68
|
self.collection: Optional[str] = None
|
|
54
69
|
self.term: Optional[str] = None
|
|
55
70
|
self.resource: str = resource
|
|
71
|
+
self.provider: ProviderType = ProviderType.IDENTIFIERS_ORG
|
|
56
72
|
|
|
57
73
|
if not qualifier:
|
|
58
74
|
raise ValueError(
|
|
@@ -75,15 +91,19 @@ class RDFAnnotation:
|
|
|
75
91
|
if match1:
|
|
76
92
|
# handle identifiers.org pattern
|
|
77
93
|
self.collection, self.term = match1.group(1), match1.group(2)
|
|
94
|
+
self.provider = ProviderType.IDENTIFIERS_ORG
|
|
78
95
|
|
|
79
96
|
if not self.collection:
|
|
80
|
-
# tests new
|
|
97
|
+
# tests new compact patterns
|
|
81
98
|
match2 = IDENTIFIERS_ORG_PATTERN2.match(resource)
|
|
82
99
|
if match2:
|
|
83
100
|
tokens = match2.group(1).split(":")
|
|
84
101
|
if len(tokens) == 2:
|
|
85
102
|
self.collection = tokens[0].lower()
|
|
103
|
+
|
|
104
|
+
# check if the namespace is embedded
|
|
86
105
|
self.term = match2.group(1)
|
|
106
|
+
self.provider = ProviderType.IDENTIFIERS_ORG
|
|
87
107
|
else:
|
|
88
108
|
logger.warning(
|
|
89
109
|
f"Identifiers.org URL does not conform to new"
|
|
@@ -94,10 +114,16 @@ class RDFAnnotation:
|
|
|
94
114
|
# other urls are directly stored as resources without collection
|
|
95
115
|
self.collection = None
|
|
96
116
|
self.term = resource
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
117
|
+
if BIOREGISTRY_PATTERN.match(resource):
|
|
118
|
+
self.provider = ProviderType.BIOREGISTRY_IO
|
|
119
|
+
console.print(self.provider)
|
|
120
|
+
else:
|
|
121
|
+
self.provider = ProviderType.NONE
|
|
122
|
+
logger.warning(
|
|
123
|
+
f"{resource} does not conform to "
|
|
124
|
+
f"http(s)://identifiers.org/collection/id or http(s)://identifiers.org/id or "
|
|
125
|
+
f"https://bioregistry.io/id .",
|
|
126
|
+
)
|
|
101
127
|
|
|
102
128
|
# handle urns
|
|
103
129
|
elif resource.startswith("urn:miriam:"):
|
|
@@ -106,6 +132,7 @@ class RDFAnnotation:
|
|
|
106
132
|
tokens = match3.group(1).split(":")
|
|
107
133
|
self.collection = tokens[0]
|
|
108
134
|
self.term = ":".join(tokens[1:]).replace("%3A", ":")
|
|
135
|
+
self.provider = ProviderType.IDENTIFIERS_ORG
|
|
109
136
|
|
|
110
137
|
logger.warning(
|
|
111
138
|
f"Deprecated urn pattern `{resource}` updated: "
|
|
@@ -118,9 +145,11 @@ class RDFAnnotation:
|
|
|
118
145
|
if len(tokens) > 1:
|
|
119
146
|
self.collection = tokens[0]
|
|
120
147
|
self.term = "/".join(tokens[1:])
|
|
148
|
+
self.provider = ProviderType.IDENTIFIERS_ORG
|
|
121
149
|
elif len(tokens) == 1 and ":" in tokens[0]:
|
|
122
150
|
self.collection = tokens[0].split(":")[0].lower()
|
|
123
151
|
self.term = tokens[0]
|
|
152
|
+
self.provider = ProviderType.IDENTIFIERS_ORG
|
|
124
153
|
|
|
125
154
|
# validation
|
|
126
155
|
if len(tokens) < 2 and not self.collection:
|
|
@@ -132,6 +161,13 @@ class RDFAnnotation:
|
|
|
132
161
|
)
|
|
133
162
|
self.collection = None
|
|
134
163
|
self.term = resource
|
|
164
|
+
self.provider = ProviderType.NONE
|
|
165
|
+
|
|
166
|
+
# shorten compact terms
|
|
167
|
+
if self.term and self.collection:
|
|
168
|
+
self.term = self.shorten_compact_term(
|
|
169
|
+
term=self.term, collection=self.collection
|
|
170
|
+
)
|
|
135
171
|
|
|
136
172
|
# clean legacy collections
|
|
137
173
|
if self.collection in self.replaced_collections:
|
|
@@ -139,6 +175,21 @@ class RDFAnnotation:
|
|
|
139
175
|
|
|
140
176
|
self.validate()
|
|
141
177
|
|
|
178
|
+
@staticmethod
|
|
179
|
+
def shorten_compact_term(term: str, collection: str) -> str:
|
|
180
|
+
"""Shorten the compact terms and return term.
|
|
181
|
+
|
|
182
|
+
If the namespace is not embeddd in the term return the shortened term.
|
|
183
|
+
"""
|
|
184
|
+
namespace = REGISTRY.ns_dict.get(collection, None)
|
|
185
|
+
if namespace and not namespace.namespaceEmbeddedInLui:
|
|
186
|
+
# shorter term
|
|
187
|
+
if term.lower().startswith(f"{collection}:"):
|
|
188
|
+
tokens = term.split(":")
|
|
189
|
+
term = ":".join(tokens[1:])
|
|
190
|
+
|
|
191
|
+
return term
|
|
192
|
+
|
|
142
193
|
@staticmethod
|
|
143
194
|
def from_tuple(t: Tuple[Union[BQB, BQM], str]) -> "RDFAnnotation":
|
|
144
195
|
"""Construct from tuple."""
|
|
@@ -164,12 +215,12 @@ class RDFAnnotation:
|
|
|
164
215
|
|
|
165
216
|
def __repr__(self) -> str:
|
|
166
217
|
"""Get representation string."""
|
|
167
|
-
return f"RDFAnnotation({self.qualifier}|{self.collection}|{self.term})"
|
|
218
|
+
return f"RDFAnnotation({self.qualifier}|{self.collection}|{self.term}|{self.provider.value})"
|
|
168
219
|
|
|
169
220
|
def to_dict(self) -> Dict:
|
|
170
221
|
"""Convert to dict."""
|
|
171
222
|
return {
|
|
172
|
-
"qualifier": self.qualifier.value,
|
|
223
|
+
"qualifier": self.qualifier.value,
|
|
173
224
|
"collection": self.collection,
|
|
174
225
|
"term": self.term,
|
|
175
226
|
}
|
|
@@ -346,52 +397,63 @@ class RDFAnnotationData(RDFAnnotation):
|
|
|
346
397
|
|
|
347
398
|
if __name__ == "__main__":
|
|
348
399
|
for annotation in [
|
|
349
|
-
# FIXME: support this
|
|
350
|
-
RDFAnnotation(
|
|
351
|
-
qualifier=BQB.IS_VERSION_OF,
|
|
352
|
-
resource="NCIT:C75913",
|
|
353
|
-
),
|
|
354
|
-
RDFAnnotation(
|
|
355
|
-
qualifier=BQB.IS_VERSION_OF,
|
|
356
|
-
resource="taxonomy/562",
|
|
357
|
-
),
|
|
358
|
-
RDFAnnotation(
|
|
359
|
-
qualifier=BQB.IS_VERSION_OF,
|
|
360
|
-
resource="http://identifiers.org/taxonomy/9606",
|
|
361
|
-
),
|
|
362
400
|
RDFAnnotation(
|
|
363
401
|
qualifier=BQB.IS_VERSION_OF,
|
|
364
|
-
resource="
|
|
365
|
-
),
|
|
366
|
-
RDFAnnotation(
|
|
367
|
-
qualifier=BQB.IS_VERSION_OF, resource="urn:miriam:obo.go:GO%3A0005623"
|
|
368
|
-
),
|
|
369
|
-
RDFAnnotation(
|
|
370
|
-
qualifier=BQB.IS_VERSION_OF, resource="urn:miriam:chebi:CHEBI%3A33699"
|
|
371
|
-
),
|
|
372
|
-
RDFAnnotation(qualifier=BQB.IS_VERSION_OF, resource="chebi/CHEBI:456215"),
|
|
373
|
-
RDFAnnotation(
|
|
374
|
-
qualifier=BQB.IS, resource="https://en.wikipedia.org/wiki/Cytosol"
|
|
375
|
-
),
|
|
376
|
-
RDFAnnotation(
|
|
377
|
-
qualifier=BQB.IS_VERSION_OF, resource="urn:miriam:uniprot:P03023"
|
|
378
|
-
),
|
|
379
|
-
RDFAnnotation(
|
|
380
|
-
qualifier=BQB.IS_VERSION_OF,
|
|
381
|
-
resource="http://identifiers.org/go/GO:0005829",
|
|
382
|
-
),
|
|
383
|
-
RDFAnnotation(
|
|
384
|
-
qualifier=BQB.IS_VERSION_OF, resource="http://identifiers.org/go/GO:0005829"
|
|
385
|
-
),
|
|
386
|
-
RDFAnnotation(
|
|
387
|
-
qualifier=BQB.IS_VERSION_OF, resource="http://identifiers.org/GO:0005829"
|
|
388
|
-
),
|
|
389
|
-
RDFAnnotation(
|
|
390
|
-
qualifier=BQB.IS_VERSION_OF, resource="http://identifiers.org/GO:0005829"
|
|
402
|
+
resource="hmdb/HMDB0000122",
|
|
391
403
|
),
|
|
392
|
-
RDFAnnotation(
|
|
393
|
-
|
|
394
|
-
|
|
404
|
+
# RDFAnnotation(
|
|
405
|
+
# qualifier=BQB.IS_VERSION_OF,
|
|
406
|
+
# resource="https://bioregistry.io/chebi:15996",
|
|
407
|
+
# ),
|
|
408
|
+
# RDFAnnotation(
|
|
409
|
+
# qualifier=BQB.IS_VERSION_OF,
|
|
410
|
+
# resource="NCIT:C75913",
|
|
411
|
+
# ),
|
|
412
|
+
# RDFAnnotation(
|
|
413
|
+
# qualifier=BQB.IS_VERSION_OF,
|
|
414
|
+
# resource="ncit:C75913",
|
|
415
|
+
# ),
|
|
416
|
+
# RDFAnnotation(
|
|
417
|
+
# qualifier=BQB.IS_VERSION_OF,
|
|
418
|
+
# resource="taxonomy/562",
|
|
419
|
+
# ),
|
|
420
|
+
# RDFAnnotation(
|
|
421
|
+
# qualifier=BQB.IS_VERSION_OF,
|
|
422
|
+
# resource="http://identifiers.org/taxonomy/9606",
|
|
423
|
+
# ),
|
|
424
|
+
# RDFAnnotation(
|
|
425
|
+
# qualifier=BQB.IS_VERSION_OF,
|
|
426
|
+
# resource="http://identifiers.org/biomodels.sbo/SBO:0000247",
|
|
427
|
+
# ),
|
|
428
|
+
# RDFAnnotation(
|
|
429
|
+
# qualifier=BQB.IS_VERSION_OF, resource="urn:miriam:obo.go:GO%3A0005623"
|
|
430
|
+
# ),
|
|
431
|
+
# RDFAnnotation(
|
|
432
|
+
# qualifier=BQB.IS_VERSION_OF, resource="urn:miriam:chebi:CHEBI%3A33699"
|
|
433
|
+
# ),
|
|
434
|
+
# RDFAnnotation(qualifier=BQB.IS_VERSION_OF, resource="chebi/CHEBI:456215"),
|
|
435
|
+
# RDFAnnotation(
|
|
436
|
+
# qualifier=BQB.IS, resource="https://en.wikipedia.org/wiki/Cytosol"
|
|
437
|
+
# ),
|
|
438
|
+
# RDFAnnotation(
|
|
439
|
+
# qualifier=BQB.IS_VERSION_OF, resource="urn:miriam:uniprot:P03023"
|
|
440
|
+
# ),
|
|
441
|
+
# RDFAnnotation(
|
|
442
|
+
# qualifier=BQB.IS_VERSION_OF,
|
|
443
|
+
# resource="http://identifiers.org/go/GO:0005829",
|
|
444
|
+
# ),
|
|
445
|
+
# RDFAnnotation(
|
|
446
|
+
# qualifier=BQB.IS_VERSION_OF, resource="http://identifiers.org/go/GO:0005829"
|
|
447
|
+
# ),
|
|
448
|
+
# RDFAnnotation(
|
|
449
|
+
# qualifier=BQB.IS_VERSION_OF, resource="http://identifiers.org/GO:0005829"
|
|
450
|
+
# ),
|
|
451
|
+
# RDFAnnotation(
|
|
452
|
+
# qualifier=BQB.IS_VERSION_OF, resource="http://identifiers.org/GO:0005829"
|
|
453
|
+
# ),
|
|
454
|
+
# RDFAnnotation(qualifier=BQB.IS_VERSION_OF, resource="bto/BTO:0000089"),
|
|
455
|
+
# RDFAnnotation(qualifier=BQB.IS_VERSION_OF, resource="BTO:0000089"),
|
|
456
|
+
# RDFAnnotation(qualifier=BQB.IS_VERSION_OF, resource="chebi/CHEBI:000012"),
|
|
395
457
|
]:
|
|
396
458
|
print("-" * 80)
|
|
397
459
|
data = RDFAnnotationData(annotation)
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Helper tools to work with identifiers registry.
|
|
3
|
+
|
|
4
|
+
https://identifiers.org/
|
|
5
|
+
https://docs.identifiers.org/articles/api.html
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import inspect
|
|
11
|
+
import os
|
|
12
|
+
import time
|
|
13
|
+
from dataclasses import dataclass, field
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
from typing import Any, Dict, List, Optional
|
|
16
|
+
|
|
17
|
+
import requests
|
|
18
|
+
|
|
19
|
+
import pymetadata
|
|
20
|
+
from pymetadata import log
|
|
21
|
+
from pymetadata.cache import DataclassJSONEncoder, read_json_cache, write_json_cache
|
|
22
|
+
from pymetadata.console import console
|
|
23
|
+
|
|
24
|
+
logger = log.get_logger(__name__)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@dataclass
|
|
28
|
+
class Resource:
|
|
29
|
+
"""Resource."""
|
|
30
|
+
|
|
31
|
+
id: Optional[int]
|
|
32
|
+
providerCode: str
|
|
33
|
+
name: str
|
|
34
|
+
urlPattern: str
|
|
35
|
+
mirId: Optional[str] = field(repr=False)
|
|
36
|
+
description: str = field(repr=False)
|
|
37
|
+
official: bool = field(repr=False)
|
|
38
|
+
|
|
39
|
+
sampleId: Optional[str] = field(repr=False)
|
|
40
|
+
resourceHomeUrl: Optional[str] = field(repr=False)
|
|
41
|
+
institution: dict = field(repr=False)
|
|
42
|
+
location: dict = field(repr=False)
|
|
43
|
+
deprecated: bool = field(repr=False)
|
|
44
|
+
deprecationDate: str = field(repr=False)
|
|
45
|
+
protectedUrls: bool = field(repr=False, default=False)
|
|
46
|
+
renderProtectedLanding: bool = field(repr=False, default=False)
|
|
47
|
+
authHelpUrl: Optional[str] = field(repr=False, default=None)
|
|
48
|
+
authHelpDescription: Optional[str] = field(repr=False, default=None)
|
|
49
|
+
|
|
50
|
+
@classmethod
|
|
51
|
+
def from_dict(cls, d: Dict[str, Any]) -> Resource:
|
|
52
|
+
"""Handle additional keyword arguments."""
|
|
53
|
+
return cls(
|
|
54
|
+
**{k: v for k, v in d.items() if k in inspect.signature(cls).parameters}
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
@dataclass
|
|
59
|
+
class Namespace:
|
|
60
|
+
"""Namespace."""
|
|
61
|
+
|
|
62
|
+
id: Optional[str]
|
|
63
|
+
prefix: Optional[str]
|
|
64
|
+
name: str
|
|
65
|
+
pattern: str
|
|
66
|
+
namespaceEmbeddedInLui: bool
|
|
67
|
+
description: str = field(repr=False)
|
|
68
|
+
mirId: Optional[str] = field(repr=False, default=None)
|
|
69
|
+
resources: Optional[List] = field(repr=False, default=None)
|
|
70
|
+
created: Optional[str] = field(repr=False, default=None)
|
|
71
|
+
modified: Optional[str] = field(repr=False, default=None)
|
|
72
|
+
sampleId: Optional[str] = field(repr=False, default=None)
|
|
73
|
+
deprecated: bool = field(repr=False, default=False)
|
|
74
|
+
deprecationDate: Optional[str] = field(repr=False, default=None)
|
|
75
|
+
|
|
76
|
+
@classmethod
|
|
77
|
+
def from_dict(cls, d: Dict[str, Any]) -> Namespace:
|
|
78
|
+
"""Handle additional keyword arguments."""
|
|
79
|
+
return cls(
|
|
80
|
+
**{k: v for k, v in d.items() if k in inspect.signature(cls).parameters}
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
def __post_init__(self) -> None:
|
|
84
|
+
"""Set resources."""
|
|
85
|
+
if self.resources is not None:
|
|
86
|
+
self.resources = [Resource.from_dict(d) for d in self.resources]
|
|
87
|
+
else:
|
|
88
|
+
self.resources = list()
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
class Registry:
|
|
92
|
+
"""Managing the available annotation information.
|
|
93
|
+
|
|
94
|
+
Registry of meta information.
|
|
95
|
+
"""
|
|
96
|
+
|
|
97
|
+
URL = "https://registry.api.identifiers.org/resolutionApi/getResolverDataset"
|
|
98
|
+
|
|
99
|
+
def __init__(
|
|
100
|
+
self,
|
|
101
|
+
cache_duration: int = 24,
|
|
102
|
+
cache: bool = True,
|
|
103
|
+
):
|
|
104
|
+
"""Initialize registry.
|
|
105
|
+
|
|
106
|
+
:param cache_path: Path of cached identifiers.org path
|
|
107
|
+
:param cache_duration: Duration of caching in hours.
|
|
108
|
+
:param cache: boolean flag to stop caching
|
|
109
|
+
"""
|
|
110
|
+
self.registry_path = pymetadata.CACHE_PATH / "identifiers_registry.json"
|
|
111
|
+
|
|
112
|
+
# check if update needed
|
|
113
|
+
if cache:
|
|
114
|
+
if os.path.exists(self.registry_path):
|
|
115
|
+
registry_age = (
|
|
116
|
+
time.time() - os.path.getmtime(self.registry_path)
|
|
117
|
+
) / 3600 # [hr]
|
|
118
|
+
update = registry_age > cache_duration
|
|
119
|
+
else:
|
|
120
|
+
update = True
|
|
121
|
+
else:
|
|
122
|
+
update = True
|
|
123
|
+
|
|
124
|
+
self.ns_dict: Dict[str, Namespace] = (
|
|
125
|
+
self.update() if update else Registry.load_registry(self.registry_path)
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
def update(self) -> Dict[str, Namespace]:
|
|
129
|
+
"""Update registry."""
|
|
130
|
+
Registry.update_registry(registry_path=self.registry_path)
|
|
131
|
+
return Registry.load_registry(registry_path=self.registry_path)
|
|
132
|
+
|
|
133
|
+
@staticmethod
|
|
134
|
+
def update_registry(
|
|
135
|
+
registry_path: Optional[Path] = None,
|
|
136
|
+
) -> Dict[str, Namespace]:
|
|
137
|
+
"""Update registry from identifiers.org webservice."""
|
|
138
|
+
logger.info(f"Update registry from '{Registry.URL}'")
|
|
139
|
+
response = requests.get(Registry.URL)
|
|
140
|
+
namespaces = response.json()["payload"]["namespaces"]
|
|
141
|
+
|
|
142
|
+
ns_dict = {}
|
|
143
|
+
for _, data in enumerate(namespaces):
|
|
144
|
+
ns = Namespace.from_dict(data)
|
|
145
|
+
ns_dict[ns.prefix] = ns
|
|
146
|
+
|
|
147
|
+
if registry_path is not None:
|
|
148
|
+
write_json_cache(
|
|
149
|
+
data=ns_dict,
|
|
150
|
+
cache_path=registry_path,
|
|
151
|
+
json_encoder=DataclassJSONEncoder,
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
return ns_dict # type: ignore
|
|
155
|
+
|
|
156
|
+
@staticmethod
|
|
157
|
+
def load_registry(registry_path: Path) -> Dict[str, Namespace]:
|
|
158
|
+
"""Load namespaces with resources from path."""
|
|
159
|
+
if not registry_path.exists():
|
|
160
|
+
Registry.update_registry(registry_path=registry_path)
|
|
161
|
+
|
|
162
|
+
d = read_json_cache(cache_path=registry_path)
|
|
163
|
+
if not d:
|
|
164
|
+
raise ValueError("Registry could not be loaded from cache.")
|
|
165
|
+
|
|
166
|
+
return {k: Namespace(**v) for k, v in d.items()}
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
REGISTRY = Registry()
|
|
170
|
+
|
|
171
|
+
if __name__ == "__main__":
|
|
172
|
+
registry = Registry(cache=False)
|
|
173
|
+
console.print(registry.ns_dict)
|