-
Notifications
You must be signed in to change notification settings - Fork 34
/
Copy pathbindings.py
116 lines (90 loc) · 3.63 KB
/
bindings.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#
# (C) Copyright 2017- ECMWF.
#
# This software is licensed under the terms of the Apache Licence Version 2.0
# which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
#
# In applying this licence, ECMWF does not waive the privileges and immunities
# granted to it by virtue of its status as an intergovernmental organisation nor
# does it submit to any jurisdiction.
#
# Authors:
# Alessandro Amici - B-Open - https://bopen.eu
# Shahram Najm - ECMWF - https://www.ecmwf.int
#
from __future__ import absolute_import, division, print_function, unicode_literals
import logging
import os
import pkgutil
import sys
import cffi
__version__ = "2.42.0"
LOG = logging.getLogger(__name__)
_MAP = {
"grib_api": "eccodes",
"gribapi": "eccodes",
}
EXTENSIONS = {
"darwin": ".dylib",
"win32": ".dll",
}
# convenient way to trace the search for the library
if int(os.environ.get("ECCODES_PYTHON_TRACE_LIB_SEARCH", "0")):
LOG.setLevel(logging.DEBUG)
LOG.addHandler(logging.StreamHandler())
def _lookup(name):
return _MAP.get(name, name)
def find_binary_libs(name):
name = _lookup(name)
env_var = "ECCODES_PYTHON_USE_FINDLIBS"
if int(os.environ.get(env_var, "0")):
LOG.debug(f"{name} lib search: {env_var} set, so using findlibs")
else:
LOG.debug(f"{name} lib search: trying to find binary wheel")
here = os.path.dirname(__file__)
# eccodes libs are actually in eccodes dir, not gribapi dir
here = os.path.abspath(os.path.join(here, os.path.pardir, "eccodes"))
extension = EXTENSIONS.get(sys.platform, ".so")
for libdir in [here + ".libs", os.path.join(here, ".dylibs"), here]:
LOG.debug(f"{name} lib search: looking in {libdir}")
if not name.startswith("lib"):
libnames = ["lib" + name, name]
else:
libnames = [name, name[3:]]
if os.path.exists(libdir):
for file in os.listdir(libdir):
if file.endswith(extension):
for libname in libnames:
if libname == file.split("-")[0].split(".")[0]:
foundlib = os.path.join(libdir, file)
LOG.debug(
f"{name} lib search: returning wheel library from {foundlib}"
)
# force linking with the C++ 'glue' library
try:
from eccodes._eccodes import versions as _versions
except ImportError as e:
LOG.warn(str(e))
raise
LOG.debug(
f"{name} lib search: versions: %s", _versions()
)
return foundlib
LOG.debug(
f"{name} lib search: did not find library from wheel; try to find as separate lib"
)
# if did not find the binary wheel, or the env var is set, fall back to findlibs
import findlibs
foundlib = findlibs.find(name)
LOG.debug(f"{name} lib search: findlibs returned {foundlib}")
return foundlib
library_path = find_binary_libs("eccodes")
if library_path is None:
raise RuntimeError("Cannot find the ecCodes library")
# default encoding for ecCodes strings
ENC = "ascii"
ffi = cffi.FFI()
CDEF = pkgutil.get_data(__name__, "grib_api.h")
CDEF += pkgutil.get_data(__name__, "eccodes.h")
ffi.cdef(CDEF.decode("utf-8").replace("\r", "\n"))
lib = ffi.dlopen(library_path)