esgvoc 0.2.1__py3-none-any.whl → 0.3.0__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.
Potentially problematic release.
This version of esgvoc might be problematic. Click here for more details.
- esgvoc/__init__.py +3 -1
- esgvoc/api/__init__.py +23 -34
- esgvoc/api/_utils.py +28 -14
- esgvoc/api/data_descriptors/__init__.py +18 -12
- esgvoc/api/data_descriptors/activity.py +8 -45
- esgvoc/api/data_descriptors/area_label.py +6 -0
- esgvoc/api/data_descriptors/branded_suffix.py +5 -0
- esgvoc/api/data_descriptors/branded_variable.py +5 -0
- esgvoc/api/data_descriptors/consortium.py +16 -56
- esgvoc/api/data_descriptors/data_descriptor.py +106 -0
- esgvoc/api/data_descriptors/date.py +3 -46
- esgvoc/api/data_descriptors/directory_date.py +3 -46
- esgvoc/api/data_descriptors/experiment.py +19 -54
- esgvoc/api/data_descriptors/forcing_index.py +3 -45
- esgvoc/api/data_descriptors/frequency.py +6 -43
- esgvoc/api/data_descriptors/grid_label.py +6 -44
- esgvoc/api/data_descriptors/horizontal_label.py +6 -0
- esgvoc/api/data_descriptors/initialisation_index.py +3 -44
- esgvoc/api/data_descriptors/institution.py +11 -54
- esgvoc/api/data_descriptors/license.py +4 -44
- esgvoc/api/data_descriptors/mip_era.py +6 -44
- esgvoc/api/data_descriptors/model_component.py +7 -45
- esgvoc/api/data_descriptors/organisation.py +3 -40
- esgvoc/api/data_descriptors/physic_index.py +3 -45
- esgvoc/api/data_descriptors/product.py +4 -43
- esgvoc/api/data_descriptors/realisation_index.py +3 -44
- esgvoc/api/data_descriptors/realm.py +4 -42
- esgvoc/api/data_descriptors/resolution.py +6 -44
- esgvoc/api/data_descriptors/source.py +18 -53
- esgvoc/api/data_descriptors/source_type.py +3 -41
- esgvoc/api/data_descriptors/sub_experiment.py +3 -41
- esgvoc/api/data_descriptors/table.py +6 -48
- esgvoc/api/data_descriptors/temporal_label.py +6 -0
- esgvoc/api/data_descriptors/time_range.py +3 -27
- esgvoc/api/data_descriptors/variable.py +13 -71
- esgvoc/api/data_descriptors/variant_label.py +3 -47
- esgvoc/api/data_descriptors/vertical_label.py +5 -0
- esgvoc/api/projects.py +187 -171
- esgvoc/api/report.py +21 -12
- esgvoc/api/search.py +3 -1
- esgvoc/api/universe.py +44 -34
- esgvoc/apps/__init__.py +3 -4
- esgvoc/apps/drs/generator.py +166 -161
- esgvoc/apps/drs/report.py +222 -131
- esgvoc/apps/drs/validator.py +103 -105
- esgvoc/cli/drs.py +29 -19
- esgvoc/cli/get.py +26 -25
- esgvoc/cli/install.py +11 -8
- esgvoc/cli/main.py +0 -2
- esgvoc/cli/status.py +5 -5
- esgvoc/cli/valid.py +40 -40
- esgvoc/core/db/models/universe.py +3 -3
- esgvoc/core/db/project_ingestion.py +1 -1
- esgvoc/core/db/universe_ingestion.py +6 -5
- esgvoc/core/logging_handler.py +1 -1
- esgvoc/core/repo_fetcher.py +4 -3
- esgvoc/core/service/__init__.py +37 -5
- esgvoc/core/service/configuration/config_manager.py +188 -0
- esgvoc/core/service/configuration/setting.py +88 -0
- esgvoc/core/service/state.py +49 -32
- {esgvoc-0.2.1.dist-info → esgvoc-0.3.0.dist-info}/METADATA +34 -3
- esgvoc-0.3.0.dist-info/RECORD +78 -0
- esgvoc/cli/config.py +0 -82
- esgvoc/core/service/settings.py +0 -73
- esgvoc/core/service/settings.toml +0 -17
- esgvoc/core/service/settings_default.toml +0 -17
- esgvoc-0.2.1.dist-info/RECORD +0 -73
- {esgvoc-0.2.1.dist-info → esgvoc-0.3.0.dist-info}/WHEEL +0 -0
- {esgvoc-0.2.1.dist-info → esgvoc-0.3.0.dist-info}/entry_points.txt +0 -0
- {esgvoc-0.2.1.dist-info → esgvoc-0.3.0.dist-info}/licenses/LICENSE.txt +0 -0
esgvoc/api/report.py
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
from pydantic import BaseModel, computed_field
|
|
2
1
|
from abc import ABC, abstractmethod
|
|
3
2
|
from typing import Any, Protocol
|
|
4
3
|
|
|
4
|
+
from pydantic import BaseModel, computed_field
|
|
5
|
+
|
|
5
6
|
import esgvoc.core.constants as api_settings
|
|
6
7
|
from esgvoc.core.db.models.mixins import TermKind
|
|
7
8
|
|
|
@@ -29,7 +30,11 @@ class ValidationError(BaseModel, ABC):
|
|
|
29
30
|
"""JSON specification of the term."""
|
|
30
31
|
term_kind: TermKind
|
|
31
32
|
"""The kind of term."""
|
|
32
|
-
|
|
33
|
+
@computed_field # type: ignore
|
|
34
|
+
@property
|
|
35
|
+
def class_name(self) -> str:
|
|
36
|
+
"""The class name of the issue for JSON serialization."""
|
|
37
|
+
return self.__class__.__name__
|
|
33
38
|
@abstractmethod
|
|
34
39
|
def accept(self, visitor: ValidationErrorVisitor) -> Any:
|
|
35
40
|
"""
|
|
@@ -46,13 +51,13 @@ class UniverseTermError(ValidationError):
|
|
|
46
51
|
"""
|
|
47
52
|
A validation error on a term from the universe.
|
|
48
53
|
"""
|
|
49
|
-
|
|
54
|
+
|
|
50
55
|
data_descriptor_id: str
|
|
51
56
|
"""The data descriptor that the term belongs."""
|
|
52
57
|
|
|
53
58
|
def accept(self, visitor: ValidationErrorVisitor) -> Any:
|
|
54
59
|
return visitor.visit_universe_term_error(self)
|
|
55
|
-
|
|
60
|
+
|
|
56
61
|
def __str__(self) -> str:
|
|
57
62
|
term_id = self.term[api_settings.TERM_ID_JSON_KEY]
|
|
58
63
|
result = f"The term {term_id} from the data descriptor {self.data_descriptor_id} "+\
|
|
@@ -66,13 +71,13 @@ class ProjectTermError(ValidationError):
|
|
|
66
71
|
"""
|
|
67
72
|
A validation error on a term from a project.
|
|
68
73
|
"""
|
|
69
|
-
|
|
74
|
+
|
|
70
75
|
collection_id: str
|
|
71
76
|
"""The collection id that the term belongs"""
|
|
72
77
|
|
|
73
78
|
def accept(self, visitor: ValidationErrorVisitor) -> Any:
|
|
74
79
|
return visitor.visit_project_term_error(self)
|
|
75
|
-
|
|
80
|
+
|
|
76
81
|
def __str__(self) -> str:
|
|
77
82
|
term_id = self.term[api_settings.TERM_ID_JSON_KEY]
|
|
78
83
|
result = f"The term {term_id} from the collection {self.collection_id} "+\
|
|
@@ -86,29 +91,33 @@ class ValidationReport(BaseModel):
|
|
|
86
91
|
"""
|
|
87
92
|
Term validation report.
|
|
88
93
|
"""
|
|
94
|
+
|
|
89
95
|
expression: str
|
|
90
96
|
"""The given expression."""
|
|
91
|
-
|
|
97
|
+
|
|
98
|
+
errors: list[UniverseTermError|ProjectTermError]
|
|
92
99
|
"""The validation errors."""
|
|
100
|
+
|
|
93
101
|
@computed_field # type: ignore
|
|
94
102
|
@property
|
|
95
103
|
def nb_errors(self) -> int:
|
|
96
104
|
"""The number of validation errors."""
|
|
97
105
|
return len(self.errors) if self.errors else 0
|
|
106
|
+
|
|
98
107
|
@computed_field # type: ignore
|
|
99
108
|
@property
|
|
100
109
|
def validated(self) -> bool:
|
|
101
110
|
"""The expression is validated or not."""
|
|
102
111
|
return False if self.errors else True
|
|
103
|
-
|
|
104
|
-
|
|
112
|
+
|
|
105
113
|
def __len__(self) -> int:
|
|
106
114
|
return self.nb_errors
|
|
107
|
-
|
|
115
|
+
|
|
108
116
|
def __bool__(self) -> bool:
|
|
109
117
|
return self.validated
|
|
110
|
-
|
|
118
|
+
|
|
111
119
|
def __str__(self) -> str:
|
|
112
120
|
return f"'{self.expression}' has {self.nb_errors} error(s)"
|
|
121
|
+
|
|
113
122
|
def __repr__(self) -> str:
|
|
114
|
-
return self.__str__()
|
|
123
|
+
return self.__str__()
|
esgvoc/api/search.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
from typing import Iterable
|
|
1
2
|
from enum import Enum
|
|
2
|
-
|
|
3
3
|
from pydantic import BaseModel
|
|
4
4
|
from sqlalchemy import ColumnElement, func
|
|
5
5
|
from sqlmodel import col
|
|
@@ -43,6 +43,8 @@ class SearchSettings(BaseModel):
|
|
|
43
43
|
"""Enable case sensitivity or not."""
|
|
44
44
|
not_operator: bool = False
|
|
45
45
|
"""Give the opposite result like the NOT SQL operator."""
|
|
46
|
+
selected_term_fields: Iterable[str]|None = None
|
|
47
|
+
"""Term fields to select"""
|
|
46
48
|
|
|
47
49
|
|
|
48
50
|
def _create_str_comparison_expression(field: str,
|
esgvoc/api/universe.py
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
from typing import Sequence
|
|
1
|
+
from typing import Sequence, Iterable
|
|
2
2
|
|
|
3
3
|
from esgvoc.api._utils import (get_universe_session,
|
|
4
4
|
instantiate_pydantic_terms)
|
|
5
5
|
from esgvoc.api.search import SearchSettings, _create_str_comparison_expression
|
|
6
|
-
from esgvoc.
|
|
7
|
-
from
|
|
6
|
+
from esgvoc.api.data_descriptors.data_descriptor import DataDescriptor
|
|
7
|
+
from esgvoc.core.db.models.universe import UDataDescriptor, UTerm
|
|
8
8
|
from sqlmodel import Session, select
|
|
9
9
|
|
|
10
10
|
|
|
@@ -16,7 +16,7 @@ def _find_terms_in_data_descriptor(data_descriptor_id: str,
|
|
|
16
16
|
where_expression = _create_str_comparison_expression(field=UTerm.id,
|
|
17
17
|
value=term_id,
|
|
18
18
|
settings=settings)
|
|
19
|
-
statement = select(UTerm).join(
|
|
19
|
+
statement = select(UTerm).join(UDataDescriptor).where(UDataDescriptor.id==data_descriptor_id,
|
|
20
20
|
where_expression)
|
|
21
21
|
results = session.exec(statement)
|
|
22
22
|
result = results.all()
|
|
@@ -26,7 +26,7 @@ def _find_terms_in_data_descriptor(data_descriptor_id: str,
|
|
|
26
26
|
def find_terms_in_data_descriptor(data_descriptor_id: str,
|
|
27
27
|
term_id: str,
|
|
28
28
|
settings: SearchSettings|None = None) \
|
|
29
|
-
-> list[
|
|
29
|
+
-> list[DataDescriptor]:
|
|
30
30
|
"""
|
|
31
31
|
Finds one or more terms in the given data descriptor based on the specified search settings.
|
|
32
32
|
This function performs an exact match on the `data_descriptor_id` and
|
|
@@ -39,8 +39,8 @@ def find_terms_in_data_descriptor(data_descriptor_id: str,
|
|
|
39
39
|
returns an empty list.
|
|
40
40
|
|
|
41
41
|
Behavior based on search type:
|
|
42
|
-
- `EXACT` and absence of `settings`: returns zero or one
|
|
43
|
-
- `REGEX`, `LIKE`, `STARTS_WITH` and `ENDS_WITH`: returns zero, one or more
|
|
42
|
+
- `EXACT` and absence of `settings`: returns zero or one term instance in the list.
|
|
43
|
+
- `REGEX`, `LIKE`, `STARTS_WITH` and `ENDS_WITH`: returns zero, one or more term \
|
|
44
44
|
instances in the list.
|
|
45
45
|
|
|
46
46
|
:param data_descriptor_id: A data descriptor id
|
|
@@ -49,13 +49,13 @@ def find_terms_in_data_descriptor(data_descriptor_id: str,
|
|
|
49
49
|
:type term_id: str
|
|
50
50
|
:param settings: The search settings
|
|
51
51
|
:type settings: SearchSettings|None
|
|
52
|
-
:returns: A list of
|
|
53
|
-
:rtype: list[
|
|
52
|
+
:returns: A list of term instances. Returns an empty list if no matches are found.
|
|
53
|
+
:rtype: list[DataDescriptor]
|
|
54
54
|
"""
|
|
55
|
-
result: list[
|
|
55
|
+
result: list[DataDescriptor] = list()
|
|
56
56
|
with get_universe_session() as session:
|
|
57
57
|
terms = _find_terms_in_data_descriptor(data_descriptor_id, term_id, session, settings)
|
|
58
|
-
instantiate_pydantic_terms(terms, result)
|
|
58
|
+
instantiate_pydantic_terms(terms, result, settings.selected_term_fields if settings else None)
|
|
59
59
|
return result
|
|
60
60
|
|
|
61
61
|
|
|
@@ -72,7 +72,7 @@ def _find_terms_in_universe(term_id: str,
|
|
|
72
72
|
|
|
73
73
|
def find_terms_in_universe(term_id: str,
|
|
74
74
|
settings: SearchSettings|None = None) \
|
|
75
|
-
-> list[
|
|
75
|
+
-> list[DataDescriptor]:
|
|
76
76
|
"""
|
|
77
77
|
Finds one or more terms of the universe.
|
|
78
78
|
The given `term_id` is searched according to the search type specified in
|
|
@@ -86,36 +86,38 @@ def find_terms_in_universe(term_id: str,
|
|
|
86
86
|
:type term_id: str
|
|
87
87
|
:param settings: The search settings
|
|
88
88
|
:type settings: SearchSettings|None
|
|
89
|
-
:returns: A list of
|
|
90
|
-
:rtype: list[
|
|
89
|
+
:returns: A list of term instances. Returns an empty list if no matches are found.
|
|
90
|
+
:rtype: list[DataDescriptor]
|
|
91
91
|
"""
|
|
92
|
-
result: list[
|
|
92
|
+
result: list[DataDescriptor] = list()
|
|
93
93
|
with get_universe_session() as session:
|
|
94
94
|
terms = _find_terms_in_universe(term_id, session, settings)
|
|
95
|
-
instantiate_pydantic_terms(terms, result)
|
|
95
|
+
instantiate_pydantic_terms(terms, result, settings.selected_term_fields if settings else None)
|
|
96
96
|
return result
|
|
97
97
|
|
|
98
98
|
|
|
99
|
-
def _get_all_terms_in_data_descriptor(data_descriptor:
|
|
100
|
-
|
|
101
|
-
|
|
99
|
+
def _get_all_terms_in_data_descriptor(data_descriptor: UDataDescriptor,
|
|
100
|
+
selected_term_fields: Iterable[str]|None) -> list[DataDescriptor]:
|
|
101
|
+
result: list[DataDescriptor] = list()
|
|
102
|
+
instantiate_pydantic_terms(data_descriptor.terms, result, selected_term_fields)
|
|
102
103
|
return result
|
|
103
104
|
|
|
104
105
|
|
|
105
106
|
def _find_data_descriptors_in_universe(data_descriptor_id: str,
|
|
106
107
|
session: Session,
|
|
107
|
-
settings: SearchSettings|None) -> Sequence[
|
|
108
|
-
where_expression = _create_str_comparison_expression(field=
|
|
108
|
+
settings: SearchSettings|None) -> Sequence[UDataDescriptor]:
|
|
109
|
+
where_expression = _create_str_comparison_expression(field=UDataDescriptor.id,
|
|
109
110
|
value=data_descriptor_id,
|
|
110
111
|
settings=settings)
|
|
111
|
-
statement = select(
|
|
112
|
+
statement = select(UDataDescriptor).where(where_expression)
|
|
112
113
|
results = session.exec(statement)
|
|
113
114
|
result = results.all()
|
|
114
115
|
return result
|
|
115
116
|
|
|
116
117
|
|
|
117
|
-
def get_all_terms_in_data_descriptor(data_descriptor_id: str
|
|
118
|
-
|
|
118
|
+
def get_all_terms_in_data_descriptor(data_descriptor_id: str,
|
|
119
|
+
selected_term_fields: Iterable[str]|None = None) \
|
|
120
|
+
-> list[DataDescriptor]:
|
|
119
121
|
"""
|
|
120
122
|
Gets all the terms of the given data descriptor.
|
|
121
123
|
This function performs an exact match on the `data_descriptor_id` and does **not** search
|
|
@@ -124,8 +126,11 @@ def get_all_terms_in_data_descriptor(data_descriptor_id: str) \
|
|
|
124
126
|
|
|
125
127
|
:param data_descriptor_id: A data descriptor id
|
|
126
128
|
:type data_descriptor_id: str
|
|
127
|
-
:
|
|
128
|
-
|
|
129
|
+
:param selected_term_fields: A list of term fields to select or `None`. If `None`, all the \
|
|
130
|
+
fields of the terms are returned.
|
|
131
|
+
:type selected_term_fields: Iterable[str]|None
|
|
132
|
+
:returns: a list of term instances. Returns an empty list if no matches are found.
|
|
133
|
+
:rtype: list[DataDescriptor]
|
|
129
134
|
"""
|
|
130
135
|
with get_universe_session() as session:
|
|
131
136
|
data_descriptors = _find_data_descriptors_in_universe(data_descriptor_id,
|
|
@@ -133,7 +138,7 @@ def get_all_terms_in_data_descriptor(data_descriptor_id: str) \
|
|
|
133
138
|
None)
|
|
134
139
|
if data_descriptors:
|
|
135
140
|
data_descriptor = data_descriptors[0]
|
|
136
|
-
result = _get_all_terms_in_data_descriptor(data_descriptor)
|
|
141
|
+
result = _get_all_terms_in_data_descriptor(data_descriptor, selected_term_fields)
|
|
137
142
|
else:
|
|
138
143
|
result = list()
|
|
139
144
|
return result
|
|
@@ -173,8 +178,8 @@ def find_data_descriptors_in_universe(data_descriptor_id: str,
|
|
|
173
178
|
return result
|
|
174
179
|
|
|
175
180
|
|
|
176
|
-
def _get_all_data_descriptors_in_universe(session: Session) -> Sequence[
|
|
177
|
-
statement = select(
|
|
181
|
+
def _get_all_data_descriptors_in_universe(session: Session) -> Sequence[UDataDescriptor]:
|
|
182
|
+
statement = select(UDataDescriptor)
|
|
178
183
|
data_descriptors = session.exec(statement)
|
|
179
184
|
result = data_descriptors.all()
|
|
180
185
|
return result
|
|
@@ -195,23 +200,28 @@ def get_all_data_descriptors_in_universe() -> list[str]:
|
|
|
195
200
|
return result
|
|
196
201
|
|
|
197
202
|
|
|
198
|
-
def get_all_terms_in_universe() -> list[
|
|
203
|
+
def get_all_terms_in_universe(selected_term_fields: Iterable[str]|None = None) -> list[DataDescriptor]:
|
|
199
204
|
"""
|
|
200
205
|
Gets all the terms of the universe.
|
|
201
206
|
Terms are unique within a data descriptor but may have some synonyms in the universe.
|
|
202
207
|
|
|
203
|
-
:
|
|
204
|
-
|
|
208
|
+
:param selected_term_fields: A list of term fields to select or `None`. If `None`, all the \
|
|
209
|
+
fields of the terms are returned.
|
|
210
|
+
:type selected_term_fields: Iterable[str]|None
|
|
211
|
+
:returns: A list of term instances.
|
|
212
|
+
:rtype: list[DataDescriptor]
|
|
205
213
|
"""
|
|
206
214
|
result = list()
|
|
207
215
|
with get_universe_session() as session:
|
|
208
216
|
data_descriptors = _get_all_data_descriptors_in_universe(session)
|
|
209
217
|
for data_descriptor in data_descriptors:
|
|
210
218
|
# Term may have some synonyms within the whole universe.
|
|
211
|
-
terms = _get_all_terms_in_data_descriptor(data_descriptor)
|
|
219
|
+
terms = _get_all_terms_in_data_descriptor(data_descriptor, selected_term_fields)
|
|
212
220
|
result.extend(terms)
|
|
213
221
|
return result
|
|
214
222
|
|
|
215
223
|
|
|
216
224
|
if __name__ == "__main__":
|
|
217
|
-
|
|
225
|
+
settings = SearchSettings()
|
|
226
|
+
settings.selected_term_fields = ('id',)
|
|
227
|
+
print(find_terms_in_data_descriptor('institution', 'ipsl', settings))
|
esgvoc/apps/__init__.py
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
|
|
2
|
-
from esgvoc.apps.drs.validator import DrsValidator
|
|
3
|
-
from esgvoc.apps.drs.report import DrsValidationReport
|
|
4
2
|
from esgvoc.apps.drs.generator import DrsGenerator
|
|
5
|
-
from esgvoc.apps.drs.report import
|
|
3
|
+
from esgvoc.apps.drs.report import DrsGenerationReport, DrsValidationReport
|
|
4
|
+
from esgvoc.apps.drs.validator import DrsValidator
|
|
6
5
|
|
|
7
|
-
__all__ = ["DrsValidator", "DrsValidationReport", "DrsGenerator", "
|
|
6
|
+
__all__ = ["DrsValidator", "DrsValidationReport", "DrsGenerator", "DrsGenerationReport"]
|