nmdc-schema 11.12.0rc2__tar.gz → 11.12.1__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.
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/PKG-INFO +1 -1
- nmdc_schema-11.12.1/nmdc_schema/__init__.py +1 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migration_recursion.py +2 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/cli/run_migrator.py +10 -14
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/helpers.py +24 -0
- nmdc_schema-11.12.1/nmdc_schema/migrators/migrator_from_11_11_0_to_11_12_0.py +35 -0
- nmdc_schema-11.12.1/nmdc_schema/migrators/partials/migrator_from_11_11_0_to_11_12_0/__init__.py +28 -0
- nmdc_schema-11.12.1/nmdc_schema/migrators/partials/migrator_from_11_11_0_to_11_12_0/migrator_from_11_11_0_to_11_12_0_part_1.py +187 -0
- nmdc_schema-11.12.1/nmdc_schema/migrators/partials/migrator_from_11_11_0_to_11_12_0/migrator_from_11_11_0_to_11_12_0_part_2.py +113 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/nmdc-pydantic.py +194 -12
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/nmdc.py +149 -7
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/nmdc.schema.json +148 -4
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/nmdc_materialized_patterns.json +291 -51
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/nmdc_materialized_patterns.schema.json +148 -4
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/nmdc_materialized_patterns.yaml +243 -41
- nmdc_schema-11.12.1/nmdc_schema/nmdc_schema_validation_plugin.py +103 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/pyproject.toml +1 -3
- nmdc_schema-11.12.0rc2/nmdc_schema/migrators/cli/__init__.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/LICENSE +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/README.md +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/README.md +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/anyuri_strings_to_iris.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/dump_single_modality.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/get_json_schema.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/get_nmdc_view.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/gold-to-mixs.sssom.tsv +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/id_helpers.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/.docker/.env.example +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/.docker/docker-compose.yaml +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/.docker/mongoKeyFile +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/.docker/mongo_init/initialize_replica_set.sh +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/.docker/wait-for-it.sh +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/README.md +0 -0
- {nmdc_schema-11.12.0rc2/nmdc_schema → nmdc_schema-11.12.1/nmdc_schema/migrators}/__init__.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/adapters/adapter_base.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/adapters/dictionary_adapter.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/adapters/mongo_adapter.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/adapters/test_dictionary_adapter.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/adapters/test_mongo_adapter.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/assets/migrator_from_10_2_0_to_11_0_0_part_08/instrument_set.yaml +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/assets/migrator_from_11_7_to_11_8/data_category_map.yaml +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/assets/migrator_from_8_1_to_9_0/study_dois_changes.yaml +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/assets/migrator_from_9_1_to_9_2/websites_dois.yaml +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/cli/README.md +0 -0
- {nmdc_schema-11.12.0rc2/nmdc_schema/migrators → nmdc_schema-11.12.1/nmdc_schema/migrators/cli}/__init__.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/cli/create_migrator.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/cli/migrator.py.template +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/migration_reporter.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/migrator_base.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/migrator_from_10_0_0_to_10_1_2.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/migrator_from_10_2_0_to_11_0_0.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/migrator_from_10_3_0_to_10_4_0.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/migrator_from_10_4_0_to_10_5_4.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/migrator_from_10_5_4_to_10_5_5.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/migrator_from_10_5_5_to_10_5_6.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/migrator_from_10_5_6_to_10_6_0.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/migrator_from_10_6_0_to_10_7_0.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/migrator_from_11_0_3_to_11_1_0.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/migrator_from_11_10_0_to_11_11_0.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/migrator_from_11_1_0_to_11_2_0.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/migrator_from_11_3_0_to_11_4_0.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/migrator_from_11_4_0_to_11_5_0.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/migrator_from_11_5_0_to_11_5_1.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/migrator_from_11_5_1_to_11_6_0.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/migrator_from_11_6_0_to_11_6_1.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/migrator_from_11_6_1_to_11_7_0.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/migrator_from_11_7_0_to_11_8_0.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/migrator_from_11_8_0_to_11_9_0.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/migrator_from_11_9_1_to_11_10_0.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/migrator_from_1_0_0_to_EXAMPLE.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/migrator_from_7_7_2_to_7_8_0.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/migrator_from_7_8_0_to_8_0_0.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/migrator_from_8_0_to_8_1.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/migrator_from_8_1_to_9_0.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/migrator_from_9_1_to_9_2.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/migrator_from_9_3_to_10_0.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/partials/README.md +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/partials/migrator_from_10_2_0_to_11_0_0/__init__.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/partials/migrator_from_10_2_0_to_11_0_0/migrator_from_10_2_0_to_11_0_0_part_01.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/partials/migrator_from_10_2_0_to_11_0_0/migrator_from_10_2_0_to_11_0_0_part_02.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/partials/migrator_from_10_2_0_to_11_0_0/migrator_from_10_2_0_to_11_0_0_part_03.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/partials/migrator_from_10_2_0_to_11_0_0/migrator_from_10_2_0_to_11_0_0_part_04.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/partials/migrator_from_10_2_0_to_11_0_0/migrator_from_10_2_0_to_11_0_0_part_05.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/partials/migrator_from_10_2_0_to_11_0_0/migrator_from_10_2_0_to_11_0_0_part_06.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/partials/migrator_from_10_2_0_to_11_0_0/migrator_from_10_2_0_to_11_0_0_part_07.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/partials/migrator_from_10_2_0_to_11_0_0/migrator_from_10_2_0_to_11_0_0_part_08.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/partials/migrator_from_10_2_0_to_11_0_0/migrator_from_10_2_0_to_11_0_0_part_09.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/partials/migrator_from_10_2_0_to_11_0_0/migrator_from_10_2_0_to_11_0_0_part_10.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/partials/migrator_from_10_2_0_to_11_0_0/migrator_from_10_2_0_to_11_0_0_part_11.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/partials/migrator_from_10_2_0_to_11_0_0/migrator_from_10_2_0_to_11_0_0_part_12.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/partials/migrator_from_10_2_0_to_11_0_0/migrator_from_10_2_0_to_11_0_0_part_13.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/partials/migrator_from_10_2_0_to_11_0_0/migrator_from_10_2_0_to_11_0_0_part_14.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/partials/migrator_from_10_2_0_to_11_0_0/migrator_from_10_2_0_to_11_0_0_part_15.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/partials/migrator_from_10_2_0_to_11_0_0/migrator_from_10_2_0_to_11_0_0_part_16.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/partials/migrator_from_11_0_3_to_11_1_0/__init__.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/partials/migrator_from_11_0_3_to_11_1_0/migrator_from_11_0_3_to_11_1_0_part_1.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/partials/migrator_from_11_0_3_to_11_1_0/migrator_from_11_0_3_to_11_1_0_part_2.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/partials/migrator_from_11_0_3_to_11_1_0/migrator_from_11_0_3_to_11_1_0_part_3.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/partials/migrator_from_11_10_0_to_11_11_0/__init__.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/partials/migrator_from_11_10_0_to_11_11_0/migrator_from_11_10_0_to_11_11_0_part_1.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/partials/migrator_from_11_10_0_to_11_11_0/migrator_from_11_10_0_to_11_11_0_part_2.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/partials/migrator_from_11_1_0_to_11_2_0/__init__.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/partials/migrator_from_11_1_0_to_11_2_0/migrator_from_11_1_0_to_11_2_0_part_1.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/partials/migrator_from_11_1_0_to_11_2_0/migrator_from_11_1_0_to_11_2_0_part_2.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/partials/migrator_from_11_5_1_to_11_6_0/__init__.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/partials/migrator_from_11_5_1_to_11_6_0/migrator_from_11_5_1_to_11_6_0_part_1.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/partials/migrator_from_11_5_1_to_11_6_0/migrator_from_11_5_1_to_11_6_0_part_2.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/partials/migrator_from_11_7_0_to_11_8_0/__init__.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/partials/migrator_from_11_7_0_to_11_8_0/migrator_from_11_7_0_to_11_8_0_part_1.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/partials/migrator_from_11_7_0_to_11_8_0/migrator_from_11_7_0_to_11_8_0_part_2.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/partials/migrator_from_11_7_0_to_11_8_0/migrator_from_11_7_0_to_11_8_0_part_3.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/partials/migrator_from_11_7_0_to_11_8_0/migrator_from_11_7_0_to_11_8_0_part_4.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/partials/migrator_from_11_7_0_to_11_8_0/migrator_from_11_7_0_to_11_8_0_part_5.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/partials/migrator_from_11_8_0_to_11_9_0/__init__.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/partials/migrator_from_11_8_0_to_11_9_0/migrator_from_11_8_0_to_11_9_0_part_1.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/partials/migrator_from_11_8_0_to_11_9_0/migrator_from_11_8_0_to_11_9_0_part_2.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/partials/migrator_from_11_9_1_to_11_10_0/__init__.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/partials/migrator_from_11_9_1_to_11_10_0/migrator_from_11_9_1_to_11_10_0_part_1.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/partials/migrator_from_11_9_1_to_11_10_0/migrator_from_11_9_1_to_11_10_0_part_2.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/migrators/partials/migrator_from_11_9_1_to_11_10_0/migrator_from_11_9_1_to_11_10_0_part_3.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/nmdc_data.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/nmdc_version.py +0 -0
- {nmdc_schema-11.12.0rc2 → nmdc_schema-11.12.1}/nmdc_schema/validate_nmdc_json.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from nmdc_schema.nmdc_schema_validation_plugin import NmdcSchemaValidationPlugin as NmdcSchemaValidationPlugin
|
|
@@ -14,6 +14,8 @@ from nmdc_schema.migrators.adapters.dictionary_adapter import DictionaryAdapter
|
|
|
14
14
|
logger = logging.getLogger(__name__)
|
|
15
15
|
click_log.basic_config(logger)
|
|
16
16
|
|
|
17
|
+
# TODO: Is this script somewhat redundant with nmdc_schema/migrators/cli/run_migrator.py? Can they
|
|
18
|
+
# be consolidated?
|
|
17
19
|
|
|
18
20
|
# todo: log before and after states of migration
|
|
19
21
|
|
|
@@ -17,6 +17,7 @@ Environment variables (loaded from .env file if present):
|
|
|
17
17
|
MONGO_PASSWORD - MongoDB password
|
|
18
18
|
MONGO_AUTH_DB - Authentication database name
|
|
19
19
|
"""
|
|
20
|
+
import importlib
|
|
20
21
|
|
|
21
22
|
import click
|
|
22
23
|
import sys
|
|
@@ -25,21 +26,15 @@ from dotenv import load_dotenv
|
|
|
25
26
|
from pymongo import MongoClient
|
|
26
27
|
from nmdc_schema.migrators.adapters.mongo_adapter import MongoAdapter
|
|
27
28
|
|
|
29
|
+
# TODO: Is this script somewhat redundant with nmdc_schema/migration_recursion.py? Can they be
|
|
30
|
+
# consolidated?
|
|
31
|
+
|
|
28
32
|
# Load environment variables from .env file if it exists
|
|
29
33
|
load_dotenv()
|
|
30
34
|
|
|
31
|
-
# Import all migrators
|
|
32
|
-
from nmdc_schema.migrators.partials.migrator_from_11_9_1_to_11_10_0 import migrator_from_11_9_1_to_11_10_0_part_1
|
|
33
|
-
|
|
34
|
-
# Map migrator names to their classes
|
|
35
|
-
MIGRATORS = {
|
|
36
|
-
"migrator_from_11_9_1_to_11_10_0": migrator_from_11_9_1_to_11_10_0_part_1.Migrator,
|
|
37
|
-
# Add other migrators here as needed
|
|
38
|
-
}
|
|
39
|
-
|
|
40
35
|
|
|
41
36
|
@click.command()
|
|
42
|
-
@click.argument("
|
|
37
|
+
@click.argument("migrator", required=True)
|
|
43
38
|
@click.argument("action", required=False, default="rollback", type=click.Choice(["commit", "rollback"]))
|
|
44
39
|
@click.option("--host", default=lambda: os.getenv("MONGO_HOST", "localhost"), help="MongoDB host (default: from MONGO_HOST env var or localhost)")
|
|
45
40
|
@click.option("--port", default=lambda: int(os.getenv("MONGO_PORT", "27022")), type=int, help="MongoDB port (default: from MONGO_PORT env var or 27022)")
|
|
@@ -47,10 +42,10 @@ MIGRATORS = {
|
|
|
47
42
|
@click.option("--auth-db", default=lambda: os.getenv("MONGO_AUTH_DB"), help="Authentication database name (default: from MONGO_AUTH_DB env var)")
|
|
48
43
|
@click.option("--username", default=lambda: os.getenv("MONGO_USERNAME"), help="MongoDB username (default: from MONGO_USERNAME env var)")
|
|
49
44
|
@click.option("--password", default=lambda: os.getenv("MONGO_PASSWORD"), help="MongoDB password (default: from MONGO_PASSWORD env var)")
|
|
50
|
-
def run_migrator(
|
|
45
|
+
def run_migrator(migrator, action, host, port, database, auth_db, username, password):
|
|
51
46
|
"""Run a specific migrator against MongoDB using PyMongo.
|
|
52
47
|
|
|
53
|
-
|
|
48
|
+
MIGRATOR should the fully qualified module name for module containing a Migrator class
|
|
54
49
|
ACTION should be either 'commit' to save changes or 'rollback' to discard changes (default: rollback).
|
|
55
50
|
"""
|
|
56
51
|
|
|
@@ -70,12 +65,13 @@ def run_migrator(migrator_name, action, host, port, database, auth_db, username,
|
|
|
70
65
|
|
|
71
66
|
commit_changes = action == "commit"
|
|
72
67
|
|
|
73
|
-
click.echo(f"Running migrator: {
|
|
68
|
+
click.echo(f"Running migrator: {migrator}")
|
|
74
69
|
click.echo(f"Action: {action.upper()} (changes will {'be saved' if commit_changes else 'be discarded'})")
|
|
75
70
|
click.echo(f"MongoDB connection: {host}:{port}/{database}")
|
|
76
71
|
|
|
77
72
|
# Get the migrator class
|
|
78
|
-
|
|
73
|
+
migrator_module = importlib.import_module(migrator)
|
|
74
|
+
migrator_class = getattr(migrator_module, "Migrator")
|
|
79
75
|
|
|
80
76
|
# Connect to MongoDB using PyMongo
|
|
81
77
|
try:
|
|
@@ -113,3 +113,27 @@ def get_classes_with_slots_by_range(schema_view: SchemaView, range_constraint: s
|
|
|
113
113
|
|
|
114
114
|
return classes_with_slots
|
|
115
115
|
|
|
116
|
+
|
|
117
|
+
# TODO: Check whether this function can be replaced by a similar function from `refscan`.
|
|
118
|
+
def get_database_collections_for_class(schema_view: SchemaView, class_name: str) -> List[str]:
|
|
119
|
+
"""
|
|
120
|
+
Returns the list of database collection names associated with the specified class.
|
|
121
|
+
This function retrieves the collection names from the slots of the Database class
|
|
122
|
+
that have the specified class as their range.
|
|
123
|
+
|
|
124
|
+
Args:
|
|
125
|
+
schema_view: SchemaView instance
|
|
126
|
+
class_name: The name of the class to find collections for
|
|
127
|
+
|
|
128
|
+
Returns:
|
|
129
|
+
List[str]: List of collection names which permit storage of instances of the specified class
|
|
130
|
+
"""
|
|
131
|
+
collection_names = set()
|
|
132
|
+
|
|
133
|
+
for database_slot_name in schema_view.class_slots(DATABASE_CLASS_NAME):
|
|
134
|
+
database_slot_def = schema_view.get_slot(database_slot_name, strict=True)
|
|
135
|
+
database_slot_range_descendants = schema_view.class_descendants(database_slot_def.range, reflexive=True)
|
|
136
|
+
if class_name in database_slot_range_descendants:
|
|
137
|
+
collection_names.add(database_slot_name)
|
|
138
|
+
|
|
139
|
+
return list(collection_names)
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
from nmdc_schema.migrators.migrator_base import MigratorBase
|
|
2
|
+
from nmdc_schema.migrators.partials.migrator_from_11_11_0_to_11_12_0 import (
|
|
3
|
+
get_migrator_classes,
|
|
4
|
+
)
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Migrator(MigratorBase):
|
|
8
|
+
r"""
|
|
9
|
+
Migrates a database between two schemas.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
_from_version = "11.11.0"
|
|
13
|
+
_to_version = "11.12.0"
|
|
14
|
+
|
|
15
|
+
def upgrade(self, commit_changes: bool = False) -> None:
|
|
16
|
+
r"""
|
|
17
|
+
Migrates the database from conforming to the original schema, to conforming to the new schema.
|
|
18
|
+
|
|
19
|
+
This migrator uses partial migrators. It runs them in the order in which they are returned by
|
|
20
|
+
the `get_migrator_classes` function.
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
commit_changes: If True, commits the changes. If False (default), performs a dry run or rollback.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
migrator_classes = get_migrator_classes()
|
|
27
|
+
num_migrators = len(migrator_classes)
|
|
28
|
+
for idx, migrator_class in enumerate(migrator_classes):
|
|
29
|
+
self.logger.info(f"Running migrator {idx + 1} of {num_migrators}")
|
|
30
|
+
self.logger.debug(
|
|
31
|
+
f"Migrating from {migrator_class.get_origin_version()} "
|
|
32
|
+
f"to {migrator_class.get_destination_version()}"
|
|
33
|
+
)
|
|
34
|
+
migrator = migrator_class(adapter=self.adapter, logger=self.logger)
|
|
35
|
+
migrator.upgrade(commit_changes=commit_changes)
|
nmdc_schema-11.12.1/nmdc_schema/migrators/partials/migrator_from_11_11_0_to_11_12_0/__init__.py
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
from typing import List, Type
|
|
2
|
+
|
|
3
|
+
from nmdc_schema.migrators.migrator_base import MigratorBase
|
|
4
|
+
from nmdc_schema.migrators.partials.migrator_from_11_11_0_to_11_12_0 import (
|
|
5
|
+
migrator_from_11_11_0_to_11_12_0_part_1,
|
|
6
|
+
migrator_from_11_11_0_to_11_12_0_part_2,
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def get_migrator_classes() -> List[Type[MigratorBase]]:
|
|
11
|
+
r"""
|
|
12
|
+
Returns a list of migrator classes in the order in which they (i.e. their `upgrade` methods)
|
|
13
|
+
were designed to be run.
|
|
14
|
+
|
|
15
|
+
>>> migrator_classes = get_migrator_classes()
|
|
16
|
+
>>> type(migrator_classes) is list and len(migrator_classes) > 0 # the function returns a list
|
|
17
|
+
True
|
|
18
|
+
>>> from inspect import isclass
|
|
19
|
+
>>> all(isclass(c) for c in migrator_classes) # each list item is a class
|
|
20
|
+
True
|
|
21
|
+
>>> all(callable(getattr(c, "upgrade")) for c in migrator_classes) # each class has an `upgrade` method
|
|
22
|
+
True
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
return [
|
|
26
|
+
migrator_from_11_11_0_to_11_12_0_part_1.Migrator,
|
|
27
|
+
migrator_from_11_11_0_to_11_12_0_part_2.Migrator,
|
|
28
|
+
]
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
from nmdc_schema.migrators.migrator_base import MigratorBase
|
|
5
|
+
from nmdc_schema.migrators.adapters.mongo_adapter import MongoAdapter
|
|
6
|
+
|
|
7
|
+
project_root = Path(__file__).parent.parent.parent
|
|
8
|
+
sys.path.insert(0, str(project_root))
|
|
9
|
+
|
|
10
|
+
class Migrator(MigratorBase):
|
|
11
|
+
r'''
|
|
12
|
+
Migrates a database between two schemas.
|
|
13
|
+
'''
|
|
14
|
+
|
|
15
|
+
_from_version = '11.11.0'
|
|
16
|
+
_to_version = '11.12.0.part_1'
|
|
17
|
+
|
|
18
|
+
def upgrade(self, commit_changes: bool = False) -> None:
|
|
19
|
+
r'''
|
|
20
|
+
Migrates the database from conforming to the original schema, to conforming to the new schema.
|
|
21
|
+
'''
|
|
22
|
+
|
|
23
|
+
if isinstance(self.adapter, MongoAdapter):
|
|
24
|
+
try:
|
|
25
|
+
self.adapter.execute_in_transaction(
|
|
26
|
+
operations_callback=self.perform_all_migration_operations,
|
|
27
|
+
commit_changes=commit_changes
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
if commit_changes:
|
|
31
|
+
self.logger.info("Transaction committed (changes have been saved)")
|
|
32
|
+
else:
|
|
33
|
+
self.logger.info("Transaction rolled back (no changes were committed)")
|
|
34
|
+
|
|
35
|
+
except Exception as e:
|
|
36
|
+
self.logger.error(f"Migration failed: {e}")
|
|
37
|
+
raise
|
|
38
|
+
else:
|
|
39
|
+
raise NotImplementedError("This migrator currently only supports MongoAdapter.")
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def perform_all_migration_operations(self, _, __) -> None:
|
|
43
|
+
self.logger.info("Moving problematic QuantityValue entries to misc_param")
|
|
44
|
+
self.adapter.process_each_document("biosample_set", [
|
|
45
|
+
self.migrate_misc_param_to_PropertyAssertion_range,
|
|
46
|
+
self.move_problematic_values_to_misc_param,
|
|
47
|
+
])
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def migrate_misc_param_to_PropertyAssertion_range(self, biosample: dict) -> dict:
|
|
51
|
+
r"""The misc_param slot on Biosample used to have range TextValue, but now has range
|
|
52
|
+
PropertyAssertion. This migrator changes misc_param values to conform to the new range.
|
|
53
|
+
|
|
54
|
+
>>> m = Migrator()
|
|
55
|
+
|
|
56
|
+
# Test: Biosample with no misc_param
|
|
57
|
+
>>> biosample_no_misc = {
|
|
58
|
+
... "id": "test1",
|
|
59
|
+
... "type": "nmdc:Biosample"
|
|
60
|
+
... }
|
|
61
|
+
>>> m.migrate_misc_param_to_PropertyAssertion_range(biosample_no_misc)
|
|
62
|
+
{'id': 'test1', 'type': 'nmdc:Biosample'}
|
|
63
|
+
|
|
64
|
+
# Test: Biosample with misc_param as TextValue
|
|
65
|
+
>>> biosample_with_misc = {
|
|
66
|
+
... "id": "test2",
|
|
67
|
+
... "type": "nmdc:Biosample",
|
|
68
|
+
... "misc_param": [{"type": "nmdc:TextValue", "has_raw_value": "biomass_yield;2.565699 Mg/ha"}]
|
|
69
|
+
... }
|
|
70
|
+
>>> m.migrate_misc_param_to_PropertyAssertion_range(biosample_with_misc)
|
|
71
|
+
{'id': 'test2', 'type': 'nmdc:Biosample', 'misc_param': [{'type': 'nmdc:PropertyAssertion', 'has_raw_value': 'biomass_yield;2.565699 Mg/ha', 'has_attribute_label': 'biomass_yield', 'has_numeric_value': 2.565699, 'has_unit': 'Mg/ha'}]}
|
|
72
|
+
"""
|
|
73
|
+
misc_param = biosample.get("misc_param")
|
|
74
|
+
if not misc_param:
|
|
75
|
+
return biosample
|
|
76
|
+
|
|
77
|
+
property_assertions = []
|
|
78
|
+
for item in misc_param:
|
|
79
|
+
if isinstance(item, dict) and item.get("type") == "nmdc:TextValue":
|
|
80
|
+
# Convert TextValue to PropertyAssertion
|
|
81
|
+
raw_value = item.get("has_raw_value")
|
|
82
|
+
if not raw_value:
|
|
83
|
+
continue
|
|
84
|
+
pa = {
|
|
85
|
+
"type": "nmdc:PropertyAssertion",
|
|
86
|
+
"has_raw_value": raw_value
|
|
87
|
+
}
|
|
88
|
+
if ";" in raw_value:
|
|
89
|
+
[label, _, value] = item.get("has_raw_value", "").partition(";")
|
|
90
|
+
pa["has_attribute_label"] = label.strip()
|
|
91
|
+
if " " in value:
|
|
92
|
+
num_str, _, unit = value.strip().partition(" ")
|
|
93
|
+
try:
|
|
94
|
+
pa["has_numeric_value"] = float(num_str)
|
|
95
|
+
except ValueError:
|
|
96
|
+
pass # If conversion fails, skip adding has_numeric_value
|
|
97
|
+
if unit:
|
|
98
|
+
pa["has_unit"] = unit.strip()
|
|
99
|
+
property_assertions.append(pa)
|
|
100
|
+
else:
|
|
101
|
+
raise ValueError(
|
|
102
|
+
f"Biosample {biosample.get('id')} has misc_param item that is not a TextValue: {item}"
|
|
103
|
+
)
|
|
104
|
+
biosample["misc_param"] = property_assertions
|
|
105
|
+
return biosample
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def move_problematic_values_to_misc_param(self, biosample: dict) -> dict:
|
|
109
|
+
r"""Move QuantityValue entries with invalid units to misc_param as PropertyAssertion.
|
|
110
|
+
|
|
111
|
+
>>> m = Migrator()
|
|
112
|
+
|
|
113
|
+
# Test: Biosample with valid QuantityValue entries
|
|
114
|
+
>>> biosample_valid = {
|
|
115
|
+
... "id": "test1",
|
|
116
|
+
... "type": "nmdc:Biosample",
|
|
117
|
+
... "abs_air_humidity": {
|
|
118
|
+
... "type": "nmdc:QuantityValue",
|
|
119
|
+
... "has_unit": "kg/kg",
|
|
120
|
+
... "has_numeric_value": 75.0
|
|
121
|
+
... },
|
|
122
|
+
... "diss_oxygen": {
|
|
123
|
+
... "type": "nmdc:QuantityValue",
|
|
124
|
+
... "has_unit": "umol/L",
|
|
125
|
+
... "has_numeric_value": 8.0
|
|
126
|
+
... },
|
|
127
|
+
... "solar_irradiance": {
|
|
128
|
+
... "type": "nmdc:QuantityValue",
|
|
129
|
+
... "has_unit": "kW/m2/d",
|
|
130
|
+
... "has_numeric_value": 200.0
|
|
131
|
+
... }
|
|
132
|
+
... }
|
|
133
|
+
>>> m.move_problematic_values_to_misc_param(biosample_valid)
|
|
134
|
+
{'id': 'test1', 'type': 'nmdc:Biosample', 'abs_air_humidity': {'type': 'nmdc:QuantityValue', 'has_unit': 'kg/kg', 'has_numeric_value': 75.0}, 'diss_oxygen': {'type': 'nmdc:QuantityValue', 'has_unit': 'umol/L', 'has_numeric_value': 8.0}, 'solar_irradiance': {'type': 'nmdc:QuantityValue', 'has_unit': 'kW/m2/d', 'has_numeric_value': 200.0}}
|
|
135
|
+
|
|
136
|
+
# Test: Biosample with problematic QuantityValue entries
|
|
137
|
+
>>> biosample_problematic = {
|
|
138
|
+
... "id": "test2",
|
|
139
|
+
... "type": "nmdc:Biosample",
|
|
140
|
+
... "abs_air_humidity": {
|
|
141
|
+
... "type": "nmdc:QuantityValue",
|
|
142
|
+
... "has_unit": "kPa",
|
|
143
|
+
... "has_numeric_value": 75.0
|
|
144
|
+
... },
|
|
145
|
+
... "diss_oxygen": {
|
|
146
|
+
... "type": "nmdc:QuantityValue",
|
|
147
|
+
... "has_unit": "mL/L",
|
|
148
|
+
... "has_numeric_value": 8.0
|
|
149
|
+
... },
|
|
150
|
+
... "solar_irradiance": {
|
|
151
|
+
... "type": "nmdc:QuantityValue",
|
|
152
|
+
... "has_unit": "W/m2",
|
|
153
|
+
... "has_numeric_value": 200.0
|
|
154
|
+
... }
|
|
155
|
+
... }
|
|
156
|
+
>>> m.move_problematic_values_to_misc_param(biosample_problematic)
|
|
157
|
+
{'id': 'test2', 'type': 'nmdc:Biosample', 'misc_param': [{'type': 'nmdc:PropertyAssertion', 'has_attribute_label': 'abs_air_humidity', 'has_attribute_id': 'MIXS:0000122', 'has_numeric_value': 75.0, 'has_unit': 'kPa'}, {'type': 'nmdc:PropertyAssertion', 'has_attribute_label': 'diss_oxygen', 'has_attribute_id': 'MIXS:0000119', 'has_numeric_value': 8.0, 'has_unit': 'mL/L'}, {'type': 'nmdc:PropertyAssertion', 'has_attribute_label': 'solar_irradiance', 'has_attribute_id': 'MIXS:0000112', 'has_numeric_value': 200.0, 'has_unit': 'W/m2'}]}
|
|
158
|
+
"""
|
|
159
|
+
problematic_units = (
|
|
160
|
+
("abs_air_humidity", "MIXS:0000122", "kPa"),
|
|
161
|
+
("diss_oxygen", "MIXS:0000119", "mL/L"),
|
|
162
|
+
("solar_irradiance", "MIXS:0000112", "W/m2"),
|
|
163
|
+
)
|
|
164
|
+
for slot_name, slot_uri, bad_unit in problematic_units:
|
|
165
|
+
qv = biosample.get(slot_name)
|
|
166
|
+
if isinstance(qv, dict) and qv.get("type") == "nmdc:QuantityValue":
|
|
167
|
+
if qv.get("has_unit") == bad_unit:
|
|
168
|
+
# Move to misc_param as PropertyAssertion
|
|
169
|
+
pa = {
|
|
170
|
+
"type": "nmdc:PropertyAssertion",
|
|
171
|
+
"has_attribute_label": slot_name,
|
|
172
|
+
"has_attribute_id": slot_uri,
|
|
173
|
+
}
|
|
174
|
+
if "has_numeric_value" in qv:
|
|
175
|
+
pa["has_numeric_value"] = qv["has_numeric_value"]
|
|
176
|
+
if "has_unit" in qv:
|
|
177
|
+
pa["has_unit"] = qv["has_unit"]
|
|
178
|
+
if "has_raw_value" in qv:
|
|
179
|
+
pa["has_raw_value"] = qv["has_raw_value"]
|
|
180
|
+
|
|
181
|
+
# Ensure misc_param is a list and append the new PropertyAssertion
|
|
182
|
+
if "misc_param" not in biosample or not isinstance(biosample["misc_param"], list):
|
|
183
|
+
biosample["misc_param"] = []
|
|
184
|
+
biosample["misc_param"].append(pa)
|
|
185
|
+
# Remove the problematic QuantityValue from its original slot
|
|
186
|
+
del biosample[slot_name]
|
|
187
|
+
return biosample
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
from linkml.validator import Validator
|
|
2
|
+
|
|
3
|
+
from nmdc_schema.migrators.migrator_base import MigratorBase
|
|
4
|
+
import sys
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from nmdc_schema.migrators.helpers import create_schema_view, get_classes_with_slots_by_range, \
|
|
7
|
+
get_database_collections_for_class
|
|
8
|
+
from nmdc_schema import NmdcSchemaValidationPlugin
|
|
9
|
+
|
|
10
|
+
project_root = Path(__file__).parent.parent.parent
|
|
11
|
+
sys.path.insert(0, str(project_root))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class Migrator(MigratorBase):
|
|
15
|
+
r"""A check-only migrator that raises an exception if any QuantityValue's has_unit slot
|
|
16
|
+
is not valid against the slot's storage_unit or UnitEnum constraints."""
|
|
17
|
+
|
|
18
|
+
_from_version = '11.11.0'
|
|
19
|
+
_to_version = '11.12.0.part_2'
|
|
20
|
+
|
|
21
|
+
def __init__(self, *args, **kwargs):
|
|
22
|
+
super().__init__(*args, **kwargs)
|
|
23
|
+
|
|
24
|
+
self.schema_view = create_schema_view()
|
|
25
|
+
self.validator = Validator(
|
|
26
|
+
self.schema_view.schema,
|
|
27
|
+
# This is intentionally *only* using the NMDC plugin, because this migrator is *only*
|
|
28
|
+
# concerned with validating the QuantityValue-related constraints that the plugin
|
|
29
|
+
# implements.
|
|
30
|
+
validation_plugins=[
|
|
31
|
+
NmdcSchemaValidationPlugin()
|
|
32
|
+
]
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
def upgrade(self, commit_changes: bool = False) -> None:
|
|
36
|
+
r'''
|
|
37
|
+
Migrates the database from conforming to the original schema, to conforming to the new schema.
|
|
38
|
+
'''
|
|
39
|
+
|
|
40
|
+
# Get the schema classes which have slots with range QuantityValue
|
|
41
|
+
classes_with_qv_slots = get_classes_with_slots_by_range(self.schema_view, 'QuantityValue')
|
|
42
|
+
|
|
43
|
+
# Get the Database collection names that can hold these classes
|
|
44
|
+
eligible_collection_names = set()
|
|
45
|
+
for class_name in classes_with_qv_slots.keys():
|
|
46
|
+
collection_names = get_database_collections_for_class(self.schema_view, class_name)
|
|
47
|
+
eligible_collection_names.update(collection_names)
|
|
48
|
+
|
|
49
|
+
# Apply migrator through collections
|
|
50
|
+
self.logger.info("Checking QuantityValue units against UnitEnum and storage_units constraints")
|
|
51
|
+
for collection_name in eligible_collection_names:
|
|
52
|
+
self.logger.info(f" Checking collection '{collection_name}'")
|
|
53
|
+
self.adapter.do_for_each_document(collection_name, self.confirm_units_fit_unitenum_and_storage_units)
|
|
54
|
+
|
|
55
|
+
def confirm_units_fit_unitenum_and_storage_units(self, document: dict) -> None:
|
|
56
|
+
r'''
|
|
57
|
+
Raise an exception if the QuantityValue's has_unit slot is not valid against slot's storage_unit or UnitEnum constraints.
|
|
58
|
+
|
|
59
|
+
>>> m = Migrator()
|
|
60
|
+
|
|
61
|
+
# Test: valid QuantityValue with proper units in biosample
|
|
62
|
+
>>> valid_biosample = {
|
|
63
|
+
... "id": "test1",
|
|
64
|
+
... "type": "nmdc:Biosample",
|
|
65
|
+
... "temp": {
|
|
66
|
+
... "type": "nmdc:QuantityValue",
|
|
67
|
+
... "has_unit": "Cel",
|
|
68
|
+
... "has_numeric_value": 25.0
|
|
69
|
+
... }
|
|
70
|
+
... }
|
|
71
|
+
>>> m.confirm_units_fit_unitenum_and_storage_units(valid_biosample) # Should not raise
|
|
72
|
+
|
|
73
|
+
# Test: invalid unit not in UnitEnum
|
|
74
|
+
>>> invalid_biosample_enum = {
|
|
75
|
+
... "id": "test2",
|
|
76
|
+
... "type": "nmdc:Biosample",
|
|
77
|
+
... "temp": {
|
|
78
|
+
... "type": "nmdc:QuantityValue",
|
|
79
|
+
... "has_unit": "invalid_unit",
|
|
80
|
+
... "has_numeric_value": 25.0
|
|
81
|
+
... }
|
|
82
|
+
... }
|
|
83
|
+
>>> m.confirm_units_fit_unitenum_and_storage_units(invalid_biosample_enum)
|
|
84
|
+
Traceback (most recent call last):
|
|
85
|
+
...
|
|
86
|
+
ValueError: In test2:
|
|
87
|
+
QuantityValue at /temp has unit 'invalid_unit' which is not allowed for slot 'temp' (allowed: Cel)
|
|
88
|
+
|
|
89
|
+
# Test: unit not allowed for specific slot's storage_units
|
|
90
|
+
>>> invalid_biosample_storage = {
|
|
91
|
+
... "id": "test3",
|
|
92
|
+
... "type": "nmdc:Biosample",
|
|
93
|
+
... "temp": {
|
|
94
|
+
... "type": "nmdc:QuantityValue",
|
|
95
|
+
... "has_unit": "m", # Wrong unit type for temperature
|
|
96
|
+
... "has_numeric_value": 25.0
|
|
97
|
+
... }
|
|
98
|
+
... }
|
|
99
|
+
>>> m.confirm_units_fit_unitenum_and_storage_units(invalid_biosample_storage)
|
|
100
|
+
Traceback (most recent call last):
|
|
101
|
+
...
|
|
102
|
+
ValueError: In test3:
|
|
103
|
+
QuantityValue at /temp has unit 'm' which is not allowed for slot 'temp' (allowed: Cel)
|
|
104
|
+
'''
|
|
105
|
+
|
|
106
|
+
document_id = document.get('id', '<unknown id>')
|
|
107
|
+
document_type = document.get('type')
|
|
108
|
+
if not document_type:
|
|
109
|
+
raise ValueError(f"Unable to infer target_class for document with id '{document_id}'")
|
|
110
|
+
target_class = document_type.replace('nmdc:', '')
|
|
111
|
+
report = self.validator.validate(document, target_class)
|
|
112
|
+
if report.results:
|
|
113
|
+
raise ValueError(f"In {document_id}:\n" + "\n".join(" " + result.message for result in report.results))
|