bam-masterdata 0.3.1__tar.gz → 0.4.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.
Files changed (130) hide show
  1. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/.github/workflows/actions.yml +4 -4
  2. bam_masterdata-0.4.0/AUTHORS +23 -0
  3. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/LICENSE +5 -1
  4. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/PKG-INFO +27 -3
  5. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/README.md +21 -1
  6. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/bam_masterdata/_version.py +2 -2
  7. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/bam_masterdata/checker/checker.py +4 -4
  8. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/bam_masterdata/checker/masterdata_validator.py +7 -2
  9. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/bam_masterdata/checker/source_loader.py +44 -12
  10. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/bam_masterdata/cli/cli.py +120 -6
  11. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/bam_masterdata/cli/fill_masterdata.py +20 -15
  12. bam_masterdata-0.4.0/bam_masterdata/datamodel/vocabulary_types.py +32238 -0
  13. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/bam_masterdata/excel/excel_to_entities.py +3 -3
  14. bam_masterdata-0.4.0/bam_masterdata/metadata/_maps.py +33 -0
  15. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/bam_masterdata/metadata/definitions.py +8 -1
  16. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/bam_masterdata/metadata/entities.py +269 -9
  17. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/bam_masterdata/openbis/get_entities.py +13 -0
  18. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/bam_masterdata.egg-info/PKG-INFO +27 -3
  19. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/bam_masterdata.egg-info/SOURCES.txt +2 -0
  20. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/tests/metadata/test_entities.py +8 -2
  21. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/tests/metadata/test_entities_dict.py +44 -44
  22. bam_masterdata-0.3.1/bam_masterdata/datamodel/vocabulary_types.py +0 -81811
  23. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/.coveragerc +0 -0
  24. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/.github/workflows/coveralls.yml +0 -0
  25. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/.github/workflows/mkdocs-deploy.yml +0 -0
  26. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/.github/workflows/publish.yml +0 -0
  27. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/.gitignore +0 -0
  28. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/.vscode/settings.json +0 -0
  29. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/bam_masterdata/__init__.py +0 -0
  30. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/bam_masterdata/checker/__init__.py +0 -0
  31. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/bam_masterdata/checker/validation_rules/all_validation_rules.json +0 -0
  32. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/bam_masterdata/checker/validation_rules/excel_validation_rules.json +0 -0
  33. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/bam_masterdata/checker/validation_rules/validation_rules.json +0 -0
  34. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/bam_masterdata/cli/__init__.py +0 -0
  35. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/bam_masterdata/cli/entities_to_excel.py +0 -0
  36. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/bam_masterdata/cli/entities_to_rdf.py +0 -0
  37. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/bam_masterdata/datamodel/__init__.py +0 -0
  38. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/bam_masterdata/datamodel/collection_types.py +0 -0
  39. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/bam_masterdata/datamodel/dataset_types.py +0 -0
  40. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/bam_masterdata/datamodel/object_types.py +0 -0
  41. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/bam_masterdata/excel/__init__.py +0 -0
  42. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/bam_masterdata/logger.py +0 -0
  43. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/bam_masterdata/metadata/__init__.py +0 -0
  44. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/bam_masterdata/metadata/entities_dict.py +0 -0
  45. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/bam_masterdata/openbis/__init__.py +0 -0
  46. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/bam_masterdata/openbis/login.py +0 -0
  47. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/bam_masterdata/utils/__init__.py +0 -0
  48. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/bam_masterdata/utils/paths.py +0 -0
  49. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/bam_masterdata/utils/utils.py +0 -0
  50. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/bam_masterdata/validation_rules/excel_validation_rules.json +0 -0
  51. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/bam_masterdata/validation_rules/validation_rules.json +0 -0
  52. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/bam_masterdata.egg-info/dependency_links.txt +0 -0
  53. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/bam_masterdata.egg-info/entry_points.txt +0 -0
  54. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/bam_masterdata.egg-info/requires.txt +0 -0
  55. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/bam_masterdata.egg-info/top_level.txt +0 -0
  56. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/docs/assets/bammasterdata_blue_transparent.png +0 -0
  57. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/docs/assets/bammasterdata_blue_transparent_text.png +0 -0
  58. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/docs/assets/bammasterdata_blue_transparent_text.svg +0 -0
  59. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/docs/assets/bammasterdata_blue_white.png +0 -0
  60. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/docs/assets/bammasterdata_blue_white_text.png +0 -0
  61. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/docs/assets/datastore-logo-white.png +0 -0
  62. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/docs/assets/datastore-logo.png +0 -0
  63. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/docs/assets/drawio/checker-structure.drawio +0 -0
  64. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/docs/assets/drawio/masterdata-workflow.drawio +0 -0
  65. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/docs/assets/drawio/masterdata-workflow.drawio.png +0 -0
  66. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/docs/assets/fonts/BAMKlavika-Light.ttf +0 -0
  67. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/docs/assets/fonts/BAMKlavika-LightItalic.ttf +0 -0
  68. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/docs/assets/fonts/BAMKlavika-Medium.ttf +0 -0
  69. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/docs/assets/fonts/BAMKlavika-MediumItalic.ttf +0 -0
  70. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/docs/explanations/data-store.md +0 -0
  71. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/docs/explanations/openbis.md +0 -0
  72. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/docs/explanations/pybis.md +0 -0
  73. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/docs/howtos/overview.md +0 -0
  74. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/docs/howtos/pybis/collections.md +0 -0
  75. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/docs/howtos/pybis/datasets.md +0 -0
  76. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/docs/howtos/pybis/objects.md +0 -0
  77. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/docs/howtos/pybis/objects_props.md +0 -0
  78. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/docs/howtos/pybis/parent_child.md +0 -0
  79. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/docs/howtos/pybis/projects.md +0 -0
  80. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/docs/howtos/pybis/searches.md +0 -0
  81. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/docs/howtos/pybis/setup.md +0 -0
  82. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/docs/howtos/pybis/spaces.md +0 -0
  83. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/docs/index.md +0 -0
  84. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/docs/references/collection.md +0 -0
  85. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/docs/references/controlled-vocabulary.md +0 -0
  86. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/docs/references/dataset.md +0 -0
  87. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/docs/stylesheets/extra.css +0 -0
  88. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/docs/tutorials/create-masterdata.md +0 -0
  89. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/docs/tutorials/pybis.md +0 -0
  90. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/mkdocs.yml +0 -0
  91. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/pyproject.toml +0 -0
  92. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/scripts/install_python_dependencies.sh +0 -0
  93. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/scripts/pkg_size.py +0 -0
  94. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/setup.cfg +0 -0
  95. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/setup.py +0 -0
  96. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/tests/__init__.py +0 -0
  97. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/tests/checker/test_source_loader.py +0 -0
  98. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/tests/cli/test_entities_to_excel.py +0 -0
  99. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/tests/cli/test_entities_to_rdf.py +0 -0
  100. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/tests/conftest.py +0 -0
  101. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/tests/data/checker/datamodel_test/collection_types.py +0 -0
  102. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/tests/data/checker/datamodel_test/dataset_types.py +0 -0
  103. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/tests/data/checker/datamodel_test/object_types.py +0 -0
  104. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/tests/data/checker/example01_codedoesnoteexists.xlsx +0 -0
  105. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/tests/data/checker/example02_codeexists_proptype_datatypechanged.xlsx +0 -0
  106. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/tests/data/checker/example03_codeexists_proptype_contvoccodechanged.xlsx +0 -0
  107. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/tests/data/checker/example04_codeexists_proptype_objectcodechanged.xlsx +0 -0
  108. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/tests/data/checker/example05_codeexists_proptype_warningdefschanged.xlsx +0 -0
  109. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/tests/data/checker/example06_codeexists_proptype_vocobjcodemiss.xlsx +0 -0
  110. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/tests/data/checker/example07_codeexists_objtype_warningdefschanged.xlsx +0 -0
  111. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/tests/data/checker/example08_codeexists_objtype_assignprop_listcodeschanged_add.xlsx +0 -0
  112. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/tests/data/checker/example09_codeexists_objtype_assignprop_listcodeschanged_del.xlsx +0 -0
  113. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/tests/data/checker/example10_codeexists_objtype_assignprop_codedoesnotexists.xlsx +0 -0
  114. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/tests/data/checker/example11_codeexists_objtype_assignprop_listcodeschanged_datatypechanged.xlsx +0 -0
  115. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/tests/data/checker/example12_codeexists_objtype_assignprop_listcodeschanged_warningdefschanged.xlsx +0 -0
  116. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/tests/data/checker/example13_codeexists_objtype_assignprop_coincide2objects.xlsx +0 -0
  117. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/tests/data/checker/example_incoming_excel.xlsx +0 -0
  118. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/tests/data/checker/example_incoming_python/collection_types.py +0 -0
  119. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/tests/data/checker/example_incoming_python/dataset_types.py +0 -0
  120. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/tests/data/checker/example_incoming_python/object_types.py +0 -0
  121. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/tests/data/checker/masterdata_example.xlsx +0 -0
  122. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/tests/data/checker/masterdata_excel_output.json +0 -0
  123. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/tests/data/checker/masterdata_python_output.json +0 -0
  124. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/tests/data/utils/example_prop_types_1.py +0 -0
  125. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/tests/data/utils/example_prop_types_2.py +0 -0
  126. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/tests/excel/test_excel_to_entities.py +0 -0
  127. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/tests/metadata/test_definitions.py +0 -0
  128. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/tests/test_logger.py +0 -0
  129. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/tests/utils/test_paths.py +0 -0
  130. {bam_masterdata-0.3.1 → bam_masterdata-0.4.0}/tests/utils/test_utils.py +0 -0
