metameq 2026.1.2__py3-none-any.whl → 2026.2.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- metameq/_version.py +3 -3
- metameq/config/config.yml +5 -1
- metameq/src/metadata_configurator.py +53 -6
- metameq/src/metadata_extender.py +58 -36
- metameq/src/util.py +9 -0
- metameq/tests/test_metadata_configurator.py +188 -2
- metameq/tests/test_metadata_extender.py +246 -93
- {metameq-2026.1.2.dist-info → metameq-2026.2.2.dist-info}/METADATA +1 -1
- {metameq-2026.1.2.dist-info → metameq-2026.2.2.dist-info}/RECORD +12 -12
- {metameq-2026.1.2.dist-info → metameq-2026.2.2.dist-info}/WHEEL +0 -0
- {metameq-2026.1.2.dist-info → metameq-2026.2.2.dist-info}/entry_points.txt +0 -0
- {metameq-2026.1.2.dist-info → metameq-2026.2.2.dist-info}/top_level.txt +0 -0
|
@@ -5,7 +5,8 @@ from metameq.src.util import \
|
|
|
5
5
|
SAMPLE_TYPE_SPECIFIC_METADATA_KEY, DEFAULT_KEY, \
|
|
6
6
|
ALIAS_KEY, BASE_TYPE_KEY, ALLOWED_KEY, ANYOF_KEY, TYPE_KEY, \
|
|
7
7
|
STUDY_SPECIFIC_METADATA_KEY, LEAVE_REQUIREDS_BLANK_KEY, \
|
|
8
|
-
OVERWRITE_NON_NANS_KEY, REQUIRED_KEY, SAMPLE_TYPE_KEY, QIITA_SAMPLE_TYPE
|
|
8
|
+
OVERWRITE_NON_NANS_KEY, REQUIRED_KEY, SAMPLE_TYPE_KEY, QIITA_SAMPLE_TYPE, \
|
|
9
|
+
HOSTTYPE_COL_OPTIONS_KEY, SAMPLETYPE_COL_OPTIONS_KEY
|
|
9
10
|
from metameq.src.metadata_configurator import \
|
|
10
11
|
combine_stds_and_study_config, \
|
|
11
12
|
_make_combined_stds_and_study_host_type_dicts, \
|
|
@@ -16,7 +17,8 @@ from metameq.src.metadata_configurator import \
|
|
|
16
17
|
_id_sample_type_definition, \
|
|
17
18
|
update_wip_metadata_dict, \
|
|
18
19
|
build_full_flat_config_dict, \
|
|
19
|
-
_resolve_sample_type_aliases_and_bases
|
|
20
|
+
_resolve_sample_type_aliases_and_bases, \
|
|
21
|
+
_push_global_settings_into_top_host
|
|
20
22
|
|
|
21
23
|
|
|
22
24
|
class TestMetadataConfigurator(TestCase):
|
|
@@ -3846,6 +3848,9 @@ class TestMetadataConfigurator(TestCase):
|
|
|
3846
3848
|
HOST_TYPE_SPECIFIC_METADATA_KEY: {
|
|
3847
3849
|
# base: top level in test_standards.yml, no default
|
|
3848
3850
|
"base": {
|
|
3851
|
+
DEFAULT_KEY: "software_default",
|
|
3852
|
+
LEAVE_REQUIREDS_BLANK_KEY: True,
|
|
3853
|
+
OVERWRITE_NON_NANS_KEY: False,
|
|
3849
3854
|
METADATA_FIELDS_KEY: {
|
|
3850
3855
|
# sample_name defined at base level
|
|
3851
3856
|
"sample_name": {
|
|
@@ -3864,6 +3869,8 @@ class TestMetadataConfigurator(TestCase):
|
|
|
3864
3869
|
"host_associated": {
|
|
3865
3870
|
# default defined at host_associated level
|
|
3866
3871
|
DEFAULT_KEY: "not provided",
|
|
3872
|
+
LEAVE_REQUIREDS_BLANK_KEY: True,
|
|
3873
|
+
OVERWRITE_NON_NANS_KEY: False,
|
|
3867
3874
|
METADATA_FIELDS_KEY: {
|
|
3868
3875
|
# description defined at host_associated level
|
|
3869
3876
|
"description": {
|
|
@@ -3918,6 +3925,8 @@ class TestMetadataConfigurator(TestCase):
|
|
|
3918
3925
|
"human": {
|
|
3919
3926
|
# default inherited from host_associated
|
|
3920
3927
|
DEFAULT_KEY: "not provided",
|
|
3928
|
+
LEAVE_REQUIREDS_BLANK_KEY: True,
|
|
3929
|
+
OVERWRITE_NON_NANS_KEY: False,
|
|
3921
3930
|
METADATA_FIELDS_KEY: {
|
|
3922
3931
|
# custom_field added from study_specific_metadata
|
|
3923
3932
|
"custom_field": {
|
|
@@ -4036,6 +4045,8 @@ class TestMetadataConfigurator(TestCase):
|
|
|
4036
4045
|
"mouse": {
|
|
4037
4046
|
# default inherited from host_associated
|
|
4038
4047
|
DEFAULT_KEY: "not provided",
|
|
4048
|
+
LEAVE_REQUIREDS_BLANK_KEY: True,
|
|
4049
|
+
OVERWRITE_NON_NANS_KEY: False,
|
|
4039
4050
|
METADATA_FIELDS_KEY: {
|
|
4040
4051
|
# description inherited from host_associated (not overridden)
|
|
4041
4052
|
"description": {
|
|
@@ -4102,6 +4113,7 @@ class TestMetadataConfigurator(TestCase):
|
|
|
4102
4113
|
}
|
|
4103
4114
|
}
|
|
4104
4115
|
}
|
|
4116
|
+
|
|
4105
4117
|
self.assertEqual(expected, result)
|
|
4106
4118
|
|
|
4107
4119
|
def test_build_full_flat_config_dict_without_study_config(self):
|
|
@@ -4129,6 +4141,9 @@ class TestMetadataConfigurator(TestCase):
|
|
|
4129
4141
|
HOST_TYPE_SPECIFIC_METADATA_KEY: {
|
|
4130
4142
|
# base: top level, no default, just sample_name/sample_type
|
|
4131
4143
|
"base": {
|
|
4144
|
+
DEFAULT_KEY: "software_default",
|
|
4145
|
+
LEAVE_REQUIREDS_BLANK_KEY: True,
|
|
4146
|
+
OVERWRITE_NON_NANS_KEY: False,
|
|
4132
4147
|
METADATA_FIELDS_KEY: {
|
|
4133
4148
|
"sample_name": {
|
|
4134
4149
|
REQUIRED_KEY: True,
|
|
@@ -4144,6 +4159,8 @@ class TestMetadataConfigurator(TestCase):
|
|
|
4144
4159
|
# host_associated: inherits from base, adds default and description
|
|
4145
4160
|
"host_associated": {
|
|
4146
4161
|
DEFAULT_KEY: "not provided",
|
|
4162
|
+
LEAVE_REQUIREDS_BLANK_KEY: True,
|
|
4163
|
+
OVERWRITE_NON_NANS_KEY: False,
|
|
4147
4164
|
METADATA_FIELDS_KEY: {
|
|
4148
4165
|
"description": {
|
|
4149
4166
|
DEFAULT_KEY: "host associated sample",
|
|
@@ -4193,6 +4210,8 @@ class TestMetadataConfigurator(TestCase):
|
|
|
4193
4210
|
# human: inherits from host_associated, overrides description
|
|
4194
4211
|
"human": {
|
|
4195
4212
|
DEFAULT_KEY: "not provided",
|
|
4213
|
+
LEAVE_REQUIREDS_BLANK_KEY: True,
|
|
4214
|
+
OVERWRITE_NON_NANS_KEY: False,
|
|
4196
4215
|
METADATA_FIELDS_KEY: {
|
|
4197
4216
|
"description": {
|
|
4198
4217
|
DEFAULT_KEY: "human sample",
|
|
@@ -4290,6 +4309,8 @@ class TestMetadataConfigurator(TestCase):
|
|
|
4290
4309
|
# mouse: inherits from host_associated, keeps parent description
|
|
4291
4310
|
"mouse": {
|
|
4292
4311
|
DEFAULT_KEY: "not provided",
|
|
4312
|
+
LEAVE_REQUIREDS_BLANK_KEY: True,
|
|
4313
|
+
OVERWRITE_NON_NANS_KEY: False,
|
|
4293
4314
|
METADATA_FIELDS_KEY: {
|
|
4294
4315
|
"description": {
|
|
4295
4316
|
DEFAULT_KEY: "host associated sample",
|
|
@@ -4394,6 +4415,12 @@ class TestMetadataConfigurator(TestCase):
|
|
|
4394
4415
|
# Flattened host types
|
|
4395
4416
|
HOST_TYPE_SPECIFIC_METADATA_KEY: {
|
|
4396
4417
|
"base": {
|
|
4418
|
+
# default from study_config overrides software_config
|
|
4419
|
+
DEFAULT_KEY: "study_default",
|
|
4420
|
+
# leave_requireds_blank from study_config overrides software_config
|
|
4421
|
+
LEAVE_REQUIREDS_BLANK_KEY: True,
|
|
4422
|
+
# overwrite_non_nans from software_config (not overridden by study)
|
|
4423
|
+
OVERWRITE_NON_NANS_KEY: True,
|
|
4397
4424
|
METADATA_FIELDS_KEY: {
|
|
4398
4425
|
"sample_name": {
|
|
4399
4426
|
REQUIRED_KEY: True,
|
|
@@ -4408,6 +4435,10 @@ class TestMetadataConfigurator(TestCase):
|
|
|
4408
4435
|
},
|
|
4409
4436
|
"host_associated": {
|
|
4410
4437
|
DEFAULT_KEY: "not provided",
|
|
4438
|
+
# leave_requireds_blank from study_config overrides software_config
|
|
4439
|
+
LEAVE_REQUIREDS_BLANK_KEY: True,
|
|
4440
|
+
# overwrite_non_nans from software_config (not overridden by study)
|
|
4441
|
+
OVERWRITE_NON_NANS_KEY: True,
|
|
4411
4442
|
METADATA_FIELDS_KEY: {
|
|
4412
4443
|
"description": {
|
|
4413
4444
|
DEFAULT_KEY: "host associated sample",
|
|
@@ -4456,6 +4487,10 @@ class TestMetadataConfigurator(TestCase):
|
|
|
4456
4487
|
},
|
|
4457
4488
|
"human": {
|
|
4458
4489
|
DEFAULT_KEY: "not provided",
|
|
4490
|
+
# leave_requireds_blank from study_config overrides software_config
|
|
4491
|
+
LEAVE_REQUIREDS_BLANK_KEY: True,
|
|
4492
|
+
# overwrite_non_nans from software_config (not overridden by study)
|
|
4493
|
+
OVERWRITE_NON_NANS_KEY: True,
|
|
4459
4494
|
METADATA_FIELDS_KEY: {
|
|
4460
4495
|
"description": {
|
|
4461
4496
|
DEFAULT_KEY: "human sample",
|
|
@@ -4552,6 +4587,10 @@ class TestMetadataConfigurator(TestCase):
|
|
|
4552
4587
|
},
|
|
4553
4588
|
"mouse": {
|
|
4554
4589
|
DEFAULT_KEY: "not provided",
|
|
4590
|
+
# leave_requireds_blank from study_config overrides software_config
|
|
4591
|
+
LEAVE_REQUIREDS_BLANK_KEY: True,
|
|
4592
|
+
# overwrite_non_nans from software_config (not overridden by study)
|
|
4593
|
+
OVERWRITE_NON_NANS_KEY: True,
|
|
4555
4594
|
METADATA_FIELDS_KEY: {
|
|
4556
4595
|
"description": {
|
|
4557
4596
|
DEFAULT_KEY: "host associated sample",
|
|
@@ -4643,9 +4682,14 @@ class TestMetadataConfigurator(TestCase):
|
|
|
4643
4682
|
DEFAULT_KEY: "not applicable",
|
|
4644
4683
|
LEAVE_REQUIREDS_BLANK_KEY: False,
|
|
4645
4684
|
OVERWRITE_NON_NANS_KEY: False,
|
|
4685
|
+
HOSTTYPE_COL_OPTIONS_KEY: ["host_common_name"],
|
|
4686
|
+
SAMPLETYPE_COL_OPTIONS_KEY: ["sample_type"],
|
|
4646
4687
|
# Flattened host types
|
|
4647
4688
|
HOST_TYPE_SPECIFIC_METADATA_KEY: {
|
|
4648
4689
|
"base": {
|
|
4690
|
+
DEFAULT_KEY: "not applicable",
|
|
4691
|
+
LEAVE_REQUIREDS_BLANK_KEY: False,
|
|
4692
|
+
OVERWRITE_NON_NANS_KEY: False,
|
|
4649
4693
|
METADATA_FIELDS_KEY: {
|
|
4650
4694
|
"sample_name": {
|
|
4651
4695
|
REQUIRED_KEY: True,
|
|
@@ -4660,6 +4704,8 @@ class TestMetadataConfigurator(TestCase):
|
|
|
4660
4704
|
},
|
|
4661
4705
|
"host_associated": {
|
|
4662
4706
|
DEFAULT_KEY: "not provided",
|
|
4707
|
+
LEAVE_REQUIREDS_BLANK_KEY: False,
|
|
4708
|
+
OVERWRITE_NON_NANS_KEY: False,
|
|
4663
4709
|
METADATA_FIELDS_KEY: {
|
|
4664
4710
|
"description": {
|
|
4665
4711
|
DEFAULT_KEY: "host associated sample",
|
|
@@ -4708,6 +4754,8 @@ class TestMetadataConfigurator(TestCase):
|
|
|
4708
4754
|
},
|
|
4709
4755
|
"human": {
|
|
4710
4756
|
DEFAULT_KEY: "not provided",
|
|
4757
|
+
LEAVE_REQUIREDS_BLANK_KEY: False,
|
|
4758
|
+
OVERWRITE_NON_NANS_KEY: False,
|
|
4711
4759
|
METADATA_FIELDS_KEY: {
|
|
4712
4760
|
"description": {
|
|
4713
4761
|
DEFAULT_KEY: "human sample",
|
|
@@ -4804,6 +4852,8 @@ class TestMetadataConfigurator(TestCase):
|
|
|
4804
4852
|
},
|
|
4805
4853
|
"mouse": {
|
|
4806
4854
|
DEFAULT_KEY: "not provided",
|
|
4855
|
+
LEAVE_REQUIREDS_BLANK_KEY: False,
|
|
4856
|
+
OVERWRITE_NON_NANS_KEY: False,
|
|
4807
4857
|
METADATA_FIELDS_KEY: {
|
|
4808
4858
|
"description": {
|
|
4809
4859
|
DEFAULT_KEY: "host associated sample",
|
|
@@ -4864,4 +4914,140 @@ class TestMetadataConfigurator(TestCase):
|
|
|
4864
4914
|
}
|
|
4865
4915
|
}
|
|
4866
4916
|
}
|
|
4917
|
+
|
|
4918
|
+
self.assertEqual(expected, result)
|
|
4919
|
+
|
|
4920
|
+
# Tests for _push_global_settings_into_top_host
|
|
4921
|
+
|
|
4922
|
+
def test__push_global_settings_into_top_host_single_setting(self):
|
|
4923
|
+
"""Test pushing a single global setting into the top-level host."""
|
|
4924
|
+
nested_hosts_dict = {
|
|
4925
|
+
HOST_TYPE_SPECIFIC_METADATA_KEY: {
|
|
4926
|
+
"base": {
|
|
4927
|
+
METADATA_FIELDS_KEY: {
|
|
4928
|
+
"field1": {TYPE_KEY: "string"}
|
|
4929
|
+
}
|
|
4930
|
+
}
|
|
4931
|
+
}
|
|
4932
|
+
}
|
|
4933
|
+
flat_config_dict = {
|
|
4934
|
+
DEFAULT_KEY: "custom_default"
|
|
4935
|
+
}
|
|
4936
|
+
|
|
4937
|
+
expected = {
|
|
4938
|
+
HOST_TYPE_SPECIFIC_METADATA_KEY: {
|
|
4939
|
+
"base": {
|
|
4940
|
+
DEFAULT_KEY: "custom_default",
|
|
4941
|
+
METADATA_FIELDS_KEY: {
|
|
4942
|
+
"field1": {TYPE_KEY: "string"}
|
|
4943
|
+
}
|
|
4944
|
+
}
|
|
4945
|
+
}
|
|
4946
|
+
}
|
|
4947
|
+
|
|
4948
|
+
result = _push_global_settings_into_top_host(
|
|
4949
|
+
nested_hosts_dict, flat_config_dict)
|
|
4950
|
+
|
|
4951
|
+
self.assertEqual(expected, result)
|
|
4952
|
+
# Original should be unchanged
|
|
4953
|
+
self.assertNotIn(
|
|
4954
|
+
DEFAULT_KEY,
|
|
4955
|
+
nested_hosts_dict[HOST_TYPE_SPECIFIC_METADATA_KEY]["base"])
|
|
4956
|
+
|
|
4957
|
+
def test__push_global_settings_into_top_host_multiple_settings(self):
|
|
4958
|
+
"""Test pushing multiple global settings into the top-level host."""
|
|
4959
|
+
nested_hosts_dict = {
|
|
4960
|
+
HOST_TYPE_SPECIFIC_METADATA_KEY: {
|
|
4961
|
+
"base": {
|
|
4962
|
+
METADATA_FIELDS_KEY: {
|
|
4963
|
+
"field1": {TYPE_KEY: "string"}
|
|
4964
|
+
}
|
|
4965
|
+
}
|
|
4966
|
+
}
|
|
4967
|
+
}
|
|
4968
|
+
flat_config_dict = {
|
|
4969
|
+
DEFAULT_KEY: "custom_default",
|
|
4970
|
+
LEAVE_REQUIREDS_BLANK_KEY: True,
|
|
4971
|
+
OVERWRITE_NON_NANS_KEY: True
|
|
4972
|
+
}
|
|
4973
|
+
|
|
4974
|
+
expected = {
|
|
4975
|
+
HOST_TYPE_SPECIFIC_METADATA_KEY: {
|
|
4976
|
+
"base": {
|
|
4977
|
+
DEFAULT_KEY: "custom_default",
|
|
4978
|
+
LEAVE_REQUIREDS_BLANK_KEY: True,
|
|
4979
|
+
OVERWRITE_NON_NANS_KEY: True,
|
|
4980
|
+
METADATA_FIELDS_KEY: {
|
|
4981
|
+
"field1": {TYPE_KEY: "string"}
|
|
4982
|
+
}
|
|
4983
|
+
}
|
|
4984
|
+
}
|
|
4985
|
+
}
|
|
4986
|
+
|
|
4987
|
+
result = _push_global_settings_into_top_host(
|
|
4988
|
+
nested_hosts_dict, flat_config_dict)
|
|
4989
|
+
|
|
4867
4990
|
self.assertEqual(expected, result)
|
|
4991
|
+
|
|
4992
|
+
def test__push_global_settings_into_top_host_no_settings(self):
|
|
4993
|
+
"""Test that function returns copy when no global settings present."""
|
|
4994
|
+
nested_hosts_dict = {
|
|
4995
|
+
HOST_TYPE_SPECIFIC_METADATA_KEY: {
|
|
4996
|
+
"base": {
|
|
4997
|
+
METADATA_FIELDS_KEY: {
|
|
4998
|
+
"field1": {TYPE_KEY: "string"}
|
|
4999
|
+
}
|
|
5000
|
+
}
|
|
5001
|
+
}
|
|
5002
|
+
}
|
|
5003
|
+
flat_config_dict = {
|
|
5004
|
+
"some_other_key": "value"
|
|
5005
|
+
}
|
|
5006
|
+
|
|
5007
|
+
expected = {
|
|
5008
|
+
HOST_TYPE_SPECIFIC_METADATA_KEY: {
|
|
5009
|
+
"base": {
|
|
5010
|
+
METADATA_FIELDS_KEY: {
|
|
5011
|
+
"field1": {TYPE_KEY: "string"}
|
|
5012
|
+
}
|
|
5013
|
+
}
|
|
5014
|
+
}
|
|
5015
|
+
}
|
|
5016
|
+
|
|
5017
|
+
result = _push_global_settings_into_top_host(
|
|
5018
|
+
nested_hosts_dict, flat_config_dict)
|
|
5019
|
+
|
|
5020
|
+
self.assertEqual(expected, result)
|
|
5021
|
+
|
|
5022
|
+
def test__push_global_settings_into_top_host_raises_on_zero_hosts(self):
|
|
5023
|
+
"""Test that ValueError is raised when no top-level hosts exist."""
|
|
5024
|
+
nested_hosts_dict = {
|
|
5025
|
+
HOST_TYPE_SPECIFIC_METADATA_KEY: {}
|
|
5026
|
+
}
|
|
5027
|
+
flat_config_dict = {
|
|
5028
|
+
DEFAULT_KEY: "custom_default"
|
|
5029
|
+
}
|
|
5030
|
+
|
|
5031
|
+
with self.assertRaisesRegex(
|
|
5032
|
+
ValueError,
|
|
5033
|
+
r"Expected exactly one top-level key.*found: \[\]"):
|
|
5034
|
+
_push_global_settings_into_top_host(
|
|
5035
|
+
nested_hosts_dict, flat_config_dict)
|
|
5036
|
+
|
|
5037
|
+
def test__push_global_settings_into_top_host_raises_on_multiple_hosts(self):
|
|
5038
|
+
"""Test that ValueError is raised when multiple top-level hosts exist."""
|
|
5039
|
+
nested_hosts_dict = {
|
|
5040
|
+
HOST_TYPE_SPECIFIC_METADATA_KEY: {
|
|
5041
|
+
"host1": {METADATA_FIELDS_KEY: {}},
|
|
5042
|
+
"host2": {METADATA_FIELDS_KEY: {}}
|
|
5043
|
+
}
|
|
5044
|
+
}
|
|
5045
|
+
flat_config_dict = {
|
|
5046
|
+
DEFAULT_KEY: "custom_default"
|
|
5047
|
+
}
|
|
5048
|
+
|
|
5049
|
+
with self.assertRaisesRegex(
|
|
5050
|
+
ValueError,
|
|
5051
|
+
r"Expected exactly one top-level key"):
|
|
5052
|
+
_push_global_settings_into_top_host(
|
|
5053
|
+
nested_hosts_dict, flat_config_dict)
|