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.
Files changed (45) hide show
  1. {eccodes-2.40.0 → eccodes-2.41.0}/CHANGELOG.rst +13 -0
  2. {eccodes-2.40.0 → eccodes-2.41.0}/PKG-INFO +16 -2
  3. {eccodes-2.40.0 → eccodes-2.41.0}/ci/requirements-docs.txt +1 -1
  4. {eccodes-2.40.0 → eccodes-2.41.0}/eccodes/eccodes.py +2 -0
  5. {eccodes-2.40.0 → eccodes-2.41.0}/eccodes/highlevel/__init__.py +1 -1
  6. {eccodes-2.40.0 → eccodes-2.41.0}/eccodes/highlevel/message.py +19 -1
  7. {eccodes-2.40.0 → eccodes-2.41.0}/eccodes/highlevel/reader.py +21 -11
  8. {eccodes-2.40.0 → eccodes-2.41.0}/eccodes.egg-info/PKG-INFO +16 -2
  9. {eccodes-2.40.0 → eccodes-2.41.0}/gribapi/__init__.py +2 -2
  10. {eccodes-2.40.0 → eccodes-2.41.0}/gribapi/bindings.py +1 -1
  11. {eccodes-2.40.0 → eccodes-2.41.0}/gribapi/grib_api.h +1 -0
  12. {eccodes-2.40.0 → eccodes-2.41.0}/gribapi/gribapi.py +15 -0
  13. {eccodes-2.40.0 → eccodes-2.41.0}/tests/test_eccodes.py +8 -0
  14. {eccodes-2.40.0 → eccodes-2.41.0}/tests/test_highlevel.py +6 -1
  15. {eccodes-2.40.0 → eccodes-2.41.0}/.dockerignore +0 -0
  16. {eccodes-2.40.0 → eccodes-2.41.0}/CONTRIBUTING.rst +0 -0
  17. {eccodes-2.40.0 → eccodes-2.41.0}/Dockerfile +0 -0
  18. {eccodes-2.40.0 → eccodes-2.41.0}/LICENSE +0 -0
  19. {eccodes-2.40.0 → eccodes-2.41.0}/MANIFEST.in +0 -0
  20. {eccodes-2.40.0 → eccodes-2.41.0}/Makefile +0 -0
  21. {eccodes-2.40.0 → eccodes-2.41.0}/README.rst +0 -0
  22. {eccodes-2.40.0 → eccodes-2.41.0}/builder.py +0 -0
  23. {eccodes-2.40.0 → eccodes-2.41.0}/ci/requirements-dev.txt +0 -0
  24. {eccodes-2.40.0 → eccodes-2.41.0}/ci/requirements-docs.in +0 -0
  25. {eccodes-2.40.0 → eccodes-2.41.0}/ci/requirements-tests.in +0 -0
  26. {eccodes-2.40.0 → eccodes-2.41.0}/ci/requirements-tests.txt +0 -0
  27. {eccodes-2.40.0 → eccodes-2.41.0}/docs/_static/.gitkeep +0 -0
  28. {eccodes-2.40.0 → eccodes-2.41.0}/docs/conf.py +0 -0
  29. {eccodes-2.40.0 → eccodes-2.41.0}/docs/index.rst +0 -0
  30. {eccodes-2.40.0 → eccodes-2.41.0}/eccodes/__init__.py +0 -0
  31. {eccodes-2.40.0 → eccodes-2.41.0}/eccodes/__main__.py +0 -0
  32. {eccodes-2.40.0 → eccodes-2.41.0}/eccodes.egg-info/SOURCES.txt +0 -0
  33. {eccodes-2.40.0 → eccodes-2.41.0}/eccodes.egg-info/dependency_links.txt +0 -0
  34. {eccodes-2.40.0 → eccodes-2.41.0}/eccodes.egg-info/requires.txt +0 -0
  35. {eccodes-2.40.0 → eccodes-2.41.0}/eccodes.egg-info/top_level.txt +0 -0
  36. {eccodes-2.40.0 → eccodes-2.41.0}/eccodes.egg-info/zip-safe +0 -0
  37. {eccodes-2.40.0 → eccodes-2.41.0}/gribapi/eccodes.h +0 -0
  38. {eccodes-2.40.0 → eccodes-2.41.0}/gribapi/errors.py +0 -0
  39. {eccodes-2.40.0 → eccodes-2.41.0}/setup.cfg +0 -0
  40. {eccodes-2.40.0 → eccodes-2.41.0}/setup.py +0 -0
  41. {eccodes-2.40.0 → eccodes-2.41.0}/tests/sample-data/era5-levels-members.grib +0 -0
  42. {eccodes-2.40.0 → eccodes-2.41.0}/tests/sample-data/tiggelam_cnmc_sfc.grib2 +0 -0
  43. {eccodes-2.40.0 → eccodes-2.41.0}/tests/test_20_main.py +0 -0
  44. {eccodes-2.40.0 → eccodes-2.41.0}/tests/test_20_messages.py +0 -0
  45. {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.2
1
+ Metadata-Version: 2.4
2
2
  Name: eccodes
3
- Version: 2.40.0
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
 
@@ -18,7 +18,7 @@ idna==3.7
18
18
  # via requests
19
19
  imagesize==1.1.0
20
20
  # via sphinx
21
- jinja2==3.1.5
21
+ jinja2==3.1.6
22
22
  # via sphinx
23
23
  markupsafe==2.1.5
24
24
  # via jinja2
@@ -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 Message(eccodes.codes_clone(self._handle))
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 GRIBMessage(handle)
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 = GRIBMessage(handle)
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, eccodes.CODES_PRODUCT_GRIB)
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.2
1
+ Metadata-Version: 2.4
2
2
  Name: eccodes
3
- Version: 2.40.0
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.38.0"
18
- min_recommended_version_int = 23800
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
@@ -23,7 +23,7 @@ import sys
23
23
 
24
24
  import cffi
25
25
 
26
- __version__ = "2.40.0"
26
+ __version__ = "2.41.0"
27
27
 
28
28
  LOG = logging.getLogger(__name__)
29
29
 
@@ -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 test_message_from_samples():
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