@@ -34,10 +34,10 @@ jobs:
34
34
  uv pip install -e '.[dev]'
35
35
  - name: mypy
36
36
  run: |
37
- python -m mypy --ignore-missing-imports --follow-imports=silent --no-strict-optional --exclude dependencies bam_masterdata tests
37
+ python -m mypy --ignore-missing-imports --follow-imports=silent --no-strict-optional bam_masterdata tests
38
38
  - name: Test with pytest
39
39
  run: |
40
- python -m pytest -sv --ignore=bam_masterdata/dependencies tests
40
+ python -m pytest -sv --ignore=tests/cli --ignore=tests/metadata/test_entities_dict.py tests
41
41
  build-and-install:
42
42
  runs-on: ubuntu-latest
43
43
  steps:
@@ -62,11 +62,11 @@ jobs:
62
62
  - uses: actions/checkout@v4
63
63
  - uses: chartboost/ruff-action@v1
64
64
  with:
65
- args: "check . --exclude bam_masterdata/dependencies"
65
+ args: "check ."
66
66
  ruff-formatting:
67
67
  runs-on: ubuntu-latest
68
68
  steps:
69
69
  - uses: actions/checkout@v4
70
70
  - uses: chartboost/ruff-action@v1
71
71
  with:
72
- args: "format . --check --verbose --exclude bam_masterdata/dependencies"
72
+ args: "format . --check --verbose"
@@ -0,0 +1,23 @@
1
+ # This is the list of BAM Masterdata's significant contributors.
2
+ #
3
+ # This does not necessarily list everyone who has contributed code,
4
+ # especially since many employees of one corporation may be contributing to the
5
+ # definition of object types, property types, and vocabularies in the Masterdata
6
+ # datamodel.
7
+ # To see the full list of code contributors, see the revision history in
8
+ # source control.
9
+
10
+ - Angela Ariza de Schellenberger
11
+ - Ingo Bressler
12
+ - Rukeia El-Athman
13
+ - Çağtay Fabry
14
+ - Tobias Fritsch
15
+ - Ralf Herrmann
16
+ - Zoltán Konthur
17
+ - Julius Kruse
18
+ - Pavlina Kruzikova
19
+ - Tarakeshwar Lakshmipathy
20
+ - Julien Lecompagnon
21
+ - Jan Lisec
22
+ - Mathias Röllig
23
+ - Bastian Rühle
@@ -1,4 +1,4 @@
1
- MIT License
1
+ MIT License - MODIFIED
2
2
 
