esgvoc 0.4.0__py3-none-any.whl → 1.0.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 +1 -1
- esgvoc/api/data_descriptors/__init__.py +50 -28
- esgvoc/api/data_descriptors/activity.py +3 -3
- esgvoc/api/data_descriptors/area_label.py +16 -1
- esgvoc/api/data_descriptors/branded_suffix.py +20 -0
- esgvoc/api/data_descriptors/branded_variable.py +12 -0
- esgvoc/api/data_descriptors/consortium.py +14 -13
- esgvoc/api/data_descriptors/contact.py +5 -0
- esgvoc/api/data_descriptors/conventions.py +6 -0
- esgvoc/api/data_descriptors/creation_date.py +5 -0
- esgvoc/api/data_descriptors/data_descriptor.py +14 -9
- esgvoc/api/data_descriptors/data_specs_version.py +5 -0
- esgvoc/api/data_descriptors/date.py +1 -1
- esgvoc/api/data_descriptors/directory_date.py +1 -1
- esgvoc/api/data_descriptors/experiment.py +13 -11
- esgvoc/api/data_descriptors/forcing_index.py +1 -1
- esgvoc/api/data_descriptors/frequency.py +3 -3
- esgvoc/api/data_descriptors/further_info_url.py +5 -0
- esgvoc/api/data_descriptors/grid_label.py +2 -2
- esgvoc/api/data_descriptors/horizontal_label.py +15 -1
- esgvoc/api/data_descriptors/initialisation_index.py +1 -1
- esgvoc/api/data_descriptors/institution.py +8 -5
- esgvoc/api/data_descriptors/known_branded_variable.py +23 -0
- esgvoc/api/data_descriptors/license.py +3 -3
- esgvoc/api/data_descriptors/mip_era.py +1 -1
- esgvoc/api/data_descriptors/model_component.py +1 -1
- esgvoc/api/data_descriptors/obs_type.py +5 -0
- esgvoc/api/data_descriptors/organisation.py +1 -1
- esgvoc/api/data_descriptors/physic_index.py +1 -1
- esgvoc/api/data_descriptors/product.py +2 -2
- esgvoc/api/data_descriptors/publication_status.py +5 -0
- esgvoc/api/data_descriptors/realisation_index.py +1 -1
- esgvoc/api/data_descriptors/realm.py +1 -1
- esgvoc/api/data_descriptors/region.py +5 -0
- esgvoc/api/data_descriptors/resolution.py +3 -3
- esgvoc/api/data_descriptors/source.py +9 -5
- esgvoc/api/data_descriptors/source_type.py +1 -1
- esgvoc/api/data_descriptors/table.py +3 -2
- esgvoc/api/data_descriptors/temporal_label.py +15 -1
- esgvoc/api/data_descriptors/time_range.py +4 -3
- esgvoc/api/data_descriptors/title.py +5 -0
- esgvoc/api/data_descriptors/tracking_id.py +5 -0
- esgvoc/api/data_descriptors/variable.py +25 -12
- esgvoc/api/data_descriptors/variant_label.py +3 -3
- esgvoc/api/data_descriptors/vertical_label.py +14 -0
- esgvoc/api/project_specs.py +117 -2
- esgvoc/api/projects.py +242 -279
- esgvoc/api/search.py +30 -3
- esgvoc/api/universe.py +42 -27
- esgvoc/apps/jsg/cmip6_template.json +74 -0
- esgvoc/apps/jsg/cmip6plus_template.json +74 -0
- esgvoc/apps/jsg/json_schema_generator.py +185 -0
- esgvoc/cli/config.py +500 -0
- esgvoc/cli/find.py +138 -0
- esgvoc/cli/get.py +43 -38
- esgvoc/cli/main.py +10 -3
- esgvoc/cli/status.py +27 -18
- esgvoc/cli/valid.py +10 -15
- esgvoc/core/db/models/project.py +11 -11
- esgvoc/core/db/models/universe.py +3 -3
- esgvoc/core/db/project_ingestion.py +40 -40
- esgvoc/core/db/universe_ingestion.py +36 -33
- esgvoc/core/logging_handler.py +24 -2
- esgvoc/core/repo_fetcher.py +61 -59
- esgvoc/core/service/data_merger.py +47 -34
- esgvoc/core/service/state.py +107 -83
- {esgvoc-0.4.0.dist-info → esgvoc-1.0.0.dist-info}/METADATA +7 -20
- esgvoc-1.0.0.dist-info/RECORD +95 -0
- esgvoc/core/logging.conf +0 -21
- esgvoc-0.4.0.dist-info/RECORD +0 -80
- {esgvoc-0.4.0.dist-info → esgvoc-1.0.0.dist-info}/WHEEL +0 -0
- {esgvoc-0.4.0.dist-info → esgvoc-1.0.0.dist-info}/entry_points.txt +0 -0
- {esgvoc-0.4.0.dist-info → esgvoc-1.0.0.dist-info}/licenses/LICENSE.txt +0 -0
|
@@ -2,5 +2,19 @@ from esgvoc.api.data_descriptors.data_descriptor import PlainTermDataDescriptor
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
class TemporalLabel(PlainTermDataDescriptor):
|
|
5
|
+
"""
|
|
6
|
+
Temporal sampling label.
|
|
7
|
+
|
|
8
|
+
This label provides information about the temporal sampling of a given dataset.
|
|
9
|
+
For a list of allowed values, see
|
|
10
|
+
[TODO think about how to cross-reference to somewhere where people can look up the allowed values,
|
|
11
|
+
e.g. some summary of the values in https://github.com/WCRP-CMIP/WCRP-universe/tree/esgvoc/temporal_label.]
|
|
12
|
+
|
|
13
|
+
This label is used as the temporal component of a branded variable's suffix
|
|
14
|
+
(see :py:class:`BrandedSuffix`).
|
|
15
|
+
By definition, the temporal label must be consistent with the branded suffix.
|
|
16
|
+
Temporal labels must not contain the separator used when constructing the branded suffix.
|
|
17
|
+
"""
|
|
18
|
+
|
|
5
19
|
description: str
|
|
6
|
-
label: str
|
|
20
|
+
label: str
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
from esgvoc.api.data_descriptors.data_descriptor import
|
|
1
|
+
from esgvoc.api.data_descriptors.data_descriptor import PatternTermDataDescriptor
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
|
|
4
|
+
class TimeRange(PatternTermDataDescriptor):
|
|
5
|
+
description: str
|
|
@@ -1,19 +1,32 @@
|
|
|
1
1
|
from pydantic import Field
|
|
2
|
+
|
|
2
3
|
from esgvoc.api.data_descriptors.data_descriptor import PlainTermDataDescriptor
|
|
3
4
|
|
|
4
5
|
|
|
5
6
|
class Variable(PlainTermDataDescriptor):
|
|
6
7
|
"""
|
|
7
|
-
A
|
|
8
|
-
|
|
9
|
-
biological properties of the Earth system
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
8
|
+
A climate-related quantity or measurement.
|
|
9
|
+
|
|
10
|
+
These quantities represent key physical, chemical or biological properties of the Earth system
|
|
11
|
+
and can be the result of direct observation of the climate system or simulations.
|
|
12
|
+
Variables cover a range of aspects of the climate system,
|
|
13
|
+
such as temperature, precipitation, sea level, radiation, or atmospheric composition.
|
|
14
|
+
Some examples of variables that have been used in CMIP:
|
|
15
|
+
|
|
16
|
+
- *tas*: Near-surface air temperature (often measured at 2 meters above the surface)
|
|
17
|
+
- *pr*: Precipitation
|
|
18
|
+
- *psl*: Sea-level pressure
|
|
19
|
+
- *zg*: Geopotential height
|
|
20
|
+
- *rlut*: Top-of-atmosphere longwave radiation
|
|
21
|
+
- *siconc*: Sea-ice concentration
|
|
22
|
+
- *co2*: Atmospheric CO2 concentration
|
|
23
|
+
|
|
24
|
+
Since CMIP7, the concept of a variable has been augmented with the idea of 'branding',
|
|
25
|
+
leading to the idea of a 'branded variable'.
|
|
26
|
+
For details, see :py:class:`BrandedVariable`.
|
|
15
27
|
"""
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
28
|
+
|
|
29
|
+
validation_method: str = Field(default="list")
|
|
30
|
+
long_name: str
|
|
31
|
+
standard_name: str | None
|
|
32
|
+
units: str | None
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
from esgvoc.api.data_descriptors.data_descriptor import
|
|
1
|
+
from esgvoc.api.data_descriptors.data_descriptor import PatternTermDataDescriptor
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
class VariantLabel(
|
|
5
|
-
description: str
|
|
4
|
+
class VariantLabel(PatternTermDataDescriptor):
|
|
5
|
+
description: str
|
|
@@ -2,4 +2,18 @@ from esgvoc.api.data_descriptors.data_descriptor import PatternTermDataDescripto
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
class VerticalLabel(PatternTermDataDescriptor):
|
|
5
|
+
"""
|
|
6
|
+
Vertical label.
|
|
7
|
+
|
|
8
|
+
This label provides information about the vertical sampling of a given dataset.
|
|
9
|
+
For a list of allowed values, see
|
|
10
|
+
[TODO think about how to cross-reference to somewhere where people can look up the allowed values,
|
|
11
|
+
e.g. some summary of the values in https://github.com/WCRP-CMIP/WCRP-universe/tree/esgvoc/vertical_label.]
|
|
12
|
+
|
|
13
|
+
This label is used as the vertical component of a branded variable's suffix
|
|
14
|
+
(see :py:class:`BrandedSuffix`).
|
|
15
|
+
By definition, the vertical label must be consistent with the branded suffix.
|
|
16
|
+
Vertical labels must not contain the separator used when constructing the branded suffix.
|
|
17
|
+
"""
|
|
18
|
+
|
|
5
19
|
pass
|
esgvoc/api/project_specs.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from enum import Enum
|
|
2
|
-
from typing import Annotated, Literal
|
|
2
|
+
from typing import Annotated, Any, Literal, Optional, Protocol
|
|
3
3
|
|
|
4
4
|
from pydantic import BaseModel, ConfigDict, Field
|
|
5
5
|
|
|
@@ -8,6 +8,7 @@ class DrsType(str, Enum):
|
|
|
8
8
|
"""
|
|
9
9
|
The types of DRS specification (directory, file name and dataset id).
|
|
10
10
|
"""
|
|
11
|
+
|
|
11
12
|
DIRECTORY = "directory"
|
|
12
13
|
"""The DRS directory specification type."""
|
|
13
14
|
FILE_NAME = "file_name"
|
|
@@ -20,6 +21,7 @@ class DrsPartKind(str, Enum):
|
|
|
20
21
|
"""
|
|
21
22
|
The kinds of DRS part (constant and collection).
|
|
22
23
|
"""
|
|
24
|
+
|
|
23
25
|
CONSTANT = "constant"
|
|
24
26
|
"""The constant part type."""
|
|
25
27
|
COLLECTION = "collection"
|
|
@@ -30,10 +32,12 @@ class DrsConstant(BaseModel):
|
|
|
30
32
|
"""
|
|
31
33
|
A constant part of a DRS specification (e.g., cmip5).
|
|
32
34
|
"""
|
|
35
|
+
|
|
33
36
|
value: str
|
|
34
37
|
"""The value of the a constant part."""
|
|
35
38
|
kind: Literal[DrsPartKind.CONSTANT] = DrsPartKind.CONSTANT
|
|
36
39
|
"""The DRS part kind."""
|
|
40
|
+
|
|
37
41
|
def __str__(self) -> str:
|
|
38
42
|
return self.value
|
|
39
43
|
|
|
@@ -42,12 +46,14 @@ class DrsCollection(BaseModel):
|
|
|
42
46
|
"""
|
|
43
47
|
A collection part of a DRS specification (e.g., institution_id for CMIP6).
|
|
44
48
|
"""
|
|
49
|
+
|
|
45
50
|
collection_id: str
|
|
46
51
|
"""The collection id."""
|
|
47
52
|
is_required: bool
|
|
48
53
|
"""Whether the collection is required for the DRS specification or not."""
|
|
49
54
|
kind: Literal[DrsPartKind.COLLECTION] = DrsPartKind.COLLECTION
|
|
50
55
|
"""The DRS part kind."""
|
|
56
|
+
|
|
51
57
|
def __str__(self) -> str:
|
|
52
58
|
return self.collection_id
|
|
53
59
|
|
|
@@ -60,6 +66,7 @@ class DrsSpecification(BaseModel):
|
|
|
60
66
|
"""
|
|
61
67
|
A DRS specification.
|
|
62
68
|
"""
|
|
69
|
+
|
|
63
70
|
type: DrsType
|
|
64
71
|
"""The type of the specification."""
|
|
65
72
|
separator: str
|
|
@@ -70,14 +77,122 @@ class DrsSpecification(BaseModel):
|
|
|
70
77
|
"""The parts of the DRS specification."""
|
|
71
78
|
|
|
72
79
|
|
|
80
|
+
class GlobalAttributeValueType(str, Enum):
|
|
81
|
+
"""
|
|
82
|
+
The types of global attribute values.
|
|
83
|
+
"""
|
|
84
|
+
|
|
85
|
+
STRING = "string"
|
|
86
|
+
"""String value type."""
|
|
87
|
+
INTEGER = "integer"
|
|
88
|
+
"""Integer value type."""
|
|
89
|
+
FLOAT = "float"
|
|
90
|
+
"""Float value type."""
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
class GlobalAttributeVisitor(Protocol):
|
|
94
|
+
"""
|
|
95
|
+
Specifications for a global attribute visitor.
|
|
96
|
+
"""
|
|
97
|
+
def visit_base_attribute(self,
|
|
98
|
+
attribute_name: str,
|
|
99
|
+
attribute: "GlobalAttributeSpecBase") -> Any:
|
|
100
|
+
"""Visit a base global attribute."""
|
|
101
|
+
pass
|
|
102
|
+
|
|
103
|
+
def visit_specific_attribute(self,
|
|
104
|
+
attribute_name: str,
|
|
105
|
+
attribute: "GlobalAttributeSpecSpecific") -> Any:
|
|
106
|
+
"""Visit a specific global attribute."""
|
|
107
|
+
pass
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
class GlobalAttributeSpecBase(BaseModel):
|
|
111
|
+
"""
|
|
112
|
+
Specification for a global attribute.
|
|
113
|
+
"""
|
|
114
|
+
|
|
115
|
+
source_collection: str
|
|
116
|
+
"""the source_collection to get the term from"""
|
|
117
|
+
value_type: GlobalAttributeValueType
|
|
118
|
+
"""The expected value type."""
|
|
119
|
+
|
|
120
|
+
def accept(self, attribute_name: str, visitor: GlobalAttributeVisitor) -> Any:
|
|
121
|
+
return visitor.visit_base_attribute(attribute_name, self)
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
class GlobalAttributeSpecSpecific(GlobalAttributeSpecBase):
|
|
125
|
+
"""
|
|
126
|
+
Specification for a global attribute.
|
|
127
|
+
with a specific key
|
|
128
|
+
"""
|
|
129
|
+
|
|
130
|
+
specific_key: str
|
|
131
|
+
"""If the validation is for the value of a specific key, for instance description or ui-label """
|
|
132
|
+
|
|
133
|
+
def accept(self, attribute_name: str, visitor: GlobalAttributeVisitor) -> Any:
|
|
134
|
+
"""
|
|
135
|
+
Accept a global attribute visitor.
|
|
136
|
+
|
|
137
|
+
:param attribute_name: The attribute name.
|
|
138
|
+
:param visitor: The global attribute visitor.
|
|
139
|
+
:type visitor: GlobalAttributeVisitor
|
|
140
|
+
:return: Depending on the visitor.
|
|
141
|
+
:rtype: Any
|
|
142
|
+
"""
|
|
143
|
+
return visitor.visit_specific_attribute(attribute_name, self)
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
GlobalAttributeSpec = GlobalAttributeSpecSpecific | GlobalAttributeSpecBase
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
class GlobalAttributeSpecs(BaseModel):
|
|
150
|
+
"""
|
|
151
|
+
Container for global attribute specifications.
|
|
152
|
+
"""
|
|
153
|
+
|
|
154
|
+
specs: dict[str, GlobalAttributeSpec] = Field(default_factory=dict)
|
|
155
|
+
"""The global attributes specifications dictionary."""
|
|
156
|
+
|
|
157
|
+
def __str__(self) -> str:
|
|
158
|
+
"""Return all keys when printing."""
|
|
159
|
+
return str(list(self.specs.keys()))
|
|
160
|
+
|
|
161
|
+
def __repr__(self) -> str:
|
|
162
|
+
"""Return all keys when using repr."""
|
|
163
|
+
return f"GlobalAttributeSpecs(keys={list(self.specs.keys())})"
|
|
164
|
+
|
|
165
|
+
# Dictionary-like access methods
|
|
166
|
+
def __getitem__(self, key: str) -> GlobalAttributeSpec:
|
|
167
|
+
return self.specs[key]
|
|
168
|
+
|
|
169
|
+
def __setitem__(self, key: str, value: GlobalAttributeSpec) -> None:
|
|
170
|
+
self.specs[key] = value
|
|
171
|
+
|
|
172
|
+
def __contains__(self, key: str) -> bool:
|
|
173
|
+
return key in self.specs
|
|
174
|
+
|
|
175
|
+
def keys(self):
|
|
176
|
+
return self.specs.keys()
|
|
177
|
+
|
|
178
|
+
def values(self):
|
|
179
|
+
return self.specs.values()
|
|
180
|
+
|
|
181
|
+
def items(self):
|
|
182
|
+
return self.specs.items()
|
|
183
|
+
|
|
184
|
+
|
|
73
185
|
class ProjectSpecs(BaseModel):
|
|
74
186
|
"""
|
|
75
187
|
A project specifications.
|
|
76
188
|
"""
|
|
189
|
+
|
|
77
190
|
project_id: str
|
|
78
191
|
"""The project id."""
|
|
79
192
|
description: str
|
|
80
193
|
"""The description of the project."""
|
|
81
194
|
drs_specs: list[DrsSpecification]
|
|
82
|
-
"""The DRS specifications of the project (directory, file name and dataset id."""
|
|
195
|
+
"""The DRS specifications of the project (directory, file name and dataset id)."""
|
|
196
|
+
global_attributes_specs: Optional[GlobalAttributeSpecs] = None
|
|
197
|
+
"""The global attributes specifications of the project."""
|
|
83
198
|
model_config = ConfigDict(extra="allow")
|