|
7 | 7 | from hdmf.build import TypeMap, CustomClassGenerator |
8 | 8 | from hdmf.build.classgenerator import ClassGenerator, MCIClassGenerator |
9 | 9 | from hdmf.container import Container, Data, MultiContainerInterface, AbstractContainer |
10 | | -from hdmf.spec import GroupSpec, AttributeSpec, DatasetSpec, SpecCatalog, SpecNamespace, NamespaceCatalog, LinkSpec |
| 10 | +from hdmf.spec import ( |
| 11 | + GroupSpec, AttributeSpec, DatasetSpec, SpecCatalog, SpecNamespace, NamespaceCatalog, LinkSpec, RefSpec |
| 12 | +) |
11 | 13 | from hdmf.testing import TestCase |
12 | 14 | from hdmf.utils import get_docval, docval |
13 | 15 |
|
@@ -734,9 +736,18 @@ def _build_separate_namespaces(self): |
734 | 736 | GroupSpec(data_type_inc='Bar', doc='a bar', quantity='?') |
735 | 737 | ] |
736 | 738 | ) |
| 739 | + moo_spec = DatasetSpec( |
| 740 | + doc='A test dataset that is a 1D array of object references of Baz', |
| 741 | + data_type_def='Moo', |
| 742 | + shape=(None,), |
| 743 | + dtype=RefSpec( |
| 744 | + reftype='object', |
| 745 | + target_type='Baz' |
| 746 | + ) |
| 747 | + ) |
737 | 748 | create_load_namespace_yaml( |
738 | 749 | namespace_name='ndx-test', |
739 | | - specs=[baz_spec], |
| 750 | + specs=[baz_spec, moo_spec], |
740 | 751 | output_dir=self.test_dir, |
741 | 752 | incl_types={ |
742 | 753 | CORE_NAMESPACE: ['Bar'], |
@@ -828,6 +839,171 @@ def test_get_class_include_from_separate_ns_4(self): |
828 | 839 |
|
829 | 840 | self._check_classes(baz_cls, bar_cls, bar_cls2, qux_cls, qux_cls2) |
830 | 841 |
|
| 842 | +class TestGetClassObjectReferences(TestCase): |
| 843 | + |
| 844 | + def setUp(self): |
| 845 | + self.test_dir = tempfile.mkdtemp() |
| 846 | + if os.path.exists(self.test_dir): # start clean |
| 847 | + self.tearDown() |
| 848 | + os.mkdir(self.test_dir) |
| 849 | + self.type_map = TypeMap() |
| 850 | + |
| 851 | + def tearDown(self): |
| 852 | + shutil.rmtree(self.test_dir) |
| 853 | + |
| 854 | + def test_get_class_include_dataset_of_references(self): |
| 855 | + """Test that get_class resolves datasets of object references.""" |
| 856 | + qux_spec = DatasetSpec( |
| 857 | + doc='A test extension', |
| 858 | + data_type_def='Qux' |
| 859 | + ) |
| 860 | + moo_spec = DatasetSpec( |
| 861 | + doc='A test dataset that is a 1D array of object references of Qux', |
| 862 | + data_type_def='Moo', |
| 863 | + shape=(None,), |
| 864 | + dtype=RefSpec( |
| 865 | + reftype='object', |
| 866 | + target_type='Qux' |
| 867 | + ), |
| 868 | + ) |
| 869 | + |
| 870 | + create_load_namespace_yaml( |
| 871 | + namespace_name='ndx-test', |
| 872 | + specs=[qux_spec, moo_spec], |
| 873 | + output_dir=self.test_dir, |
| 874 | + incl_types={}, |
| 875 | + type_map=self.type_map |
| 876 | + ) |
| 877 | + # no types should be resolved to start |
| 878 | + assert self.type_map.get_container_classes('ndx-test') == [] |
| 879 | + |
| 880 | + self.type_map.get_dt_container_cls('Moo', 'ndx-test') |
| 881 | + # now, Moo and Qux should be resolved |
| 882 | + assert len(self.type_map.get_container_classes('ndx-test')) == 2 |
| 883 | + assert "Moo" in [c.__name__ for c in self.type_map.get_container_classes('ndx-test')] |
| 884 | + assert "Qux" in [c.__name__ for c in self.type_map.get_container_classes('ndx-test')] |
| 885 | + |
| 886 | + def test_get_class_include_attribute_object_reference(self): |
| 887 | + """Test that get_class resolves data types with an attribute that is an object reference.""" |
| 888 | + qux_spec = DatasetSpec( |
| 889 | + doc='A test extension', |
| 890 | + data_type_def='Qux' |
| 891 | + ) |
| 892 | + woo_spec = DatasetSpec( |
| 893 | + doc='A test dataset that has a scalar object reference to a Qux', |
| 894 | + data_type_def='Woo', |
| 895 | + attributes=[ |
| 896 | + AttributeSpec( |
| 897 | + name='attr1', |
| 898 | + doc='a string attribute', |
| 899 | + dtype=RefSpec(reftype='object', target_type='Qux') |
| 900 | + ), |
| 901 | + ] |
| 902 | + ) |
| 903 | + create_load_namespace_yaml( |
| 904 | + namespace_name='ndx-test', |
| 905 | + specs=[qux_spec, woo_spec], |
| 906 | + output_dir=self.test_dir, |
| 907 | + incl_types={}, |
| 908 | + type_map=self.type_map |
| 909 | + ) |
| 910 | + # no types should be resolved to start |
| 911 | + assert self.type_map.get_container_classes('ndx-test') == [] |
| 912 | + |
| 913 | + self.type_map.get_dt_container_cls('Woo', 'ndx-test') |
| 914 | + # now, Woo and Qux should be resolved |
| 915 | + assert len(self.type_map.get_container_classes('ndx-test')) == 2 |
| 916 | + assert "Woo" in [c.__name__ for c in self.type_map.get_container_classes('ndx-test')] |
| 917 | + assert "Qux" in [c.__name__ for c in self.type_map.get_container_classes('ndx-test')] |
| 918 | + |
| 919 | + def test_get_class_include_nested_object_reference(self): |
| 920 | + """Test that get_class resolves nested datasets that are object references.""" |
| 921 | + qux_spec = DatasetSpec( |
| 922 | + doc='A test extension', |
| 923 | + data_type_def='Qux' |
| 924 | + ) |
| 925 | + spam_spec = DatasetSpec( |
| 926 | + doc='A test extension', |
| 927 | + data_type_def='Spam', |
| 928 | + shape=(None,), |
| 929 | + dtype=RefSpec( |
| 930 | + reftype='object', |
| 931 | + target_type='Qux' |
| 932 | + ), |
| 933 | + ) |
| 934 | + goo_spec = GroupSpec( |
| 935 | + doc='A test dataset that has a nested dataset (Spam) that has a scalar object reference to a Qux', |
| 936 | + data_type_def='Goo', |
| 937 | + datasets=[ |
| 938 | + DatasetSpec( |
| 939 | + doc='a dataset', |
| 940 | + data_type_inc='Spam', |
| 941 | + ), |
| 942 | + ], |
| 943 | + ) |
| 944 | + |
| 945 | + create_load_namespace_yaml( |
| 946 | + namespace_name='ndx-test', |
| 947 | + specs=[qux_spec, spam_spec, goo_spec], |
| 948 | + output_dir=self.test_dir, |
| 949 | + incl_types={}, |
| 950 | + type_map=self.type_map |
| 951 | + ) |
| 952 | + # no types should be resolved to start |
| 953 | + assert self.type_map.get_container_classes('ndx-test') == [] |
| 954 | + |
| 955 | + self.type_map.get_dt_container_cls('Goo', 'ndx-test') |
| 956 | + # now, Goo, Spam, and Qux should be resolved |
| 957 | + assert len(self.type_map.get_container_classes('ndx-test')) == 3 |
| 958 | + assert "Goo" in [c.__name__ for c in self.type_map.get_container_classes('ndx-test')] |
| 959 | + assert "Spam" in [c.__name__ for c in self.type_map.get_container_classes('ndx-test')] |
| 960 | + assert "Qux" in [c.__name__ for c in self.type_map.get_container_classes('ndx-test')] |
| 961 | + |
| 962 | + def test_get_class_include_nested_attribute_object_reference(self): |
| 963 | + """Test that get_class resolves nested datasets that have an attribute that is an object reference.""" |
| 964 | + qux_spec = DatasetSpec( |
| 965 | + doc='A test extension', |
| 966 | + data_type_def='Qux' |
| 967 | + ) |
| 968 | + bam_spec = DatasetSpec( |
| 969 | + doc='A test extension', |
| 970 | + data_type_def='Bam', |
| 971 | + attributes=[ |
| 972 | + AttributeSpec( |
| 973 | + name='attr1', |
| 974 | + doc='a string attribute', |
| 975 | + dtype=RefSpec(reftype='object', target_type='Qux') |
| 976 | + ), |
| 977 | + ], |
| 978 | + ) |
| 979 | + boo_spec = GroupSpec( |
| 980 | + doc='A test dataset that has a nested dataset (Spam) that has a scalar object reference to a Qux', |
| 981 | + data_type_def='Boo', |
| 982 | + datasets=[ |
| 983 | + DatasetSpec( |
| 984 | + doc='a dataset', |
| 985 | + data_type_inc='Bam', |
| 986 | + ), |
| 987 | + ], |
| 988 | + ) |
| 989 | + |
| 990 | + create_load_namespace_yaml( |
| 991 | + namespace_name='ndx-test', |
| 992 | + specs=[qux_spec, bam_spec, boo_spec], |
| 993 | + output_dir=self.test_dir, |
| 994 | + incl_types={}, |
| 995 | + type_map=self.type_map |
| 996 | + ) |
| 997 | + # no types should be resolved to start |
| 998 | + assert self.type_map.get_container_classes('ndx-test') == [] |
| 999 | + |
| 1000 | + self.type_map.get_dt_container_cls('Boo', 'ndx-test') |
| 1001 | + # now, Boo, Bam, and Qux should be resolved |
| 1002 | + assert len(self.type_map.get_container_classes('ndx-test')) == 3 |
| 1003 | + assert "Boo" in [c.__name__ for c in self.type_map.get_container_classes('ndx-test')] |
| 1004 | + assert "Bam" in [c.__name__ for c in self.type_map.get_container_classes('ndx-test')] |
| 1005 | + assert "Qux" in [c.__name__ for c in self.type_map.get_container_classes('ndx-test')] |
| 1006 | + |
831 | 1007 |
|
832 | 1008 | class EmptyBar(Container): |
833 | 1009 | pass |
|
0 commit comments