3
3
  Copyright (c) 2025 Bundesanstalt für Materialforschung und -prüfung
4
4
 
@@ -19,3 +19,7 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
19
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
20
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
21
  SOFTWARE.
22
+
23
+ **MODIFICATION**: the datamodel files are excluded from this license agreement and
24
+ we reserve all rights on them for developments. Appropriate recognition has to be
25
+ done if you use parts of this datamodel in your own modelling.
@@ -1,10 +1,10 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bam-masterdata
3
- Version: 0.3.1
3
+ Version: 0.4.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
7
+ License: MIT License - MODIFIED
8
8
 
9
9
  Copyright (c) 2025 Bundesanstalt für Materialforschung und -prüfung
10
10
 
@@ -26,6 +26,9 @@ License: MIT License
26
26
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27
27
  SOFTWARE.
28
28
 
29
+ **MODIFICATION**: the datamodel files are excluded from this license agreement and
30
+ we reserve all rights on them for developments. Appropriate recognition has to be
31
+ done if you use parts of this datamodel in your own modelling.
29
32
  Project-URL: Homepage, https://github.com/BAMresearch/bam-masterdata
30
33
  Project-URL: Bug Tracker, https://github.com/BAMresearch/bam-masterdata/issues
31
34
  Classifier: Natural Language :: English
