vortex-nwp 2.2.0__tar.gz → 2.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {vortex_nwp-2.2.0/src/vortex_nwp.egg-info → vortex_nwp-2.3.0}/PKG-INFO +4 -1
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/pyproject.toml +8 -2
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/__init__.py +3 -2
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/algo/components.py +20 -2
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/algo/mpitools.py +5 -6
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/data/executables.py +28 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/data/geometries.ini +89 -24
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/data/providers.py +44 -10
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/data/stores.py +110 -3
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/algo/assim.py +1 -31
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/algo/forecasts.py +30 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/algo/ifsroot.py +34 -20
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/algo/monitoring.py +2 -2
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/algo/odbtools.py +2 -2
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/data/consts.py +61 -1
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/data/diagnostics.py +2 -4
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/tools/conftools.py +7 -6
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/tools/systems.py +33 -3
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0/src/vortex_nwp.egg-info}/PKG-INFO +4 -1
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex_nwp.egg-info/requires.txt +6 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/tests/test_conftools.py +1 -1
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/LICENSE +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/README.md +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/setup.cfg +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/algo/__init__.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/algo/mpitools_templates/__init__.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/algo/mpitools_templates/envelope_wrapper_default.tpl +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/algo/mpitools_templates/envelope_wrapper_mpiauto.tpl +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/algo/mpitools_templates/wrapstd_wrapper_default.tpl +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/algo/serversynctools.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/config.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/data/__init__.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/data/abstractstores.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/data/containers.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/data/contents.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/data/flow.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/data/geometries.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/data/handlers.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/data/outflow.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/data/resources.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/data/sync_templates/__init__.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/gloves.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/layout/__init__.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/layout/contexts.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/layout/dataflow.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/layout/monitor.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/__init__.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/algo/__init__.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/algo/clim.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/algo/coupling.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/algo/eda.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/algo/eps.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/algo/fpserver.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/algo/ifsnaming.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/algo/mpitools.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/algo/oopsroot.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/algo/oopstests.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/algo/request.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/algo/stdpost.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/data/__init__.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/data/assim.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/data/boundaries.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/data/climfiles.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/data/configfiles.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/data/ctpini.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/data/eda.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/data/eps.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/data/executables.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/data/fields.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/data/gridfiles.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/data/logs.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/data/modelstates.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/data/monitoring.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/data/namelists.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/data/obs.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/data/oopsexec.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/data/providers.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/data/query.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/data/stores.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/data/surfex.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/syntax/__init__.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/syntax/stdattrs.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/tools/__init__.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/tools/addons.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/tools/agt.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/tools/bdap.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/tools/bdcp.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/tools/bdm.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/tools/bdmp.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/tools/drhook.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/tools/grib.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/tools/gribdiff.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/tools/ifstools.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/tools/igastuff.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/tools/mars.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/tools/odb.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/tools/partitioning.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/tools/satrad.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/util/__init__.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/util/async.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/util/beacon.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/util/diffpygram.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/util/ens.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/util/hooks.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/util/taskdeco.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/util/usepygram.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/nwp/util/usetnt.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/proxy.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/sessions.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/syntax/__init__.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/syntax/stdattrs.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/syntax/stddeco.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/toolbox.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/tools/__init__.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/tools/actions.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/tools/addons.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/tools/arm.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/tools/compression.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/tools/date.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/tools/ddhpack.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/tools/delayedactions.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/tools/env.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/tools/folder.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/tools/grib.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/tools/lfi.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/tools/listings.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/tools/names.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/tools/net.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/tools/odb.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/tools/parallelism.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/tools/prestaging.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/tools/rawfiles.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/tools/schedulers.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/tools/services.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/tools/storage.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/tools/surfex.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/tools/targets.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/util/__init__.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/util/config.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/util/empty.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/util/helpers.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/util/introspection.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/util/iosponge.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/util/roles.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/util/storefunctions.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/util/structs.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex/util/worker.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex_nwp.egg-info/SOURCES.txt +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex_nwp.egg-info/dependency_links.txt +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/src/vortex_nwp.egg-info/top_level.txt +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/tests/test_algo_server.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/tests/test_arpifs_listings_integration.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/tests/test_cfgparser.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/tests/test_cfgtemplating.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/tests/test_compression.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/tests/test_config.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/tests/test_containers.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/tests/test_doctests.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/tests/test_ecflow.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/tests/test_ecmwf_interface.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/tests/test_env.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/tests/test_epygram.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/tests/test_gco.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/tests/test_geometries.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/tests/test_ifstools.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/tests/test_import.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/tests/test_iosponge.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/tests/test_job_examples.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/tests/test_layoutappconf.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/tests/test_layoutjobs.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/tests/test_layoutmonitor.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/tests/test_layoutnodes.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/tests/test_net_netstat.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/tests/test_net_ssh.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/tests/test_partitioning.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/tests/test_providers.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/tests/test_sessions_stuff.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/tests/test_simpleworkflow.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/tests/test_smartftget.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/tests/test_ssh.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/tests/test_storage.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/tests/test_stores.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/tests/test_syntax.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/tests/test_targets.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/tests/test_templates.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/tests/test_toolsodb.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/tests/test_uget.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/tests/test_user_remote_dtree.py +0 -0
- {vortex_nwp-2.2.0 → vortex_nwp-2.3.0}/tests/test_vortexnames.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: vortex-nwp
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.3.0
|
|
4
4
|
Summary: A Python library to write Numerical Weather Prediction pipelines components
|
|
5
5
|
Author-email: The Vortex Team <vortex.support@meteo.fr>
|
|
6
6
|
License: CECILL-C
|
|
@@ -14,6 +14,7 @@ Requires-Dist: footprints
|
|
|
14
14
|
Requires-Dist: taylorism
|
|
15
15
|
Requires-Dist: tomli
|
|
16
16
|
Requires-Dist: arpifs_listings
|
|
17
|
+
Requires-Dist: importlib_metadata; python_version < "3.8"
|
|
17
18
|
Provides-Extra: docs
|
|
18
19
|
Requires-Dist: sphinx; extra == "docs"
|
|
19
20
|
Requires-Dist: sphinx-book-theme; extra == "docs"
|
|
@@ -21,6 +22,8 @@ Requires-Dist: sphinx-copybutton; extra == "docs"
|
|
|
21
22
|
Provides-Extra: dev
|
|
22
23
|
Requires-Dist: ruff==0.9.1; extra == "dev"
|
|
23
24
|
Requires-Dist: pytest; extra == "dev"
|
|
25
|
+
Provides-Extra: git
|
|
26
|
+
Requires-Dist: pygit2; extra == "git"
|
|
24
27
|
Dynamic: license-file
|
|
25
28
|
|
|
26
29
|
## vortex
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "vortex-nwp"
|
|
7
|
-
version = "2.
|
|
7
|
+
version = "2.3.0"
|
|
8
8
|
description = "A Python library to write Numerical Weather Prediction pipelines components"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.7"
|
|
@@ -18,12 +18,18 @@ classifiers = [
|
|
|
18
18
|
"License :: CeCILL-C Free Software License Agreement (CECILL-C)",
|
|
19
19
|
]
|
|
20
20
|
dependencies = [
|
|
21
|
-
"bronx",
|
|
21
|
+
"bronx",
|
|
22
|
+
"footprints",
|
|
23
|
+
"taylorism",
|
|
24
|
+
"tomli",
|
|
25
|
+
"arpifs_listings",
|
|
26
|
+
"importlib_metadata; python_version < '3.8'",
|
|
22
27
|
]
|
|
23
28
|
|
|
24
29
|
[project.optional-dependencies]
|
|
25
30
|
docs = ["sphinx", "sphinx-book-theme", "sphinx-copybutton"]
|
|
26
31
|
dev = ["ruff==0.9.1", "pytest"]
|
|
32
|
+
git = ["pygit2"]
|
|
27
33
|
|
|
28
34
|
[tool.setuptools.packages.find]
|
|
29
35
|
where = ["src"]
|
|
@@ -50,13 +50,14 @@ from .toolbox import promise as promise
|
|
|
50
50
|
from .toolbox import diff as diff
|
|
51
51
|
from .toolbox import defaults as defaults
|
|
52
52
|
from .toolbox import algo as task
|
|
53
|
+
from .toolbox import VortexForceComplete as VortexForceComplete
|
|
53
54
|
|
|
54
55
|
from . import nwp as nwp # footprints import
|
|
55
56
|
|
|
56
|
-
__version__ = "2.
|
|
57
|
+
__version__ = "2.3.0"
|
|
57
58
|
__prompt__ = "Vortex v-" + __version__ + ":"
|
|
58
59
|
|
|
59
|
-
__nextversion__ = "2.
|
|
60
|
+
__nextversion__ = "2.3.1"
|
|
60
61
|
__tocinfoline__ = "VORTEX core package"
|
|
61
62
|
|
|
62
63
|
__all__ = [
|
|
@@ -1548,12 +1548,25 @@ class Expresso(ExecutableAlgoComponent):
|
|
|
1548
1548
|
attr=dict(
|
|
1549
1549
|
interpreter=dict(
|
|
1550
1550
|
info="The interpreter needed to run the script.",
|
|
1551
|
-
values=[
|
|
1551
|
+
values=[
|
|
1552
|
+
"current",
|
|
1553
|
+
"awk",
|
|
1554
|
+
"ksh",
|
|
1555
|
+
"bash",
|
|
1556
|
+
"perl",
|
|
1557
|
+
"python",
|
|
1558
|
+
"singularity",
|
|
1559
|
+
],
|
|
1552
1560
|
),
|
|
1553
1561
|
interpreter_path=dict(
|
|
1554
1562
|
info="The interpreter command.",
|
|
1555
1563
|
optional=True,
|
|
1556
1564
|
),
|
|
1565
|
+
interpreter_args=dict(
|
|
1566
|
+
info="Some options to pass to the expresso",
|
|
1567
|
+
optional=True,
|
|
1568
|
+
default="",
|
|
1569
|
+
),
|
|
1557
1570
|
engine=dict(values=["exec", "launch"]),
|
|
1558
1571
|
),
|
|
1559
1572
|
)
|
|
@@ -1581,11 +1594,16 @@ class Expresso(ExecutableAlgoComponent):
|
|
|
1581
1594
|
)
|
|
1582
1595
|
|
|
1583
1596
|
def _interpreter_args_fix(self, rh, opts):
|
|
1597
|
+
cmd_opts = shlex.split(self.interpreter_args)
|
|
1598
|
+
|
|
1584
1599
|
absexec = self.absexcutable(rh.container.localpath())
|
|
1585
1600
|
if self.interpreter == "awk":
|
|
1586
|
-
return ["-f", absexec]
|
|
1601
|
+
return [*cmd_opts, "-f", absexec]
|
|
1602
|
+
if self.interpreter == "singularity":
|
|
1603
|
+
return ["run", *cmd_opts, absexec]
|
|
1587
1604
|
else:
|
|
1588
1605
|
return [
|
|
1606
|
+
*cmd_opts,
|
|
1589
1607
|
absexec,
|
|
1590
1608
|
]
|
|
1591
1609
|
|
|
@@ -544,10 +544,6 @@ class MpiTool(footprints.FootprintBase):
|
|
|
544
544
|
"""When group are defined, associate each MPI rank with a "real" slot."""
|
|
545
545
|
if self._ranks_map_cache is None:
|
|
546
546
|
self._complex_ranks_map = False
|
|
547
|
-
if not self.envelope:
|
|
548
|
-
raise RuntimeError(
|
|
549
|
-
"Ranks mapping should always be used within an envelope."
|
|
550
|
-
)
|
|
551
547
|
# First deal with bingroups
|
|
552
548
|
ranks_map = dict()
|
|
553
549
|
has_bin_groups = not all([b.group is None for b in self.binaries])
|
|
@@ -624,7 +620,7 @@ class MpiTool(footprints.FootprintBase):
|
|
|
624
620
|
if self._complex_ranks_map or do_bin_distribution:
|
|
625
621
|
if not self.envelope:
|
|
626
622
|
raise RuntimeError(
|
|
627
|
-
"Ranks mapping
|
|
623
|
+
"Ranks mapping should always be used within an envelope."
|
|
628
624
|
)
|
|
629
625
|
if do_bin_distribution:
|
|
630
626
|
if not self._supports_manual_ranks_mapping:
|
|
@@ -1404,7 +1400,10 @@ class SRun(MpiTool):
|
|
|
1404
1400
|
),
|
|
1405
1401
|
optmap=dict(
|
|
1406
1402
|
default=footprints.FPDict(
|
|
1407
|
-
nn="nodes",
|
|
1403
|
+
nn="nodes",
|
|
1404
|
+
nnp="ntasks-per-node",
|
|
1405
|
+
np="ntasks",
|
|
1406
|
+
openmp="cpus-per-task",
|
|
1408
1407
|
)
|
|
1409
1408
|
),
|
|
1410
1409
|
slurmversion=dict(type=int, optional=True),
|
|
@@ -106,6 +106,34 @@ class Script(Executable):
|
|
|
106
106
|
return self.rawopts
|
|
107
107
|
|
|
108
108
|
|
|
109
|
+
class SingularityImage(Executable):
|
|
110
|
+
"""Singularity container image executable."""
|
|
111
|
+
|
|
112
|
+
_footprint = dict(
|
|
113
|
+
attr=dict(
|
|
114
|
+
kind=dict(
|
|
115
|
+
values=["image"],
|
|
116
|
+
),
|
|
117
|
+
cmd=dict(
|
|
118
|
+
info="Command to run inside the container",
|
|
119
|
+
optional=True,
|
|
120
|
+
default="",
|
|
121
|
+
),
|
|
122
|
+
),
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
@property
|
|
126
|
+
def realkind(self):
|
|
127
|
+
return "image"
|
|
128
|
+
|
|
129
|
+
# Called by AlgoComponent.spawn_command_line
|
|
130
|
+
def command_line(self, **opts):
|
|
131
|
+
return " ".join(
|
|
132
|
+
["--{:s} {:s}".format(opt, val) for opt, val in opts.items()]
|
|
133
|
+
+ [self.cmd]
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
|
|
109
137
|
class GnuScript(Executable):
|
|
110
138
|
"""Basic interpreted executable with standard command line arguments."""
|
|
111
139
|
|
|
@@ -659,6 +659,13 @@ area = indonesie1
|
|
|
659
659
|
resolution = 2.50
|
|
660
660
|
runit = km
|
|
661
661
|
|
|
662
|
+
[asscomindonesie2sp]
|
|
663
|
+
info = Arome asscom14 - indonesie2 spectral geometry
|
|
664
|
+
kind = projected
|
|
665
|
+
area = indonesie2
|
|
666
|
+
resolution = 2.50
|
|
667
|
+
runit = km
|
|
668
|
+
|
|
662
669
|
[lace20km]
|
|
663
670
|
info = Coupling grid for LACE partners
|
|
664
671
|
kind = projected
|
|
@@ -673,6 +680,13 @@ area = lace
|
|
|
673
680
|
resolution = 8.0
|
|
674
681
|
runit = km
|
|
675
682
|
|
|
683
|
+
[lace47]
|
|
684
|
+
info = LACE canari domain
|
|
685
|
+
kind = projected
|
|
686
|
+
area = lace47
|
|
687
|
+
resolution = 4.71
|
|
688
|
+
runit = km
|
|
689
|
+
|
|
676
690
|
[afgt20km]
|
|
677
691
|
info = Coupling grid for afgt-Praha
|
|
678
692
|
kind = projected
|
|
@@ -1201,15 +1215,15 @@ nlon = 641
|
|
|
1201
1215
|
[paris1s100]
|
|
1202
1216
|
info = PARIS 0.01
|
|
1203
1217
|
kind = lonlat
|
|
1204
|
-
area =
|
|
1218
|
+
area = PARIS1S100
|
|
1205
1219
|
resolution = 0.01
|
|
1206
|
-
nlat =
|
|
1207
|
-
nlon =
|
|
1220
|
+
nlat = 187
|
|
1221
|
+
nlon = 279
|
|
1208
1222
|
|
|
1209
1223
|
[medalp1s100]
|
|
1210
1224
|
info = MEDALP 0.01
|
|
1211
1225
|
kind = lonlat
|
|
1212
|
-
area =
|
|
1226
|
+
area = MEDALP1S100
|
|
1213
1227
|
resolution = 0.01
|
|
1214
1228
|
nlat = 481
|
|
1215
1229
|
nlon = 501
|
|
@@ -1677,6 +1691,17 @@ nlat = 172800
|
|
|
1677
1691
|
latmax = 83.999
|
|
1678
1692
|
latmin = -55.999
|
|
1679
1693
|
|
|
1694
|
+
[srtm_01s]
|
|
1695
|
+
info = alternative to no_arctics7.5s used to create arome-500m PGD clim
|
|
1696
|
+
kind = lonlat
|
|
1697
|
+
area = srtm
|
|
1698
|
+
resolution = 1
|
|
1699
|
+
runit = s
|
|
1700
|
+
nlon = 999
|
|
1701
|
+
nlat = 999
|
|
1702
|
+
latmax = 999
|
|
1703
|
+
latmin = 999
|
|
1704
|
+
|
|
1680
1705
|
[europe_sw3s]
|
|
1681
1706
|
kind = lonlat
|
|
1682
1707
|
area = europe_sw
|
|
@@ -2468,39 +2493,39 @@ nlon = 896
|
|
|
2468
2493
|
resolution = 0.05
|
|
2469
2494
|
runit = deg
|
|
2470
2495
|
|
|
2471
|
-
[
|
|
2472
|
-
info = Shom HYCOM3D Med-
|
|
2496
|
+
[hycom3dmednowe]
|
|
2497
|
+
info = Shom HYCOM3D Med-NorthWest at 1/60
|
|
2473
2498
|
kind = lonlat
|
|
2474
|
-
area =
|
|
2475
|
-
nlat =
|
|
2476
|
-
nlon =
|
|
2499
|
+
area = mednowe
|
|
2500
|
+
nlat = 437
|
|
2501
|
+
nlon = 761
|
|
2477
2502
|
resolution = 0.017
|
|
2478
2503
|
runit = deg
|
|
2479
2504
|
|
|
2480
|
-
[
|
|
2481
|
-
info = Shom HYCOM3D Med-
|
|
2505
|
+
[hycom3dmedsowe]
|
|
2506
|
+
info = Shom HYCOM3D Med-SouthWest at 1/60
|
|
2482
2507
|
kind = lonlat
|
|
2483
|
-
area =
|
|
2484
|
-
nlat =
|
|
2485
|
-
nlon =
|
|
2508
|
+
area = medsowe
|
|
2509
|
+
nlat = 481
|
|
2510
|
+
nlon = 1080
|
|
2486
2511
|
resolution = 0.017
|
|
2487
2512
|
runit = deg
|
|
2488
2513
|
|
|
2489
|
-
[
|
|
2490
|
-
info = Shom HYCOM3D Med-
|
|
2514
|
+
[hycom3dmedea]
|
|
2515
|
+
info = Shom HYCOM3D Med-East at 1/60
|
|
2491
2516
|
kind = lonlat
|
|
2492
|
-
area =
|
|
2493
|
-
nlat =
|
|
2494
|
-
nlon =
|
|
2517
|
+
area = medea
|
|
2518
|
+
nlat = 706
|
|
2519
|
+
nlon = 855
|
|
2495
2520
|
resolution = 0.017
|
|
2496
2521
|
runit = deg
|
|
2497
2522
|
|
|
2498
|
-
[
|
|
2499
|
-
info = Shom HYCOM3D
|
|
2523
|
+
[hycom3dmedinte]
|
|
2524
|
+
info = Shom HYCOM3D Med-Interior at 1/60
|
|
2500
2525
|
kind = lonlat
|
|
2501
|
-
area =
|
|
2502
|
-
nlat =
|
|
2503
|
-
nlon =
|
|
2526
|
+
area = medinte
|
|
2527
|
+
nlat = 935
|
|
2528
|
+
nlon = 781
|
|
2504
2529
|
resolution = 0.017
|
|
2505
2530
|
runit = deg
|
|
2506
2531
|
|
|
@@ -2575,6 +2600,13 @@ area = corsica
|
|
|
2575
2600
|
resolution = 2.5
|
|
2576
2601
|
runit = km
|
|
2577
2602
|
|
|
2603
|
+
[nl2500]
|
|
2604
|
+
info = HARMONIE-AROME 2.5km NL domain for DAVAI
|
|
2605
|
+
kind = projected
|
|
2606
|
+
area = nl
|
|
2607
|
+
resolution = 2.5
|
|
2608
|
+
runit = km
|
|
2609
|
+
|
|
2578
2610
|
[cors1s40]
|
|
2579
2611
|
info = Corsica 0.025 deg
|
|
2580
2612
|
kind = lonlat
|
|
@@ -2669,6 +2701,39 @@ area = chmh2325
|
|
|
2669
2701
|
resolution = 2.33
|
|
2670
2702
|
runit = km
|
|
2671
2703
|
|
|
2704
|
+
[armcu]
|
|
2705
|
+
info = MUSC Single point ARMCU
|
|
2706
|
+
kind = unstructured
|
|
2707
|
+
area = armcu
|
|
2708
|
+
|
|
2709
|
+
[global31c1]
|
|
2710
|
+
info = ARPEGE T31C1.0 geometry (from Mitraillette tests)
|
|
2711
|
+
kind = gauss
|
|
2712
|
+
area = france
|
|
2713
|
+
truncation = 31
|
|
2714
|
+
stretching = 1.0
|
|
2715
|
+
|
|
2716
|
+
[global30c24]
|
|
2717
|
+
info = ARPEGE T30C2.4 geometry (from Mitraillette tests)
|
|
2718
|
+
kind = gauss
|
|
2719
|
+
area = france
|
|
2720
|
+
truncation = 30
|
|
2721
|
+
stretching = 2.4
|
|
2722
|
+
|
|
2723
|
+
[portugal21km]
|
|
2724
|
+
info = Mitraillette Portugal grid
|
|
2725
|
+
kind = projected
|
|
2726
|
+
area = portugal
|
|
2727
|
+
resolution = 21.3
|
|
2728
|
+
runit = km
|
|
2729
|
+
|
|
2730
|
+
[occitanie4km]
|
|
2731
|
+
info = Mitraillette Occitanie grid
|
|
2732
|
+
kind = projected
|
|
2733
|
+
area = occitanie
|
|
2734
|
+
resolution = 4.4
|
|
2735
|
+
runit = km
|
|
2736
|
+
|
|
2672
2737
|
#R ===================
|
|
2673
2738
|
#R Combined geometries
|
|
2674
2739
|
#R ===================
|
|
@@ -64,13 +64,6 @@ class Provider(footprints.FootprintBase):
|
|
|
64
64
|
fastkeys={"namespace"},
|
|
65
65
|
)
|
|
66
66
|
|
|
67
|
-
def __init__(self, *args, **kw):
|
|
68
|
-
logger.debug("Abstract provider init %s", self.__class__)
|
|
69
|
-
super().__init__(*args, **kw)
|
|
70
|
-
|
|
71
|
-
if not self.username:
|
|
72
|
-
self.username = vortex.ticket().glove.user
|
|
73
|
-
|
|
74
67
|
def _str_more(self):
|
|
75
68
|
"""Additional information to print representation."""
|
|
76
69
|
try:
|
|
@@ -92,7 +85,9 @@ class Provider(footprints.FootprintBase):
|
|
|
92
85
|
|
|
93
86
|
def netuser_name(self, resource): # @UnusedVariable
|
|
94
87
|
"""Abstract method."""
|
|
95
|
-
|
|
88
|
+
if self.username is not None:
|
|
89
|
+
return self.username
|
|
90
|
+
return vortex.ticket().glove.user
|
|
96
91
|
|
|
97
92
|
def pathname(self, resource):
|
|
98
93
|
"""Abstract method."""
|
|
@@ -124,10 +119,11 @@ class Provider(footprints.FootprintBase):
|
|
|
124
119
|
The different operations of the algorithm can be redefined by subclasses.
|
|
125
120
|
"""
|
|
126
121
|
username = self.netuser_name(resource)
|
|
122
|
+
netloc = self.netloc(resource)
|
|
127
123
|
fullnetloc = (
|
|
128
124
|
"{:s}@{:s}".format(username, self.netloc(resource))
|
|
129
|
-
if username
|
|
130
|
-
else
|
|
125
|
+
if (username and netloc)
|
|
126
|
+
else netloc
|
|
131
127
|
)
|
|
132
128
|
logger.debug(
|
|
133
129
|
"scheme %s netloc %s normpath %s urlquery %s",
|
|
@@ -279,6 +275,44 @@ def set_namespace_from_cache_settings(usecache, usearchive):
|
|
|
279
275
|
return ".".join(("vortex", domain, "fr"))
|
|
280
276
|
|
|
281
277
|
|
|
278
|
+
class Git(Provider):
|
|
279
|
+
_footprint = dict(
|
|
280
|
+
info="Git provider",
|
|
281
|
+
attr=dict(
|
|
282
|
+
ref=dict(
|
|
283
|
+
type=str,
|
|
284
|
+
optional=True,
|
|
285
|
+
default=None,
|
|
286
|
+
info="The reference's SHA-1 hash id",
|
|
287
|
+
),
|
|
288
|
+
repo=dict(
|
|
289
|
+
type=str,
|
|
290
|
+
info="Path to the Git repository",
|
|
291
|
+
),
|
|
292
|
+
path=dict(
|
|
293
|
+
type=str,
|
|
294
|
+
info="File path within the repository",
|
|
295
|
+
),
|
|
296
|
+
),
|
|
297
|
+
)
|
|
298
|
+
|
|
299
|
+
def scheme(self, resource):
|
|
300
|
+
return "git"
|
|
301
|
+
|
|
302
|
+
def urlquery(self, resource):
|
|
303
|
+
return (
|
|
304
|
+
f"repo={self.repo}&ref={self.ref}"
|
|
305
|
+
if self.ref
|
|
306
|
+
else f"repo={self.repo}"
|
|
307
|
+
)
|
|
308
|
+
|
|
309
|
+
def basename(self, resource):
|
|
310
|
+
return self.path
|
|
311
|
+
|
|
312
|
+
def pathname(sef, resource):
|
|
313
|
+
return "."
|
|
314
|
+
|
|
315
|
+
|
|
282
316
|
class Vortex(Provider):
|
|
283
317
|
"""Main provider of the toolbox, using a fix-size path and a dedicated name factory."""
|
|
284
318
|
|
|
@@ -8,8 +8,11 @@ Store objects use the :mod:`footprints` mechanism.
|
|
|
8
8
|
import copy
|
|
9
9
|
import ftplib
|
|
10
10
|
import io
|
|
11
|
+
from pathlib import Path
|
|
11
12
|
import os
|
|
12
13
|
import re
|
|
14
|
+
import shutil
|
|
15
|
+
import subprocess
|
|
13
16
|
|
|
14
17
|
from bronx.fancies import loggers
|
|
15
18
|
import footprints
|
|
@@ -33,6 +36,13 @@ __all__ = []
|
|
|
33
36
|
|
|
34
37
|
logger = loggers.getLogger(__name__)
|
|
35
38
|
|
|
39
|
+
try:
|
|
40
|
+
import pygit2
|
|
41
|
+
|
|
42
|
+
NO_PYGIT2 = False
|
|
43
|
+
except ImportError:
|
|
44
|
+
NO_PYGIT2 = True
|
|
45
|
+
|
|
36
46
|
|
|
37
47
|
def get_cache_location():
|
|
38
48
|
try:
|
|
@@ -335,7 +345,6 @@ class Finder(Store):
|
|
|
335
345
|
def _ftpinfos(self, remote, **kwargs):
|
|
336
346
|
args = kwargs.copy()
|
|
337
347
|
args["hostname"] = self.hostname()
|
|
338
|
-
args["logname"] = remote["username"]
|
|
339
348
|
port = self.hostname().netport
|
|
340
349
|
if port is not None:
|
|
341
350
|
args["port"] = port
|
|
@@ -422,6 +431,98 @@ class Finder(Store):
|
|
|
422
431
|
return rc
|
|
423
432
|
|
|
424
433
|
|
|
434
|
+
class GitStore(Store):
|
|
435
|
+
_footprint = dict(
|
|
436
|
+
info="A store to access Git repositories",
|
|
437
|
+
attr=dict(
|
|
438
|
+
scheme=dict(
|
|
439
|
+
values=["git"],
|
|
440
|
+
),
|
|
441
|
+
),
|
|
442
|
+
)
|
|
443
|
+
|
|
444
|
+
def gitget(self, remote, local, options):
|
|
445
|
+
if NO_PYGIT2:
|
|
446
|
+
raise ModuleNotFoundError(
|
|
447
|
+
"pygit2 is not installed in the current environment"
|
|
448
|
+
)
|
|
449
|
+
annex_cache_path = Path(remote["query"]["repo"][0])
|
|
450
|
+
|
|
451
|
+
# If no git reference is provided, only make a copy of the
|
|
452
|
+
# worktree
|
|
453
|
+
if "ref" not in remote["query"]:
|
|
454
|
+
shutil.copy(
|
|
455
|
+
src=Path(annex_cache_path) / remote["path"].lstrip("/"),
|
|
456
|
+
dst=local,
|
|
457
|
+
)
|
|
458
|
+
return local
|
|
459
|
+
|
|
460
|
+
assert "ref" in remote["query"]
|
|
461
|
+
path = remote["path"].lstrip("/")
|
|
462
|
+
repo = pygit2.Repository(annex_cache_path)
|
|
463
|
+
oid = repo.revparse_single(remote["query"]["ref"][0])
|
|
464
|
+
obj = oid.peel(pygit2.Tree) / path
|
|
465
|
+
if obj.filemode == pygit2.enums.FileMode.LINK:
|
|
466
|
+
# Here we need to discriminate between links that point
|
|
467
|
+
# to git-annex managed files and all other symlinks.
|
|
468
|
+
|
|
469
|
+
# If the file is a git-annex link, work out the location
|
|
470
|
+
# of the data within the .git/annex dir and copy this
|
|
471
|
+
# file into the cwd with the right name
|
|
472
|
+
if ".git/annex/objects" in obj.data.decode("ASCII"):
|
|
473
|
+
gitannex_key = Path(obj.data.decode("ASCII")).name
|
|
474
|
+
subprocess.run(
|
|
475
|
+
args=["git-annex", "get", "--key", gitannex_key],
|
|
476
|
+
cwd=str(annex_cache_path),
|
|
477
|
+
)
|
|
478
|
+
gitannex_content_location = subprocess.run(
|
|
479
|
+
args=["git-annex", "contentlocation", gitannex_key],
|
|
480
|
+
cwd=str(annex_cache_path),
|
|
481
|
+
capture_output=True,
|
|
482
|
+
encoding="ASCII",
|
|
483
|
+
).stdout
|
|
484
|
+
shutil.copy(
|
|
485
|
+
src=annex_cache_path / Path(gitannex_content_location),
|
|
486
|
+
dst=local,
|
|
487
|
+
follow_symlinks=True,
|
|
488
|
+
)
|
|
489
|
+
return local
|
|
490
|
+
os.symlink(
|
|
491
|
+
src=obj.data.decode("ASCII"),
|
|
492
|
+
dst=local,
|
|
493
|
+
)
|
|
494
|
+
return local
|
|
495
|
+
|
|
496
|
+
if obj.filemode == pygit2.enums.FileMode.BLOB:
|
|
497
|
+
with open(local, "wb") as dst:
|
|
498
|
+
# Could also use pygit2.BlobIO to stream content
|
|
499
|
+
# without having to load the entire blob data in
|
|
500
|
+
# memory:
|
|
501
|
+
#
|
|
502
|
+
# with pygit2.BlobIO(obj) as src:
|
|
503
|
+
# shutil.copyfileobj(fsrc=src, fdst=dst)
|
|
504
|
+
dst.write(obj.data)
|
|
505
|
+
return local
|
|
506
|
+
|
|
507
|
+
if obj.filemode == pygit2.enums.FileMode.TREE:
|
|
508
|
+
if local.endswith("/"):
|
|
509
|
+
localpath = "."
|
|
510
|
+
else:
|
|
511
|
+
localpath = local
|
|
512
|
+
os.mkdir(local)
|
|
513
|
+
for subobj in obj:
|
|
514
|
+
r = {
|
|
515
|
+
"query": {"ref": remote["query"]["ref"]},
|
|
516
|
+
"path": str(Path(path) / subobj.name),
|
|
517
|
+
}
|
|
518
|
+
self.gitget(
|
|
519
|
+
remote=r,
|
|
520
|
+
local=str(Path(localpath) / subobj.name),
|
|
521
|
+
options=None,
|
|
522
|
+
)
|
|
523
|
+
return local
|
|
524
|
+
|
|
525
|
+
|
|
425
526
|
class _VortexStackedStorageMixin:
|
|
426
527
|
"""Mixin class that adds utility functions to work with stacked data."""
|
|
427
528
|
|
|
@@ -985,7 +1086,10 @@ class VortexCacheMtStore(_VortexCacheBaseStore):
|
|
|
985
1086
|
except config.ConfigurationError:
|
|
986
1087
|
cacheloc = os.path.join(os.environ["HOME"], ".vortex.d")
|
|
987
1088
|
|
|
988
|
-
|
|
1089
|
+
current_vortex_user = self.system.glove.user
|
|
1090
|
+
cacheloc = cacheloc.replace("%usr%", current_vortex_user)
|
|
1091
|
+
|
|
1092
|
+
if self.username != current_vortex_user:
|
|
989
1093
|
return os.path.join(cacheloc, self.username)
|
|
990
1094
|
|
|
991
1095
|
return cacheloc
|
|
@@ -1205,6 +1309,9 @@ class VortexStackStore(_AbstractVortexStackMultiStore):
|
|
|
1205
1309
|
"""Go through the various stacked stores."""
|
|
1206
1310
|
return [f"{self.netloc.firstname}.stacked-cache-mt.fr"]
|
|
1207
1311
|
|
|
1312
|
+
def alternates_fpextras(self):
|
|
1313
|
+
return dict(username=self.username)
|
|
1314
|
+
|
|
1208
1315
|
|
|
1209
1316
|
class VortexVsopStackStore(_AbstractVortexStackMultiStore):
|
|
1210
1317
|
"""Store intended to read and write data into VORTEX R&D stacks."""
|
|
@@ -1336,7 +1443,7 @@ class PromiseCacheStore(VortexCacheMtStore):
|
|
|
1336
1443
|
)
|
|
1337
1444
|
|
|
1338
1445
|
@property
|
|
1339
|
-
def
|
|
1446
|
+
def cache_entry(self):
|
|
1340
1447
|
return os.path.join(super().cache_entry, "promise")
|
|
1341
1448
|
|
|
1342
1449
|
@staticmethod
|
|
@@ -5,7 +5,7 @@ AlgoComponents dedicated to computations related to Data Assimilation systems.
|
|
|
5
5
|
from bronx.fancies import loggers
|
|
6
6
|
from bronx.stdtypes.date import Date
|
|
7
7
|
|
|
8
|
-
from vortex.algo.components import BlindRun
|
|
8
|
+
from vortex.algo.components import BlindRun
|
|
9
9
|
from vortex.syntax.stdattrs import a_date
|
|
10
10
|
from .ifsroot import IFSParallel
|
|
11
11
|
from ..tools import odb, drhook
|
|
@@ -16,36 +16,6 @@ __all__ = []
|
|
|
16
16
|
logger = loggers.getLogger(__name__)
|
|
17
17
|
|
|
18
18
|
|
|
19
|
-
class MergeVarBC(Parallel):
|
|
20
|
-
"""Merge two VarBC files.
|
|
21
|
-
|
|
22
|
-
The VarBC file resulting from the MergeVarBC contains all the items of the
|
|
23
|
-
first VarBC file plus any new item that would be present in the second file.
|
|
24
|
-
"""
|
|
25
|
-
|
|
26
|
-
_footprint = dict(
|
|
27
|
-
attr=dict(
|
|
28
|
-
kind=dict(
|
|
29
|
-
values=["mergevarbc"],
|
|
30
|
-
),
|
|
31
|
-
varbcout=dict(
|
|
32
|
-
optional=True,
|
|
33
|
-
default="VARBC.cycle_out",
|
|
34
|
-
),
|
|
35
|
-
)
|
|
36
|
-
)
|
|
37
|
-
|
|
38
|
-
def prepare(self, rh, opts):
|
|
39
|
-
"""Find any ODB candidate in input files."""
|
|
40
|
-
|
|
41
|
-
sh = self.system
|
|
42
|
-
|
|
43
|
-
sh.touch(self.varbcout)
|
|
44
|
-
|
|
45
|
-
# Let ancesters doing real stuff
|
|
46
|
-
super().prepare(rh, opts)
|
|
47
|
-
|
|
48
|
-
|
|
49
19
|
class Anamix(IFSParallel):
|
|
50
20
|
"""Merge the surface and atmospheric analyses into a single file"""
|
|
51
21
|
|
|
@@ -112,6 +112,8 @@ class Forecast(IFSParallel):
|
|
|
112
112
|
# Possibly fix post-processing clim files
|
|
113
113
|
self.all_localclim_fixer(rh, thismonth)
|
|
114
114
|
|
|
115
|
+
self.grab(analysis, comment="analysis")
|
|
116
|
+
|
|
115
117
|
# File linking for IAU increments
|
|
116
118
|
#
|
|
117
119
|
# In the case of a forecast with IAU, the IFS executable
|
|
@@ -884,3 +886,31 @@ class OfflineSurfex(Parallel, DrHookDecoMixin):
|
|
|
884
886
|
if namsec.rh.contents.dumps_needs_update:
|
|
885
887
|
namsec.rh.save()
|
|
886
888
|
logger.info("Namelist dump: \n%s", namsec.rh.container.read())
|
|
889
|
+
|
|
890
|
+
|
|
891
|
+
class MUSCForecast(Forecast):
|
|
892
|
+
"""Forecast for MUSC single-column model."""
|
|
893
|
+
|
|
894
|
+
_footprint = dict(
|
|
895
|
+
info="Run a forecast with a MUSC single-column model.",
|
|
896
|
+
attr=dict(
|
|
897
|
+
kind=dict(
|
|
898
|
+
values=["musc"],
|
|
899
|
+
),
|
|
900
|
+
),
|
|
901
|
+
)
|
|
902
|
+
|
|
903
|
+
def postfix(self, rh, opts):
|
|
904
|
+
"""Post forecast information and cleaning."""
|
|
905
|
+
sh = self.system
|
|
906
|
+
# rename specific output files with hours term on 4 digits for compatibility for fmth formatting
|
|
907
|
+
fmt = re.compile(r"Out\.(?P<termh>\d{3})\.\d{4}\.lfa$")
|
|
908
|
+
for f in [
|
|
909
|
+
fmt.match(f)
|
|
910
|
+
for f in sh.listdir()
|
|
911
|
+
if f.startswith("Out.") and f.endswith(".lfa")
|
|
912
|
+
]:
|
|
913
|
+
sh.rename(
|
|
914
|
+
f.string, "Out.{:>04}.0000.lfa".format(int(f.group("termh")))
|
|
915
|
+
)
|
|
916
|
+
super().postfix(rh, opts)
|