Skip to content

Commit

Permalink
Merge branch 'develop' into feature/master-to-develop
Browse files Browse the repository at this point in the history
  • Loading branch information
iainrussell authored Sep 9, 2024
2 parents 0f4a219 + b0bc302 commit 540750e
Show file tree
Hide file tree
Showing 13 changed files with 233 additions and 7 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,19 @@
Changelog for eccodes-python
============================

2.38.0 (2024-MM-DD)
--------------------

- ECC-1790: Add codes_get_offset
- ECC-1899: API function to allow setting debug level
- Function to query library features

2.37.0 (2024-09-09)
-------------------

- bundle ecCodes binary library with the PyPi distribution, for Linux and MacOS


1.7.1 (2024-06-19)
--------------------

Expand Down
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Installation
follow the version numbering of the ecCodes binary library. See below for details.**


The package is installed from PyPI with::
The package can be installed from PyPI with::

$ pip install eccodes

Expand Down
15 changes: 15 additions & 0 deletions ci/requirements-dev.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
check-manifest
detox
IPython
matplotlib
notebook
pip-tools
pyroma
pytest-mypy
setuptools
tox
tox-pyenv
wheel
zest.releaser
black

3 changes: 3 additions & 0 deletions ci/requirements-docs.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Sphinx
pytest-runner