@@ -39,6 +42,7 @@ Classifier: Programming Language :: Python :: 3.12
39
42
  Requires-Python: >=3.9
40
43
  Description-Content-Type: text/markdown
41
44
  License-File: LICENSE
45
+ License-File: AUTHORS
42
46
  Requires-Dist: pybis~=1.37.1rc4
43
47
  Requires-Dist: openpyxl
44
48
  Requires-Dist: click
@@ -207,11 +211,31 @@ INFO - [14:07:47] Watching paths for changes: 'docs', 'mkdocs.yml'
207
211
  INFO - [14:07:47] Serving on http://127.0.0.1:8000/
208
212
  ```
209
213
 
210
- Simply click on `http://127.0.0.1:8000/`. The changes in the `md` files of the documentation are inmediately reflected when the files are saved (the local web will automatically refresh).
214
+ Simply click on `http://127.0.0.1:8000/`. The changes in the `md` files of the documentation are immediately reflected when the files are saved (the local web will automatically refresh).
211
215
 
212
216
  ## Main contributors
213
217
 
218
+ The main code developers are:
219
+
214
220
  | Name | E-mail |
215
221
  | ------------------- | ------------------------------------------------------------ |
216
222
  | Carlos Madariaga | [carlos.madariaga@bam.de](mailto:carlos.madariaga@bam.de) |
217
223
  | Dr. Jose M. Pizarro | [jose.pizarro-blanco@bam.de](mailto:jose.pizarro-blanco@bam.de) |
224
+
225
+
226
+ The main datamodel developers are:
227
+
228
+ - Angela Ariza de Schellenberger
229
+ - Ingo Bressler
230
+ - Rukeia El-Athman
231
+ - Çağtay Fabry
232
+ - Tobias Fritsch
233
+ - Ralf Herrmann
234
+ - Zoltán Konthur
235
+ - Julius Kruse
236
+ - Pavlina Kruzikova
237
+ - Tarakeshwar Lakshmipathy
238
+ - Julien Lecompagnon
239
+ - Jan Lisec
240
+ - Mathias Röllig
241
+ - Bastian Rühle
@@ -146,11 +146,31 @@ INFO - [14:07:47] Watching paths for changes: 'docs', 'mkdocs.yml'
146
146
  INFO - [14:07:47] Serving on http://127.0.0.1:8000/
147
147
  ```
148
148
 
149
- Simply click on `http://127.0.0.1:8000/`. The changes in the `md` files of the documentation are inmediately reflected when the files are saved (the local web will automatically refresh).
149
+ Simply click on `http://127.0.0.1:8000/`. The changes in the `md` files of the documentation are immediately reflected when the files are saved (the local web will automatically refresh).
150
150
 
151
151
  ## Main contributors
152
152
 
153
+ The main code developers are:
154
+
153
155
  | Name | E-mail |
154
156
  | ------------------- | ------------------------------------------------------------ |
155
157
  | Carlos Madariaga | [carlos.madariaga@bam.de](mailto:carlos.madariaga@bam.de) |
156
158
  | Dr. Jose M. Pizarro | [jose.pizarro-blanco@bam.de](mailto:jose.pizarro-blanco@bam.de) |
159
+
160
+
161
+ The main datamodel developers are:
162
+
163
+ - Angela Ariza de Schellenberger
164
+ - Ingo Bressler
165
+ - Rukeia El-Athman
166
+ - Çağtay Fabry
167
+ - Tobias Fritsch
168
+ - Ralf Herrmann
169
+ - Zoltán Konthur
170
+ - Julius Kruse
171
+ - Pavlina Kruzikova
172
+ - Tarakeshwar Lakshmipathy
173
+ - Julien Lecompagnon
174
+ - Jan Lisec
175
+ - Mathias Röllig
176
+ - Bastian Rühle
@@ -17,5 +17,5 @@ __version__: str
17
17
  __version_tuple__: VERSION_TUPLE
18
18
  version_tuple: VERSION_TUPLE
19
19
 
20
- __version__ = version = '0.3.1'
21
- __version_tuple__ = version_tuple = (0, 3, 1)
20
+ __version__ = version = '0.4.0'
21
+ __version_tuple__ = version_tuple = (0, 4, 0)
@@ -58,23 +58,23 @@ class MasterdataChecker:
58
58
 
