18574: Adds 'preferred_label' virtual attribute. Avoids storing the voc twice.
[arvados.git] / sdk / python / arvados / vocabulary.py
1 # Copyright (C) The Arvados Authors. All rights reserved.
2 #
3 # SPDX-License-Identifier: Apache-2.0
4
5 import logging
6
7 from . import api
8
9 _logger = logging.getLogger('arvados.vocabulary')
10
11 def load_vocabulary(api_client=api('v1')):
12     """Load the Arvados vocabulary from the API.
13     """
14     return Vocabulary(api_client.vocabulary())
15
16 class Vocabulary(object):
17     def __init__(self, voc_definition={}):
18         self.strict_keys = voc_definition.get('strict_tags', False)
19         self.key_aliases = {}
20
21         for key_id, val in voc_definition.get('tags', {}).items():
22             strict = val.get('strict', False)
23             key_labels = [l['label'] for l in val.get('labels', [])]
24             values = {}
25             for v_id, v_val in val.get('values', {}).items():
26                 labels = [l['label'] for l in v_val.get('labels', [])]
27                 values[v_id] = VocabularyValue(v_id, labels)
28             vk = VocabularyKey(key_id, key_labels, values, strict)
29             self.key_aliases[key_id] = vk
30             for alias in vk.aliases:
31                 self.key_aliases[alias.lower()] = vk
32
33     def __getitem__(self, key):
34         return self.key_aliases[key.lower()]
35
36 class VocabularyData(object):
37     def __init__(self, identifier, aliases=[]):
38         self.identifier = identifier
39         self.aliases = aliases
40
41     def __getattribute__(self, name):
42         if name == 'preferred_label':
43             return self.aliases[0]
44         return super(VocabularyData, self).__getattribute__(name)
45
46 class VocabularyValue(VocabularyData):
47     def __init__(self, identifier, aliases=[]):
48         super(VocabularyValue, self).__init__(identifier, aliases)
49
50 class VocabularyKey(VocabularyData):
51     def __init__(self, identifier, aliases=[], values={}, strict=False):
52         super(VocabularyKey, self).__init__(identifier, aliases)
53         self.strict = strict
54         self.value_aliases = {}
55         for v_id, v_val in values.items():
56             self.value_aliases[v_id] = v_val
57             for v_alias in v_val.aliases:
58                 self.value_aliases[v_alias.lower()] = v_val
59
60     def __getitem__(self, key):
61         return self.value_aliases[key.lower()]