eccodes 2.40.0__tar.gz → 2.41.0__tar.gz
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.
- {eccodes-2.40.0 → eccodes-2.41.0}/CHANGELOG.rst +13 -0
- {eccodes-2.40.0 → eccodes-2.41.0}/PKG-INFO +16 -2
- {eccodes-2.40.0 → eccodes-2.41.0}/ci/requirements-docs.txt +1 -1
- {eccodes-2.40.0 → eccodes-2.41.0}/eccodes/eccodes.py +2 -0
- {eccodes-2.40.0 → eccodes-2.41.0}/eccodes/highlevel/__init__.py +1 -1
- {eccodes-2.40.0 → eccodes-2.41.0}/eccodes/highlevel/message.py +19 -1
- {eccodes-2.40.0 → eccodes-2.41.0}/eccodes/highlevel/reader.py +21 -11
- {eccodes-2.40.0 → eccodes-2.41.0}/eccodes.egg-info/PKG-INFO +16 -2
- {eccodes-2.40.0 → eccodes-2.41.0}/gribapi/__init__.py +2 -2
- {eccodes-2.40.0 → eccodes-2.41.0}/gribapi/bindings.py +1 -1
- {eccodes-2.40.0 → eccodes-2.41.0}/gribapi/grib_api.h +1 -0
- {eccodes-2.40.0 → eccodes-2.41.0}/gribapi/gribapi.py +15 -0
- {eccodes-2.40.0 → eccodes-2.41.0}/tests/test_eccodes.py +8 -0
- {eccodes-2.40.0 → eccodes-2.41.0}/tests/test_highlevel.py +6 -1
- {eccodes-2.40.0 → eccodes-2.41.0}/.dockerignore +0 -0
- {eccodes-2.40.0 → eccodes-2.41.0}/CONTRIBUTING.rst +0 -0
- {eccodes-2.40.0 → eccodes-2.41.0}/Dockerfile +0 -0
- {eccodes-2.40.0 → eccodes-2.41.0}/LICENSE +0 -0
- {eccodes-2.40.0 → eccodes-2.41.0}/MANIFEST.in +0 -0
- {eccodes-2.40.0 → eccodes-2.41.0}/Makefile +0 -0
- {eccodes-2.40.0 → eccodes-2.41.0}/README.rst +0 -0
- {eccodes-2.40.0 → eccodes-2.41.0}/builder.py +0 -0
- {eccodes-2.40.0 → eccodes-2.41.0}/ci/requirements-dev.txt +0 -0
- {eccodes-2.40.0 → eccodes-2.41.0}/ci/requirements-docs.in +0 -0
- {eccodes-2.40.0 → eccodes-2.41.0}/ci/requirements-tests.in +0 -0
- {eccodes-2.40.0 → eccodes-2.41.0}/ci/requirements-tests.txt +0 -0
- {eccodes-2.40.0 → eccodes-2.41.0}/docs/_static/.gitkeep +0 -0
- {eccodes-2.40.0 → eccodes-2.41.0}/docs/conf.py +0 -0
- {eccodes-2.40.0 → eccodes-2.41.0}/docs/index.rst +0 -0
- {eccodes-2.40.0 → eccodes-2.41.0}/eccodes/__init__.py +0 -0
- {eccodes-2.40.0 → eccodes-2.41.0}/eccodes/__main__.py +0 -0
- {eccodes-2.40.0 → eccodes-2.41.0}/eccodes.egg-info/SOURCES.txt +0 -0
- {eccodes-2.40.0 → eccodes-2.41.0}/eccodes.egg-info/dependency_links.txt +0 -0
- {eccodes-2.40.0 → eccodes-2.41.0}/eccodes.egg-info/requires.txt +0 -0
- {eccodes-2.40.0 → eccodes-2.41.0}/eccodes.egg-info/top_level.txt +0 -0
- {eccodes-2.40.0 → eccodes-2.41.0}/eccodes.egg-info/zip-safe +0 -0
- {eccodes-2.40.0 → eccodes-2.41.0}/gribapi/eccodes.h +0 -0
- {eccodes-2.40.0 → eccodes-2.41.0}/gribapi/errors.py +0 -0
- {eccodes-2.40.0 → eccodes-2.41.0}/setup.cfg +0 -0
- {eccodes-2.40.0 → eccodes-2.41.0}/setup.py +0 -0
- {eccodes-2.40.0 → eccodes-2.41.0}/tests/sample-data/era5-levels-members.grib +0 -0
- {eccodes-2.40.0 → eccodes-2.41.0}/tests/sample-data/tiggelam_cnmc_sfc.grib2 +0 -0
- {eccodes-2.40.0 → eccodes-2.41.0}/tests/test_20_main.py +0 -0
- {eccodes-2.40.0 → eccodes-2.41.0}/tests/test_20_messages.py +0 -0
- {eccodes-2.40.0 → eccodes-2.41.0}/tox.ini +0 -0
|
@@ -2,6 +2,19 @@
|
|
|
2
2
|
Changelog for eccodes-python
|
|
3
3
|
============================
|
|
4
4
|
|
|
5
|
+
2.41.0 (2025-04-10)
|
|
6
|
+
--------------------
|
|
7
|
+
|
|
8
|
+
- ECC-2034: GRIB encoding: Data quality checks via the API
|
|
9
|
+
- GitHub pull request #124: Add basic BUFR support (high-level interface)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
2.40.1 (2025-03-17)
|
|
13
|
+
--------------------
|
|
14
|
+
|
|
15
|
+
- Update version to be the same as the ecCodes library
|
|
16
|
+
|
|
17
|
+
|
|
5
18
|
2.40.0 (2025-02-12)
|
|
6
19
|
--------------------
|
|
7
20
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: eccodes
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.41.0
|
|
4
4
|
Summary: Python interface to the ecCodes GRIB and BUFR decoder/encoder
|
|
5
5
|
Home-page: https://github.com/ecmwf/eccodes-python
|
|
6
6
|
Author: European Centre for Medium-Range Weather Forecasts (ECMWF)
|
|
@@ -31,6 +31,7 @@ Dynamic: description
|
|
|
31
31
|
Dynamic: home-page
|
|
32
32
|
Dynamic: keywords
|
|
33
33
|
Dynamic: license
|
|
34
|
+
Dynamic: license-file
|
|
34
35
|
Dynamic: requires-dist
|
|
35
36
|
Dynamic: summary
|
|
36
37
|
|
|
@@ -210,6 +211,19 @@ does it submit to any jurisdiction.
|
|
|
210
211
|
Changelog for eccodes-python
|
|
211
212
|
============================
|
|
212
213
|
|
|
214
|
+
2.41.0 (2025-04-10)
|
|
215
|
+
--------------------
|
|
216
|
+
|
|
217
|
+
- ECC-2034: GRIB encoding: Data quality checks via the API
|
|
218
|
+
- GitHub pull request #124: Add basic BUFR support (high-level interface)
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
2.40.1 (2025-03-17)
|
|
222
|
+
--------------------
|
|
223
|
+
|
|
224
|
+
- Update version to be the same as the ecCodes library
|
|
225
|
+
|
|
226
|
+
|
|
213
227
|
2.40.0 (2025-02-12)
|
|
214
228
|
--------------------
|
|
215
229
|
|
|
@@ -132,6 +132,7 @@ from gribapi import grib_no_fail_on_wrong_length as codes_no_fail_on_wrong_lengt
|
|
|
132
132
|
from gribapi import grib_release as codes_release
|
|
133
133
|
from gribapi import grib_set as codes_set
|
|
134
134
|
from gribapi import grib_set_array as codes_set_array
|
|
135
|
+
from gribapi import grib_set_data_quality_checks as codes_set_data_quality_checks
|
|
135
136
|
from gribapi import grib_set_debug as codes_set_debug
|
|
136
137
|
from gribapi import grib_set_definitions_path as codes_set_definitions_path
|
|
137
138
|
from gribapi import grib_set_double as codes_set_double
|
|
@@ -348,6 +349,7 @@ __all__ = [
|
|
|
348
349
|
"codes_samples_path",
|
|
349
350
|
"codes_dump",
|
|
350
351
|
"codes_set_array",
|
|
352
|
+
"codes_set_data_quality_checks",
|
|
351
353
|
"codes_set_debug",
|
|
352
354
|
"codes_set_definitions_path",
|
|
353
355
|
"codes_set_double_array",
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
from .message import GRIBMessage, Message # noqa
|
|
1
|
+
from .message import BUFRMessage, GRIBMessage, Message # noqa
|
|
2
2
|
from .reader import FileReader, MemoryReader, StreamReader # noqa
|
|
@@ -33,7 +33,7 @@ class Message:
|
|
|
33
33
|
|
|
34
34
|
def copy(self):
|
|
35
35
|
"""Create a copy of the current message"""
|
|
36
|
-
return
|
|
36
|
+
return self.__class__(eccodes.codes_clone(self._handle))
|
|
37
37
|
|
|
38
38
|
def __copy__(self):
|
|
39
39
|
return self.copy()
|
|
@@ -242,6 +242,24 @@ class Message:
|
|
|
242
242
|
return eccodes.codes_get_message(self._handle)
|
|
243
243
|
|
|
244
244
|
|
|
245
|
+
class BUFRMessage(Message):
|
|
246
|
+
def __init__(self, handle):
|
|
247
|
+
super().__init__(handle)
|
|
248
|
+
|
|
249
|
+
def pack(self):
|
|
250
|
+
"""Pack the underlying data"""
|
|
251
|
+
self.set("pack", 1, check_values=False)
|
|
252
|
+
|
|
253
|
+
def unpack(self):
|
|
254
|
+
"""Unpack the underlying data"""
|
|
255
|
+
self.set("unpack", 1, check_values=False)
|
|
256
|
+
|
|
257
|
+
@classmethod
|
|
258
|
+
def from_samples(cls, name):
|
|
259
|
+
"""Create a message from a sample"""
|
|
260
|
+
return cls(eccodes.codes_bufr_new_from_samples(name))
|
|
261
|
+
|
|
262
|
+
|
|
245
263
|
class GRIBMessage(Message):
|
|
246
264
|
def __init__(self, handle):
|
|
247
265
|
super().__init__(handle)
|
|
@@ -2,12 +2,22 @@ import eccodes
|
|
|
2
2
|
import gribapi
|
|
3
3
|
from gribapi import ffi
|
|
4
4
|
|
|
5
|
-
from .message import GRIBMessage
|
|
5
|
+
from .message import BUFRMessage, GRIBMessage
|
|
6
|
+
|
|
7
|
+
_MSG_CLASSES = {
|
|
8
|
+
eccodes.CODES_PRODUCT_GRIB: GRIBMessage,
|
|
9
|
+
eccodes.CODES_PRODUCT_BUFR: BUFRMessage,
|
|
10
|
+
}
|
|
6
11
|
|
|
7
12
|
|
|
8
13
|
class ReaderBase:
|
|
9
|
-
def __init__(self):
|
|
14
|
+
def __init__(self, kind=eccodes.CODES_PRODUCT_GRIB):
|
|
10
15
|
self._peeked = None
|
|
16
|
+
self._kind = kind
|
|
17
|
+
cls = _MSG_CLASSES.get(kind)
|
|
18
|
+
if cls is None:
|
|
19
|
+
raise ValueError(f"Unsupported product type {kind}")
|
|
20
|
+
self._msg_class = cls
|
|
11
21
|
|
|
12
22
|
def __iter__(self):
|
|
13
23
|
return self
|
|
@@ -20,7 +30,7 @@ class ReaderBase:
|
|
|
20
30
|
handle = self._next_handle()
|
|
21
31
|
if handle is None:
|
|
22
32
|
raise StopIteration
|
|
23
|
-
return
|
|
33
|
+
return self._msg_class(handle)
|
|
24
34
|
|
|
25
35
|
def _next_handle(self):
|
|
26
36
|
raise NotImplementedError
|
|
@@ -36,19 +46,19 @@ class ReaderBase:
|
|
|
36
46
|
if self._peeked is None:
|
|
37
47
|
handle = self._next_handle()
|
|
38
48
|
if handle is not None:
|
|
39
|
-
self._peeked =
|
|
49
|
+
self._peeked = self._msg_class(handle)
|
|
40
50
|
return self._peeked
|
|
41
51
|
|
|
42
52
|
|
|
43
53
|
class FileReader(ReaderBase):
|
|
44
54
|
"""Read messages from a file"""
|
|
45
55
|
|
|
46
|
-
def __init__(self, path):
|
|
47
|
-
super().__init__()
|
|
56
|
+
def __init__(self, path, kind=eccodes.CODES_PRODUCT_GRIB):
|
|
57
|
+
super().__init__(kind=kind)
|
|
48
58
|
self.file = open(path, "rb")
|
|
49
59
|
|
|
50
60
|
def _next_handle(self):
|
|
51
|
-
return eccodes.codes_new_from_file(self.file,
|
|
61
|
+
return eccodes.codes_new_from_file(self.file, self._kind)
|
|
52
62
|
|
|
53
63
|
def __enter__(self):
|
|
54
64
|
self.file.__enter__()
|
|
@@ -61,8 +71,8 @@ class FileReader(ReaderBase):
|
|
|
61
71
|
class MemoryReader(ReaderBase):
|
|
62
72
|
"""Read messages from memory"""
|
|
63
73
|
|
|
64
|
-
def __init__(self, buf):
|
|
65
|
-
super().__init__()
|
|
74
|
+
def __init__(self, buf, kind=eccodes.CODES_PRODUCT_GRIB):
|
|
75
|
+
super().__init__(kind=kind)
|
|
66
76
|
self.buf = buf
|
|
67
77
|
|
|
68
78
|
def _next_handle(self):
|
|
@@ -128,14 +138,14 @@ def codes_new_from_stream(stream):
|
|
|
128
138
|
class StreamReader(ReaderBase):
|
|
129
139
|
"""Read messages from a stream (an object with a ``read`` method)"""
|
|
130
140
|
|
|
131
|
-
def __init__(self, stream):
|
|
141
|
+
def __init__(self, stream, kind=eccodes.CODES_PRODUCT_GRIB):
|
|
132
142
|
if cstd is None:
|
|
133
143
|
raise OSError("This feature is not supported on Windows")
|
|
134
144
|
if pyread_callback is None:
|
|
135
145
|
raise OSError(
|
|
136
146
|
"This feature cannot be used because the OS prevents allocating write+execute memory"
|
|
137
147
|
)
|
|
138
|
-
super().__init__()
|
|
148
|
+
super().__init__(kind=kind)
|
|
139
149
|
self.stream = stream
|
|
140
150
|
|
|
141
151
|
def _next_handle(self):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: eccodes
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.41.0
|
|
4
4
|
Summary: Python interface to the ecCodes GRIB and BUFR decoder/encoder
|
|
5
5
|
Home-page: https://github.com/ecmwf/eccodes-python
|
|
6
6
|
Author: European Centre for Medium-Range Weather Forecasts (ECMWF)
|
|
@@ -31,6 +31,7 @@ Dynamic: description
|
|
|
31
31
|
Dynamic: home-page
|
|
32
32
|
Dynamic: keywords
|
|
33
33
|
Dynamic: license
|
|
34
|
+
Dynamic: license-file
|
|
34
35
|
Dynamic: requires-dist
|
|
35
36
|
Dynamic: summary
|
|
36
37
|
|
|
@@ -210,6 +211,19 @@ does it submit to any jurisdiction.
|
|
|
210
211
|
Changelog for eccodes-python
|
|
211
212
|
============================
|
|
212
213
|
|
|
214
|
+
2.41.0 (2025-04-10)
|
|
215
|
+
--------------------
|
|
216
|
+
|
|
217
|
+
- ECC-2034: GRIB encoding: Data quality checks via the API
|
|
218
|
+
- GitHub pull request #124: Add basic BUFR support (high-level interface)
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
2.40.1 (2025-03-17)
|
|
222
|
+
--------------------
|
|
223
|
+
|
|
224
|
+
- Update version to be the same as the ecCodes library
|
|
225
|
+
|
|
226
|
+
|
|
213
227
|
2.40.0 (2025-02-12)
|
|
214
228
|
--------------------
|
|
215
229
|
|
|
@@ -14,8 +14,8 @@ from .gribapi import * # noqa
|
|
|
14
14
|
from .gribapi import __version__, lib
|
|
15
15
|
|
|
16
16
|
# The minimum recommended version for the ecCodes package
|
|
17
|
-
min_recommended_version_str = "2.
|
|
18
|
-
min_recommended_version_int =
|
|
17
|
+
min_recommended_version_str = "2.39.0"
|
|
18
|
+
min_recommended_version_int = 23900
|
|
19
19
|
|
|
20
20
|
if lib.grib_get_api_version() < min_recommended_version_int:
|
|
21
21
|
import warnings
|
|
@@ -133,6 +133,7 @@ void grib_gribex_mode_on(grib_context* c);
|
|
|
133
133
|
void grib_gribex_mode_off(grib_context* c);
|
|
134
134
|
void grib_context_set_definitions_path(grib_context* c, const char* path);
|
|
135
135
|
void grib_context_set_debug(grib_context* c, int mode);
|
|
136
|
+
void grib_context_set_data_quality_checks(grib_context* c, int val);
|
|
136
137
|
void grib_context_set_samples_path(grib_context* c, const char* path);
|
|
137
138
|
void grib_multi_support_on(grib_context* c);
|
|
138
139
|
void grib_multi_support_off(grib_context* c);
|
|
@@ -2438,6 +2438,21 @@ def grib_set_debug(dmode):
|
|
|
2438
2438
|
lib.grib_context_set_debug(context, dmode)
|
|
2439
2439
|
|
|
2440
2440
|
|
|
2441
|
+
@require(val=int)
|
|
2442
|
+
def grib_set_data_quality_checks(val):
|
|
2443
|
+
"""
|
|
2444
|
+
@brief Enable/Disable GRIB data quality checks
|
|
2445
|
+
|
|
2446
|
+
@param val 0, 1 or 2
|
|
2447
|
+
0 -> disable data quality checks
|
|
2448
|
+
1 -> failure results in an error
|
|
2449
|
+
2 -> failure results in a warning
|
|
2450
|
+
"""
|
|
2451
|
+
assert val == 0 or val == 1 or val == 2
|
|
2452
|
+
context = lib.grib_context_get_default()
|
|
2453
|
+
lib.grib_context_set_data_quality_checks(context, val)
|
|
2454
|
+
|
|
2455
|
+
|
|
2441
2456
|
@require(defs_path=str)
|
|
2442
2457
|
def grib_set_definitions_path(defs_path):
|
|
2443
2458
|
"""
|
|
@@ -55,6 +55,14 @@ def test_codes_set_debug():
|
|
|
55
55
|
eccodes.codes_set_debug(0)
|
|
56
56
|
|
|
57
57
|
|
|
58
|
+
def test_codes_set_data_quality_checks():
|
|
59
|
+
if eccodes.codes_get_api_version(int) < 24100:
|
|
60
|
+
pytest.skip("ecCodes version too old")
|
|
61
|
+
eccodes.codes_set_data_quality_checks(2)
|
|
62
|
+
eccodes.codes_set_data_quality_checks(1)
|
|
63
|
+
eccodes.codes_set_data_quality_checks(0)
|
|
64
|
+
|
|
65
|
+
|
|
58
66
|
def test_codes_set_definitions_path():
|
|
59
67
|
eccodes.codes_set_definitions_path(eccodes.codes_definition_path())
|
|
60
68
|
|
|
@@ -166,8 +166,13 @@ def test_write_message(tmp_path):
|
|
|
166
166
|
assert np.all(message1.data == message2.data)
|
|
167
167
|
|
|
168
168
|
|
|
169
|
-
def
|
|
169
|
+
def test_grib_message_from_samples():
|
|
170
170
|
message = eccodes.GRIBMessage.from_samples("regular_ll_sfc_grib2")
|
|
171
171
|
assert message["edition"] == 2
|
|
172
172
|
assert message["gridType"] == "regular_ll"
|
|
173
173
|
assert message["levtype"] == "sfc"
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
def test_bufr_message_from_samples():
|
|
177
|
+
message = eccodes.BUFRMessage.from_samples("BUFR4")
|
|
178
|
+
assert message["edition"] == 4
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|