59
59
  # Load required models based on the selected mode
60
60
  if (
61
- mode in ["self", "validate", "compare", "all"]
61
+ mode in ["self", "validate", "compare", "all", "individual"]
62
62
  and self.current_model is None
63
63
  ):
64
64
  self.logger.info("Current model is missing. Loading now...")
65
65
  self.load_current_model()
66
66
 
67
67
  if (
68
- mode in ["incoming", "validate", "compare", "all"]
68
+ mode in ["incoming", "validate", "compare", "all", "individual"]
69
69
  and self.new_entities is None
70
70
  ):
71
71
  raise ValueError(
72
- "New entities must be loaded before validation in 'incoming', 'validate', 'compare', or 'all' modes."
72
+ "New entities must be loaded before validation in 'incoming', 'validate', 'individual', 'compare', or 'all' modes."
73
73
  )
74
74
 
75
75
  # Load the validation rules
76
76
  if (
77
- mode in ["self", "incoming", "validate", "all"]
77
+ mode in ["self", "incoming", "validate", "all", "individual"]
78
78
  and self.validation_rules == {}
79
79
  ):
80
80
  self.validation_rules = load_validation_rules(self.logger)
@@ -67,7 +67,7 @@ class MasterdataValidator:
67
67
 
68
68
  if mode == "individual":
69
69
  self.logger.info(
70
- "Validating new DSST entities and comparing them with current model..."
70
+ "Validating new entities and comparing them with current model..."
71
71
  )
72
72
  self.validation_results = {
73
73
  "incoming_model": {},
@@ -427,6 +427,11 @@ class MasterdataValidator:
427
427
  is_terms=True,
428
428
  )
429
429
 
430
+ if not self.validation_results.get("comparisons"):
431
+ logger.info(
432
+ "No critical conflicts found between new entities compared to the current model."
433
+ )
434
+
430
435
  return self.validation_results
431
436
 
432
437
  def _compare_assigned_properties(
@@ -524,7 +529,7 @@ class MasterdataValidator:
524
529
  )
525
530
  other_entity_props = {prop["code"] for prop in other_entity_properties}
526
531
 
527
- if incoming_prop_codes == other_entity_props:
532
+ if (incoming_prop_codes == other_entity_props) and incoming_prop_codes:
528
533
  log_message = (
529
534
  "Entity will not be imported in openBIS. "
530
535
  f"The entity {entity_code} at row {incoming_entity['defs'].get('row_location')} has the same properties defined as {other_entity_code}. "
@@ -64,18 +64,34 @@ class SourceLoader:
64
64
  transformed_data[entity_type] = {}
65
65
 
66
66
  for entity_name, entity_data in entities.items():
67
- transformed_entity = {
68
- "properties": [], # Now placed before "defs"
69
- "defs": { # Metadata moved to the end
70
- "code": entity_data.get("code"),
71
- "description": entity_data.get("description", ""),
72
- "id": format_json_id(entity_name), # PascalCase for entity ID
73
- "row_location": entity_data.get("row_location"),
74
- "validation_script": entity_data.get("validationPlugin")
75
- or None, # Convert "" to None
76
- "iri": entity_data.get("iri") or None, # Convert "" to None
77
- },
78
- }
67
+ if entity_type == "vocabulary_types":
68
+ transformed_entity = {
69
+ "terms": [], # Now placed before "defs"
70
+ "defs": { # Metadata moved to the end
71
+ "code": entity_data.get("code"),
72
+ "description": entity_data.get("description", ""),
73
+ "id": format_json_id(
74
+ entity_name
75
+ ), # PascalCase for entity ID
76
+ "row_location": entity_data.get("row_location"),
77
+ "url_template": entity_data.get("url_template") or None,
78
+ },
79
+ }
80
+ else:
81
+ transformed_entity = {
82
+ "properties": [], # Now placed before "defs"
83
+ "defs": { # Metadata moved to the end
84
+ "code": entity_data.get("code"),
85
+ "description": entity_data.get("description", ""),
86
+ "id": format_json_id(
87
+ entity_name
88
+ ), # PascalCase for entity ID
89
+ "row_location": entity_data.get("row_location"),
90
+ "validation_script": entity_data.get("validationPlugin")
91
+ or None, # Convert "" to None
92
+ "iri": entity_data.get("iri") or None, # Convert "" to None
93
+ },
94
+ }
79
95
 
80
96
  # Handle additional fields specific to dataset_types
81
97
  if entity_type == "dataset_types":
@@ -123,6 +139,22 @@ class SourceLoader:
123
139
  }
