bam-masterdata 0.1.0__tar.gz → 0.2.0__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.
- bam_masterdata-0.2.0/.coveragerc +6 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/.vscode/settings.json +13 -0
- bam_masterdata-0.2.0/LICENSE +21 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/PKG-INFO +37 -5
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/README.md +10 -3
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/bam_masterdata/_version.py +2 -2
- bam_masterdata-0.2.0/bam_masterdata/checker/__init__.py +1 -0
- bam_masterdata-0.2.0/bam_masterdata/checker/checker.py +45 -0
- bam_masterdata-0.2.0/bam_masterdata/checker/datamodel_loader.py +9 -0
- bam_masterdata-0.2.0/bam_masterdata/checker/masterdata_validator.py +34 -0
- bam_masterdata-0.2.0/bam_masterdata/checker/source_loader.py +27 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/bam_masterdata/cli/cli.py +136 -13
- bam_masterdata-0.2.0/bam_masterdata/cli/entities_to_rdf.py +236 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/bam_masterdata/cli/fill_masterdata.py +9 -4
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/bam_masterdata/datamodel/property_types.py +4 -2
- bam_masterdata-0.2.0/bam_masterdata/excel/__init__.py +1 -0
- bam_masterdata-0.2.0/bam_masterdata/excel/excel_to_entities.py +692 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/bam_masterdata/metadata/definitions.py +37 -5
- bam_masterdata-0.2.0/bam_masterdata/metadata/entities.py +390 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/bam_masterdata/utils/__init__.py +2 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/bam_masterdata/utils/utils.py +96 -6
- bam_masterdata-0.2.0/bam_masterdata/validation_rules/excel_validation_rules.json +73 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/bam_masterdata.egg-info/PKG-INFO +37 -5
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/bam_masterdata.egg-info/SOURCES.txt +14 -1
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/bam_masterdata.egg-info/requires.txt +3 -1
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/docs/assets/drawio/masterdata-workflow.drawio +73 -77
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/pyproject.toml +3 -1
- bam_masterdata-0.2.0/tests/cli/test_entities_to_rdf.py +111 -0
- bam_masterdata-0.2.0/tests/data/utils/example_prop_types_1.py +23 -0
- bam_masterdata-0.2.0/tests/data/utils/example_prop_types_2.py +16 -0
- bam_masterdata-0.2.0/tests/excel/test_excel_to_entities.py +1470 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/tests/metadata/test_definitions.py +40 -21
- bam_masterdata-0.2.0/tests/metadata/test_entities.py +116 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/tests/utils/test_utils.py +145 -3
- bam_masterdata-0.1.0/.coveragerc +0 -4
- bam_masterdata-0.1.0/bam_masterdata/cli/excel_to_entities.py +0 -884
- bam_masterdata-0.1.0/bam_masterdata/metadata/entities.py +0 -181
- bam_masterdata-0.1.0/tests/metadata/test_entities.py +0 -54
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/.github/workflows/actions.yml +0 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/.github/workflows/coveralls.yml +0 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/.github/workflows/mkdocs-deploy.yml +0 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/.github/workflows/publish.yml +0 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/.gitignore +0 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/bam_masterdata/__init__.py +0 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/bam_masterdata/cli/__init__.py +0 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/bam_masterdata/cli/entities_to_excel.py +0 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/bam_masterdata/cli/entities_to_json.py +0 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/bam_masterdata/datamodel/__init__.py +0 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/bam_masterdata/datamodel/collection_types.py +0 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/bam_masterdata/datamodel/dataset_types.py +0 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/bam_masterdata/datamodel/object_types.py +0 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/bam_masterdata/datamodel/vocabulary_types.py +0 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/bam_masterdata/logger.py +0 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/bam_masterdata/metadata/__init__.py +0 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/bam_masterdata/openbis/__init__.py +0 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/bam_masterdata/openbis/get_entities.py +0 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/bam_masterdata/openbis/login.py +0 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/bam_masterdata.egg-info/dependency_links.txt +0 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/bam_masterdata.egg-info/entry_points.txt +0 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/bam_masterdata.egg-info/top_level.txt +0 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/docs/assets/bammasterdata_blue_transparent.png +0 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/docs/assets/bammasterdata_blue_transparent_text.png +0 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/docs/assets/bammasterdata_blue_transparent_text.svg +0 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/docs/assets/bammasterdata_blue_white.png +0 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/docs/assets/bammasterdata_blue_white_text.png +0 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/docs/assets/datastore-logo-white.png +0 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/docs/assets/datastore-logo.png +0 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/docs/assets/drawio/masterdata-workflow.drawio.png +0 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/docs/assets/fonts/BAMKlavika-Light.ttf +0 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/docs/assets/fonts/BAMKlavika-LightItalic.ttf +0 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/docs/assets/fonts/BAMKlavika-Medium.ttf +0 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/docs/assets/fonts/BAMKlavika-MediumItalic.ttf +0 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/docs/explanations/data-store.md +0 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/docs/explanations/openbis.md +0 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/docs/explanations/pybis.md +0 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/docs/howtos/overview.md +0 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/docs/howtos/pybis/collections.md +0 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/docs/howtos/pybis/datasets.md +0 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/docs/howtos/pybis/objects.md +0 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/docs/howtos/pybis/objects_props.md +0 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/docs/howtos/pybis/parent_child.md +0 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/docs/howtos/pybis/projects.md +0 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/docs/howtos/pybis/searches.md +0 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/docs/howtos/pybis/setup.md +0 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/docs/howtos/pybis/spaces.md +0 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/docs/index.md +0 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/docs/references/collection.md +0 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/docs/references/controlled-vocabulary.md +0 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/docs/references/dataset.md +0 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/docs/stylesheets/extra.css +0 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/docs/tutorials/create-masterdata.md +0 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/docs/tutorials/pybis.md +0 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/mkdocs.yml +0 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/scripts/install_python_dependencies.sh +0 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/scripts/pkg_size.py +0 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/setup.cfg +0 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/setup.py +0 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/tests/__init__.py +0 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/tests/cli/test_entities_to_excel.py +0 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/tests/cli/test_entities_to_json.py +0 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/tests/conftest.py +0 -0
- {bam_masterdata-0.1.0 → bam_masterdata-0.2.0}/tests/test_logger.py +0 -0
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
"type": "debugpy",
|
|
34
34
|
"request": "launch",
|
|
35
35
|
"console": "integratedTerminal",
|
|
36
|
+
"justMyCode": false,
|
|
36
37
|
"program": "${workspaceFolder}/bam_masterdata/metadata/entities.py", // path to your entry point Python module
|
|
37
38
|
},
|
|
38
39
|
{
|
|
@@ -80,6 +81,18 @@
|
|
|
80
81
|
"justMyCode": false,
|
|
81
82
|
"args": ["export_to_excel"]
|
|
82
83
|
},
|
|
84
|
+
{
|
|
85
|
+
"name": "BM export-to-rdf",
|
|
86
|
+
"type": "debugpy",
|
|
87
|
+
"request": "launch",
|
|
88
|
+
"cwd": "${workspaceFolder}",
|
|
89
|
+
"program": "${workspaceFolder}/.venv/bin/bam_masterdata",
|
|
90
|
+
"justMyCode": false,
|
|
91
|
+
"args": [
|
|
92
|
+
"export_to_rdf",
|
|
93
|
+
// "--python-path=${workspaceFolder}/bam_masterdata/datamodel/property_types.py"
|
|
94
|
+
]
|
|
95
|
+
},
|
|
83
96
|
]
|
|
84
97
|
},
|
|
85
98
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Bundesanstalt für Materialforschung und -prüfung
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -1,9 +1,31 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: bam-masterdata
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: The BAM Data Store utility tools and masterdata models wrapped in a Python package with a front-end web interface.
|
|
5
5
|
Author-email: BAM Data Store <datastore@bam.de>
|
|
6
6
|
Maintainer-email: "Jose M. Pizarro" <jose.pizarro-blanco@bam.de>
|
|
7
|
+
License: MIT License
|
|
8
|
+
|
|
9
|
+
Copyright (c) 2025 Bundesanstalt für Materialforschung und -prüfung
|
|
10
|
+
|
|
11
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
12
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
13
|
+
in the Software without restriction, including without limitation the rights
|
|
14
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
15
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
16
|
+
furnished to do so, subject to the following conditions:
|
|
17
|
+
|
|
18
|
+
The above copyright notice and this permission notice shall be included in all
|
|
19
|
+
copies or substantial portions of the Software.
|
|
20
|
+
|
|
21
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
22
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
23
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
24
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
25
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
26
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
27
|
+
SOFTWARE.
|
|
28
|
+
|
|
7
29
|
Project-URL: Homepage, https://github.com/BAMresearch/bam-masterdata
|
|
8
30
|
Project-URL: Bug Tracker, https://github.com/BAMresearch/bam-masterdata/issues
|
|
9
31
|
Classifier: Natural Language :: English
|
|
@@ -16,10 +38,13 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
16
38
|
Classifier: Programming Language :: Python :: 3.12
|
|
17
39
|
Requires-Python: >=3.9
|
|
18
40
|
Description-Content-Type: text/markdown
|
|
41
|
+
License-File: LICENSE
|
|
19
42
|
Requires-Dist: pybis~=1.37.1rc4
|
|
20
43
|
Requires-Dist: openpyxl
|
|
21
44
|
Requires-Dist: click
|
|
22
|
-
Requires-Dist: pydantic
|
|
45
|
+
Requires-Dist: pydantic~=2.10.5
|
|
46
|
+
Requires-Dist: rdflib
|
|
47
|
+
Requires-Dist: h5py~=3.12.1
|
|
23
48
|
Provides-Extra: dev
|
|
24
49
|
Requires-Dist: mypy==1.0.1; extra == "dev"
|
|
25
50
|
Requires-Dist: ruff; extra == "dev"
|
|
@@ -47,15 +72,22 @@ Requires-Dist: mkdocstrings-python; extra == "docu"
|
|
|
47
72
|
|
|
48
73
|
[](https://github.com/BAMresearch/bam-masterdata/actions/workflows/actions.yml/badge.svg)
|
|
49
74
|
[](https://coveralls.io/repos/github/BAMresearch/bam-masterdata/badge.svg?branch=main)
|
|
75
|
+
[](https://img.shields.io/pypi/v/bam-masterdata)
|
|
76
|
+
[](https://img.shields.io/pypi/pyversions/bam-masterdata)
|
|
50
77
|
|
|
51
78
|
</h4>
|
|
52
79
|
|
|
53
80
|
The BAM Masterdata is a repository containing all the masterdata schema defining in BAM, as well as some utility functions to handle the masterdata.
|
|
54
81
|
|
|
55
|
-
|
|
56
|
-
|
|
82
|
+
If you want to install it, do:
|
|
83
|
+
```sh
|
|
84
|
+
pip install bam-masterdata
|
|
85
|
+
```
|
|
57
86
|
|
|
58
|
-
|
|
87
|
+
In order to include the CLI functionalities, you have to add the optional `[dev]` dependencies when pip installing the package:
|
|
88
|
+
```sh
|
|
89
|
+
pip install bam-masterdata[dev]
|
|
90
|
+
```
|
|
59
91
|
|
|
60
92
|
## Development
|
|
61
93
|
|
|
@@ -12,15 +12,22 @@
|
|
|
12
12
|
|
|
13
13
|
[](https://github.com/BAMresearch/bam-masterdata/actions/workflows/actions.yml/badge.svg)
|
|
14
14
|
[](https://coveralls.io/repos/github/BAMresearch/bam-masterdata/badge.svg?branch=main)
|
|
15
|
+
[](https://img.shields.io/pypi/v/bam-masterdata)
|
|
16
|
+
[](https://img.shields.io/pypi/pyversions/bam-masterdata)
|
|
15
17
|
|
|
16
18
|
</h4>
|
|
17
19
|
|
|
18
20
|
The BAM Masterdata is a repository containing all the masterdata schema defining in BAM, as well as some utility functions to handle the masterdata.
|
|
19
21
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
+
If you want to install it, do:
|
|
23
|
+
```sh
|
|
24
|
+
pip install bam-masterdata
|
|
25
|
+
```
|
|
22
26
|
|
|
23
|
-
|
|
27
|
+
In order to include the CLI functionalities, you have to add the optional `[dev]` dependencies when pip installing the package:
|
|
28
|
+
```sh
|
|
29
|
+
pip install bam-masterdata[dev]
|
|
30
|
+
```
|
|
24
31
|
|
|
25
32
|
## Development
|
|
26
33
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .checker import MasterdataChecker
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
from bam_masterdata.checker.datamodel_loader import DataModelLoader
|
|
2
|
+
from bam_masterdata.checker.masterdata_validator import MasterDataValidator
|
|
3
|
+
from bam_masterdata.checker.source_loader import SourceLoader
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class MasterdataChecker:
|
|
7
|
+
def __init__(self, validation_rules_path: str):
|
|
8
|
+
"""
|
|
9
|
+
Initialize the comparator with validation rules.
|
|
10
|
+
"""
|
|
11
|
+
self.validation_rules = self._load_validation_rules(validation_rules_path)
|
|
12
|
+
self.current_model = None
|
|
13
|
+
self.new_entities = None
|
|
14
|
+
|
|
15
|
+
def _load_validation_rules(self, path: str) -> dict:
|
|
16
|
+
"""
|
|
17
|
+
Load validation rules from a JSON file.
|
|
18
|
+
"""
|
|
19
|
+
pass
|
|
20
|
+
|
|
21
|
+
def load_current_model(self, source_path: str):
|
|
22
|
+
"""
|
|
23
|
+
Load and transform the current data model (Pydantic classes) into JSON.
|
|
24
|
+
"""
|
|
25
|
+
# loader = DataModelLoader(source_path)
|
|
26
|
+
# self.current_model = loader.parse_pydantic_models()
|
|
27
|
+
|
|
28
|
+
def load_new_entities(self, source: str, source_type: str):
|
|
29
|
+
"""
|
|
30
|
+
Load new entities from various sources (Python classes, Excel, etc.).
|
|
31
|
+
"""
|
|
32
|
+
# loader = SourceLoader(source, source_type)
|
|
33
|
+
# self.new_entities = loader.load()
|
|
34
|
+
|
|
35
|
+
def validate(self, mode: str = "all") -> dict:
|
|
36
|
+
"""
|
|
37
|
+
Run validations. Mode can be:
|
|
38
|
+
- "self" -> Validate only the new entity structure.
|
|
39
|
+
- "compare" -> Validate new entities against current model.
|
|
40
|
+
- "all" -> Run both validation types.
|
|
41
|
+
"""
|
|
42
|
+
validator = MasterDataValidator(
|
|
43
|
+
self.new_entities, self.current_model, self.validation_rules
|
|
44
|
+
)
|
|
45
|
+
return validator.validate(mode)
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
class MasterDataValidator:
|
|
2
|
+
def __init__(self, new_entities: dict, current_model: dict, validation_rules: dict):
|
|
3
|
+
self.new_entities = new_entities
|
|
4
|
+
self.current_model = current_model
|
|
5
|
+
self.validation_rules = validation_rules
|
|
6
|
+
|
|
7
|
+
def validate(self, mode: str = "all") -> dict:
|
|
8
|
+
"""
|
|
9
|
+
Run validations based on mode:
|
|
10
|
+
- "self": Validate new entity JSON structure.
|
|
11
|
+
- "compare": Validate new entities against the current model.
|
|
12
|
+
- "all": Run both.
|
|
13
|
+
"""
|
|
14
|
+
results = {}
|
|
15
|
+
|
|
16
|
+
if mode in ["self", "all"]:
|
|
17
|
+
results["self_validation"] = self._validate_new_entities()
|
|
18
|
+
|
|
19
|
+
if mode in ["compare", "all"]:
|
|
20
|
+
results["comparison"] = self._compare_with_current_model()
|
|
21
|
+
|
|
22
|
+
return results
|
|
23
|
+
|
|
24
|
+
def _validate_new_entities(self) -> dict:
|
|
25
|
+
"""
|
|
26
|
+
Check structure, ordering, and internal consistency of new entity JSON.
|
|
27
|
+
"""
|
|
28
|
+
pass
|
|
29
|
+
|
|
30
|
+
def _compare_with_current_model(self) -> dict:
|
|
31
|
+
"""
|
|
32
|
+
Compare new entities against the current model using validation rules.
|
|
33
|
+
"""
|
|
34
|
+
pass
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
class SourceLoader:
|
|
2
|
+
def __init__(self, source: str, source_type: str):
|
|
3
|
+
self.source = source
|
|
4
|
+
self.source_type = source_type
|
|
5
|
+
|
|
6
|
+
def load(self) -> dict:
|
|
7
|
+
"""
|
|
8
|
+
Read and transform the new entity data into JSON.
|
|
9
|
+
"""
|
|
10
|
+
if self.source_type == "python":
|
|
11
|
+
return self._parse_python_classes()
|
|
12
|
+
elif self.source_type == "excel":
|
|
13
|
+
return self._parse_excel()
|
|
14
|
+
else:
|
|
15
|
+
raise NotImplementedError(f"Source type {self.source_type} not supported.")
|
|
16
|
+
|
|
17
|
+
def _parse_python_classes(self) -> dict:
|
|
18
|
+
"""
|
|
19
|
+
Parse new entities defined as Python classes.
|
|
20
|
+
"""
|
|
21
|
+
pass
|
|
22
|
+
|
|
23
|
+
def _parse_excel(self) -> dict:
|
|
24
|
+
"""
|
|
25
|
+
Parse new entities stored in an Excel file.
|
|
26
|
+
"""
|
|
27
|
+
pass
|
|
@@ -6,18 +6,40 @@ from pathlib import Path
|
|
|
6
6
|
import click
|
|
7
7
|
from decouple import config as environ
|
|
8
8
|
from openpyxl import Workbook
|
|
9
|
+
from rdflib import Graph
|
|
9
10
|
|
|
10
11
|
from bam_masterdata.cli.entities_to_excel import entities_to_excel
|
|
11
12
|
from bam_masterdata.cli.entities_to_json import entities_to_json
|
|
13
|
+
from bam_masterdata.cli.entities_to_rdf import entities_to_rdf
|
|
12
14
|
from bam_masterdata.cli.fill_masterdata import MasterdataCodeGenerator
|
|
13
15
|
from bam_masterdata.logger import logger
|
|
14
16
|
from bam_masterdata.utils import (
|
|
15
17
|
delete_and_create_dir,
|
|
18
|
+
duplicated_property_types,
|
|
16
19
|
import_module,
|
|
17
20
|
listdir_py_modules,
|
|
18
21
|
)
|
|
19
22
|
|
|
20
|
-
|
|
23
|
+
|
|
24
|
+
def find_datamodel_dir():
|
|
25
|
+
"""Search for 'datamodel/' in possible locations and return its absolute path."""
|
|
26
|
+
possible_locations = [
|
|
27
|
+
# Case: Running from a project with `datamodel/`
|
|
28
|
+
Path.cwd() / "datamodel",
|
|
29
|
+
# Case: Running inside bam-masterdata
|
|
30
|
+
Path.cwd() / "bam_masterdata" / "datamodel",
|
|
31
|
+
# Case: Running inside installed package
|
|
32
|
+
Path(__file__).parent / "datamodel",
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
for path in possible_locations:
|
|
36
|
+
if path.exists():
|
|
37
|
+
return str(path.resolve())
|
|
38
|
+
|
|
39
|
+
raise FileNotFoundError("Could not find a valid 'datamodel/' directory.")
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
DATAMODEL_DIR = find_datamodel_dir()
|
|
21
43
|
|
|
22
44
|
|
|
23
45
|
@click.group(help="Entry point to run `bam_masterdata` CLI commands.")
|
|
@@ -129,11 +151,20 @@ def fill_masterdata(url, excel_file):
|
|
|
129
151
|
Default is `./bam_masterdata/datamodel/`.
|
|
130
152
|
""",
|
|
131
153
|
)
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
154
|
+
@click.option(
|
|
155
|
+
"--export-dir",
|
|
156
|
+
type=str,
|
|
157
|
+
required=False,
|
|
158
|
+
default="./artifacts",
|
|
159
|
+
help="The directory where the JSON files will be exported. Default is `./artifacts`.",
|
|
160
|
+
)
|
|
161
|
+
def export_to_json(force_delete, python_path, export_dir):
|
|
136
162
|
# Delete and create the export directory
|
|
163
|
+
if force_delete:
|
|
164
|
+
click.confirm(
|
|
165
|
+
f"Are you sure you want to delete the directory {export_dir}?",
|
|
166
|
+
abort=True,
|
|
167
|
+
)
|
|
137
168
|
delete_and_create_dir(
|
|
138
169
|
directory_path=export_dir,
|
|
139
170
|
logger=logger,
|
|
@@ -145,6 +176,12 @@ def export_to_json(force_delete, python_path):
|
|
|
145
176
|
|
|
146
177
|
# Process each module using the `model_to_json` method of each entity
|
|
147
178
|
for module_path in py_modules:
|
|
179
|
+
if module_path.endswith("property_types.py"):
|
|
180
|
+
if duplicated_property_types(module_path=module_path, logger=logger):
|
|
181
|
+
click.echo(
|
|
182
|
+
"Please fix the duplicated property types before exporting to RDF/XML."
|
|
183
|
+
)
|
|
184
|
+
return
|
|
148
185
|
entities_to_json(module_path=module_path, export_dir=export_dir, logger=logger)
|
|
149
186
|
|
|
150
187
|
click.echo(f"All entity artifacts have been generated and saved to {export_dir}")
|
|
@@ -173,11 +210,20 @@ def export_to_json(force_delete, python_path):
|
|
|
173
210
|
Default is `./bam_masterdata/datamodel/`.
|
|
174
211
|
""",
|
|
175
212
|
)
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
213
|
+
@click.option(
|
|
214
|
+
"--export-dir",
|
|
215
|
+
type=str,
|
|
216
|
+
required=False,
|
|
217
|
+
default="./artifacts",
|
|
218
|
+
help="The directory where the Excel file will be exported. Default is `./artifacts`.",
|
|
219
|
+
)
|
|
220
|
+
def export_to_excel(force_delete, python_path, export_dir):
|
|
180
221
|
# Delete and create the export directory
|
|
222
|
+
if force_delete:
|
|
223
|
+
click.confirm(
|
|
224
|
+
f"Are you sure you want to delete the directory {export_dir}?",
|
|
225
|
+
abort=True,
|
|
226
|
+
)
|
|
181
227
|
delete_and_create_dir(
|
|
182
228
|
directory_path=export_dir,
|
|
183
229
|
logger=logger,
|
|
@@ -188,14 +234,19 @@ def export_to_excel(force_delete, python_path):
|
|
|
188
234
|
py_modules = listdir_py_modules(directory_path=python_path, logger=logger)
|
|
189
235
|
|
|
190
236
|
# Load the definitions module classes
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
)
|
|
237
|
+
definitions_path = Path(__file__).parent / ".." / "metadata" / "definitions.py"
|
|
238
|
+
definitions_module = import_module(module_path=str(definitions_path.resolve()))
|
|
194
239
|
|
|
195
240
|
# Process the modules and save the entities to the openBIS masterdata Excel file
|
|
196
|
-
masterdata_file = os.path.join(
|
|
241
|
+
masterdata_file = os.path.join(export_dir, "masterdata.xlsx")
|
|
197
242
|
wb = Workbook()
|
|
198
243
|
for i, module_path in enumerate(py_modules):
|
|
244
|
+
if module_path.endswith("property_types.py"):
|
|
245
|
+
if duplicated_property_types(module_path=module_path, logger=logger):
|
|
246
|
+
click.echo(
|
|
247
|
+
"Please fix the duplicated property types before exporting to RDF/XML."
|
|
248
|
+
)
|
|
249
|
+
return
|
|
199
250
|
if i == 0:
|
|
200
251
|
ws = wb.active
|
|
201
252
|
else:
|
|
@@ -216,5 +267,77 @@ def export_to_excel(force_delete, python_path):
|
|
|
216
267
|
click.echo(f"All masterdata have been generated and saved to {masterdata_file}")
|
|
217
268
|
|
|
218
269
|
|
|
270
|
+
@cli.command(
|
|
271
|
+
name="export_to_rdf",
|
|
272
|
+
help="Export entities to a RDF/XML file in the path `./artifacts/bam_masterdata.owl`.",
|
|
273
|
+
)
|
|
274
|
+
@click.option(
|
|
275
|
+
"--force-delete",
|
|
276
|
+
type=bool,
|
|
277
|
+
required=False,
|
|
278
|
+
default=False,
|
|
279
|
+
help="""
|
|
280
|
+
(Optional) If set to `True`, it will delete the current `./artifacts/` folder and create a new one. Default is `False`.
|
|
281
|
+
""",
|
|
282
|
+
)
|
|
283
|
+
@click.option(
|
|
284
|
+
"--python-path",
|
|
285
|
+
type=str,
|
|
286
|
+
required=False,
|
|
287
|
+
default=DATAMODEL_DIR,
|
|
288
|
+
help="""
|
|
289
|
+
(Optional) The path to the individual Python module or the directory containing the Python modules to process the datamodel.
|
|
290
|
+
Default is `./bam_masterdata/datamodel/`.
|
|
291
|
+
""",
|
|
292
|
+
)
|
|
293
|
+
@click.option(
|
|
294
|
+
"--export-dir",
|
|
295
|
+
type=str,
|
|
296
|
+
required=False,
|
|
297
|
+
default="./artifacts",
|
|
298
|
+
help="The directory where the RDF/XML file will be exported. Default is `./artifacts`.",
|
|
299
|
+
)
|
|
300
|
+
def export_to_rdf(force_delete, python_path, export_dir):
|
|
301
|
+
# Delete and create the export directory
|
|
302
|
+
if force_delete:
|
|
303
|
+
click.confirm(
|
|
304
|
+
f"Are you sure you want to delete the directory {export_dir}?",
|
|
305
|
+
abort=True,
|
|
306
|
+
)
|
|
307
|
+
delete_and_create_dir(
|
|
308
|
+
directory_path=export_dir,
|
|
309
|
+
logger=logger,
|
|
310
|
+
force_delete=force_delete,
|
|
311
|
+
)
|
|
312
|
+
|
|
313
|
+
# Get the Python modules to process the datamodel
|
|
314
|
+
py_modules = listdir_py_modules(directory_path=python_path, logger=logger)
|
|
315
|
+
# ! Remove the module containing 'vocabulary_types.py'
|
|
316
|
+
py_modules = [
|
|
317
|
+
module for module in py_modules if "vocabulary_types.py" not in module
|
|
318
|
+
]
|
|
319
|
+
|
|
320
|
+
# Process each module using the `model_to_rdf` method of each entity
|
|
321
|
+
graph = Graph()
|
|
322
|
+
for module_path in py_modules:
|
|
323
|
+
if module_path.endswith("property_types.py"):
|
|
324
|
+
if duplicated_property_types(module_path=module_path, logger=logger):
|
|
325
|
+
click.echo(
|
|
326
|
+
"Please fix the duplicated property types before exporting to RDF/XML."
|
|
327
|
+
)
|
|
328
|
+
return
|
|
329
|
+
entities_to_rdf(graph=graph, module_path=module_path, logger=logger)
|
|
330
|
+
|
|
331
|
+
# Saving RDF/XML to file
|
|
332
|
+
rdf_output = graph.serialize(format="pretty-xml")
|
|
333
|
+
masterdata_file = os.path.join(export_dir, "masterdata.owl")
|
|
334
|
+
with open(masterdata_file, "w", encoding="utf-8") as f:
|
|
335
|
+
f.write(rdf_output)
|
|
336
|
+
|
|
337
|
+
click.echo(
|
|
338
|
+
f"All masterdata has been generated in RDF/XML format and saved to {masterdata_file}"
|
|
339
|
+
)
|
|
340
|
+
|
|
341
|
+
|
|
219
342
|
if __name__ == "__main__":
|
|
220
343
|
cli()
|