1d20777823a285bb65bb9bfec2c41f9a0ac52923
[arvados.git] / sdk / python / tests / test_vocabulary.py
1 # Copyright (C) The Arvados Authors. All rights reserved.
2 #
3 # SPDX-License-Identifier: Apache-2.0
4
5 import arvados
6 import unittest
7 import mock
8
9 from arvados import api, vocabulary
10
11 class VocabularyTest(unittest.TestCase):
12     EXAMPLE_VOC = {
13         'tags': {
14             'IDTAGANIMALS': {
15                 'strict': False,
16                 'labels': [
17                     {'label': 'Animal'},
18                     {'label': 'Creature'},
19                 ],
20                 'values': {
21                     'IDVALANIMAL1': {
22                         'labels': [
23                             {'label': 'Human'},
24                             {'label': 'Homo sapiens'},
25                         ],
26                     },
27                     'IDVALANIMAL2': {
28                         'labels': [
29                             {'label': 'Elephant'},
30                             {'label': 'Loxodonta'},
31                         ],
32                     },
33                 },
34             },
35             'IDTAGIMPORTANCES': {
36                 'strict': True,
37                 'labels': [
38                     {'label': 'Importance'},
39                     {'label': 'Priority'},
40                 ],
41                 'values': {
42                     'IDVALIMPORTANCE1': {
43                         'labels': [
44                             {'label': 'High'},
45                             {'label': 'High priority'},
46                         ],
47                     },
48                     'IDVALIMPORTANCE2': {
49                         'labels': [
50                             {'label': 'Medium'},
51                             {'label': 'Medium priority'},
52                         ],
53                     },
54                     'IDVALIMPORTANCE3': {
55                         'labels': [
56                             {'label': 'Low'},
57                             {'label': 'Low priority'},
58                         ],
59                     },
60                 },
61             },
62             'IDTAGCOMMENTS': {
63                 'strict': False,
64                 'labels': [
65                     {'label': 'Comment'},
66                     {'label': 'Notes'},
67                 ],
68             },
69         },
70     }
71
72     def setUp(self):
73         self.api = arvados.api('v1')
74         self.voc = vocabulary.Vocabulary(self.EXAMPLE_VOC)
75         self.api.vocabulary = mock.MagicMock(return_value=self.EXAMPLE_VOC)
76
77     def test_vocabulary_keys(self):
78         self.assertEqual(self.voc.strict_keys, False)
79         self.assertEqual(
80             self.voc.key_aliases.keys(),
81             set(['idtaganimals', 'creature', 'animal',
82                 'idtagimportances', 'importance', 'priority',
83                 'idtagcomments', 'comment', 'notes'])
84         )
85
86         vk = self.voc.key_aliases['creature']
87         self.assertEqual(vk.strict, False)
88         self.assertEqual(vk.identifier, 'IDTAGANIMALS')
89         self.assertEqual(vk.aliases, ['Animal', 'Creature'])
90         self.assertEqual(vk.preferred_label, 'Animal')
91         self.assertEqual(
92             vk.value_aliases.keys(),
93             set(['idvalanimal1', 'human', 'homo sapiens',
94                 'idvalanimal2', 'elephant', 'loxodonta'])
95         )
96
97     def test_vocabulary_values(self):
98         vk = self.voc.key_aliases['creature']
99         vv = vk.value_aliases['human']
100         self.assertEqual(vv.identifier, 'IDVALANIMAL1')
101         self.assertEqual(vv.aliases, ['Human', 'Homo sapiens'])
102         self.assertEqual(vv.preferred_label, 'Human')
103
104     def test_vocabulary_indexing(self):
105         self.assertEqual(self.voc['creature']['human'].identifier, 'IDVALANIMAL1')
106         self.assertEqual(self.voc['Creature']['Human'].identifier, 'IDVALANIMAL1')
107         self.assertEqual(self.voc['CREATURE']['HUMAN'].identifier, 'IDVALANIMAL1')
108         with self.assertRaises(KeyError):
109             inexistant = self.voc['foo']
110
111     def test_empty_vocabulary(self):
112         voc = vocabulary.Vocabulary({})
113         self.assertEqual(voc.strict_keys, False)
114         self.assertEqual(voc.key_aliases, {})
115
116     def test_load_vocabulary_with_api(self):
117         voc = vocabulary.load_vocabulary(self.api)
118         self.assertEqual(voc['creature']['human'].identifier, 'IDVALANIMAL1')
119         self.assertEqual(voc['Creature']['Human'].identifier, 'IDVALANIMAL1')
120         self.assertEqual(voc['CREATURE']['HUMAN'].identifier, 'IDVALANIMAL1')
121
122     def test_convert_to_identifiers(self):
123         cases = [
124             {'IDTAGIMPORTANCES': 'IDVALIMPORTANCE1'},
125             {'IDTAGIMPORTANCES': 'High'},
126             {'importance': 'IDVALIMPORTANCE1'},
127             {'priority': 'high priority'},
128         ]
129         for case in cases:
130             self.assertEqual(
131                 self.voc.convert_to_identifiers(case),
132                 {'IDTAGIMPORTANCES': 'IDVALIMPORTANCE1'},
133                 "failing test case: {}".format(case)
134             )
135
136     def test_convert_to_identifiers_multiple_pairs(self):
137         cases = [
138             {'IDTAGIMPORTANCES': 'IDVALIMPORTANCE1', 'IDTAGANIMALS': 'IDVALANIMAL1', 'IDTAGCOMMENTS': 'Very important person'},
139             {'IDTAGIMPORTANCES': 'High', 'IDTAGANIMALS': 'IDVALANIMAL1', 'comment': 'Very important person'},
140             {'importance': 'IDVALIMPORTANCE1', 'animal': 'IDVALANIMAL1', 'notes': 'Very important person'},
141             {'priority': 'high priority', 'animal': 'IDVALANIMAL1', 'NOTES': 'Very important person'},
142         ]
143         for case in cases:
144             self.assertEqual(
145                 self.voc.convert_to_identifiers(case),
146                 {'IDTAGIMPORTANCES': 'IDVALIMPORTANCE1', 'IDTAGANIMALS': 'IDVALANIMAL1', 'IDTAGCOMMENTS': 'Very important person'},
147                 "failing test case: {}".format(case)
148             )
149
150     def test_convert_to_identifiers_value_lists(self):
151         cases = [
152             {'IDTAGIMPORTANCES': ['IDVALIMPORTANCE1', 'IDVALIMPORTANCE2']},
153             {'IDTAGIMPORTANCES': ['High', 'Medium']},
154             {'importance': ['IDVALIMPORTANCE1', 'IDVALIMPORTANCE2']},
155             {'priority': ['high', 'medium']},
156         ]
157         for case in cases:
158             self.assertEqual(
159                 self.voc.convert_to_identifiers(case),
160                 {'IDTAGIMPORTANCES': ['IDVALIMPORTANCE1', 'IDVALIMPORTANCE2']},
161                 "failing test case: {}".format(case)
162             )
163
164     def test_convert_to_identifiers_unknown_key(self):
165         # Non-strict vocabulary
166         self.assertEqual(self.voc.strict_keys, False)
167         self.assertEqual(self.voc.convert_to_identifiers({'foo': 'bar'}), {'foo': 'bar'})
168         # Strict vocabulary
169         strict_voc = arvados.vocabulary.Vocabulary(self.EXAMPLE_VOC)
170         strict_voc.strict_keys = True
171         with self.assertRaises(KeyError):
172             strict_voc.convert_to_identifiers({'foo': 'bar'})
173
174     def test_convert_to_identifiers_unknown_value(self):
175         # Non-strict key
176         self.assertEqual(self.voc['animal'].strict, False)
177         self.assertEqual(self.voc.convert_to_identifiers({'Animal': 'foo'}), {'IDTAGANIMALS': 'foo'})
178         # Strict key
179         self.assertEqual(self.voc['priority'].strict, True)
180         with self.assertRaises(ValueError):
181             self.voc.convert_to_identifiers({'Priority': 'foo'})
182
183     def test_convert_to_labels(self):
184         cases = [
185             {'IDTAGIMPORTANCES': 'IDVALIMPORTANCE1'},
186             {'IDTAGIMPORTANCES': 'High'},
187             {'importance': 'IDVALIMPORTANCE1'},
188             {'priority': 'high priority'},
189         ]
190         for case in cases:
191             self.assertEqual(
192                 self.voc.convert_to_labels(case),
193                 {'Importance': 'High'},
194                 "failing test case: {}".format(case)
195             )
196
197     def test_convert_to_labels_multiple_pairs(self):
198         cases = [
199             {'IDTAGIMPORTANCES': 'IDVALIMPORTANCE1', 'IDTAGANIMALS': 'IDVALANIMAL1', 'IDTAGCOMMENTS': 'Very important person'},
200             {'IDTAGIMPORTANCES': 'High', 'IDTAGANIMALS': 'IDVALANIMAL1', 'comment': 'Very important person'},
201             {'importance': 'IDVALIMPORTANCE1', 'animal': 'IDVALANIMAL1', 'notes': 'Very important person'},
202             {'priority': 'high priority', 'animal': 'IDVALANIMAL1', 'NOTES': 'Very important person'},
203         ]
204         for case in cases:
205             self.assertEqual(
206                 self.voc.convert_to_labels(case),
207                 {'Importance': 'High', 'Animal': 'Human', 'Comment': 'Very important person'},
208                 "failing test case: {}".format(case)
209             )
210
211     def test_convert_to_labels_value_lists(self):
212         cases = [
213             {'IDTAGIMPORTANCES': ['IDVALIMPORTANCE1', 'IDVALIMPORTANCE2']},
214             {'IDTAGIMPORTANCES': ['High', 'Medium']},
215             {'importance': ['IDVALIMPORTANCE1', 'IDVALIMPORTANCE2']},
216             {'priority': ['high', 'medium']},
217         ]
218         for case in cases:
219             self.assertEqual(
220                 self.voc.convert_to_labels(case),
221                 {'Importance': ['High', 'Medium']},
222                 "failing test case: {}".format(case)
223             )
224
225     def test_convert_to_labels_unknown_key(self):
226         # Non-strict vocabulary
227         self.assertEqual(self.voc.strict_keys, False)
228         self.assertEqual(self.voc.convert_to_labels({'foo': 'bar'}), {'foo': 'bar'})
229         # Strict vocabulary
230         strict_voc = arvados.vocabulary.Vocabulary(self.EXAMPLE_VOC)
231         strict_voc.strict_keys = True
232         with self.assertRaises(KeyError):
233             strict_voc.convert_to_labels({'foo': 'bar'})
234
235     def test_convert_to_labels_unknown_value(self):
236         # Non-strict key
237         self.assertEqual(self.voc['animal'].strict, False)
238         self.assertEqual(self.voc.convert_to_labels({'IDTAGANIMALS': 'foo'}), {'Animal': 'foo'})
239         # Strict key
240         self.assertEqual(self.voc['priority'].strict, True)
241         with self.assertRaises(ValueError):
242             self.voc.convert_to_labels({'IDTAGIMPORTANCES': 'foo'})
243
244     def test_convert_roundtrip(self):
245         initial = {'IDTAGIMPORTANCES': 'IDVALIMPORTANCE1', 'IDTAGANIMALS': 'IDVALANIMAL1', 'IDTAGCOMMENTS': 'Very important person'}
246         converted = self.voc.convert_to_labels(initial)
247         self.assertNotEqual(converted, initial)
248         self.assertEqual(self.voc.convert_to_identifiers(converted), initial)