124
140
  transformed_entity["properties"].append(transformed_property)
125
141
 
142
+ if "terms" in entity_data:
143
+ for term_name, term_data in entity_data["terms"].items():
144
+ transformed_term = {
145
+ "code": term_data.get("code"),
146
+ "description": term_data.get("description", ""),
147
+ "id": format_json_id(
148
+ term_name
149
+ ), # Now correctly formatted to PascalCase
150
+ "row_location": term_data.get("row_location"),
151
+ "url_template": term_data.get("url_template")
152
+ or None, # Convert "" to None
153
+ "label": term_data.get("label"),
154
+ "official": term_data.get("official"),
155
+ }
156
+ transformed_entity["terms"].append(transformed_term)
157
+
126
158
  transformed_data[entity_type][entity_name] = transformed_entity
127
159
 
128
160
  return transformed_data
@@ -1,6 +1,8 @@
1
+ import glob
2
+ import inspect
1
3
  import json
2
4
  import os
3
- import subprocess
5
+ import shutil
4
6
  import time
5
7
  from pathlib import Path
6
8
 
@@ -15,6 +17,7 @@ from bam_masterdata.cli.entities_to_rdf import entities_to_rdf
15
17
  from bam_masterdata.cli.fill_masterdata import MasterdataCodeGenerator
16
18
  from bam_masterdata.logger import logger
17
19
  from bam_masterdata.metadata.entities_dict import EntitiesDict
