ecmwflibs-0.7.0/0000775000175000017500000000000015201521775013662 5ustar alastairalastairecmwflibs-0.7.0/ecmwflibs/0000775000175000017500000000000015201521641015625 5ustar alastairalastairecmwflibs-0.7.0/ecmwflibs/__init__.py0000664000175000017500000001346115201521641017743 0ustar alastairalastair#!/usr/bin/env python3 # (C) Copyright 2020 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. # import atexit import json import os import sys import tempfile import warnings from findlibs import find as _find_library __version__ = "0.7.0" _here = os.path.join(os.path.dirname(__file__)) _universal = os.path.exists(os.path.join(_here, "_universal")) if _universal: _versions = dict else: _fonts = f""" {_here}/share/magics/ttf """ _fontcfg = tempfile.mktemp("ecmwflibs.xml") with open(_fontcfg, "w") as _f: print(_fonts, file=_f) if "ECMWFLIBS_MAGPLUS" not in os.environ: os.environ["FONTCONFIG_FILE"] = os.environ.get( "ECMWFLIBS_FONTCONFIG_FILE", _fontcfg ) os.environ["PROJ_LIB"] = os.environ.get( "ECMWFLIBS_PROJ_LIB", os.path.join(_here, "share", "proj") ) os.environ["MAGPLUS_HOME"] = os.environ.get("ECMWFLIBS_MAGPLUS_HOME", _here) if "ECMWFLIBS_ECCODES" not in os.environ: for env in ( "ECCODES_DEFINITION_PATH", "ECCODES_EXTRA_DEFINITION_PATH", "ECCODES_EXTRA_SAMPLES_PATH", "ECCODES_SAMPLES_PATH", "GRIB_DEFINITION_PATH", "GRIB_SAMPLES_PATH", ): if env in os.environ: if "ECMWFLIBS_" + env in os.environ: os.environ[env] = os.environ["ECMWFLIBS_" + env] warnings.warn( "ecmwflibs: using provided '{}' set to '{}".format( env, os.environ[env] ) ) else: warnings.warn( ( "ecmwflibs: ignoring provided '{}' set to '{}'. " "If you want ecmwflibs to use this environment variable, use ECMWFLIBS_{} instead. " "If you want to use your own ECCODES library, use ECMWFLIBS_ECCODES." ).format(env, os.environ[env], env) ) del os.environ[env] # This comes *after* the variables are set, so c++ has access to them try: from ._ecmwflibs import versions as _versions except ImportError as e: # ImportError: DLL load failed while importing _ecmwflibs: The specified module could not be found. warnings.warn(str(e)) raise def universal(): return _universal def _cleanup(): try: os.unlink(_fontcfg) except Exception: pass if not _universal: atexit.register(_cleanup) _MAP = { "magics": "MagPlus", "magplus": "MagPlus", "grib_api": "eccodes", "gribapi": "eccodes", } EXTENSIONS = { "darwin": ".dylib", "win32": ".dll", } def _lookup(name): return _MAP.get(name, name) def find(name): """Returns the path to the selected library, or None if not found.""" name = _lookup(name) if int(os.environ.get("ECMWFLIBS_DISABLED", "0")): warnings.warn(f"ECMWFLIBS_DISABLED is set looking for {name}") return None if int(os.environ.get("ECMWFLIBS_USED_INSTALLED", "0")): path = _find_library(name) if path is None: warnings.warn(f"ECMWFLIBS_USED_INSTALLED did not find {name}") else: warnings.warn(f"ECMWFLIBS_USED_INSTALLED found {name} at {path}") return path if _universal: # Universal version path = _find_library(name) if path: warnings.warn(f"ecmwflibs universal: found {name} at {path}") else: warnings.warn(f"ecmwflibs universal: cannot find a library called {name}") return path env = "ECMWFLIBS_" + name.upper() if env in os.environ: warnings.warn( "ecmwflibs: using provided '{}' set to '{}".format(env, os.environ[env]) ) return os.environ[env] here = os.path.dirname(__file__) extension = EXTENSIONS.get(sys.platform, ".so") for libdir in [here + ".libs", os.path.join(here, ".dylibs"), here]: if not name.startswith("lib"): names = ["lib" + name, name] else: names = [name, name[3:]] if os.path.exists(libdir): for file in os.listdir(libdir): if file.endswith(extension): for name in names: if name == file.split("-")[0].split(".")[0]: return os.path.join(libdir, file) return None def versions(): """Returns the list of libraries and their version.""" v = {"ecmwflibs": __version__} v.update(_versions()) return v def files(): here = os.path.dirname(__file__) for root, dirs, files in os.walk(here): for file in files: yield os.path.join(root, file).replace(here, "") def credits(): """Displays the list of embedded libraries and their copyright notices and/or licenses.""" here = os.path.dirname(__file__) with open(os.path.join(here, "copying/list.json")) as f: x = json.loads(f.read()) for k, v in sorted(x.items()): print("*" * 80) print("name", k) print("home", v["home"]) print("*" * 80) print() with open(os.path.join(here, v["path"])) as f: print(f.read()) print("*" * 80) def builds(): here = os.path.dirname(__file__) with open(os.path.join(here, "versions.txt")) as f: for d in f.readlines(): print(d) ecmwflibs-0.7.0/ecmwflibs/copying/0000775000175000017500000000000015201521641017275 5ustar alastairalastairecmwflibs-0.7.0/ecmwflibs/copying/.gitignore0000664000175000017500000000001515201521641021261 0ustar alastairalastair*.txt *.json ecmwflibs-0.7.0/ecmwflibs/_ecmwflibs.cc0000664000175000017500000000144115201521641020246 0ustar alastairalastair#include #include #include #include extern "C" const char* knowndrivers_(); static PyObject* versions(PyObject *self, PyObject *args) { long s = grib_get_api_version(); // Force linking auto p = knowndrivers_(); return Py_BuildValue("{s:s,s:s}", "eccodes", ECCODES_VERSION_STR, "magics", MAGICS_VERSION_STR); } static PyMethodDef ecmwflibs_methods[] = { { "versions", versions, METH_NOARGS, "Versions", }, {0,} }; static struct PyModuleDef ecmwflibs_definition = { PyModuleDef_HEAD_INIT, "ecmwflibs", "Load ECMWF libraries.", -1, ecmwflibs_methods }; PyMODINIT_FUNC PyInit__ecmwflibs(void) { Py_Initialize(); return PyModule_Create(&ecmwflibs_definition); } ecmwflibs-0.7.0/ecmwflibs/__main__.py0000664000175000017500000000032715201521641017721 0ustar alastairalastairimport sys from ecmwflibs import credits if sys.argv[-1] != "credits": print("Type 'python -m ecmwflibs credits' to see the") print("Open Source software installed with ecmwflibs.") exit(0) credits() ecmwflibs-0.7.0/ecmwflibs/.gitignore0000664000175000017500000000000715201521641017612 0ustar alastairalastairshare/ ecmwflibs-0.7.0/ecmwflibs/etc/0000775000175000017500000000000015201521641016400 5ustar alastairalastairecmwflibs-0.7.0/ecmwflibs/etc/README0000664000175000017500000000010515201521641017254 0ustar alastairalastairAdd files to this drirectory that will be installed with the package ecmwflibs-0.7.0/tests/0000775000175000017500000000000015201521641015014 5ustar alastairalastairecmwflibs-0.7.0/tests/requirements.txt0000664000175000017500000000002615201521641020276 0ustar alastairalastairmagics eccodes pytest ecmwflibs-0.7.0/tests/test_versions.py0000664000175000017500000000074015201521641020276 0ustar alastairalastairimport json import ecmwflibs def test_versions(): versions = ecmwflibs.versions() print(json.dumps(versions, sort_keys=True, indent=4)) assert "eccodes" in versions, versions assert "magics" in versions, versions assert "ecmwflibs" in versions, versions for lib in ("eccodes", "magics"): print(lib, ecmwflibs.find(lib)) assert ecmwflibs.find(lib) is not None # def test_files(): # for f in ecmwflibs.files(): # print(f) ecmwflibs-0.7.0/tests/test_climetlab.py0000664000175000017500000001247315201521641020370 0ustar alastairalastair#!/usr/bin/env python3 import pytest from Magics import macro def test_climetlab_grib(): actions = [ macro.output( output_formats=["png"], output_name="climetlab_grib_1", output_name_first_page_number=False, output_width=680, page_frame=False, page_id_line=False, page_x_length=10.0, page_y_length=5.555555555555555, subpage_x_length=10.0, subpage_x_position=0.0, subpage_y_length=5.555555555555555, subpage_y_position=0.0, super_page_x_length=10.0, super_page_y_length=5.555555555555555, ), macro.mmap( subpage_lower_left_latitude=33.0, subpage_lower_left_longitude=-27.0, subpage_map_projection="cylindrical", subpage_upper_right_latitude=73.0, subpage_upper_right_longitude=45.0, ), macro.mcoast( map_boundaries=True, map_coastline_colour="tan", map_coastline_land_shade=True, map_coastline_land_shade_colour="cream", map_grid=False, map_grid_colour="tan", map_grid_frame=True, map_grid_frame_thickness=5, map_label=False, ), macro.mgrib( grib_field_position=0, grib_file_address_mode="byte_offset", grib_input_file_name="climetlab.grib", ), macro.mcont( contour_automatic_setting="climetlab", legend=False, ), macro.mcoast( map_grid=False, map_grid_frame=True, map_grid_frame_thickness=5, map_label=False, ), ] print(actions) macro.plot(*actions) actions = [ macro.output( output_formats=["png"], output_name="climetlab_grib_2", output_name_first_page_number=False, output_width=680, page_frame=False, page_id_line=False, page_x_length=10.0, page_y_length=5.555555555555555, subpage_x_length=10.0, subpage_x_position=0.0, subpage_y_length=5.555555555555555, subpage_y_position=0.0, super_page_x_length=10.0, super_page_y_length=5.555555555555555, ), macro.mmap( subpage_lower_left_latitude=33.0, subpage_lower_left_longitude=-27.0, subpage_map_projection="cylindrical", subpage_upper_right_latitude=73.0, subpage_upper_right_longitude=45.0, ), macro.mcoast( map_boundaries=True, map_coastline_colour="tan", map_coastline_land_shade=True, map_coastline_land_shade_colour="cream", map_grid=False, map_grid_colour="tan", map_grid_frame=True, map_grid_frame_thickness=5, map_label=False, ), macro.mgrib( grib_field_position=526, grib_file_address_mode="byte_offset", grib_input_file_name="climetlab.grib", ), macro.mcont( contour_automatic_setting="climetlab", legend=False, ), macro.mcoast( map_grid=False, map_grid_frame=True, map_grid_frame_thickness=5, map_label=False, ), ] print(actions) macro.plot(*actions) @pytest.mark.parametrize("filename", ["climetlab.nc", "test.nc4"]) def test_climetlab_netcdf(filename): from Magics import macro output = filename.replace(".", "-") + ".png" actions = [ macro.output( output_file=output, output_width=680, page_frame=False, page_id_line=False, page_x_length=10, page_y_length=5.555555555555555, subpage_frame=False, subpage_x_length=10, subpage_x_position=0.0, subpage_y_length=5.555555555555555, subpage_y_position=0.0, super_page_frame=False, super_page_x_length=10, super_page_y_length=5.555555555555555, ), macro.mmap( subpage_lower_left_latitude=33.0, subpage_lower_left_longitude=-27.0, subpage_map_projection="cylindrical", subpage_upper_right_latitude=73.0, subpage_upper_right_longitude=45.0, ), macro.mcoast( map_boundaries=True, map_coastline_colour="tan", map_coastline_land_shade=True, map_coastline_land_shade_colour="cream", map_grid=False, map_grid_colour="tan", map_grid_frame=True, map_grid_frame_thickness=5, map_label=False, ), macro.mnetcdf( netcdf_filename=filename, netcdf_value_variable="t2m", ), macro.mcont( contour_automatic_setting="climetlab", legend=False, ), macro.mcoast( map_grid=False, map_grid_frame=True, map_grid_frame_thickness=5, map_label=False, ), ] print(actions) macro.plot(*actions) if __name__ == "__main__": test_climetlab_netcdf() # test_climetlab_grib() ecmwflibs-0.7.0/tests/test_eccodes.py0000664000175000017500000000053415201521641020034 0ustar alastairalastairfrom eccodes import codes_get, codes_grib_new_from_file, codes_release def test_versions(): with open("data.grib", "rb") as f: grib = codes_grib_new_from_file(f) date = codes_get(grib, "date") assert date == 20130325, date print(date) print(codes_get(grib, "shortName")) codes_release(grib) ecmwflibs-0.7.0/tests/open_netcdf.c0000664000175000017500000000065715201521641017454 0ustar alastairalastair #include #include #include int main(int argc, const char* argv[]) { int ncid, e; if (argc != 2) { fprintf(stderr, "Usage: %s file.nc\n", argv[0]); exit(1); } if ((e = nc_open(argv[1], NC_NOWRITE, &ncid))) { fprintf(stderr,"%s: %s\n", argv[1], nc_strerror(e)); exit(1); } printf("%s: file opened successfully\n", argv[1]); exit(0); } ecmwflibs-0.7.0/tests/.gitignore0000664000175000017500000000010415201521641016777 0ustar alastairalastairCMakeFiles/ Makefile open_netcdf CMakeCache.txt cmake_install.cmake ecmwflibs-0.7.0/tests/test_magics.py0000664000175000017500000000133715201521641017674 0ustar alastairalastair#!/usr/bin/env python3 from Magics import macro as magics def test_magics_plot(): # Setting of the output file name output = magics.output( output_formats=["png"], output_name_first_page_number="off", output_name="magics1", ) # Import the data data = magics.mgrib( grib_input_file_name="data.grib", ) # proj = magics.mmap(subpage_map_projection="mollweide") # proj = magics.mmap(subpage_map_projection="cylindrical") proj = magics.mmap(subpage_map_projection="robinson") # Apply an automatic styling contour = magics.mcont( contour_automatic_setting="ecmwf", ) coast = magics.mcoast() magics.plot(output, proj, data, contour, coast) ecmwflibs-0.7.0/tests/test.nc40000664000175000017500000006266715201521641016422 0ustar alastairalastairHDF  e0kYsOHDR " %_OO L : GRIB_edition  % GRIB_centreecmf ^GRIB_centreDescription2European Centre for Medium-Range Weather Forecasts < GRIB_subCentre  ' ConventionsCF-1.7 S institution2European Centre for Medium-Range Weather Forecasts historyGRIB to CDM+CF via cfgrib-0.9.5/ecCodes-2.17.0 with source='/Users/baudouin/git/climet/test.grib', filter_by_keys={}, encode_cf=('parameter', 'time', 'geography', 'vertical')ical')VOHDR  ?@4 4*t +CLASSDIMENSION_SCALE $NAME longitudeN DOCHKja ?KOCHK + _Netcdf4Dimid  D _FillValue ?@4 4 'units degrees_east ,standard_name longitude ( long_name longitude=5OHDR   ?@4 4* P:PXxG>OCHKt=@JgFSSEt;zX FSSE9 /f 11DOCHK E_NCProperties"version=2,netcdf=4.8.0,hdf5=1.10.6.8.0,hdf5=1.10.6.10.6;73.&?@"@*@1@5@9@=@@@B@D@F@cC@C`NC-C`:C@ECˆC`dCCsCC@C]CC`!C CaC@CgC@CC@ƇC҇CC ƇC@C(C`QCшCkCCχC`#CC C&C`COCC yC`ACHCOCqCCउCۉC C$C`C ٌCkC`{C؋C`CKCC CwCjC/CACbCC(C rC0CҊC`C@ފC&CDCOCƉC2C׎CCҌC CC,C`C"C zCƋCڌC@C/CC CC@LCC`C CԍCލC്C}CCC1C WCC@XCώC :C 'CjC mC mCCC C +CC`C [C@.C@C` C&CwC9CCC@CCCCpCoC@БC CC`C@CMCCBCCC CFC=C)CCC@UCCCC %CC?CCC _CMC@GrGGp'G0GG8GG0)GNGAG(GGH"G G G GxG`GGG GؐG(@G8 GGG5GXVGG`GIGG8G[GpfGhGG1G X- 5 < * -MK5[qCa`u5[HMC`_2OkD\+ bBTINMC[퍃jBTLF+ e >`l"5 rA [`2OiqCFh?1kD_}5 ,kH#&ɩ\cEc! }u%L> olMGCOL^^^^ ^  ^ FHDBS_":DIMENSION_LIST  FHDBS7"GRIB_iDirectionIncrementInDegrees ?@4 4@ GRIB_iScansNegatively (GRIB_longitudeOfFirstGridPointInDegrees ?@4 4;'GRIB_longitudeOfLastGridPointInDegrees ?@4 4F@ GRIB_Ny  "GRIB_jDirectionIncrementInDegrees ?@4 4@ GRIB_jPointsAreConsecutive  GRIB_jScansPositively 'GRIB_latitudeOfFirstGridPointInDegrees ?@4 4@R@&GRIB_latitudeOfLastGridPointInDegrees ?@4 4@@unitsK coordinates#number surface time step valid_time _Netcdf4Dimid FHDBSŴn _Netcdf4Coordinates  _FillValue   GRIB_paramId GRIB_shortName2t GRIB_unitsK GRIB_name2 metre temperatureGRIB_cfVarNamet2mGRIB_dataTypean GRIB_missingValue ' GRIB_numberOfPoints  GRIB_totalNumber GRIB_typeOfLevelsurface GRIB_NV  GRIB_stepUnits GRIB_stepTypeinstantGRIB_gridType regular_llGRIB_gridDefinitionDescriptionLatitude/Longitude Grid GRIB_Nx  long_name2 metre temperatureFHIBS3/+/?OHDR $     *m D#:(;N;l>8mOCHKmsl7msl7FSHD Px _7EOCHK # long_nametimeD% OCHK |0REFERENCE_LIST6datasetdimension 7;BTHDd(&Q :bFHIB:KGCF3FRHPt; #(H:۲BTHDd(?#V3BTHD  d(=###~FSHD*Px(//xBTLF[~oa6u:2 6L <[@$KK./- N5<QAx/Re-LfUT?-G^;*g%_A7uK[6y' gfцBTLF E[@:'"6T?'%? A _> - 5 <;*e-K5K[CaJ`5[:HC`%_6AD Z\!+"m BTINC[;A8tgLBTLF+"e >J`l"5 rA [`6iCFh? 1D _}5 ,k:H#'ɩZ\!cEc" }%L_> oFHDB:^ coordinates#number surface time step valid_timeDIMENSION_LIST   _Netcdf4Dimid FHDB: GRIB_Nx "GRIB_iDirectionIncrementInDegrees ?@4 4@ GRIB_iScansNegatively (GRIB_longitudeOfFirstGridPointInDegrees ?@4 4;'GRIB_longitudeOfLastGridPointInDegrees ?@4 4F@ GRIB_Ny  "GRIB_jDirectionIncrementInDegrees ?@4 4@ GRIB_jPointsAreConsecutive  GRIB_jScansPositively 'GRIB_latitudeOfFirstGridPointInDegrees ?@4 4@R@&GRIB_latitudeOfLastGridPointInDegrees ?@4 4@@ long_nameMean sea level pressurestandard_nameair_pressure_at_mean_sea_levelFHDB: _Netcdf4Coordinates  _FillValue   GRIB_paramId GRIB_shortNamemsl GRIB_unitsPa GRIB_nameMean sea level pressure GRIB_cfNameair_pressure_at_mean_sea_levelGRIB_cfVarNamemslGRIB_dataTypean GRIB_missingValue ' GRIB_numberOfPoints  GRIB_totalNumber GRIB_typeOfLevelsurface GRIB_NV  GRIB_stepUnits GRIB_stepTypeinstantGRIB_gridType regular_llGRIB_gridDefinitionDescriptionLatitude/Longitude GridunitsPaBTHD d(_ &h3BTHDd(a 疀FRHPP (&U\BTHD  d(&S :(i}| M0$0x BTLF +A#d+D(+&'M0}| _FIFHDBP}?CLASSDIMENSION_SCALENAME latitude _Netcdf4Dimid  _FillValue ?@4 4units degrees_northstandard_namelatitude long_namelatitudestored_direction decreasing0REFERENCE_LIST6datasetdimension 7OHDR    *  ; long_nameensemble member numerical id units1 .standard_name realizationoOHDR b   *  7 long_nameinitial time of forecast :standard_nameforecast_reference_time Bunits'seconds since 1970-01-01T00:00:00+00:00 1 calendarproleptic_gregorian_OHDR a ?@4 4* D _FillValue ?@4 4 A long_name"time since forecast_reference_time 2standard_nameforecast_period unitshoursX7POHDR    * O long_name0original GRIB coordinate for key: level(surface) units1qOHDR  ?@4 4* D _FillValue ?@4 4 'standard_nametimeW91 CFRHP 9  cWQfmBTLF8?xWLBX^P^1tzgebdDKaxj`7BTLFLb1x ) πFHDB%_.o longitudelatitude^t2mmsl7number&Ytime2Zstep[surface ] valid_time^ecmwflibs-0.7.0/tests/CMakeLists.txt0000664000175000017500000000051315201521641017553 0ustar alastairalastairproject( open_netcdf LANGUAGES C ) cmake_minimum_required(VERSION 3.21) find_path (NETCDF_INCLUDES_C netcdf.h HINTS NETCDF_DIR NETCDF_DIR) include_directories(${NETCDF_INCLUDES_C}) find_library (NETCDF_LIBRARIES_C NAMES netcdf) add_executable(open_netcdf open_netcdf.c) target_link_libraries(open_netcdf ${NETCDF_LIBRARIES_C}) ecmwflibs-0.7.0/scripts/0000775000175000017500000000000015201521641015341 5ustar alastairalastairecmwflibs-0.7.0/scripts/build-macos.sh0000775000175000017500000000647215201521641020110 0ustar alastairalastair#!/usr/bin/env bash # (C) Copyright 2020 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. set -eaux : > versions uname -a # HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 HOMEBREW_NO_INSTALL_CLEANUP=1 arch=$(arch) [[ $arch == "i386" ]] && arch="x86_64" # GitHub Actions on macOS declare i386 ARCH="arch -$arch" source scripts/common.sh brew_home=$(brew config | grep HOMEBREW_PREFIX | sed 's/.* //') $ARCH brew install cmake ninja pkg-config automake # brew cat cairo # We don't want a dependency on X11 brew cat cairo | sed ' s/xcb=enabled/xcb=disabled/ s/xlib=enabled/xlib=disabled/ s/enable-tee/disable-tee/ s/enable-xcb/disable-xcb/ s/enable-xlib/disable-xlib/ s/enable-xlib-xrender/disable-xlib-xrender/ s/enable-quartz-image/disable-quartz-image/' > cairo.rb cat cairo.rb $ARCH brew install pango $ARCH brew install netcdf $ARCH brew install proj $ARCH brew install libaec # Try to build cairo from local formula, fall back to standard cairo if it fails if ! $ARCH brew install --build-from-source ./cairo.rb 2>/dev/null then $ARCH brew install cairo fi for p in netcdf proj pango cairo do v=$(brew info $p | grep Cellar | awk '{print $1;}' | awk -F/ '{print $NF;}') echo "brew $p $v" >> versions done # Build eccodes cd $TOPDIR/build-ecmwf/eccodes # We disable JASPER because of a linking issue. JPEG support comes from # other librarues $ARCH $TOPDIR/src/ecbuild/bin/ecbuild \ $TOPDIR/src/eccodes \ -GNinja \ -DCMAKE_OSX_ARCHITECTURES=$arch \ -DCMAKE_BUILD_TYPE=RelWithDebInfo \ -DENABLE_PYTHON=0 \ -DENABLE_FORTRAN=0 \ -DENABLE_BUILD_TOOLS=0 \ -DENABLE_JPG_LIBJASPER=0 \ -DENABLE_MEMFS=1 \ -DENABLE_INSTALL_ECCODES_DEFINITIONS=0 \ -DENABLE_INSTALL_ECCODES_SAMPLES=0 \ -DCMAKE_INSTALL_PREFIX=$TOPDIR/install \ -DCMAKE_INSTALL_RPATH=$TOPDIR/install/lib $ECCODES_EXTRA_CMAKE_OPTIONS cd $TOPDIR $ARCH cmake --build build-ecmwf/eccodes --target install # Build magics cd $TOPDIR/build-ecmwf/magics $ARCH $TOPDIR/src/ecbuild/bin/ecbuild \ $TOPDIR/src/magics \ -GNinja \ -DCMAKE_OSX_ARCHITECTURES=$arch \ -DCMAKE_BUILD_TYPE=RelWithDebInfo \ -DENABLE_PYTHON=0 \ -DENABLE_FORTRAN=0 \ -DENABLE_BUILD_TOOLS=0 \ -Deccodes_DIR=$TOPDIR/install/lib/cmake/eccodes \ -DCMAKE_INSTALL_PREFIX=$TOPDIR/install \ -DCMAKE_INSTALL_RPATH=$TOPDIR/install/lib cd $TOPDIR $ARCH cmake --build build-ecmwf/magics --target install # Create wheel rm -fr dist wheelhouse ecmwflibs/share mkdir -p install/share/magics cp -r install/share ecmwflibs/ cp -r $brew_home/Cellar/proj/*/share ecmwflibs/ rm -fr ecmwflibs/share/proj/*.tif rm -fr ecmwflibs/share/proj/*.txt rm -fr ecmwflibs/share/proj/*.pol rm -fr ecmwflibs/share/magics/efas # echo "================================================================================" # for n in install/lib/*.dylib # do # echo $n # ./scripts/libs-macos.py $n # done # echo "================================================================================" strip -S install/lib/*.dylib ./scripts/versions.sh > ecmwflibs/versions.txt ecmwflibs-0.7.0/scripts/libs-macos.py0000775000175000017500000000164415201521641017754 0ustar alastairalastair#!/usr/bin/env python3 # -*- coding: utf-8 -*- import os import subprocess import sys null = open(os.devnull, "w") def otool(name): try: return subprocess.check_output(["otool", "-L", name], stderr=null).decode( "utf-8" ) except Exception: return "" def process(name, seen, depth=0): if name in seen: return seen.add(name) if name.endswith(".dylib"): print(f"{' ' * depth}{name}") deps = otool(name) for line in deps.split("\n"): line = line.strip() if line.endswith(":"): continue bits = line.split() if len(bits) < 1: continue lib = bits[0] if lib.startswith("@"): continue if name == lib: continue process(lib, seen, depth + 2) for n in sys.argv[1:]: process(n, set()) ecmwflibs-0.7.0/scripts/wheel-macos.sh0000775000175000017500000000303315201521641020103 0ustar alastairalastair#!/usr/bin/env bash # (C) Copyright 2020 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. set -eaux echo $PATH VERSION=${1:-""} echo ${GITHUB_PATH:-""} || true if [[ -n "${GITHUB_PATH:-}" && -f "${GITHUB_PATH}" ]] then cat "${GITHUB_PATH}" || true fi python3 --version which python3 which pip3 # PATH=/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin # unset PKG_CONFIG_PATH # env | sort rm -fr tmp/wheel-venv python3 -m venv tmp/wheel-venv source tmp/wheel-venv/bin/activate python3 -m pip install --upgrade pip python3 -m pip install wheel delocate setuptools # https://setuptools.pypa.io/en/latest/userguide/ext_modules.html#cross-platform-compilation # Prevent ext_modules from being built as universal # CXX=./scripts/cxx-no-arch.sh # CC=./scripts/c-no-arch.sh which python3 python3 --version which delocate-wheel rm -fr dist wheelhouse python3 setup.py bdist_wheel # Do it twice to get the list of libraries delocate-wheel -w wheelhouse dist/*.whl unzip -l wheelhouse/*.whl | grep 'dylib' >libs python3 -m pip install -r tools/requirements.txt python3 ./tools/copy-licences.py libs rm -fr dist wheelhouse python3 setup.py bdist_wheel delocate-wheel -w wheelhouse dist/*.whl ecmwflibs-0.7.0/scripts/build-macos-m1.sh0000775000175000017500000000234715201521641020420 0ustar alastairalastair#!/usr/bin/env bash # (C) Copyright 2020 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. set -eaux platform=$(uname) arch=$(uname -a | sed 's/.* //') if [[ "$platform.$arch" != "Darwin.arm64" ]] then exit 1 fi here=$(dirname $0) cd $here/.. rm -fr build* dist install wheelhouse cairo.rb ./scripts/build-macos.sh mkdir -p /tmp/build-macos-m1 PATH=/tmp/build-macos-m1:$PATH for n in 10 11 12 13 14 do rm -fr wheelhouse brew install python@3.$n ln -sf $(ls -1d /opt/homebrew/Cellar/python@3.$n/*/bin/python3.$n) /tmp/build-macos-m1/python3 ln -sf $(ls -1d /opt/homebrew/Cellar/python@3.$n/*/bin/python3.$n) /tmp/build-macos-m1/python ln -sf $(ls -1d /opt/homebrew/Cellar/python@3.$n/*/bin/pip3.$n) /tmp/build-macos-m1/pip3 ln -sf $(ls -1d /opt/homebrew/Cellar/python@3.$n/*/bin/pip3.$n) /tmp/build-macos-m1/pip ./scripts/wheel-macos.sh "3.$n" pip3 install twine twine upload wheelhouse/*.whl done ecmwflibs-0.7.0/scripts/select-python.sh0000775000175000017500000000115315201521641020476 0ustar alastairalastair#!/bin/bash set -xe version=$1 brew install python@$1 echo /opt/homebrew/opt/python@$version/libexec/bin >> $GITHUB_PATH ls -l /opt/homebrew/opt/python@$version/libexec/bin # Looks like python3 is not a symlink to python in 3.11 if [[ ! -f /opt/homebrew/opt/python@$version/libexec/bin/python3 ]] then ln -s /opt/homebrew/opt/python@$version/libexec/bin/python /opt/homebrew/opt/python@$version/libexec/bin/python3 fi if [[ ! -f /opt/homebrew/opt/python@$version/libexec/bin/pip3 ]] then ln -s /opt/homebrew/opt/python@$version/libexec/bin/pip /opt/homebrew/opt/python@$version/libexec/bin/pip3 fi ls -l ecmwflibs-0.7.0/scripts/versions.sh0000775000175000017500000000122115201521641017544 0ustar alastairalastair#!/usr/bin/env bash # (C) Copyright 2020 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. set -eaux if [[ ! -s versions ]] then echo "versions is missing or empty" >&2 exit 1 fi cat versions cd src for n in * do cd $n url=$(git remote -v | head -1 | awk '{print $2;}') sha1=$(git rev-parse HEAD) echo git $url $sha1 cd .. done cd .. ecmwflibs-0.7.0/scripts/common.sh0000775000175000017500000000445515201521641017200 0ustar alastairalastair#!/usr/bin/env bash # (C) Copyright 2020 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. set -eaux GIT_ECBUILD=https://github.com/ecmwf/ecbuild.git ECBUILD_VERSION=master GIT_ECCODES=https://github.com/ecmwf/eccodes.git ECCODES_VERSION=2.46.3 ECCODES_EXTRA_CMAKE_OPTIONS="-DENABLE_PNG=ON -DENABLE_JPG=ON" GIT_MAGICS=https://github.com/ecmwf/magics.git MAGICS_VERSION=4.16.1 GIT_SQLITE=https://github.com/sqlite/sqlite.git SQLITE_VERSION=master GIT_PROJ=https://github.com/OSGeo/PROJ.git PROJ_VERSION=master GIT_AEC=https://github.com/MathisRosenhauer/libaec.git AEC_VERSION=v1.1.3 GIT_PIXMAN=https://gitlab.freedesktop.org/pixman/pixman PIXMAN_VERSION=master GIT_CAIRO=https://gitlab.freedesktop.org/cairo/cairo CAIRO_VERSION=1.17.6 GIT_HARFBUZZ=https://github.com/harfbuzz/harfbuzz.git HARFBUZZ_VERSION=master GIT_FRIBIDI=https://github.com/fribidi/fribidi.git FRIBIDI_VERSION=master GIT_PANGO=https://gitlab.gnome.org/GNOME/pango.git PANGO_VERSION=master GIT_UDUNITS=https://github.com/b8raoult/UDUNITS-2.git UDUNITS_VERSION=master GIT_NETCDF=https://github.com/Unidata/netcdf-c.git NETCDF_VERSION=${NETCDF_VERSION:=master} GIT_HDF5=https://github.com/HDFGroup/hdf5.git HDF5_VERSION=${HDF5_VERSION:=hdf5_1_14_6} GIT_JPEG=https://github.com/libjpeg-turbo/libjpeg-turbo.git JPEG_VERSION=3.1.4.1 GIT_JASPER=https://github.com/jasper-software/jasper.git JASPER_VERSION=version-4.2.9 mkdir -p src rm -fr src/ecbuild src/eccodes src/magics mkdir -p build build-ecmwf find build -mindepth 1 -maxdepth 1 -exec rm -rf {} + find build-ecmwf -mindepth 1 -maxdepth 1 -exec rm -rf {} + git clone --branch $ECBUILD_VERSION $GIT_ECBUILD src/ecbuild git clone --branch $ECCODES_VERSION $GIT_ECCODES src/eccodes git clone --branch $MAGICS_VERSION $GIT_MAGICS src/magics mkdir -p build-ecmwf/eccodes mkdir -p build-ecmwf/magics TOPDIR=$(/bin/pwd) echo "================================================================================" env | sort echo "================================================================================" ecmwflibs-0.7.0/scripts/build-windows.sh0000775000175000017500000001025115201521641020466 0ustar alastairalastair#!/usr/bin/env bash # (C) Copyright 2020 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. set -eaux : > versions source scripts/common.sh here=$(pwd) cd $VCPKG_INSTALLATION_ROOT url=$(git remote -v | head -1 | awk '{print $2;}') # git checkout 2021.05.12 sha1=$(git rev-parse HEAD) cd $here echo git $url $sha1 > versions # the results of the following suggested that pkg-config.exe is not installed on the latest # Windows runner #find /c/ -name pkg-config.exe #exit 1 # if [[ $WINARCH == "x64" ]]; then # PKG_CONFIG_EXECUTABLE=/c/rtools43/mingw64/bin/pkg-config.exe # else # PKG_CONFIG_EXECUTABLE=/c/rtools43/mingw32/bin/pkg-config.exe # fi vcpkg install pkgconf for p in expat netcdf-c[netcdf-4] pango sqlite3[core,tool] libpng do vcpkg install $p:$WINARCH-windows n=$(echo $p | sed 's/\[.*//') v=$(vcpkg list $n | awk '{print $2;}') echo "vcpkg $n $v" >> versions done echo ================================================================= find $VCPKG_INSTALLATION_ROOT -type f -name png.h -print echo ================================================================= pip install ninja wheel dll-diagnostics echo "pip $(pip freeze | grep dll-diagnostics | sed 's/==/ /')" >> versions # Build libaec git clone $GIT_AEC src/aec cd src/aec git checkout $AEC_VERSION cd $TOPDIR mkdir -p build-other/aec cd build-other/aec cmake \ $TOPDIR/src/aec -G"NMake Makefiles" \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_INSTALL_PREFIX=$TOPDIR/install \ -DCMAKE_TOOLCHAIN_FILE=/c/vcpkg/scripts/buildsystems/vcpkg.cmake \ -DCMAKE_C_COMPILER=cl.exe cd $TOPDIR cmake --build build-other/aec --target install # Build proj git clone $GIT_PROJ src/proj cd src/proj git checkout $PROJ_VERSION cd $TOPDIR mkdir -p build-other/proj cd build-other/proj cmake \ $TOPDIR/src/proj -G"NMake Makefiles" \ -DCMAKE_BUILD_TYPE=RelWithDebInfo \ -DENABLE_TIFF=0 \ -DENABLE_CURL=0 \ -DBUILD_TESTING=0 \ -DBUILD_PROJSYNC=0 \ -DSQLITE3_BIN_PATH=C:/vcpkg/packages/sqlite3_${WINARCH}-windows/tools/sqlite3.exe \ -DBUILD_SHARED_LIBS=1 \ -DCMAKE_INSTALL_PREFIX=$TOPDIR/install \ -DCMAKE_TOOLCHAIN_FILE=/c/vcpkg/scripts/buildsystems/vcpkg.cmake \ -DCMAKE_C_COMPILER=cl.exe cd $TOPDIR cmake --build build-other/proj --target install # Build eccodes cd $TOPDIR/build-ecmwf/eccodes $TOPDIR/src/ecbuild/bin/ecbuild \ $TOPDIR/src/eccodes \ -G"NMake Makefiles" \ -DCMAKE_BUILD_TYPE=RelWithDebInfo \ -DENABLE_PYTHON=0 \ -DENABLE_FORTRAN=0 \ -DENABLE_BUILD_TOOLS=0 \ -DENABLE_MEMFS=1 \ -DENABLE_INSTALL_ECCODES_DEFINITIONS=0 \ -DENABLE_INSTALL_ECCODES_SAMPLES=0 \ -DCMAKE_INSTALL_PREFIX=$TOPDIR/install \ -DCMAKE_TOOLCHAIN_FILE=/c/vcpkg/scripts/buildsystems/vcpkg.cmake \ -DCMAKE_C_COMPILER=cl.exe $ECCODES_EXTRA_CMAKE_OPTIONS # -DPKG_CONFIG_EXECUTABLE=$PKG_CONFIG_EXECUTABLE cd $TOPDIR cmake --build build-ecmwf/eccodes --target install # Build magics # -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON # cd $TOPDIR/build-ecmwf/magics $TOPDIR/src/ecbuild/bin/ecbuild \ $TOPDIR/src/magics \ -G"NMake Makefiles" \ -DCMAKE_BUILD_TYPE=RelWithDebInfo \ -DENABLE_PYTHON=0 \ -DENABLE_FORTRAN=0 \ -DENABLE_BUILD_TOOLS=0 \ -Deccodes_DIR=$TOPDIR/install/lib/cmake/eccodes \ -DCMAKE_INSTALL_PREFIX=$TOPDIR/install \ -DCMAKE_TOOLCHAIN_FILE=/c/vcpkg/scripts/buildsystems/vcpkg.cmake \ -DCMAKE_C_COMPILER=cl.exe # -DPKG_CONFIG_EXECUTABLE=$PKG_CONFIG_EXECUTABLE cd $TOPDIR cmake --build build-ecmwf/magics --target install # Create wheel rm -fr dist wheelhouse ecmwflibs/share cp -r install/share ecmwflibs/ rm -fr ecmwflibs/share/magics/efas mkdir -p ecmwflibs/share/proj python tools/copy-dlls.py install/bin/MagPlus.dll ecmwflibs/ pip install -r tools/requirements.txt find ecmwflibs -name '*.dll' > libs python ./tools/copy-licences.py libs mkdir -p install/include ./scripts/versions.sh > ecmwflibs/versions.txt ecmwflibs-0.7.0/scripts/c-no-arch.sh0000775000175000017500000000034515201521641017451 0ustar alastairalastair#!/bin/bash set -ex skip=0 for c do shift if [[ "$c" == "-arch" ]]; then skip=1 continue fi if [[ $skip -eq 1 ]]; then skip=0 continue fi set -- "$@" "$c" done clang "$@" ecmwflibs-0.7.0/scripts/wheel-macos-arm.sh0000775000175000017500000000337315201521641020667 0ustar alastairalastair#!/usr/bin/env bash # (C) Copyright 2020 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. set -eaux arch=$(arch) [[ $arch == "i386" ]] && arch="x86_64" # GitHub Actions on macOS declare i386 ARCH="arch -$arch" diet() { if [[ $arch == "x86_64" ]]; then return fi # Remove the architectures we don't need echo ================================================================= pwd cd dist pwd name=$(ls -1 *.whl) echo $name unzip *.whl ls -l cd ecmwflibs ls -l so=$(ls -1 *.so) echo "$so" lipo -thin $arch $so -output $so.$arch mv $so.$arch $so lipo -info $so cd .. pwd zip -r $name ecmwflibs cd .. echo ================================================================= pwd ls -l dist } # version=$(echo $1| sed 's/\.//') env | sort pip3 install wheel delocate setuptools rm -fr dist wheelhouse tmp $ARCH python3 setup.py bdist_wheel diet name=$(ls -1 dist/*.whl) newname=$(echo $name | sed "s/_universal2/_${arch}/") echo $name $newname # Do it twice to get the list of libraries $ARCH delocate-wheel -w wheelhouse dist/*.whl unzip -l wheelhouse/*.whl | grep 'dylib' >libs pip3 install -r tools/requirements.txt python3 ./tools/copy-licences.py libs DISTUTILS_DEBUG=1 rm -fr dist wheelhouse $ARCH python3 setup.py bdist_wheel # --plat-name $arch diet # mv dist/$name $newname # find dist/*.dist-info -print $ARCH delocate-wheel -w wheelhouse dist/*.whl ecmwflibs-0.7.0/scripts/wheel-linux.sh0000775000175000017500000000230515201521641020141 0ustar alastairalastair#!/usr/bin/env bash # (C) Copyright 2020 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. set -eaux version=$(echo $1| sed 's/\.//') pybin=$(ls -1d /opt/python/cp${version}-cp${version}*/bin/python3 2>/dev/null | head -1) if [[ -z "$pybin" ]] then pybin=$(ls -1d /opt/python/cp${version}t-cp${version}t*/bin/python3 2>/dev/null | head -1) fi if [[ -z "$pybin" ]] then echo "Cannot find Python binary for cp${version} under /opt/python" exit 1 fi TOPDIR=$(/bin/pwd) export LD_LIBRARY_PATH=$TOPDIR/install/lib:$TOPDIR/install/lib64:${LD_LIBRARY_PATH:-} rm -fr dist wheelhouse $pybin setup.py bdist_wheel # Do it twice to get the list of libraries auditwheel repair dist/*.whl unzip -l wheelhouse/*.whl | grep 'ecmwflibs.libs/' > libs pip3 install -r tools/requirements.txt python3 ./tools/copy-licences.py libs rm -fr dist wheelhouse $pybin setup.py bdist_wheel auditwheel repair dist/*.whl rm -fr dist ecmwflibs-0.7.0/scripts/wheel-windows.sh0000775000175000017500000000105715201521641020477 0ustar alastairalastair#!/usr/bin/env bash # (C) Copyright 2020 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. set -eaux python -m pip install --upgrade pip setuptools wheel rm -fr dist wheelhouse ecmwflibs.egg-info build python setup.py bdist_wheel mv dist wheelhouse ecmwflibs-0.7.0/scripts/debug-windows.sh0000775000175000017500000000132115201521641020453 0ustar alastairalastair#!/usr/bin/env bash # (C) Copyright 2020 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. set -eaux for p in netcdf-c[core,netcdf-4,hdf5] do echo $p:$WINARCH-windows vcpkg install $p:$WINARCH-windows done cd tests cmake . \ -G"NMake Makefiles" \ -DCMAKE_TOOLCHAIN_FILE=/c/vcpkg/scripts/buildsystems/vcpkg.cmake \ -DCMAKE_C_COMPILER=cl.exe cmake --build . ls -lrt ./open_netcdf test.nc4 ecmwflibs-0.7.0/scripts/cxx-no-arch.sh0000775000175000017500000000034715201521641020033 0ustar alastairalastair#!/bin/bash set -ex skip=0 for c do shift if [[ "$c" == "-arch" ]]; then skip=1 continue fi if [[ $skip -eq 1 ]]; then skip=0 continue fi set -- "$@" "$c" done clang++ "$@" ecmwflibs-0.7.0/scripts/build-linux.sh0000775000175000017500000002401215201521641020133 0ustar alastairalastair#!/usr/bin/env bash # (C) Copyright 2020 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. # (rm -fr build-other/netcdf/; cd src/netcdf/; git checkout -- .; git clean -f .) set -eaux : > versions SUDO="" if [[ $(id -u) -ne 0 ]] then SUDO="sudo" fi PKG_MGR="" if command -v yum >/dev/null 2>&1 then PKG_MGR="yum" elif command -v dnf >/dev/null 2>&1 then PKG_MGR="dnf" else echo "Neither yum nor dnf found" exit 1 fi PKG_MGR_INSTALL_OPTS=(-y) if [[ "$PKG_MGR" == "dnf" ]] then repo_files=(/etc/yum.repos.d/*.repo) if grep -Eq '/8\.[0-9]+/' "${repo_files[@]}" 2>/dev/null then $SUDO sed -i -E 's#/8\.[0-9]+/#/8/#g' "${repo_files[@]}" || true fi rhel_major=$(rpm -E '%{rhel}' 2>/dev/null || true) if [[ -n "$rhel_major" ]] then PKG_MGR_INSTALL_OPTS+=(--releasever="$rhel_major") fi PKG_MGR_INSTALL_OPTS+=(--refresh) $SUDO dnf clean all || true fi pkg_install() { local pkg="$1" local max_attempts=3 local attempt=1 while (( attempt <= max_attempts )) do if $SUDO $PKG_MGR install "${PKG_MGR_INSTALL_OPTS[@]}" "$pkg" then return 0 fi if (( attempt == max_attempts )) then return 1 fi sleep $(( attempt * 5 )) attempt=$(( attempt + 1 )) done } # We want the sqlite3 we just compiled PATH=$(pwd)/install/bin:$PATH # The version in master does not compile with disabled curl support NETCDF_VERSION=v4.6.0 source scripts/common.sh for p in libpng-devel libtiff-devel fontconfig-devel gobject-introspection-devel expat-devel cairo-devel do pkg_install "$p" # There may be a better way $SUDO $PKG_MGR install "${PKG_MGR_INSTALL_OPTS[@]}" "$p" 2>&1 > tmp cat tmp v=$(grep 'already installed' < tmp | awk '{print $2;}' | sed 's/\\d://') echo "yum $p $v" >> versions done pkg_install flex pkg_install bison pkg_install pax-utils # For lddtree bootstrap_python=$(ls -1d /opt/python/cp3*/bin/python3 | head -1) bootstrap_pip=$(dirname "$bootstrap_python")/pip3 bootstrap_python_config=$(dirname "$bootstrap_python")/python3-config $SUDO ln -sf "$bootstrap_python" /usr/local/bin/python3 $SUDO ln -sf "$bootstrap_python_config" /usr/local/bin/python3-config $SUDO ln -sf "$bootstrap_pip" /usr/local/bin/pip3 $SUDO pip3 install ninja auditwheel meson $SUDO ln -sf $(dirname "$bootstrap_python")/meson /usr/local/bin/meson $SUDO ln -sf $(dirname "$bootstrap_python")/ninja /usr/local/bin/ninja export PKG_CONFIG_PATH=/usr/lib64/pkgconfig:/usr/lib/pkgconfig:${PKG_CONFIG_PATH:-} export PKG_CONFIG_PATH=$TOPDIR/install/lib/pkgconfig:$TOPDIR/install/lib64/pkgconfig:$PKG_CONFIG_PATH export LD_LIBRARY_PATH=$TOPDIR/install/lib:$TOPDIR/install/lib64:${LD_LIBRARY_PATH:-} # Build sqlite [[ -d src/sqlite ]] || git clone --depth 1 $GIT_SQLITE src/sqlite cd src/sqlite ./configure \ --disable-tcl \ --prefix=$TOPDIR/install cd $TOPDIR make -C src/sqlite install # Build proj [[ -d src/proj ]] || git clone $GIT_PROJ src/proj cd src/proj git checkout $PROJ_VERSION cd $TOPDIR mkdir -p build-other/proj cd build-other/proj cmake \ $TOPDIR/src/proj -GNinja \ -DCMAKE_BUILD_TYPE=RelWithDebInfo \ -DENABLE_TIFF=0 \ -DENABLE_CURL=0 \ -DBUILD_TESTING=0 \ -DBUILD_PROJSYNC=0 \ -DBUILD_SHARED_LIBS=1 \ -DCMAKE_INSTALL_PREFIX=$TOPDIR/install cd $TOPDIR cmake --build build-other/proj --target install # Build libaec (required by ecCodes for CCSDS/AEC compression) [[ -d src/aec ]] || git clone $GIT_AEC src/aec cd src/aec git checkout $AEC_VERSION cd $TOPDIR mkdir -p build-other/aec cd build-other/aec cmake \ $TOPDIR/src/aec -GNinja \ -DCMAKE_BUILD_TYPE=RelWithDebInfo \ -DBUILD_SHARED_LIBS=1 \ -DCMAKE_INSTALL_PREFIX=$TOPDIR/install cd $TOPDIR cmake --build build-other/aec --target install libaec_config_file=$(find "$TOPDIR/install" -maxdepth 6 \( -name 'libaec-config.cmake' -o -name 'libaecConfig.cmake' \) -print | head -1 || true) libaec_cmake_dir="" if [[ -n "$libaec_config_file" ]] then libaec_cmake_dir=$(dirname "$libaec_config_file") fi if [[ -z "$libaec_cmake_dir" ]] then echo "Could not find libaec CMake package under $TOPDIR/install" find "$TOPDIR/install" -maxdepth 5 \( -name 'libaec-config.cmake' -o -name 'libaecConfig.cmake' \) -print || true exit 1 fi # Build jasper (provides libjasper.so, required by ecCodes) [[ -d src/jasper ]] || git clone $GIT_JASPER src/jasper cd src/jasper git checkout $JASPER_VERSION cd $TOPDIR mkdir -p build-other/jasper cd build-other/jasper cmake \ $TOPDIR/src/jasper -GNinja \ -DCMAKE_BUILD_TYPE=RelWithDebInfo \ -DBUILD_SHARED_LIBS=1 \ -DJAS_ENABLE_OPENGL=OFF \ -DJAS_ENABLE_DOC=OFF \ -DJAS_ENABLE_PROGRAMS=OFF \ -DCMAKE_PREFIX_PATH=$TOPDIR/install \ -DCMAKE_INSTALL_PREFIX=$TOPDIR/install cd $TOPDIR cmake --build build-other/jasper --target install # Build libjpeg-turbo (provides libjpeg.so.62, required by ecCodes JPEG support) [[ -d src/jpeg ]] || git clone $GIT_JPEG src/jpeg cd src/jpeg git checkout $JPEG_VERSION cd $TOPDIR mkdir -p build-other/jpeg cd build-other/jpeg cmake \ $TOPDIR/src/jpeg -GNinja \ -DCMAKE_BUILD_TYPE=RelWithDebInfo \ -DBUILD_SHARED_LIBS=1 \ -DCMAKE_INSTALL_PREFIX=$TOPDIR/install cd $TOPDIR cmake --build build-other/jpeg --target install # Build HDF5 (provides libhdf5.so + libhdf5_hl.so, required by netcdf and ecCodes) [[ -d src/hdf5 ]] || git clone $GIT_HDF5 src/hdf5 cd src/hdf5 git checkout $HDF5_VERSION cd $TOPDIR mkdir -p build-other/hdf5 cd build-other/hdf5 cmake \ $TOPDIR/src/hdf5 -GNinja \ -DCMAKE_BUILD_TYPE=RelWithDebInfo \ -DBUILD_SHARED_LIBS=1 \ -DHDF5_BUILD_HL_LIB=ON \ -DHDF5_BUILD_TOOLS=OFF \ -DHDF5_BUILD_EXAMPLES=OFF \ -DHDF5_BUILD_TESTS=OFF \ -DHDF5_ENABLE_Z_LIB_SUPPORT=ON \ -DCMAKE_INSTALL_PREFIX=$TOPDIR/install cd $TOPDIR cmake --build build-other/hdf5 --target install # Build netcdf [[ -d src/netcdf ]] || git clone $GIT_NETCDF src/netcdf cd src/netcdf git checkout $NETCDF_VERSION rm -fr $TOPDIR/build-other/netcdf mkdir -p $TOPDIR/build-other/netcdf cd $TOPDIR/build-other/netcdf cmake -GNinja \ $TOPDIR/src/netcdf \ -DCMAKE_BUILD_TYPE=RelWithDebInfo \ -DENABLE_DAP=0 \ -DENABLE_DISKLESS=0 \ -DBUILD_TESTING:BOOL=OFF \ -DENABLE_TESTS:BOOL=OFF \ -DHDF5_ROOT=$TOPDIR/install \ -DCMAKE_PREFIX_PATH=$TOPDIR/install \ -DCMAKE_INSTALL_PREFIX=$TOPDIR/install cd $TOPDIR cmake --build build-other/netcdf --target install # Pixman is needed by cairo [[ -d src/pixman ]] || git clone --depth 1 $GIT_PIXMAN src/pixman cd src/pixman meson setup --prefix=$TOPDIR/install \ -Dwrap_mode=nofallback \ $TOPDIR/build-other/pixman cd $TOPDIR ninja -C build-other/pixman install # Build cairo # -Dqt=disabled [[ -d src/cairo ]] || git clone $GIT_CAIRO src/cairo cd src/cairo git checkout $CAIRO_VERSION meson setup --prefix=$TOPDIR/install \ -Dwrap_mode=nofallback \ -Dxlib=disabled \ -Dxcb=disabled \ $TOPDIR/build-other/cairo cd $TOPDIR ninja -C build-other/cairo install # Build harfbuzz needed by pango [[ -d src/harfbuzz ]] || git clone --depth 1 $GIT_HARFBUZZ src/harfbuzz mkdir -p build-other/harfbuzz cd src/harfbuzz meson setup --prefix=$TOPDIR/install \ -Dwrap_mode=nofallback \ $TOPDIR/build-other/harfbuzz cd $TOPDIR ninja -C build-other/harfbuzz install # Build fridibi needed by pango [[ -d src/fridibi ]] || git clone --depth 1 $GIT_FRIBIDI src/fridibi mkdir -p build-other/fridibi cd src/fridibi meson setup --prefix=$TOPDIR/install \ -Dwrap_mode=nofallback \ -Ddocs=false \ $TOPDIR/build-other/fridibi cd $TOPDIR ninja -C build-other/fridibi install # Build pango # Versions after 1.43.0 require versions of glib2 higher than # the one in the dockcross image # We undefine G_LOG_USE_STRUCTURED because otherwise we will have a # undefined symbol g_log_structured_standard() when running on recent # docker images with recent versions of glib [[ -d src/pango ]] || git clone --branch 1.43.0 $GIT_PANGO src/pango # cd src/pango # git checkout 1.43.0 sed 's/.*G_LOG_USE_STRUCTURED.*//' < src/pango/meson.build > src/pango/meson.build.patched cp src/pango/meson.build.patched src/pango/meson.build sed 's/.*G_LOG_USE_STRUCTURED.*//' < src/pango/pango/meson.build > src/pango/pango/meson.build.patched cp src/pango/pango/meson.build.patched src/pango/pango/meson.build mkdir -p build-other/pango cd src/pango meson setup --prefix=$TOPDIR/install \ -Dwrap_mode=nofallback \ $TOPDIR/build-other/pango cd $TOPDIR ninja -C build-other/pango install # Build eccodes cd $TOPDIR/build-ecmwf/eccodes $TOPDIR/src/ecbuild/bin/ecbuild \ $TOPDIR/src/eccodes \ -GNinja \ -DCMAKE_BUILD_TYPE=RelWithDebInfo \ -DENABLE_PYTHON=0 \ -DENABLE_FORTRAN=0 \ -DENABLE_BUILD_TOOLS=0 \ -DENABLE_MEMFS=1 \ -DENABLE_INSTALL_ECCODES_DEFINITIONS=0 \ -DENABLE_INSTALL_ECCODES_SAMPLES=0 \ -DCMAKE_PREFIX_PATH="$TOPDIR/install;$TOPDIR/install/lib/cmake;$TOPDIR/install/lib64/cmake" \ -Dlibaec_DIR="$libaec_cmake_dir" \ -DCMAKE_INSTALL_PREFIX=$TOPDIR/install $ECCODES_EXTRA_CMAKE_OPTIONS cd $TOPDIR cmake --build build-ecmwf/eccodes --target install # Build magics cd $TOPDIR/build-ecmwf/magics $TOPDIR/src/ecbuild/bin/ecbuild \ $TOPDIR/src/magics \ -GNinja \ -DCMAKE_BUILD_TYPE=RelWithDebInfo \ -DENABLE_PYTHON=0 \ -DENABLE_FORTRAN=0 \ -DENABLE_BUILD_TOOLS=0 \ -Deccodes_DIR=$TOPDIR/install/lib/cmake/eccodes \ -DCMAKE_INSTALL_PREFIX=$TOPDIR/install cd $TOPDIR cmake --build build-ecmwf/magics --target install # Create wheel lddtree install/lib*/libMagPlus.so rm -fr dist wheelhouse ecmwflibs/share cp -r install/share ecmwflibs/ rm -fr ecmwflibs/share/magics/efas cp install/lib64/*.so install/lib/ strip --strip-debug install/lib/*.so ./scripts/versions.sh > ecmwflibs/versions.txt ecmwflibs-0.7.0/README.md0000664000175000017500000000214415201521641015132 0ustar alastairalastair# ecmwflibs A Python package that wraps some of ECMWF libraries to be used by Python interfaces to ECMWF software. ## Requirements - Python 3.10 or newer The snippet of code below should return the path to the *ecCodes* shared library. ```python import ecmwflibs lib = ecmwflibs.find("eccodes") ``` You can get the versions of libraries: ```python import ecmwflibs print(ecmwflibs.versions()) {'eccodes': '2.46.3', 'magics': '4.16.1', 'ecmwflibs': '0.7.0'} ``` ## Possible issues If you get this message on Windows: `DLL load failed while importing _ecmwflibs: The specified module could not be found.` this means that the C++ runtime library is not installed. Please download and install `vc_redist.x86.exe` or `vc_redist.x64.exe` from https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads. ## Acknowledgements *ecmwflibs* comes packaged with some third-party open source libraries which are dependencies of *Magics* and *ecCodes*. To display the list of embedded libraries and their copyright notices and/or licenses, please type: ```bash python3 -m ecmwflibs credits ``` ecmwflibs-0.7.0/test.py0000664000175000017500000000015315201521641015202 0ustar alastairalastairfrom climetlab.utils.html import urlify print(urlify("https://raspstephan.github.io/blog/weatherbench/")) ecmwflibs-0.7.0/NOTICE.md0000664000175000017500000000023115201521641015151 0ustar alastairalastair# Notice To display the list of embedded libraries and their copyright notices and/or licenses, please type: ```bash python3 -m ecmwflibs credits ``` ecmwflibs-0.7.0/tools/0000775000175000017500000000000015201521641015012 5ustar alastairalastairecmwflibs-0.7.0/tools/copy-dlls.py0000664000175000017500000000172015201521641017272 0ustar alastairalastair#!/usr/bin/env python import os import shutil import sys from dlldiag.common import ModuleHeader VCPKG1 = "C:/vcpkg/installed/{}-windows/bin/{}" VCPKG2 = "C:/vcpkg/installed/{}-windows/debug/bin/{}" def scan_module(module, depth, seen): name = os.path.basename(module) if name in seen: return if not os.path.exists(module): return print(" " * depth, module) seen[name] = module header = ModuleHeader(module) cwd = os.path.dirname(module) architecture = header.getArchitecture() for dll in header.listAllImports(): # print("DEBUG", dll) scan_module((cwd + "/" + dll), depth + 3, seen) scan_module(VCPKG1.format(architecture, dll), depth + 3, seen) scan_module(VCPKG2.format(architecture, dll), depth + 3, seen) seen = {} scan_module(sys.argv[1], 0, seen) for k, v in seen.items(): target = sys.argv[2] + "/" + k print("Copy", v, "to", target) shutil.copyfile(v, target) ecmwflibs-0.7.0/tools/sha1.sh0000775000175000017500000000052215201521641016204 0ustar alastairalastair#!/usr/bin/env bash here=$(dirname $0) source $here/../make/VERSIONS.make eccodes=$(git ls-remote $GIT_ECCODES $ECCODES_VERSION | awk '{print $1;}') magics=$(git ls-remote $GIT_MAGICS $MAGICS_VERSION | awk '{print $1;}') echo $eccodes echo $magics echo "::set-output name=eccodes::${eccodes}" echo "::set-output name=magics::${magics}" ecmwflibs-0.7.0/tools/requirements.txt0000664000175000017500000000001215201521641020267 0ustar alastairalastairhtml2text ecmwflibs-0.7.0/tools/copy-licences.py0000664000175000017500000002715715201521641020135 0ustar alastairalastair#!/usr/bin/env python import json import os import re import socket import time import sys import urllib.error import urllib.request try: from html2text import html2text except ImportError: html2text = None def identity(x): return x _HEADERS = { "User-Agent": ( "Mozilla/5.0 (X11; Linux x86_64; rv:125.0) Gecko/20100101 Firefox/125.0" ), "Accept": "text/html,text/plain,*/*;q=0.8", "Accept-Language": "en-US,en;q=0.5", } def _local_fallback_path(url): base = os.path.basename(url.rstrip("/")) if not base: return None licenses_dir = os.path.join(os.path.dirname(__file__), "licenses") for candidate in (base, base.lower()): path = os.path.join(licenses_dir, candidate) if os.path.exists(path): return path return None def fetch_url_text(url, lib_name, timeout=30, attempts=3): errors = [] for attempt in range(1, attempts + 1): try: req = urllib.request.Request(url, headers=_HEADERS) with urllib.request.urlopen(req, timeout=timeout) as response: return response.read().decode("utf-8") except urllib.error.HTTPError as error: body_preview = error.read().decode("utf-8", errors="replace").strip() if len(body_preview) > 500: body_preview = f"{body_preview[:500]}..." details = [ f"URL: {url}", f"Attempt: {attempt}/{attempts}", f"HTTP status: {error.code}", f"Reason: {error.reason}", ] if body_preview: details.append(f"Response body (first 500 chars):\n{body_preview}") errors.append("\n".join(details)) except (urllib.error.URLError, TimeoutError, socket.timeout, OSError) as error: reason = getattr(error, "reason", str(error)) errors.append( f"URL: {url}\n" f"Attempt: {attempt}/{attempts}\n" f"Network error: {reason}" ) if attempt < attempts: time.sleep(attempt) fallback_path = _local_fallback_path(url) if fallback_path: with open(fallback_path, "r", encoding="utf-8") as fallback_file: return fallback_file.read() raise RuntimeError( f"Failed to download license for {lib_name}.\n" + "\n\n---\n\n".join(errors) ) ENTRIES = { "libMagPlus": { "home": "https://github.com/ecmwf/magics", "copying": "https://raw.githubusercontent.com/ecmwf/magics/develop/LICENSE", }, "libeccodes": { "home": "https://github.com/ecmwf/eccodes", "copying": "https://raw.githubusercontent.com/ecmwf/eccodes/develop/LICENSE", }, "libnetcdf": { "home": "https://github.com/Unidata/netcdf-c", "copying": "https://raw.githubusercontent.com/Unidata/netcdf-c/master/COPYRIGHT", }, "libproj": { "home": "https://github.com/OSGeo/PROJ", "copying": "https://raw.githubusercontent.com/OSGeo/PROJ/master/COPYING", }, "libpixman": { "home": "https://gitlab.freedesktop.org/pixman/pixman", "copying": "https://gitlab.freedesktop.org/pixman/pixman/-/raw/master/COPYING", }, "libfribidi": { "home": "https://github.com/fribidi/fribidi", "copying": "https://raw.githubusercontent.com/fribidi/fribidi/master/COPYING", }, "libharfbuzz": { "home": "https://github.com/fribidi/fribidi", "copying": "https://raw.githubusercontent.com/fribidi/fribidi/master/COPYING", }, "libuuid": { "home": "https://github.com/karelzak/util-linux/tree/master/libuuid", "copying": "https://raw.githubusercontent.com/karelzak/util-linux/master/libuuid/COPYING", }, "libpango": { "home": "https://github.com/GNOME/pango", "copying": "https://raw.githubusercontent.com/GNOME/pango/master/COPYING", }, "libsqlite3": { "home": "https://sqlite.org/index.html", "copying": "Public Domain, see https://sqlite.org/copyright.html", }, "libfontconfig": { "home": "https://gitlab.freedesktop.org/fontconfig/fontconfig", "copying": "https://gitlab.freedesktop.org/fontconfig/fontconfig/-/raw/main/COPYING", }, "libbz2": { "home": "https://gitlab.com/federicomenaquintero/bzip2", "copying": "https://gitlab.com/federicomenaquintero/bzip2/-/raw/master/COPYING", }, "libhdf5": { "home": "https://github.com/HDFGroup/hdf5", "copying": "https://raw.githubusercontent.com/HDFGroup/hdf5/develop/LICENSE", }, "libhdf5_hl": None, # Assumed to be part of libhdf5 (hl = high level) "libpng": { "home": "https://github.com/glennrp/libpng", "copying": "https://raw.githubusercontent.com/glennrp/libpng/libpng16/LICENSE", }, "libaec": { "home": "https://github.com/MathisRosenhauer/libaec", "copying": "https://raw.githubusercontent.com/MathisRosenhauer/libaec/v1.1.3/LICENSE.txt", }, "libexpat": { "home": "https://libexpat.github.io", "copying": "https://raw.githubusercontent.com/libexpat/libexpat/master/expat/COPYING", }, "libz": { "home": "https://zlib.net", "copying": "https://zlib.net/zlib_license.html", "html": True, }, "libcairo": { "home": "https://cairographics.org", "copying": "https://gitlab.freedesktop.org/cairo/cairo/-/raw/master/COPYING", }, "libjasper": { "home": "https://github.com/jasper-software/jasper", "copying": "https://raw.githubusercontent.com/jasper-software/jasper/master/LICENSE.txt", }, "libopenjp2": { "home": "https://github.com/uclouvain/openjpeg", "copying": "https://raw.githubusercontent.com/uclouvain/openjpeg/master/LICENSE", }, # We build libjpeg-turbo from source (drop-in replacement, installs as libjpeg.so.62) "libjpeg": { "home": "https://github.com/libjpeg-turbo/libjpeg-turbo", "copying": "https://raw.githubusercontent.com/libjpeg-turbo/libjpeg-turbo/main/LICENSE.md", }, "libfreetype": { "home": "https://gitlab.freedesktop.org/freetype/freetype/", "copying": "https://gitlab.freedesktop.org/freetype/freetype/-/raw/master/docs/FTL.TXT", }, "libdatrie": { "home": "https://github.com/tlwg/libdatrie", "copying": "https://raw.githubusercontent.com/tlwg/libdatrie/master/COPYING", }, "libthai": { "home": "https://github.com/tlwg/libthai", "copying": "https://raw.githubusercontent.com/tlwg/libthai/master/COPYING", }, "libX11": { "home": "https://github.com/mirror/libX11", "copying": "https://raw.githubusercontent.com/mirror/libX11/master/COPYING", }, "libxcb": { "home": "https://github.com/corngood/libxcb", "copying": "https://raw.githubusercontent.com/corngood/libxcb/master/COPYING", }, "libpcre": { "home": "https://github.com/vmg/libpcre", "copying": "https://raw.githubusercontent.com/vmg/libpcre/master/LICENCE", }, "libgraphite2": { "home": "https://github.com/silnrsi/graphite", "copying": "https://raw.githubusercontent.com/silnrsi/graphite/master/COPYING", }, "libffi": { "home": "https://github.com/libffi/libffi", "copying": "https://raw.githubusercontent.com/libffi/libffi/master/LICENSE", }, "libtiff": { "home": "https://gitlab.com/libtiff/libtiff", "copying": "https://gitlab.com/libtiff/libtiff/-/raw/master/LICENSE.md", }, # See also https://www.gnu.org/software/gettext/manual/html_node/Discussions.html # intl(gettext) is GPL while libintl is LGPL "libintl": { "home": "https://www.gnu.org/software/gettext/manual/html_node/Licenses.html", "copying": "https://www.gnu.org/licenses/lgpl-3.0.txt", "html": True, }, # See also https://www.gnu.org/software/libiconv/ # iconv is GPL while libiconv is LGPL "libiconv": { "home": "https://www.gnu.org/software/libiconv/", "copying": "https://www.gnu.org/licenses/lgpl-3.0.txt", }, "libglib": { "home": "https://gitlab.gnome.org/GNOME/glib", "copying": "https://gitlab.gnome.org/GNOME/glib/-/raw/main/COPYING", }, "libbrotli": { "home": "https://github.com/google/brotli", "copying": "https://raw.githubusercontent.com/google/brotli/master/LICENSE", }, "libpcre2": { "home": "https://github.com/PCRE2Project/pcre2", "copying": "https://raw.githubusercontent.com/PCRE2Project/pcre2/main/LICENCE.md", }, "libzstd": { "home": "https://github.com/facebook/zstd", "copying": "https://raw.githubusercontent.com/facebook/zstd/master/LICENSE", }, # not completely clear what the definitive source for this library is "liblzma": { "home": "https://github.com/ShiftMediaProject/liblzma", "copying": "https://raw.githubusercontent.com/ShiftMediaProject/liblzma/master/COPYING", }, "libcurl": { "home": "https://github.com/curl/curl", "copying": "https://raw.githubusercontent.com/curl/curl/master/COPYING", }, "libtinyxml2": { "home": "https://github.com/leethomason/tinyxml2", "copying": "https://raw.githubusercontent.com/leethomason/tinyxml2/master/LICENSE.txt", }, } PATTERNS = { r"^libpng\d+$": "libpng", r"^libproj(_\d+)+$": "libproj", } ALIASES = { "libbrotlicommon": "libbrotli", "libbrotlidec": "libbrotli", "libpangowin32": "libpango", "libzlib1": "libz", "libeccodes_memfs": "libeccodes", "libgobject": "libglib", # Part of libglib "libgmodule": "libglib", # Part of libglib "libgio": "libglib", # Part of libglib "libpangoft2": "libpango", # Assumed to be part of libpango "libpangocairo": "libpango", # Assumed to be part of libpango "libhdf5_hl": "libhdf5", # Legacy HDF SZIP license pages were retired; map to libaec. "libsz": "libaec", "libszip": "libaec", # X.Org stack libraries shipped transitively with cairo/pango. "libXrender": "libX11", "libXdmcp": "libX11", "libXau": "libX11", "libXext": "libX11", } if False: for e in ENTRIES.values(): if isinstance(e, dict): copying = e["copying"] if copying.startswith("http"): urllib.request.urlopen(copying).close() libs = {} missing = [] seen = set() for line in open(sys.argv[1], "r", encoding="utf-8"): lib = "-no-regex-" lib = line.strip().split("/")[-1] lib = lib.split("-")[0].split(".")[0] if lib == "": continue if not lib.startswith("lib"): lib = f"lib{lib}" for k, v in PATTERNS.items(): if re.match(k, lib): lib = v lib = ALIASES.get(lib, lib) if lib not in ENTRIES: missing.append((lib, line)) continue if lib in seen: continue seen.add(lib) e = ENTRIES[lib] if e is None: continue libs[lib] = dict(path=f"copying/{lib}.txt", home=e["home"]) copying = e["copying"] filtering = identity if e.get("html") and html2text is not None: filtering = html2text if copying.startswith("http://") or copying.startswith("https://"): text = fetch_url_text(copying, lib) output_lines = filtering(text).split("\n") else: output_lines = copying.split("\n") with open(f"ecmwflibs/copying/{lib}.txt", "w", encoding="utf-8") as f: for n in output_lines: print(n, file=f) with open("ecmwflibs/copying/list.json", "w", encoding="utf-8") as f: print(json.dumps(libs), file=f) assert len(missing) == 0, json.dumps(missing, indent=4, sort_keys=True) ecmwflibs-0.7.0/tools/licenses/0000775000175000017500000000000015201521641016617 5ustar alastairalastairecmwflibs-0.7.0/tools/licenses/lgpl-3.0.txt0000664000175000017500000001674415201521641020630 0ustar alastairalastair GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. 0. Additional Definitions. As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to version 3 of the GNU General Public License. "The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. An "Application" is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. A "Combined Work" is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the "Linked Version". The "Minimal Corresponding Source" for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. The "Corresponding Application Code" for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. 1. Exception to Section 3 of the GNU GPL. You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. 2. Conveying Modified Versions. If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version: a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy. 3. Object Code Incorporating Material from Library Header Files. The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following: a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the object code with a copy of the GNU GPL and this license document. 4. Combined Works. You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following: a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the Combined Work with a copy of the GNU GPL and this license document. c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document. d) Do one of the following: 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source. 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version. e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.) 5. Combined Libraries. You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 6. Revised Versions of the GNU Lesser General Public License. The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. ecmwflibs-0.7.0/setup.py0000664000175000017500000000633615201521641015374 0ustar alastairalastair#!/usr/bin/env python3 # (C) Copyright 2020 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. # import io import os import os.path import sys from setuptools import Extension, find_packages, setup def read(fname): file_path = os.path.join(os.path.dirname(__file__), fname) return io.open(file_path, encoding="utf-8").read() version = None for line in read("ecmwflibs/__init__.py").split("\n"): if line.startswith("__version__"): version = line.split("=")[-1].strip()[1:-1] assert version libdir = os.path.realpath("install/lib") incdir = os.path.realpath("install/include") libs = ["eccodes", "MagPlus"] # https://docs.python.org/3/distutils/apiref.html ext_modules = [ Extension( "ecmwflibs._ecmwflibs", sources=["ecmwflibs/_ecmwflibs.cc"], language="c++", libraries=libs, library_dirs=[libdir], include_dirs=[incdir, os.path.join(incdir, "magics")], extra_link_args=["-Wl,-rpath," + libdir], ) ] def shared(directory): result = [] for path, dirs, files in os.walk(directory): for f in files: result.append(os.path.join(path, f)) return result # Paths must be relative to package directory... shared_files = ["versions.txt"] shared_files += [x[len("install/") :] for x in shared("install/share/magics")] shared_files += [x[len("ecmwflibs/") :] for x in shared("ecmwflibs/share/proj")] shared_files += [x[len("ecmwflibs/") :] for x in shared("ecmwflibs/etc")] shared_files += [x[len("ecmwflibs/") :] for x in shared("ecmwflibs/copying")] if os.name == "nt": for n in os.listdir("ecmwflibs"): if n.endswith(".dll"): shared_files.append(n) # print(shared_files) if "--universal" in sys.argv: ext_modules = [] with open("ecmwflibs/_universal", "wt"): pass shared_files = ["_universal"] setup( name="ecmwflibs", version=version, author="ECMWF", author_email="software.support@ecmwf.int", license="Apache 2.0", url="https://github.com/ecmwf/ecmwflibs", description="Wraps ECMWF tools (experimental)", long_description=read("README.md"), long_description_content_type="text/markdown", packages=find_packages(), include_package_data=True, package_data={"": shared_files}, install_requires=[ "findlibs", ], python_requires=">=3.10", zip_safe=True, classifiers=[ "Development Status :: 3 - Alpha", "Intended Audience :: Developers", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Programming Language :: Python :: 3.14", "Programming Language :: Python :: Implementation :: CPython", "Operating System :: OS Independent", ], ext_modules=ext_modules, ) ecmwflibs-0.7.0/tox.ini0000664000175000017500000000027615201521641015172 0ustar alastairalastair[flake8] ; ignore = E226,E302,E41 max-line-length = 120 ; exclude = tests/* ; See https://black.readthedocs.io/en/stable/the_black_code_style.html extend-ignore = E203 [isort] profile=black ecmwflibs-0.7.0/.gitignore0000664000175000017500000000412015201521641015637 0ustar alastairalastair# Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] *$py.class # C extensions *.so # Distribution / packaging .Python build/ develop-eggs/ dist/ downloads/ eggs/ .eggs/ lib/ lib64/ parts/ sdist/ var/ wheels/ pip-wheel-metadata/ share/python-wheels/ *.egg-info/ .installed.cfg *.egg MANIFEST # PyInstaller # Usually these files are written by a python script from a template # before PyInstaller builds the exe, so as to inject date/other infos into it. *.manifest *.spec # Installer logs pip-log.txt pip-delete-this-directory.txt # Unit test / coverage reports htmlcov/ .tox/ .nox/ .coverage .coverage.* .cache nosetests.xml coverage.xml *.cover *.py,cover .hypothesis/ .pytest_cache/ # Translations *.mo *.pot # Django stuff: *.log local_settings.py db.sqlite3 db.sqlite3-journal # Flask stuff: instance/ .webassets-cache # Scrapy stuff: .scrapy # Sphinx documentation docs/_build/ # PyBuilder target/ # Jupyter Notebook .ipynb_checkpoints # IPython profile_default/ ipython_config.py # pyenv .python-version # pipenv # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. # However, in case of collaboration, if having platform-specific dependencies or dependencies # having no cross-platform support, pipenv may install dependencies that don't work, or not # install all needed dependencies. #Pipfile.lock # PEP 582; used by e.g. github.com/David-OConnor/pyflow __pypackages__/ # Celery stuff celerybeat-schedule celerybeat.pid # SageMath parsed files *.sage.py # Environments .env .venv env/ venv/ ENV/ env.bak/ venv.bak/ # Spyder project settings .spyderproject .spyproject # Rope project settings .ropeproject # mkdocs documentation /site # mypy .mypy_cache/ .dmypy.json dmypy.json # Pyre type checker .pyre/ *.swp *.whl build/ wheelhouse/ dist/ build-ecmwf/ install-ecmwf/ install-other/ src/ build-other/ install/ dockcross-* .inited 2m_temperature.grib magics.png junk/ *.old ? ?.* *.save *.grib *.png *.nc ecmwflibs/versions.txt libs tmp .gitignore *.rb versions ecmwflibs/_ecmwflibs.py ecmwflibs/_universal *.ps .DS_Store build-m1/ ecmwflibs-0.7.0/LICENSE0000664000175000017500000002613515201521641014666 0ustar alastairalastair Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ecmwflibs-0.7.0/ecmwflibs.code-workspace0000664000175000017500000000032015201521641020450 0ustar alastairalastair{ "folders": [ { "path": "." }, { "path": "../magics-python" }, { "path": "../cfgrib" } ], "settings": { "files.associations": { "*.make": "makefile", "vector": "cpp" } } } ecmwflibs-0.7.0/HOWTO.md0000664000175000017500000000447215201521641015103 0ustar alastairalastair# ecmwflibs ## Compiling on a Mac ### Creating the macos version of the package Supported Python versions: 3.10 to 3.14. First make sure you have the required packages: ```bash brew install python3 brew install cmake brew install pango cairo proj pkg-config brew install netcdf ninja pip3 install delocate wheel ``` This can be achieved by simply typing: ```bash make tools ``` Then: ```bash cd ~/git/ecmwflibs make clean make twine upload wheelhouse/* ``` ### To select a specific supported Python version, use pyenv: ```bash brew install pyenv brew install pyenv-virtualenv pyenv install 3.10.16 pyenv virtualenv 3.10.16 py310 pyenv activate py310 pip3 install ninja delocate wheel cd ~/git/ecmwflibs make clean make twine upload wheelhouse/* ``` ### Creating the linux version of the package Cross compiling a Linux version on a Mac requires Docker installed. ```bash cd ~/git/ecmwflibs make image make clean ./dockcross-build-ecmwflibs make twine upload wheelhouse/* ``` You can also compile interactivaly ```bash ./dockcross-build-ecmwflibs bash make exit ``` ### Creating *all* linux versions of the package ```bash cd ~/git/ecmwflibs make image make clean ./dockcross-build-ecmwflibs make wheels.linux twine upload wheelhouse/* ``` ## Compiling on Linux Not tried, but the docker-based solution should work. # Usefull links On wheels: https://snarky.ca/the-challenges-in-designing-a-library-for-pep-425/ * https://stackoverflow.com/questions/47042483/how-to-build-and-distribute-a-python-cython-package-that-depends-on-third-party * https://cython.readthedocs.io/en/latest/src/tutorial/cython_tutorial.html * https://malramsay.com/post/perils_of_packaging/ * https://python-packaging-tutorial.readthedocs.io/en/latest/binaries_dependencies.html * https://scikit-build.readthedocs.io/en/latest/ * https://stackoverflow.com/questions/24347450/how-do-you-add-additional-files-to-a-wheel [vagrant@centos8 ~]$ pip3 install ecmwflibs Collecting ecmwflibs Could not find a version that satisfies the requirement ecmwflibs (from versions: ) No matching distribution found for ecmwflibs [vagrant@centos8 ~]$ pip3 install --upgrade pip3 Collecting pip3 Could not find a version that satisfies the requirement pip3 (from versions: ) No matching distribution found for pip3 [vagrant@centos8 ~]$ pip3 install --upgrade pip Collecting pip ecmwflibs-0.7.0/.github/0000775000175000017500000000000015201521641015212 5ustar alastairalastairecmwflibs-0.7.0/.github/workflows/0000775000175000017500000000000015201521641017247 5ustar alastairalastairecmwflibs-0.7.0/.github/workflows/build-macos.yml0000664000175000017500000001261215201521641022173 0ustar alastairalastair# (C) Copyright 2020 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. name: Build MacOS on: workflow_dispatch: {} release: types: [ created ] # repository_dispatch: # types: [eccodes-updated, magics-updated] push: paths: - "scripts/common.sh" - "scripts/build-macos.sh" - "scripts/wheel-macos.sh" - "tools/copy-licences.py" pull_request: branches: - master paths: - "scripts/common.sh" - "scripts/build-macos.sh" - "scripts/wheel-macos.sh" - "tools/copy-licences.py" jobs: build: # if: false runs-on: macos-latest name: Build steps: - uses: actions/checkout@v6 - name: Set up Python 3.10 uses: actions/setup-python@v5 with: python-version: "3.10" - run: ./scripts/build-macos.sh ################################################################ - name: Set up Python 3.10 uses: actions/setup-python@v5 with: python-version: "3.10" - run: ./scripts/wheel-macos.sh "3.10" - uses: actions/upload-artifact@v4 if: ${{ github.event_name != 'pull_request' }} name: Upload wheel 3.10 with: name: wheel-macos-3.10 path: wheelhouse/*.whl ################################################################ - name: Set up Python 3.11 uses: actions/setup-python@v5 with: python-version: "3.11" - run: ./scripts/wheel-macos.sh "3.11" - uses: actions/upload-artifact@v4 if: ${{ github.event_name != 'pull_request' }} name: Upload wheel 3.11 with: name: wheel-macos-3.11 path: wheelhouse/*.whl ################################################################ - name: Set up Python 3.12 uses: actions/setup-python@v5 with: python-version: "3.12" - run: ./scripts/wheel-macos.sh "3.12" - uses: actions/upload-artifact@v4 if: ${{ github.event_name != 'pull_request' }} name: Upload wheel 3.12 with: name: wheel-macos-3.12 path: wheelhouse/*.whl ################################################################ - name: Set up Python 3.13 uses: actions/setup-python@v5 with: python-version: "3.13" - run: ./scripts/wheel-macos.sh "3.13" - uses: actions/upload-artifact@v4 if: ${{ github.event_name != 'pull_request' }} name: Upload wheel 3.13 with: name: wheel-macos-3.13 path: wheelhouse/*.whl ################################################################ - name: Set up Python 3.14 uses: actions/setup-python@v5 with: python-version: "3.14" - run: ./scripts/wheel-macos.sh "3.14" - uses: actions/upload-artifact@v4 if: ${{ github.event_name != 'pull_request' }} name: Upload wheel 3.14 with: name: wheel-macos-3.14 path: wheelhouse/*.whl test: if: ${{ github.event_name != 'pull_request' }} needs: build runs-on: macos-latest strategy: fail-fast: true matrix: python-version: [ "3.10", "3.11", "3.12", "3.13", "3.14" ] name: Test with Python ${{ matrix.python-version }} steps: - uses: actions/checkout@v6 - name: Set up Python uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - uses: actions/download-artifact@v4 with: name: wheel-macos-${{ matrix.python-version }} # This is needed by numpy on some Python versions - run: pip install numpy - run: pip install *.whl - run: pip install -r tests/requirements.txt - run: pip freeze - name: Get some data run: | curl -L http://download.ecmwf.int/test-data/magics/2m_temperature.grib -o data.grib curl -L https://github.com/ecmwf/climetlab/raw/main/docs/examples/test.grib -o climetlab.grib curl -L https://github.com/ecmwf/climetlab/raw/main/docs/examples/test.nc -o climetlab.nc ls -l working-directory: tests - run: pytest -v -s working-directory: tests - uses: actions/upload-artifact@v4 if: ${{ github.event_name != 'pull_request' }} with: name: tests-macos-${{ matrix.python-version }} path: tests/*.png deploy: if: ${{ github.event_name == 'release' }} needs: [ test, build ] name: Deploy wheel ${{ matrix.python-version }} runs-on: ubuntu-latest strategy: fail-fast: true matrix: python-version: [ "3.10", "3.11", "3.12", "3.13", "3.14" ] steps: - name: Set up Python uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - run: pip install twine - uses: actions/download-artifact@v4 with: name: wheel-macos-${{ matrix.python-version }} - run: twine upload *.whl env: TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }} TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} ecmwflibs-0.7.0/.github/workflows/debug-windows.yml0000664000175000017500000000172515201521641022555 0ustar alastairalastair# (C) Copyright 2020 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. name: Debug Windows on: workflow_dispatch: {} push: paths: - "scripts/debug-windows.sh" jobs: build: runs-on: windows-latest defaults: run: shell: bash name: Debug Windows env: WINARCH: x64 steps: - uses: actions/checkout@v6 - uses: seanmiddleditch/gha-setup-vsdevenv@master with: arch: x64 - name: Set up Python uses: actions/setup-python@v5 with: python-version: "3.14" architecture: x64 - run: ./scripts/debug-windows.sh env: WINARCH: x64 ecmwflibs-0.7.0/.github/workflows/build-linux.yml0000664000175000017500000001463115201521641022233 0ustar alastairalastair# (C) Copyright 2020 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. name: Build Linux on: workflow_dispatch: {} release: types: [ created ] # repository_dispatch: # types: [eccodes-updated, magics-updated] push: branches: - master paths: - "scripts/common.sh" - "scripts/build-linux.sh" - "scripts/wheel-linux.sh" - "tools/copy-licences.py" pull_request: branches: - master paths: - "scripts/common.sh" - "scripts/build-linux.sh" - "scripts/wheel-linux.sh" - "tools/copy-licences.py" jobs: build_manylinux2014: runs-on: ubuntu-latest name: Build manylinux2014 steps: - uses: actions/checkout@v6 - run: | docker run --rm \ -v "$PWD:/workspace" \ -w /workspace \ dockcross/manylinux2014-x64:latest \ bash -lc './scripts/build-linux.sh' ################################################################ - run: | docker run --rm \ -v "$PWD:/workspace" \ -w /workspace \ dockcross/manylinux2014-x64:latest \ bash -lc './scripts/wheel-linux.sh 3.10' - uses: actions/upload-artifact@v4 name: Upload wheel 3.10 with: name: wheel-manylinux2014-3.10 path: wheelhouse/*.whl ################################################################ - run: | docker run --rm \ -v "$PWD:/workspace" \ -w /workspace \ dockcross/manylinux2014-x64:latest \ bash -lc './scripts/wheel-linux.sh 3.11' - uses: actions/upload-artifact@v4 name: Upload wheel 3.11 with: name: wheel-manylinux2014-3.11 path: wheelhouse/*.whl ################################################################ - run: | docker run --rm \ -v "$PWD:/workspace" \ -w /workspace \ dockcross/manylinux2014-x64:latest \ bash -lc './scripts/wheel-linux.sh 3.12' - uses: actions/upload-artifact@v4 name: Upload wheel 3.12 with: name: wheel-manylinux2014-3.12 path: wheelhouse/*.whl ################################################################ - run: | docker run --rm \ -v "$PWD:/workspace" \ -w /workspace \ dockcross/manylinux2014-x64:latest \ bash -lc './scripts/wheel-linux.sh 3.13' - uses: actions/upload-artifact@v4 name: Upload wheel 3.13 with: name: wheel-manylinux2014-3.13 path: wheelhouse/*.whl build_manylinux_2_28: runs-on: ubuntu-latest name: Build manylinux_2_28 steps: - uses: actions/checkout@v6 - run: | docker run --rm \ -v "$PWD:/workspace" \ -w /workspace \ dockcross/manylinux_2_28-x64:latest \ bash -lc './scripts/build-linux.sh' ################################################################ - run: | docker run --rm \ -v "$PWD:/workspace" \ -w /workspace \ dockcross/manylinux_2_28-x64:latest \ bash -lc './scripts/wheel-linux.sh 3.14' - uses: actions/upload-artifact@v4 name: Upload wheel 3.14 with: name: wheel-manylinux_2_28-3.14 path: wheelhouse/*.whl test: needs: [ build_manylinux2014, build_manylinux_2_28 ] strategy: fail-fast: false matrix: include: - python-version: "3.10" wheel-tag: manylinux2014 - python-version: "3.11" wheel-tag: manylinux2014 - python-version: "3.12" wheel-tag: manylinux2014 - python-version: "3.13" wheel-tag: manylinux2014 - python-version: "3.14" wheel-tag: manylinux_2_28 runs-on: ubuntu-latest env: ECCODES_PYTHON_USE_FINDLIBS: "1" name: Test with ${{ matrix.python-version }} steps: - uses: actions/checkout@v6 - name: Set up Python uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - uses: actions/download-artifact@v4 with: name: wheel-${{ matrix.wheel-tag }}-${{ matrix.python-version }} - run: pip install *.whl - run: pip install -r tests/requirements.txt - run: pip freeze - run: env | sort - name: Get some data run: | curl -L https://get.ecmwf.int/repository/test-data/metview/gallery/2m_temperature.grib -o data.grib curl -L https://github.com/ecmwf/climetlab/raw/main/docs/examples/test.grib -o climetlab.grib curl -L https://github.com/ecmwf/climetlab/raw/main/docs/examples/test.nc -o climetlab.nc ls -l working-directory: tests - run: pytest -v -s working-directory: tests - uses: actions/upload-artifact@v4 with: name: tests-${{ matrix.wheel-tag }}-${{ matrix.python-version }} path: tests/*.png deploy: if: ${{ github.event_name == 'release' }} strategy: fail-fast: false matrix: include: - python-version: "3.10" wheel-tag: manylinux2014 - python-version: "3.11" wheel-tag: manylinux2014 - python-version: "3.12" wheel-tag: manylinux2014 - python-version: "3.13" wheel-tag: manylinux2014 - python-version: "3.14" wheel-tag: manylinux_2_28 needs: [ test, build_manylinux2014, build_manylinux_2_28 ] name: Deploy wheel ${{ matrix.python-version }} runs-on: ubuntu-latest steps: - name: Set up Python uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - run: pip install twine - uses: actions/download-artifact@v4 with: name: wheel-${{ matrix.wheel-tag }}-${{ matrix.python-version }} - run: twine upload *.whl env: TWINE_USERNAME: __token__ TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }} ecmwflibs-0.7.0/.github/workflows/build-windows.yml0000664000175000017500000002015315201521641022562 0ustar alastairalastair# (C) Copyright 2020 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. name: Build Windows on: workflow_dispatch: {} release: types: [ created ] # repository_dispatch: # types: [eccodes-updated, magics-updated] push: paths: - "scripts/common.sh" - "scripts/build-windows.sh" - "scripts/wheel-windows.sh" - "tools/copy-licences.py" - "tools/copy-dlls.py" pull_request: branches: - master paths: - "scripts/common.sh" - "scripts/build-windows.sh" - "scripts/wheel-windows.sh" - "tools/copy-licences.py" - "tools/copy-dlls.py" jobs: build: runs-on: windows-latest strategy: fail-fast: false matrix: architecture: [ "x64" ] defaults: run: shell: bash name: Build on ${{ matrix.architecture }} env: WINARCH: ${{ matrix.architecture }} steps: - uses: actions/checkout@v6 - uses: seanmiddleditch/gha-setup-vsdevenv@master with: arch: ${{ matrix.architecture }} - name: Set up Python uses: actions/setup-python@v5 with: python-version: "3.10" architecture: ${{ matrix.architecture }} - name: Apply mirror if: false run: | import os a = "repo.msys2.org" b = "mirror.yandex.ru/mirrors/msys2" for root, _, files in os.walk("c:/vcpkg"): for f in files: if f.endswith(".cmake"): path = os.path.join(root, f) with open(path) as f: text = f.read() changed = text.replace(a, b) if text != changed: print("CHANGED", path) with open(path, "w") as f: f.write(changed) shell: python - run: ./scripts/build-windows.sh env: WINARCH: ${{ matrix.architecture }} ################################################################ - name: Set up Python 3.10 uses: actions/setup-python@v5 with: python-version: "3.10" architecture: ${{ matrix.architecture }} - run: ./scripts/wheel-windows.sh "3.10" - uses: actions/upload-artifact@v4 if: ${{ github.event_name != 'pull_request' }} name: Upload wheel 3.10 with: name: wheel-windows-3.10-${{ matrix.architecture }} path: wheelhouse/*.whl ################################################################ - name: Set up Python 3.11 uses: actions/setup-python@v5 with: python-version: "3.11" architecture: ${{ matrix.architecture }} - run: ./scripts/wheel-windows.sh "3.11" - uses: actions/upload-artifact@v4 if: ${{ github.event_name != 'pull_request' }} name: Upload wheel 3.11 with: name: wheel-windows-3.11-${{ matrix.architecture }} path: wheelhouse/*.whl ################################################################ - name: Set up Python 3.12 uses: actions/setup-python@v5 with: python-version: "3.12" architecture: ${{ matrix.architecture }} - run: ./scripts/wheel-windows.sh "3.12" - uses: actions/upload-artifact@v4 if: ${{ github.event_name != 'pull_request' }} name: Upload wheel 3.12 with: name: wheel-windows-3.12-${{ matrix.architecture }} path: wheelhouse/*.whl ################################################################ - name: Set up Python 3.13 uses: actions/setup-python@v5 with: python-version: "3.13" architecture: ${{ matrix.architecture }} - run: ./scripts/wheel-windows.sh "3.13" - uses: actions/upload-artifact@v4 if: ${{ github.event_name != 'pull_request' }} name: Upload wheel 3.13 with: name: wheel-windows-3.13-${{ matrix.architecture }} path: wheelhouse/*.whl ################################################################ - name: Set up Python 3.14 uses: actions/setup-python@v5 with: python-version: "3.14" architecture: ${{ matrix.architecture }} - run: ./scripts/wheel-windows.sh "3.14" - uses: actions/upload-artifact@v4 if: ${{ github.event_name != 'pull_request' }} name: Upload wheel 3.14 with: name: wheel-windows-3.14-${{ matrix.architecture }} path: wheelhouse/*.whl test: if: ${{ github.event_name != 'pull_request' }} needs: build runs-on: windows-latest strategy: fail-fast: true matrix: python-version: [ "3.10", "3.11", "3.12", "3.13", "3.14" ] architecture: [ "x64" ] defaults: run: shell: bash env: ECCODES_PYTHON_USE_FINDLIBS: "1" name: Test with Python ${{ matrix.python-version }} ${{ matrix.architecture }} steps: - uses: actions/checkout@v6 - name: Set up Python uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} architecture: ${{ matrix.architecture }} - uses: actions/download-artifact@v4 with: name: wheel-windows-${{ matrix.python-version }}-${{ matrix.architecture }} - run: pip install *.whl - run: pip install -r tests/requirements.txt - name: Configure ecCodes runtime lookup shell: python run: | import os import pathlib import ecmwflibs eccodes_path = ecmwflibs.find("eccodes") if not eccodes_path: raise RuntimeError("Cannot resolve bundled ecCodes path from ecmwflibs") libs_dir = str(pathlib.Path(eccodes_path).parent) with open(os.environ["GITHUB_ENV"], "a", encoding="utf-8") as f: print(f"ECMWFLIBS_ECCODES={eccodes_path}", file=f) print(f"PATH={libs_dir};{os.environ.get('PATH', '')}", file=f) - run: pip freeze - name: Get some data run: | curl -L https://get.ecmwf.int/repository/test-data/metview/gallery/2m_temperature.grib -o data.grib curl -L https://github.com/ecmwf/climetlab/raw/main/docs/examples/test.grib -o climetlab.grib curl -L https://github.com/ecmwf/climetlab/raw/main/docs/examples/test.nc -o climetlab.nc ls -l working-directory: tests - run: pytest --verbose -s working-directory: tests timeout-minutes: 2 - uses: actions/upload-artifact@v4 if: ${{ github.event_name != 'pull_request' }} with: name: tests-windows-${{ matrix.python-version }}-${{ matrix.architecture }} path: tests/*.png deploy: if: ${{ github.event_name == 'release' }} needs: [ test, build ] name: Deploy wheel ${{ matrix.python-version }} ${{ matrix.architecture }} runs-on: ubuntu-latest strategy: fail-fast: true matrix: python-version: [ "3.10", "3.11", "3.12", "3.13", "3.14" ] architecture: [ "x64" ] steps: - name: Set up Python uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - run: pip install twine - uses: actions/download-artifact@v4 with: name: wheel-windows-${{ matrix.python-version }}-${{ matrix.architecture }} - run: twine upload *.whl env: TWINE_USERNAME: __token__ TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }} notify: if: ${{ github.event_name == 'release' }} name: Notify universal needs: deploy runs-on: ubuntu-latest steps: - uses: mvasigh/dispatch-action@main with: token: ${{ secrets.NOTIFY_ECMWFLIBS }} repo: ecmwflibs owner: ecmwf event_type: ecmwflibs-windows-uploaded ecmwflibs-0.7.0/.github/workflows/build-macos-intel.yml0000664000175000017500000001255115201521641023306 0ustar alastairalastair# (C) Copyright 2020 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. name: Build MacOS Intel on: workflow_dispatch: {} release: types: [ created ] # repository_dispatch: # types: [eccodes-updated, magics-updated] push: paths: - "scripts/common.sh" - "scripts/build-macos.sh" - "scripts/wheel-macos.sh" - "tools/copy-licences.py" pull_request: branches: - master paths: - "scripts/common.sh" - "scripts/build-macos.sh" - "scripts/wheel-macos.sh" - "tools/copy-licences.py" jobs: build: # if: false runs-on: macos-latest name: Build steps: - uses: actions/checkout@v6 - name: Set up Python 3.10 uses: actions/setup-python@v5 with: python-version: "3.10" - run: ./scripts/build-macos.sh ################################################################ - name: Set up Python 3.10 uses: actions/setup-python@v5 with: python-version: "3.10" - run: ./scripts/wheel-macos.sh "3.10" - uses: actions/upload-artifact@v4 if: ${{ github.event_name != 'pull_request' }} name: Upload wheel 3.10 with: name: wheel-macos-3.10 path: wheelhouse/*.whl ################################################################ - name: Set up Python 3.11 uses: actions/setup-python@v5 with: python-version: "3.11" - run: ./scripts/wheel-macos.sh "3.11" - uses: actions/upload-artifact@v4 if: ${{ github.event_name != 'pull_request' }} name: Upload wheel 3.11 with: name: wheel-macos-3.11 path: wheelhouse/*.whl ################################################################ - name: Set up Python 3.12 uses: actions/setup-python@v5 with: python-version: "3.12" - run: ./scripts/wheel-macos.sh "3.12" - uses: actions/upload-artifact@v4 if: ${{ github.event_name != 'pull_request' }} name: Upload wheel 3.12 with: name: wheel-macos-3.12 path: wheelhouse/*.whl ################################################################ - name: Set up Python 3.13 uses: actions/setup-python@v5 with: python-version: "3.13" - run: ./scripts/wheel-macos.sh "3.13" - uses: actions/upload-artifact@v4 if: ${{ github.event_name != 'pull_request' }} name: Upload wheel 3.13 with: name: wheel-macos-3.13 path: wheelhouse/*.whl ################################################################ - name: Set up Python 3.14 uses: actions/setup-python@v5 with: python-version: "3.14" - run: ./scripts/wheel-macos.sh "3.14" - uses: actions/upload-artifact@v4 if: ${{ github.event_name != 'pull_request' }} name: Upload wheel 3.14 with: name: wheel-macos-3.14 path: wheelhouse/*.whl test: if: ${{ github.event_name != 'pull_request' }} needs: build runs-on: macos-latest strategy: fail-fast: true matrix: python-version: [ "3.10", "3.11", "3.12", "3.13", "3.14" ] name: Test with Python ${{ matrix.python-version }} steps: - uses: actions/checkout@v6 - name: Set up Python uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - uses: actions/download-artifact@v4 with: name: wheel-macos-${{ matrix.python-version }} - run: python -m pip install --upgrade pip - run: pip install *.whl - run: pip install -r tests/requirements.txt - run: pip freeze - name: Get some data run: | curl -L https://get.ecmwf.int/repository/test-data/metview/gallery/2m_temperature.grib -o data.grib curl -L https://github.com/ecmwf/climetlab/raw/main/docs/examples/test.grib -o climetlab.grib curl -L https://github.com/ecmwf/climetlab/raw/main/docs/examples/test.nc -o climetlab.nc ls -l working-directory: tests - run: pytest -v -s working-directory: tests - uses: actions/upload-artifact@v4 if: ${{ github.event_name != 'pull_request' }} with: name: tests-macos-${{ matrix.python-version }} path: tests/*.png deploy: if: ${{ github.event_name == 'release' }} needs: [ test, build ] name: Deploy wheel ${{ matrix.python-version }} runs-on: ubuntu-latest strategy: fail-fast: true matrix: python-version: [ "3.10", "3.11", "3.12", "3.13", "3.14" ] steps: - name: Set up Python uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - run: pip install twine - uses: actions/download-artifact@v4 with: name: wheel-macos-${{ matrix.python-version }} - run: twine upload *.whl env: TWINE_USERNAME: __token__ TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }} ecmwflibs-0.7.0/.github/workflows/test-universal.yml0000664000175000017500000000231415201521641022757 0ustar alastairalastair# This workflow will upload a Python Package using Twine when a release is created # For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries name: Test Universal on: workflow_dispatch: {} jobs: checks: name: Checks runs-on: ubuntu-latest defaults: run: shell: bash steps: - uses: actions/checkout@v6 - name: Set up Python uses: actions/setup-python@v5 with: python-version: "3.x" - name: Install packages run: | pip install black pytest flake8 isort - name: Code QA run: | black --version isort --check --profile=black . black --check . flake8 . - run: | python -m pip install --upgrade pip pip install setuptools wheel python setup.py bdist_wheel --universal pip install dist/ecmwflibs*none-any.whl mv ecmwflibs ecmwflibs.no rm -fr dist *.egg* ls -l - shell: python run: | import ecmwflibs print(ecmwflibs.__file__) assert ecmwflibs.universal() ecmwflibs-0.7.0/.github/workflows/build-macos-arm.yml0000664000175000017500000001344015201521641022750 0ustar alastairalastair# (C) Copyright 2020 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. name: Build MacOS ARM on: workflow_dispatch: {} release: types: [ created ] # repository_dispatch: # types: [eccodes-updated, magics-updated] push: paths: - "scripts/common.sh" - "scripts/build-macos.sh" - "scripts/wheel-macos.sh" - "tools/copy-licences.py" pull_request: branches: - master paths: - "scripts/common.sh" - "scripts/build-macos.sh" - "scripts/wheel-macos.sh" - "tools/copy-licences.py" # We don't use the setup-python action here as it installs a universal python # which creates universal wheels. We want to create wheels for the specific # architecture we are running on. jobs: build: # if: false runs-on: [ self-hosted, macOS, ARM64 ] # runs-on: [self-hosted, platform-builder-macos13-m2-000] name: Build steps: - run: sudo mkdir -p /Users/runner - run: sudo chown administrator:staff /Users/runner - uses: actions/checkout@v6 - run: ./scripts/select-python.sh "3.10" - run: ./scripts/build-macos.sh ################################################################ - run: ./scripts/select-python.sh "3.10" - run: ./scripts/wheel-macos.sh "3.10" - run: ls -l wheelhouse - uses: actions/upload-artifact@v4 if: ${{ github.event_name != 'pull_request' }} name: Upload wheel 3.10 with: name: wheel-macos-3.10 path: wheelhouse/*.whl - run: rm -fr wheelhouse ################################################################ - run: ./scripts/select-python.sh "3.11" - run: ./scripts/wheel-macos.sh "3.11" - run: ls -l wheelhouse - uses: actions/upload-artifact@v4 if: ${{ github.event_name != 'pull_request' }} name: Upload wheel 3.11 with: name: wheel-macos-3.11 path: wheelhouse/*.whl - run: rm -fr wheelhouse ################################################################ - run: ./scripts/select-python.sh "3.12" - run: ./scripts/wheel-macos.sh "3.12" - run: ls -l wheelhouse - uses: actions/upload-artifact@v4 if: ${{ github.event_name != 'pull_request' }} name: Upload wheel 3.12 with: name: wheel-macos-3.12 path: wheelhouse/*.whl - run: rm -fr wheelhouse ################################################################ - run: ./scripts/select-python.sh "3.13" - run: ./scripts/wheel-macos.sh "3.13" - run: ls -l wheelhouse - uses: actions/upload-artifact@v4 if: ${{ github.event_name != 'pull_request' }} name: Upload wheel 3.13 with: name: wheel-macos-3.13 path: wheelhouse/*.whl - run: rm -fr wheelhouse ################################################################ - run: ./scripts/select-python.sh "3.14" - run: ./scripts/wheel-macos.sh "3.14" - run: ls -l wheelhouse - uses: actions/upload-artifact@v4 if: ${{ github.event_name != 'pull_request' }} name: Upload wheel 3.14 with: name: wheel-macos-3.14 path: wheelhouse/*.whl - run: rm -fr wheelhouse test: if: ${{ github.event_name != 'pull_request' }} needs: build runs-on: [ self-hosted, macOS, ARM64 ] strategy: fail-fast: true max-parallel: 1 matrix: python-version: [ "3.10", "3.11", "3.12", "3.13", "3.14" ] name: Test with Python ${{ matrix.python-version }} steps: - uses: actions/checkout@v6 - uses: actions/download-artifact@v4 with: name: wheel-macos-${{ matrix.python-version }} - run: ls -l - run: ./scripts/select-python.sh ${{ matrix.python-version }} - run: echo $PATH - run: pip3 install --upgrade pip - run: ls -l /opt/homebrew/opt/python@${{ matrix.python-version }}/libexec/bin - run: which python3 - run: python3 --version - run: pwd - run: ls -l - run: pip3 install *.whl - run: pip3 install -r tests/requirements.txt - run: pip3 freeze - name: Get some data run: | curl -L https://get.ecmwf.int/repository/test-data/metview/gallery/2m_temperature.grib -o data.grib curl -L https://github.com/ecmwf/climetlab/raw/main/docs/examples/test.grib -o climetlab.grib curl -L https://github.com/ecmwf/climetlab/raw/main/docs/examples/test.nc -o climetlab.nc ls -l working-directory: tests - run: pytest -v -s working-directory: tests - uses: actions/upload-artifact@v4 if: ${{ github.event_name != 'pull_request' }} with: name: tests-macos-${{ matrix.python-version }} path: tests/*.png - run: rm -fr *.whl tests deploy: if: ${{ github.event_name == 'release' }} needs: [ test, build ] name: Deploy wheel ${{ matrix.python-version }} runs-on: [ self-hosted, macOS, ARM64 ] strategy: fail-fast: true max-parallel: 1 matrix: python-version: [ "3.10", "3.11", "3.12", "3.13", "3.14" ] steps: - run: ./scripts/select-python.sh ${{ matrix.python-version }} - run: pip3 install twine - uses: actions/download-artifact@v4 with: name: wheel-macos-${{ matrix.python-version }} - run: twine upload *.whl env: TWINE_USERNAME: __token__ TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }} ecmwflibs-0.7.0/.github/workflows/deploy-universal.yml0000664000175000017500000000453415201521641023302 0ustar alastairalastair# This workflow will upload a Python Package using Twine when a release is created # For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries name: Deploy Universal on: workflow_dispatch: {} # repository_dispatch: # types: [ecmwflibs-windows-uploaded] # workflow_run: # workflows: ["Build Windows"] # branches: [main] # types: [completed] jobs: # First check that the wheels are properly pushed to PiPy so # no one gets the universal version by accident, because # it is pushed first checks: runs-on: ${{ matrix.os }} name: "Check ${{ matrix.os }}" strategy: matrix: os: [ "ubuntu-latest", "macos-latest", "windows-latest" ] defaults: run: shell: bash steps: - uses: actions/checkout@v6 - name: Set up Python uses: actions/setup-python@v5 with: python-version: "3.x" - name: Install packages run: | pip install black pytest flake8 isort setuptools - name: Code QA run: | black --version isort --check --profile=black . black --check . flake8 . - run: | python -m pip install --upgrade pip version=$(python ./setup.py --version) mv ecmwflibs ecmwflibs.no rm -fr dist *.egg* ls -l pip install ecmwflibs==$version - shell: python run: | import ecmwflibs print(ecmwflibs.__file__) assert not ecmwflibs.universal() deploy: runs-on: ubuntu-latest needs: checks steps: - uses: actions/checkout@v6 - name: Set up Python uses: actions/setup-python@v5 with: python-version: "3.x" # - name: Check version # run: | # release=${GITHUB_REF##*/} # version=$(python setup.py --version) # test "$release" == "$version" - name: Install dependencies run: | python -m pip install --upgrade pip pip install setuptools wheel twine - name: Build and publish env: TWINE_USERNAME: __token__ TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }} run: | python setup.py bdist_wheel --universal twine upload dist/*