48 changes: 48 additions & 0 deletions ci/requirements-docs.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#
# This file is autogenerated by pip-compile
# To update, run:
#
# pip-compile --output-file ci/requirements-docs.txt setup.py ci/requirements-docs.in
#
alabaster==0.7.12
# via sphinx
babel==2.9.1
# via sphinx
certifi==2024.7.4
# via requests
charset-normalizer==3.3.2
# via requests
docutils==0.14
# via sphinx
idna==3.7
# via requests
imagesize==1.1.0
# via sphinx
jinja2==3.1.4
# via sphinx
markupsafe==2.1.5
# via jinja2
packaging==19.0
# via sphinx
pygments==2.15.0
# via sphinx
pyparsing==2.3.1
# via packaging
pytest-runner==4.4
# via -r requirements-docs.in
pytz==2018.9
# via babel
requests==2.32.2
# via sphinx
six==1.12.0
# via
# packaging
# sphinx
snowballstemmer==1.2.1
# via sphinx
sphinx==1.8.5
# via -r requirements-docs.in
sphinxcontrib-websupport==1.1.0
# via sphinx
urllib3==1.26.19
# via requests
6 changes: 6 additions & 0 deletions ci/requirements-tests.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
pytest
pytest-cov
pytest-flakes
pytest-mccabe
pytest-pep8
pytest-runner
52 changes: 52 additions & 0 deletions ci/requirements-tests.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#
# This file is autogenerated by pip-compile
# To update, run:
#
# pip-compile --output-file ci/requirements-tests.txt setup.py ci/requirements-tests.in
#
apipkg==1.5
# via execnet
atomicwrites==1.3.0
# via pytest
attrs==19.1.0
# via pytest
coverage==4.5.3
# via pytest-cov
execnet==1.5.0
# via pytest-cache
mccabe==0.6.1
# via pytest-mccabe
more-itertools==5.0.0
# via pytest
pep8==1.7.1
# via pytest-pep8
pluggy==0.9.0
# via pytest
pyflakes==2.1.1
# via pytest-flakes
pytest==4.3.1
# via
# -r requirements-tests.in
# pytest-cache
# pytest-cov
# pytest-flakes
# pytest-mccabe
# pytest-pep8
pytest-cache==1.0
# via
# pytest-mccabe
# pytest-pep8
pytest-cov==2.6.1
# via -r requirements-tests.in
pytest-flakes==4.0.0
# via -r requirements-tests.in
pytest-mccabe==0.1
# via -r requirements-tests.in
pytest-pep8==1.0.6
# via -r requirements-tests.in
pytest-runner==4.4
# via -r requirements-tests.in
six==1.12.0
# via
# more-itertools
# pytest
12 changes: 12 additions & 0 deletions eccodes/eccodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
#
#
from gribapi import (
CODES_FEATURES_ALL,
CODES_FEATURES_DISABLED,
CODES_FEATURES_ENABLED,
CODES_PRODUCT_ANY,
CODES_PRODUCT_BUFR,
CODES_PRODUCT_GRIB,
Expand Down Expand Up @@ -44,6 +47,7 @@
codes_dump,
codes_extract_offsets,
codes_extract_offsets_sizes,
codes_get_features,
codes_get_gaussian_latitudes,
codes_get_library_path,
codes_get_version_info,
Expand Down Expand Up @@ -73,6 +77,7 @@
from gribapi import grib_get_message_offset as codes_get_message_offset
from gribapi import grib_get_message_size as codes_get_message_size
from gribapi import grib_get_native_type as codes_get_native_type
from gribapi import grib_get_offset as codes_get_offset
from gribapi import grib_get_size as codes_get_size
from gribapi import grib_get_string as codes_get_string
from gribapi import grib_get_string_array as codes_get_string_array
Expand Down Expand Up @@ -123,6 +128,7 @@
from gribapi import grib_release as codes_release
from gribapi import grib_set as codes_set
from gribapi import grib_set_array as codes_set_array
from gribapi import grib_set_debug as codes_set_debug
from gribapi import grib_set_definitions_path as codes_set_definitions_path
from gribapi import grib_set_double as codes_set_double
from gribapi import grib_set_double_array as codes_set_double_array
Expand Down Expand Up @@ -247,6 +253,9 @@
"codes_definition_path",
"codes_extract_offsets",
"codes_extract_offsets_sizes",
"CODES_FEATURES_ALL",
"CODES_FEATURES_ENABLED",
"CODES_FEATURES_DISABLED",
"codes_get_api_version",
"codes_get_array",
"codes_get_double_array",
Expand All @@ -263,13 +272,15 @@
"codes_get_message_size",
"codes_get_message",
"codes_get_native_type",
"codes_get_offset",
"codes_get_size",
"codes_get_string_array",
"codes_get_string_length",
"codes_get_string",
"codes_get_values",
"codes_get_version_info",
"codes_get",
"codes_get_features",
"codes_grib_find_nearest_multiple",
"codes_grib_find_nearest",
"codes_grib_get_data",
Expand Down Expand Up @@ -333,6 +344,7 @@
"codes_samples_path",
"codes_dump",
"codes_set_array",
"codes_set_debug",
"codes_set_definitions_path",
"codes_set_double_array",
"codes_set_double",
Expand Down
2 changes: 1 addition & 1 deletion gribapi/bindings.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

import cffi

__version__ = "2.37.0"
__version__ = "2.38.0"

LOG = logging.getLogger(__name__)

Expand Down
2 changes: 1 addition & 1 deletion gribapi/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class GribInternalError(Exception):
def __init__(self, value):
# Call the base class constructor with the parameters it needs
Exception.__init__(self, value)
if type(value) is int:
if isinstance(value, int):
self.msg = ffi.string(lib.grib_get_error_message(value)).decode(ENC)
else:
self.msg = value
Expand Down
7 changes: 6 additions & 1 deletion gribapi/grib_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,14 +100,15 @@ int grib_nearest_find_multiple(const grib_handle* h, int is_lsm,
double* outlats, double* outlons,
double* values, double* distances, int* indexes);

int grib_get_offset(const grib_handle* h, const char* key, size_t* offset);
int grib_get_size(const grib_handle* h, const char* key,size_t *size);

int grib_get_length(const grib_handle* h, const char* key,size_t *length);
int grib_get_long(const grib_handle* h, const char* key, long* value);
int grib_get_double(const grib_handle* h, const char* key, double* value);
int grib_get_double_element(const grib_handle* h, const char* key, int i, double* value);
int grib_get_double_elements(const grib_handle* h, const char* key, const int* index_array, long size, double* value);
int grib_get_string(const grib_handle* h, const char* key, char* mesg, size_t *length);
int grib_get_string(const grib_handle* h, const char* key, char* value, size_t *length);
int grib_get_string_array(const grib_handle* h, const char* key, char** vals, size_t *length);
int grib_get_double_array(const grib_handle* h, const char* key, double* vals, size_t *length);
int grib_get_float_array(const grib_handle* h, const char* key, float* vals, size_t *length);
Expand All @@ -131,6 +132,7 @@ void grib_gts_header_off(grib_context* c);
void grib_gribex_mode_on(grib_context* c);
void grib_gribex_mode_off(grib_context* c);
void grib_context_set_definitions_path(grib_context* c, const char* path);
void grib_context_set_debug(grib_context* c, int mode);
void grib_context_set_samples_path(grib_context* c, const char* path);
void grib_multi_support_on(grib_context* c);
void grib_multi_support_off(grib_context* c);
Expand Down Expand Up @@ -174,6 +176,9 @@ int parse_keyval_string(const char *grib_tool, char *arg, int values_required, i
int grib_get_data(const grib_handle *h, double *lats, double *lons, double *values);
int grib_get_gaussian_latitudes(long trunc, double* lats);

int codes_is_feature_enabled(const char* feature);
int codes_get_features(char* result, size_t* length, int select);

/* EXPERIMENTAL */
typedef struct codes_bufr_header {
unsigned long message_offset;
Expand Down
50 changes: 50 additions & 0 deletions gribapi/gribapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,12 @@
GRIB_NEAREST_SAME_DATA = 1 << 1
GRIB_NEAREST_SAME_POINT = 1 << 2

# Constants for feature selection
CODES_FEATURES_ALL = 0
CODES_FEATURES_ENABLED = 1
CODES_FEATURES_DISABLED = 2


# ECC-1029: Disable function-arguments type-checking unless
# environment variable is defined and equal to 1
enable_type_checks = os.environ.get("ECCODES_PYTHON_ENABLE_TYPE_CHECKS") == "1"
Expand Down Expand Up @@ -578,6 +584,23 @@ def grib_multi_append(ingribid, startsection, multigribid):
GRIB_CHECK(lib.grib_multi_handle_append(h, startsection, mh))


@require(msgid=int, key=str)
def grib_get_offset(msgid, key):
"""
@brief Get the byte offset of a key. If several keys of the same name
are present, the offset of the last one is returned
@param msgid id of the message loaded in memory
@param key name of the key
@exception CodesInternalError
"""
h = get_handle(msgid)
offset_p = ffi.new("size_t*")
err = lib.grib_get_offset(h, key.encode(ENC), offset_p)
GRIB_CHECK(err)
return offset_p[0]


@require(msgid=int, key=str)
def grib_get_size(msgid, key):
"""
Expand Down Expand Up @@ -2405,6 +2428,16 @@ def codes_samples_path():
return ffi.string(spath).decode(ENC)


def grib_set_debug(dmode):
"""
@brief Set the debug mode
@param dmode -1, 0 or 1
"""
context = lib.grib_context_get_default()
lib.grib_context_set_debug(context, dmode)


@require(defs_path=str)
def grib_set_definitions_path(defs_path):
"""
Expand Down Expand Up @@ -2617,6 +2650,23 @@ def codes_extract_offsets_sizes(filepath, product_kind, is_strict=True):
i += 1


@require(select=int)
def codes_get_features(select=CODES_FEATURES_ALL):
"""
@brief Get the list of library features.
@param select One of CODES_FEATURES_ALL, CODES_FEATURES_ENABLED or CODES_FEATURES_DISABLED
@return space-separated string of feature names
@exception CodesInternalError
"""
ssize = 1024
result = ffi.new("char[]", ssize)
size_p = ffi.new("size_t *", ssize)
err = lib.codes_get_features(result, size_p, select)
GRIB_CHECK(err)
return ffi.string(result).decode(ENC)


# -------------------------------
# EXPERIMENTAL FEATURES
# -------------------------------
Expand Down
Loading

0 comments on commit 540750e

Please sign in to comment.