20
+ from bam_masterdata.openbis.login import ologin
18
21
  from bam_masterdata.utils import (
19
22
  DATAMODEL_DIR,
20
23
  delete_and_create_dir,
@@ -410,7 +413,6 @@ def checker(file_path, mode, datamodel_path):
410
413
  click.echo(
411
414
  f"There are problems in the current model for entity {entity} that need to be solved"
412
415
  )
413
- click.echo(f"Errors: {errors}")
414
416
 
415
417
  # Check if there are problems with the incoming model
416
418
  if mode in ["incoming", "all", "validate"] and validation_results.get(
@@ -421,7 +423,6 @@ def checker(file_path, mode, datamodel_path):
421
423
  click.echo(
422
424
  f"There are problems in the incoming model in {file_path} for entity {entity} that need to be solved"
423
425
  )
424
- click.echo(f"Errors: {errors}")
425
426
 
426
427
  # Check if there are comparison problems
427
428
  if mode in ["compare", "all"] and validation_results.get("comparisons", {}):
@@ -430,7 +431,6 @@ def checker(file_path, mode, datamodel_path):
430
431
  click.echo(
431
432
  f"There are problems when checking the incoming model in {file_path} against the current model {datamodel_path} for entity {entity} that need to be solved"
432
433
  )
433
- click.echo(f"Errors: {errors}")
434
434
 
435
435
  # Check if there are individual repository problems
436
436
  if (
@@ -443,17 +443,131 @@ def checker(file_path, mode, datamodel_path):
443
443
  click.echo(
444
444
  f"There are problems in the individual repositories when validating them for entity {entity} that need to be solved"
445
445
  )
446
- click.echo(f"Errors: {errors}")
447
446
  for entity, errors in validation_results.get("comparisons", {}).items():
448
447
  if errors:
449
448
  click.echo(
450
449
  f"There are problems in the individual repositories when comparing them with respect to bam-masterdata for entity {entity} that need to be solved"
451
450
  )
452
- click.echo(f"Errors: {errors}")
453
451
 
454
452
  # Check if no problems were found
455
453
  if no_validation_errors(validation_results):
456
454
  click.echo("No problems found in the datamodel and incoming model.")
455
+ else:
456
+ raise click.ClickException(
457
+ "Problems found in the datamodel. Please, check the logs."
458
+ )
459
+
460
+
461
+ @cli.command(
462
+ name="push_to_openbis",
463
+ help="Uploads to openBIS the entities contained in the file specified in the tag `--file-path` after passing correctly all the checks from the `checker`.",
464
+ )
465
+ @click.option(
466
+ "--file-path",
467
+ "file_path", # alias
468
+ type=click.Path(exists=True),
469
+ required=True,
470
+ help="""The path to the file or directory containing Python modules or the Excel file to be checked.""",
471
+ )
472
+ @click.option(
473
+ "--datamodel-path",
474
+ "datamodel_path", # alias
475
+ type=click.Path(exists=True, dir_okay=True),
476
+ default=DATAMODEL_DIR,
477
+ help="""Path to the directory containing the Python modules defining the datamodel (defaults to './bam_masterdata/datamodel/').""",
478
+ )
479
+ def push_to_openbis(file_path, datamodel_path):
480
+ # Check if the path is a single .py file OR a directory containing .py files
481
+ if file_path.endswith(".py") or (
482
+ os.path.isdir(file_path) and any(glob.glob(os.path.join(file_path, "*.py")))
483
+ ):
484
+ source_type = "python"
485
+ elif file_path.endswith(".xlsx"):
486
+ source_type = "excel"
487
+ else:
488
+ source_type = None
489
+ logger.warning(f"Unsupported source type for path: {file_path}")
490
+
491
+ # Handle source_type
492
+ if source_type == "python":
493
+ # Copy all .py files to the tmp directory
494
+ if os.path.isdir(file_path):
495
+ tmp_dir = file_path
496
+ else:
497
+ tmp_dir = os.path.dirname(file_path)
498
+ logger.info(f"Copied Python files to {tmp_dir}")
499
+
500
+ elif source_type == "excel":
501
+ tmp_dir = "./bam_masterdata/tmp"
502
+ os.makedirs(tmp_dir, exist_ok=True)
503
+
504
+ generator = MasterdataCodeGenerator(path=file_path, row_cell_info=True)
505
+
506
+ for module_name in ["collection", "dataset", "object", "vocabulary"]:
507
+ output_file = Path(os.path.join(tmp_dir, f"{module_name}_types.py"))
508
+
509
+ # Get the method from `MasterdataCodeGenerator`
510
+ code = getattr(generator, f"generate_{module_name}_types")().rstrip()
511
+
512
+ if code != "":
513
+ output_file.write_text(code + "\n", encoding="utf-8")
514
+ click.echo(f"Generated {module_name} types in {output_file}\n")
515
+ else:
516
+ click.echo(f"Skipping {module_name}_types.py (empty entity data)")
517
+ logger.info(f"Processed Excel file and exported to {tmp_dir}")
518
+
519
+ # Instantiate the checker class and run validation
520
+ checker = MasterdataChecker()
521
+
522
+ # Load current model from datamodel path
523
+ checker.load_current_model(datamodel_dir=datamodel_path)
524
+
525
+ # Load new entities from the specified file path (could be a Python file, directory, or Excel)
526
+ checker.load_new_entities(source=file_path)
527
+
528
+ # Run the checker in the specified mode
529
+ validation_results = checker.check(mode="individual")
530
+
531
+ if not validation_results.get("incoming_model"):
532
+ logger.info("No problems found in the new entities definition.")
533
+
534
+ # If there are no problems, push to openBIS
535
+ if all(
536
+ isinstance(value, dict) and all(not sub_value for sub_value in value.values())
537
+ for value in validation_results.values()
538
+ ):
539
+ click.echo("No problems found in the datamodel and incoming model.")
540
+ # Push to openBIS
541
+
542
+ url = environ("OPENBIS_URL")
543
+ openbis = ologin(url=url)
544
+ click.echo(f"Using the openBIS instance: {url}\n")
545
+
546
+ # Push each entity type
547
+ for module_path in listdir_py_modules(tmp_dir):
548
+ module = import_module(module_path=module_path)
549
+ for _, obj in inspect.getmembers(module, inspect.isclass):
550
+ if hasattr(obj, "defs") and callable(getattr(obj, "to_openbis")):
551
+ obj_instance = obj()
552
+ obj_instance.to_openbis(openbis=openbis, logger=logger)
553
+
554
+ else:
555
+ logger.error(
556
+ f"The checking of the new entities definition located in {file_path} did not pass. Please, check your entity definitions."
557
+ )
558
+ click.echo(
559
+ f"There are problems in the incoming model located in {file_path} that need to be solved"
560
+ )
561
+ return
562
+
563
+ if source_type == "excel":
564
+ # Clean up the tmp directory
565
+ shutil.rmtree(tmp_dir)
566
+ click.echo(f"Temporary files in {tmp_dir} have been deleted.")
567
+
568
+ logger.info(
569
+ f"Push to openBIS of the new entities located in {file_path} completed."
570
+ )
457
571
 
458
572
 
459
573
  if __name__ == "__main__":
@@ -18,6 +18,7 @@ class MasterdataCodeGenerator:
18
18
  self.row_cell_info = kwargs.get("row_cell_info", False)
19
19
  # * This part takes some time due to the loading of all entities from Openbis
20
20
  if url:
21
+ self.generator_type = "openbis"
21
22
  self.properties = OpenbisEntities(url=url).get_property_dict()
22
23
  self.collections = OpenbisEntities(url=url).get_collection_dict()
23
24
  self.datasets = OpenbisEntities(url=url).get_dataset_dict()
@@ -28,9 +29,11 @@ class MasterdataCodeGenerator:
28
29
  f"Loaded OpenBIS entities in `MasterdataCodeGenerator` initialization {elapsed_time:.2f} seconds\n"
29
30
  )
30
31
  else:
32
+ self.generator_type = "excel"
31
33
  entities_dict = MasterdataExcelExtractor(
32
34
  excel_path=path, row_cell_info=self.row_cell_info
33
35
  ).excel_to_entities()
36
+ self.properties = entities_dict.get("property_types", {})
34
37
  self.collections = entities_dict.get("collection_types", {})
35
38
  self.datasets = entities_dict.get("dataset_types", {})
36
39
  self.objects = entities_dict.get("object_types", {})
@@ -76,7 +79,7 @@ class MasterdataCodeGenerator:
76
79
 
77
80
  return parent_code, parent_class, class_name
78
81
 
79
- def get_property_object_code(self, prop_code: str) -> str:
82
+ def get_property_object_code(self, prop_data: dict) -> str:
80
83
  """
81
84
  Get the object code (or vocabulary code) used for reference for the assigned property with `prop_code`.
82
85
 
@@ -86,18 +89,21 @@ class MasterdataCodeGenerator:
86
89
  Returns:
87
90
  str: The object/vocabulary code used for reference for the assigned property.
88
91
  """
89
- data = self.properties.get(prop_code, {})
90
- if not data:
92
+ if not prop_data:
91
93
  return ""
92
94
 
93
- object_code = data.get("sampleType", "")
95
+ # TODO check excel extractor to add sampleType column
96
+ object_code = prop_data.get("sampleType", "")
94
97
  if object_code:
95
98
  return object_code
96
- vocabulary_code = data.get("vocabulary", "")
97
- if vocabulary_code:
98
- return vocabulary_code
99
99
 
100
- return ""
100
+ # TODO fix this patch and avoid using generator type
101
+ vocabulary_code = ""
102
+ if self.generator_type == "openbis":
103
+ vocabulary_code = prop_data.get("vocabulary", "")
104
+ elif self.generator_type == "excel":
105
+ vocabulary_code = prop_data.get("vocabularyType", "")
106
+ return vocabulary_code
101
107
 
102
108
  def add_properties(
103
109
  self, entities: dict, parent_code: str, data: dict, lines: list
@@ -115,14 +121,13 @@ class MasterdataCodeGenerator:
115
121
  data (dict): The data information for the entity as obtained from openBIS.
116
122
  lines (list): A list of strings to be printed to the Python module.
117
123
  """
118
- parent_properties = entities.get(parent_code, {}).get("properties", {}).keys()
124
+ parent_properties_code = (
125
+ entities.get(parent_code, {}).get("properties", {}).keys()
126
+ )
119
127
  for prop_code, prop_data in data.get("properties", {}).items():
120
128
  # Skip "UNKNOWN" properties
121
- if prop_code == "UNKNOWN":
122
- continue
123
-
124
129
  # We check if the property is inherited from the parent class
125
- if prop_code in parent_properties:
130
+ if prop_code == "UNKNOWN" or prop_code in parent_properties_code:
126
131
  continue
127
132
 
128
133
  prop_name = prop_code.lstrip("$").replace(".", "_").lower()
@@ -134,11 +139,11 @@ class MasterdataCodeGenerator:
134
139
  data_type = "OBJECT"
135
140
  lines.append(f' data_type="{data_type}",')
136
141
  if data_type == "OBJECT":
137
- object_code = self.get_property_object_code(prop_code=prop_code)
142
+ object_code = self.get_property_object_code(prop_data=prop_data)
138
143
  if object_code:
139
144
  lines.append(f' object_code="{object_code}",')
140
145
  elif data_type == "CONTROLLEDVOCABULARY":
141
- vocabulary_code = self.get_property_object_code(prop_code=prop_code)
146
+ vocabulary_code = self.get_property_object_code(prop_data=prop_data)
142
147
  if vocabulary_code:
143
148
  lines.append(f' vocabulary_code="{vocabulary_code}",')
144
149