|
16 | 16 | # along with this program. If not, see <https://www.gnu.org/licenses/gpl-3.0.html>.
|
17 | 17 | #
|
18 | 18 | """Python Client Library for the LCCS Web Service."""
|
| 19 | +from typing import List, Optional |
19 | 20 | from .utils import Utils
|
20 | 21 |
|
21 | 22 |
|
22 | 23 | class ClassesGroup(dict):
|
23 |
| - """Group of classes mappings.""" |
| 24 | + """Group of classification system classes.""" |
24 | 25 |
|
25 |
| - def __init__(self, data, validate=False): |
26 |
| - """Initialize instance with dictionary data. |
| 26 | + def __init__(self, data: dict, validate: bool = False) -> None: |
| 27 | + """ |
| 28 | + Initialize instance with dictionary data. |
27 | 29 |
|
28 |
| - :param data: Dict with Item Collection metadata. |
29 |
| - :param validate: true if the Item Collection should be validate using its jsonschema. Default is False. |
| 30 | + :param data: Dictionary containing classification group data. |
| 31 | + :param validate: Whether to validate the data using jsonschema. Default is False. |
30 | 32 | """
|
| 33 | + super().__init__(data or {}) |
31 | 34 | self._validate = validate
|
32 |
| - super(ClassesGroup, self).__init__(data or {}) |
33 |
| - self._classes = [ClassificationSystemClass(i, self._validate) for i in self['classes']] |
| 35 | + self._classes: List[ClassificationSystemClass] = [ |
| 36 | + ClassificationSystemClass(i, self._validate) for i in self.get('classes', []) |
| 37 | + ] |
34 | 38 |
|
35 | 39 | @property
|
36 |
| - def classes(self): |
37 |
| - """:return: classes.""" |
| 40 | + def classes(self) -> List['ClassificationSystemClass']: |
| 41 | + """Return the list of classification system classes.""" |
38 | 42 | return self._classes
|
39 | 43 |
|
40 |
| - def _repr_html_(self): |
41 |
| - """HTML repr.""" |
| 44 | + def _repr_html_(self) -> str: |
| 45 | + """Render HTML representation.""" |
42 | 46 | return Utils.render_html('mapping.html', mappings=self)
|
43 | 47 |
|
44 |
| - def __repr__(self): |
45 |
| - """Return the string representation of a mapping group object.""" |
46 |
| - text = '' |
47 |
| - for i in self._classes: |
48 |
| - text += f'\n\t{i}' |
49 |
| - return text |
| 48 | + def __repr__(self) -> str: |
| 49 | + """Return the string representation of the group.""" |
| 50 | + return "\n".join([str(cls) for cls in self._classes]) |
50 | 51 |
|
51 |
| - def __str__(self): |
52 |
| - """Return the string representation of a mapping group object.""" |
53 |
| - text = '' |
54 |
| - for i in self._classes: |
55 |
| - text += f'\n\t{i}' |
56 |
| - return text |
| 52 | + def __str__(self) -> str: |
| 53 | + """Return the string representation of the group (readable).""" |
| 54 | + return self.__repr__() |
57 | 55 |
|
58 | 56 |
|
59 | 57 | class ClassificationSystemClass(dict):
|
60 |
| - """Class of the classification system.""" |
61 |
| - |
62 |
| - def __init__(self, data, validate=False) -> None: |
63 |
| - """Initialize instance with dictionary data. |
| 58 | + """Class representing a classification system.""" |
64 | 59 |
|
65 |
| - :param data: Dict with Class metadata. |
| 60 | + def __init__(self, data: dict, validate: bool = False) -> None: |
| 61 | + """ |
| 62 | + Initialize instance with dictionary data. |
66 | 63 |
|
67 |
| - :param validate: true if the Class should be validate using its jsonschema. Default is False. |
| 64 | + :param data: Dictionary containing class metadata. |
| 65 | + :param validate: Whether to validate the data using jsonschema. Default is False. |
68 | 66 | """
|
| 67 | + super().__init__(data or {}) |
69 | 68 | self._validate = validate
|
70 |
| - super(ClassificationSystemClass, self).__init__(data or {}) |
71 | 69 |
|
72 | 70 | @property
|
73 |
| - def id(self): |
74 |
| - """:return: the class id.""" |
75 |
| - return self['id'] |
| 71 | + def id(self) -> str: |
| 72 | + """Return the class ID.""" |
| 73 | + return self.get('id') |
76 | 74 |
|
77 | 75 | @property
|
78 |
| - def name(self): |
79 |
| - """:return: the class name.""" |
80 |
| - return self['name'] |
| 76 | + def name(self) -> str: |
| 77 | + """Return the class name.""" |
| 78 | + return self.get('name') |
81 | 79 |
|
82 | 80 | @property
|
83 |
| - def title(self): |
84 |
| - """:return: the class title.""" |
85 |
| - return self['title'] |
| 81 | + def title(self) -> str: |
| 82 | + """Return the class title.""" |
| 83 | + return self.get('title') |
86 | 84 |
|
87 | 85 | @property
|
88 |
| - def description(self): |
89 |
| - """:return: the class description.""" |
90 |
| - return self['description'] if 'description' in self else None |
| 86 | + def description(self) -> Optional[str]: |
| 87 | + """Return the class description.""" |
| 88 | + return self.get('description') |
91 | 89 |
|
92 | 90 | @property
|
93 |
| - def color(self): |
94 |
| - """:return: the class description.""" |
95 |
| - return self['color'] if 'color' in self else None |
| 91 | + def color(self) -> Optional[str]: |
| 92 | + """Return the class color.""" |
| 93 | + return self.get('color') |
96 | 94 |
|
97 | 95 | @property
|
98 |
| - def code(self): |
99 |
| - """:return: the class code.""" |
100 |
| - return self['code'] |
| 96 | + def code(self) -> str: |
| 97 | + """Return the class code.""" |
| 98 | + return self.get('code') |
101 | 99 |
|
102 | 100 | @property
|
103 |
| - def links(self): |
104 |
| - """:return: the class links.""" |
105 |
| - return self['links'] |
| 101 | + def links(self) -> List[dict]: |
| 102 | + """Return the class links.""" |
| 103 | + return self.get('links', []) |
106 | 104 |
|
107 | 105 | @property
|
108 |
| - def class_parent_id(self): |
109 |
| - """:return: the class parent id.""" |
110 |
| - return self['class_parent_id'] if 'class_parent_id' in self else None |
| 106 | + def class_parent_id(self) -> Optional[str]: |
| 107 | + """Return the parent class ID.""" |
| 108 | + return self.get('class_parent_id') |
111 | 109 |
|
112 | 110 | @property
|
113 |
| - def class_parent_name(self): |
114 |
| - """:return: class_parent_name of classification system.""" |
| 111 | + def class_parent_name(self) -> Optional[str]: |
| 112 | + """Return the parent class name.""" |
115 | 113 | return self._get_parent_name()
|
116 | 114 |
|
117 |
| - def _get_parent_name(self): |
118 |
| - if 'class_parent_id' in self: |
119 |
| - parent = [link['href'] for link in self['links'] if link['rel'] == 'parent'][0] |
120 |
| - system = parent.rsplit('/', maxsplit=1)[1].split('?')[0] |
121 |
| - |
122 |
| - if len(parent.rsplit('/', maxsplit=1)[1].split('?')) > 1: |
123 |
| - token = parent.rsplit('/', maxsplit=1)[1].split('?')[1] |
124 |
| - parent_class_uri = parent.rsplit('/', maxsplit=1)[ |
125 |
| - 0] + f'/{system}' + f'/classes/{self["class_parent_id"]}?{token}' |
126 |
| - else: |
127 |
| - parent_class_uri = parent.rsplit('/', maxsplit=1)[ |
128 |
| - 0] + f'/{system}' + f'/classes/{self["class_parent_id"]}' |
129 |
| - class_parent_name = ClassificationSystemClass(Utils._get(parent_class_uri)).name |
130 |
| - return class_parent_name |
131 |
| - else: |
132 |
| - return None |
| 115 | + def _get_parent_name(self) -> Optional[str]: |
| 116 | + """Resolve and return the parent class name, if available.""" |
| 117 | + if self.class_parent_id: |
| 118 | + parent_link = next((link for link in self.links if link.get('rel') == 'parent'), None) |
| 119 | + if parent_link: |
| 120 | + try: |
| 121 | + parent_url = self._build_parent_url(parent_link['href']) |
| 122 | + parent_data = Utils._get(parent_url) |
| 123 | + return ClassificationSystemClass(parent_data).name |
| 124 | + except Exception as e: |
| 125 | + return None |
| 126 | + return None |
| 127 | + |
| 128 | + def _build_parent_url(self, href: str) -> str: |
| 129 | + """Build the full URL for the parent class.""" |
| 130 | + system = href.rsplit('/', maxsplit=1)[1].split('?')[0] |
| 131 | + token = href.split('?')[-1] if '?' in href else "" |
| 132 | + base_url = href.rsplit('/', maxsplit=1)[0] |
| 133 | + return f"{base_url}/{system}/classes/{self['class_parent_id']}?{token}" if token else f"{base_url}/{system}/classes/{self['class_parent_id']}" |
0 commit comments