vortex-nwp 2.1.3__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.
Files changed (189) hide show
  1. {vortex_nwp-2.1.3/src/vortex_nwp.egg-info → vortex_nwp-2.3.0}/PKG-INFO +4 -1
  2. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/pyproject.toml +8 -2
  3. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/__init__.py +3 -2
  4. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/algo/components.py +20 -2
  5. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/algo/mpitools.py +5 -6
  6. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/data/abstractstores.py +43 -39
  7. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/data/executables.py +28 -0
  8. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/data/geometries.ini +89 -24
  9. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/data/geometries.py +24 -7
  10. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/data/handlers.py +1 -0
  11. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/data/providers.py +49 -10
  12. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/data/stores.py +152 -42
  13. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/algo/assim.py +1 -31
  14. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/algo/forecasts.py +30 -0
  15. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/algo/ifsroot.py +34 -20
  16. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/algo/monitoring.py +2 -2
  17. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/algo/odbtools.py +2 -2
  18. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/data/consts.py +61 -1
  19. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/data/diagnostics.py +2 -4
  20. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/tools/conftools.py +7 -6
  21. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/sessions.py +3 -2
  22. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/tools/storage.py +12 -10
  23. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/tools/systems.py +33 -3
  24. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0/src/vortex_nwp.egg-info}/PKG-INFO +4 -1
  25. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex_nwp.egg-info/SOURCES.txt +1 -0
  26. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex_nwp.egg-info/requires.txt +6 -0
  27. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/tests/test_conftools.py +1 -1
  28. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/tests/test_geometries.py +8 -25
  29. vortex_nwp-2.3.0/tests/test_user_remote_dtree.py +91 -0
  30. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/LICENSE +0 -0
  31. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/README.md +0 -0
  32. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/setup.cfg +0 -0
  33. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/algo/__init__.py +0 -0
  34. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/algo/mpitools_templates/__init__.py +0 -0
  35. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/algo/mpitools_templates/envelope_wrapper_default.tpl +0 -0
  36. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/algo/mpitools_templates/envelope_wrapper_mpiauto.tpl +0 -0
  37. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/algo/mpitools_templates/wrapstd_wrapper_default.tpl +0 -0
  38. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/algo/serversynctools.py +0 -0
  39. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/config.py +0 -0
  40. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/data/__init__.py +0 -0
  41. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/data/containers.py +0 -0
  42. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/data/contents.py +0 -0
  43. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/data/flow.py +0 -0
  44. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/data/outflow.py +0 -0
  45. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/data/resources.py +0 -0
  46. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/data/sync_templates/__init__.py +0 -0
  47. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/gloves.py +0 -0
  48. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/layout/__init__.py +0 -0
  49. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/layout/contexts.py +0 -0
  50. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/layout/dataflow.py +0 -0
  51. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/layout/monitor.py +0 -0
  52. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/__init__.py +0 -0
  53. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/algo/__init__.py +0 -0
  54. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/algo/clim.py +0 -0
  55. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/algo/coupling.py +0 -0
  56. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/algo/eda.py +0 -0
  57. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/algo/eps.py +0 -0
  58. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/algo/fpserver.py +0 -0
  59. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/algo/ifsnaming.py +0 -0
  60. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/algo/mpitools.py +0 -0
  61. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/algo/oopsroot.py +0 -0
  62. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/algo/oopstests.py +0 -0
  63. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/algo/request.py +0 -0
  64. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/algo/stdpost.py +0 -0
  65. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/data/__init__.py +0 -0
  66. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/data/assim.py +0 -0
  67. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/data/boundaries.py +0 -0
  68. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/data/climfiles.py +0 -0
  69. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/data/configfiles.py +0 -0
  70. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/data/ctpini.py +0 -0
  71. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/data/eda.py +0 -0
  72. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/data/eps.py +0 -0
  73. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/data/executables.py +0 -0
  74. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/data/fields.py +0 -0
  75. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/data/gridfiles.py +0 -0
  76. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/data/logs.py +0 -0
  77. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/data/modelstates.py +0 -0
  78. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/data/monitoring.py +0 -0
  79. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/data/namelists.py +0 -0
  80. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/data/obs.py +0 -0
  81. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/data/oopsexec.py +0 -0
  82. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/data/providers.py +0 -0
  83. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/data/query.py +0 -0
  84. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/data/stores.py +0 -0
  85. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/data/surfex.py +0 -0
  86. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/syntax/__init__.py +0 -0
  87. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/syntax/stdattrs.py +0 -0
  88. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/tools/__init__.py +0 -0
  89. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/tools/addons.py +0 -0
  90. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/tools/agt.py +0 -0
  91. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/tools/bdap.py +0 -0
  92. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/tools/bdcp.py +0 -0
  93. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/tools/bdm.py +0 -0
  94. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/tools/bdmp.py +0 -0
  95. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/tools/drhook.py +0 -0
  96. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/tools/grib.py +0 -0
  97. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/tools/gribdiff.py +0 -0
  98. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/tools/ifstools.py +0 -0
  99. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/tools/igastuff.py +0 -0
  100. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/tools/mars.py +0 -0
  101. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/tools/odb.py +0 -0
  102. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/tools/partitioning.py +0 -0
  103. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/tools/satrad.py +0 -0
  104. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/util/__init__.py +0 -0
  105. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/util/async.py +0 -0
  106. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/util/beacon.py +0 -0
  107. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/util/diffpygram.py +0 -0
  108. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/util/ens.py +0 -0
  109. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/util/hooks.py +0 -0
  110. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/util/taskdeco.py +0 -0
  111. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/util/usepygram.py +0 -0
  112. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/nwp/util/usetnt.py +0 -0
  113. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/proxy.py +0 -0
  114. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/syntax/__init__.py +0 -0
  115. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/syntax/stdattrs.py +0 -0
  116. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/syntax/stddeco.py +0 -0
  117. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/toolbox.py +0 -0
  118. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/tools/__init__.py +0 -0
  119. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/tools/actions.py +0 -0
  120. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/tools/addons.py +0 -0
  121. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/tools/arm.py +0 -0
  122. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/tools/compression.py +0 -0
  123. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/tools/date.py +0 -0
  124. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/tools/ddhpack.py +0 -0
  125. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/tools/delayedactions.py +0 -0
  126. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/tools/env.py +0 -0
  127. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/tools/folder.py +0 -0
  128. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/tools/grib.py +0 -0
  129. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/tools/lfi.py +0 -0
  130. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/tools/listings.py +0 -0
  131. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/tools/names.py +0 -0
  132. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/tools/net.py +0 -0
  133. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/tools/odb.py +0 -0
  134. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/tools/parallelism.py +0 -0
  135. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/tools/prestaging.py +0 -0
  136. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/tools/rawfiles.py +0 -0
  137. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/tools/schedulers.py +0 -0
  138. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/tools/services.py +0 -0
  139. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/tools/surfex.py +0 -0
  140. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/tools/targets.py +0 -0
  141. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/util/__init__.py +0 -0
  142. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/util/config.py +0 -0
  143. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/util/empty.py +0 -0
  144. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/util/helpers.py +0 -0
  145. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/util/introspection.py +0 -0
  146. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/util/iosponge.py +0 -0
  147. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/util/roles.py +0 -0
  148. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/util/storefunctions.py +0 -0
  149. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/util/structs.py +0 -0
  150. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex/util/worker.py +0 -0
  151. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex_nwp.egg-info/dependency_links.txt +0 -0
  152. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/src/vortex_nwp.egg-info/top_level.txt +0 -0
  153. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/tests/test_algo_server.py +0 -0
  154. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/tests/test_arpifs_listings_integration.py +0 -0
  155. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/tests/test_cfgparser.py +0 -0
  156. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/tests/test_cfgtemplating.py +0 -0
  157. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/tests/test_compression.py +0 -0
  158. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/tests/test_config.py +0 -0
  159. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/tests/test_containers.py +0 -0
  160. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/tests/test_doctests.py +0 -0
  161. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/tests/test_ecflow.py +0 -0
  162. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/tests/test_ecmwf_interface.py +0 -0
  163. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/tests/test_env.py +0 -0
  164. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/tests/test_epygram.py +0 -0
  165. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/tests/test_gco.py +0 -0
  166. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/tests/test_ifstools.py +0 -0
  167. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/tests/test_import.py +0 -0
  168. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/tests/test_iosponge.py +0 -0
  169. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/tests/test_job_examples.py +0 -0
  170. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/tests/test_layoutappconf.py +0 -0
  171. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/tests/test_layoutjobs.py +0 -0
  172. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/tests/test_layoutmonitor.py +0 -0
  173. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/tests/test_layoutnodes.py +0 -0
  174. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/tests/test_net_netstat.py +0 -0
  175. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/tests/test_net_ssh.py +0 -0
  176. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/tests/test_partitioning.py +0 -0
  177. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/tests/test_providers.py +0 -0
  178. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/tests/test_sessions_stuff.py +0 -0
  179. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/tests/test_simpleworkflow.py +0 -0
  180. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/tests/test_smartftget.py +0 -0
  181. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/tests/test_ssh.py +0 -0
  182. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/tests/test_storage.py +0 -0
  183. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/tests/test_stores.py +0 -0
  184. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/tests/test_syntax.py +0 -0
  185. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/tests/test_targets.py +0 -0
  186. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/tests/test_templates.py +0 -0
  187. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/tests/test_toolsodb.py +0 -0
  188. {vortex_nwp-2.1.3 → vortex_nwp-2.3.0}/tests/test_uget.py +0 -0
  189. {vortex_nwp-2.1.3 → 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.1.3
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.1.3"
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", "footprints", "taylorism", "tomli", "arpifs_listings",
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.1.3"
57
+ __version__ = "2.3.0"
57
58
  __prompt__ = "Vortex v-" + __version__ + ":"
58
59
 
59
- __nextversion__ = "2.1.4"
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=["current", "awk", "ksh", "bash", "perl", "python"],
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 shoudl always be used within an envelope."
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", nnp="ntasks-per-node", np="ntasks"
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),
@@ -14,7 +14,12 @@ from bronx.system import hash as hashutils
14
14
  import footprints
15
15
 
16
16
  from vortex import sessions
17
- from vortex.config import from_config, ConfigurationError, is_defined
17
+ from vortex.config import (
18
+ from_config,
19
+ ConfigurationError,
20
+ is_defined,
21
+ get_from_config_w_default,
22
+ )
18
23
  from vortex.syntax.stdattrs import (
19
24
  hashalgo,
20
25
  hashalgo_avail_list,
@@ -438,6 +443,7 @@ class MultiStore(footprints.FootprintBase):
438
443
  attr=dict(
439
444
  scheme=dict(alias=("protocol",)),
440
445
  netloc=dict(type=Namespace, alias=("domain", "namespace")),
446
+ username=dict(type=str),
441
447
  refillstore=dict(
442
448
  type=bool,
443
449
  optional=True,
@@ -792,6 +798,9 @@ class ArchiveStore(Store):
792
798
  netloc=dict(
793
799
  values=["open.archive.fr"],
794
800
  ),
801
+ username=dict(
802
+ type=str,
803
+ ),
795
804
  storehash=dict(
796
805
  values=hashalgo_avail_list,
797
806
  ),
@@ -843,6 +852,13 @@ class ArchiveStore(Store):
843
852
  def underlying_archive_kind(self):
844
853
  return "std"
845
854
 
855
+ @property
856
+ def archive_entry(self):
857
+ pattern = get_from_config_w_default(
858
+ section="storage", key="rootdir", default="~/vortex"
859
+ )
860
+ return pattern.replace("%usr%", self.username)
861
+
846
862
  @property
847
863
  def actual_storage(self):
848
864
  """This archive network name (potentially read form the configuration file)."""
@@ -894,6 +910,7 @@ class ArchiveStore(Store):
894
910
  storage=self.actual_storage,
895
911
  tube=self.actual_storetube,
896
912
  readonly=self.readonly,
913
+ entry=self.archive_entry,
897
914
  )
898
915
  self._archives_object_stack.add(self._archive)
899
916
  return self._archive
@@ -909,25 +926,12 @@ class ArchiveStore(Store):
909
926
 
910
927
  archive = property(_get_archive, _set_archive, _del_archive)
911
928
 
912
- def _inarchiveformatpath(self, remote):
913
- # Remove extra slashes
914
- formatted = remote["path"].lstrip(self.system.path.sep)
915
- # Store head ?
916
- if self.storehead:
917
- formatted = self.system.path.join(self.storehead, formatted)
918
- # Store root (if specified)
919
- pathroot = remote.get("root", self.storeroot)
920
- if pathroot is not None:
921
- formatted = self.system.path.join(pathroot, formatted)
922
- return formatted
923
-
924
929
  def inarchivecheck(self, remote, options):
925
930
  """Use the archive object to check if **remote** exists."""
926
931
  # Try to delete the md5 file but ignore errors...
927
932
  if self._hash_check_or_delete(self.inarchivecheck, remote, options):
928
933
  return self.archive.check(
929
- self._inarchiveformatpath(remote),
930
- username=remote.get("username", None),
934
+ remote["path"],
931
935
  fmt=options.get("fmt", "foo"),
932
936
  compressionpipeline=self._actual_cpipeline,
933
937
  )
@@ -937,8 +941,7 @@ class ArchiveStore(Store):
937
941
  def inarchivelocate(self, remote, options):
938
942
  """Use the archive object to obtain **remote** physical location."""
939
943
  return self.archive.fullpath(
940
- self._inarchiveformatpath(remote),
941
- username=remote.get("username", None),
944
+ remote["path"],
942
945
  fmt=options.get("fmt", "foo"),
943
946
  compressionpipeline=self._actual_cpipeline,
944
947
  )
@@ -946,15 +949,13 @@ class ArchiveStore(Store):
946
949
  def inarchivelist(self, remote, options):
947
950
  """Use the archive object to list available files."""
948
951
  return self.archive.list(
949
- self._inarchiveformatpath(remote),
950
- username=remote.get("username", None),
952
+ remote["path"],
951
953
  )
952
954
 
953
955
  def inarchiveprestageinfo(self, remote, options):
954
956
  """Returns the prestaging informations"""
955
957
  return self.archive.prestageinfo(
956
- self._inarchiveformatpath(remote),
957
- username=remote.get("username", None),
958
+ remote["path"],
958
959
  fmt=options.get("fmt", "foo"),
959
960
  compressionpipeline=self._actual_cpipeline,
960
961
  )
@@ -965,16 +966,15 @@ class ArchiveStore(Store):
965
966
  "inarchiveget on %s://%s/%s (to: %s)",
966
967
  self.scheme,
967
968
  self.netloc,
968
- self._inarchiveformatpath(remote),
969
+ remote["path"],
969
970
  local,
970
971
  )
971
972
  rc = self.archive.retrieve(
972
- self._inarchiveformatpath(remote),
973
+ remote["path"],
973
974
  local,
974
975
  intent=options.get("intent", ARCHIVE_GET_INTENT_DEFAULT),
975
976
  fmt=options.get("fmt", "foo"),
976
977
  info=options.get("rhandler", None),
977
- username=remote["username"],
978
978
  compressionpipeline=self._actual_cpipeline,
979
979
  )
980
980
  return rc and self._hash_get_check(
@@ -987,16 +987,15 @@ class ArchiveStore(Store):
987
987
  "inarchiveearlyget on %s://%s/%s (to: %s)",
988
988
  self.scheme,
989
989
  self.netloc,
990
- self._inarchiveformatpath(remote),
990
+ remote["path"],
991
991
  local,
992
992
  )
993
993
  rc = self.archive.earlyretrieve(
994
- self._inarchiveformatpath(remote),
994
+ remote["path"],
995
995
  local,
996
996
  intent=options.get("intent", ARCHIVE_GET_INTENT_DEFAULT),
997
997
  fmt=options.get("fmt", "foo"),
998
998
  info=options.get("rhandler", None),
999
- username=remote["username"],
1000
999
  compressionpipeline=self._actual_cpipeline,
1001
1000
  )
1002
1001
  return rc
@@ -1007,17 +1006,16 @@ class ArchiveStore(Store):
1007
1006
  "inarchivefinaliseget on %s://%s/%s (to: %s)",
1008
1007
  self.scheme,
1009
1008
  self.netloc,
1010
- self._inarchiveformatpath(remote),
1009
+ remote["path"],
1011
1010
  local,
1012
1011
  )
1013
1012
  rc = self.archive.finaliseretrieve(
1014
1013
  result_id,
1015
- self._inarchiveformatpath(remote),
1014
+ remote["path"],
1016
1015
  local,
1017
1016
  intent=options.get("intent", ARCHIVE_GET_INTENT_DEFAULT),
1018
1017
  fmt=options.get("fmt", "foo"),
1019
1018
  info=options.get("rhandler", None),
1020
- username=remote["username"],
1021
1019
  compressionpipeline=self._actual_cpipeline,
1022
1020
  )
1023
1021
  return rc and self._hash_get_check(
@@ -1030,16 +1028,15 @@ class ArchiveStore(Store):
1030
1028
  "inarchiveput to %s://%s/%s (from: %s)",
1031
1029
  self.scheme,
1032
1030
  self.netloc,
1033
- self._inarchiveformatpath(remote),
1031
+ remote["path"],
1034
1032
  local,
1035
1033
  )
1036
1034
  rc = self.archive.insert(
1037
- self._inarchiveformatpath(remote),
1035
+ remote["path"],
1038
1036
  local,
1039
1037
  intent=ARCHIVE_PUT_INTENT,
1040
1038
  fmt=options.get("fmt", "foo"),
1041
1039
  info=options.get("rhandler"),
1042
- username=remote["username"],
1043
1040
  compressionpipeline=self._actual_cpipeline,
1044
1041
  enforcesync=options.get("enforcesync", False),
1045
1042
  usejeeves=options.get("delayed", None),
@@ -1051,15 +1048,14 @@ class ArchiveStore(Store):
1051
1048
  "inarchivedelete on %s://%s/%s",
1052
1049
  self.scheme,
1053
1050
  self.netloc,
1054
- self._inarchiveformatpath(remote),
1051
+ remote["path"],
1055
1052
  )
1056
1053
  # Try to delete the md5 file but ignore errors...
1057
1054
  self._hash_check_or_delete(self.inarchivedelete, remote, options)
1058
1055
  return self.archive.delete(
1059
- self._inarchiveformatpath(remote),
1056
+ remote["path"],
1060
1057
  fmt=options.get("fmt", "foo"),
1061
1058
  info=options.get("rhandler", None),
1062
- username=remote["username"],
1063
1059
  compressionpipeline=self._actual_cpipeline,
1064
1060
  )
1065
1061
 
@@ -1081,6 +1077,9 @@ class CacheStore(Store):
1081
1077
  netloc=dict(
1082
1078
  values=["open.cache.fr"],
1083
1079
  ),
1080
+ username=dict(
1081
+ type=str,
1082
+ ),
1084
1083
  storehash=dict(
1085
1084
  values=hashalgo_avail_list,
1086
1085
  ),
@@ -1130,7 +1129,7 @@ class CacheStore(Store):
1130
1129
  def _get_cache(self):
1131
1130
  if not self._cache:
1132
1131
  self._cache = footprints.proxy.caches.default(
1133
- entry=self.location,
1132
+ entry=self.cache_entry,
1134
1133
  rtouch=self.rtouch,
1135
1134
  rtouchskip=self.rtouchskip,
1136
1135
  readonly=self.readonly,
@@ -1255,6 +1254,7 @@ class PromiseStore(footprints.FootprintBase):
1255
1254
  attr=dict(
1256
1255
  scheme=dict(alias=("protocol",)),
1257
1256
  netloc=dict(type=Namespace, alias=("domain", "namespace")),
1257
+ username=dict(type=str),
1258
1258
  storetrack=dict(
1259
1259
  type=bool,
1260
1260
  default=True,
@@ -1282,12 +1282,14 @@ class PromiseStore(footprints.FootprintBase):
1282
1282
  scheme=self.proxyscheme,
1283
1283
  netloc=self.prstorename,
1284
1284
  storetrack=self.storetrack,
1285
+ username=self.username,
1285
1286
  )
1286
1287
  if self.promise is None:
1287
1288
  logger.critical(
1288
- "Could not find store scheme <%s> netloc <%s>",
1289
+ "Could not find store scheme <%s> netloc <%s> username <%s>",
1289
1290
  self.proxyscheme,
1290
1291
  self.prstorename,
1292
+ self.username,
1291
1293
  )
1292
1294
  raise ValueError("Could not get a Promise Store")
1293
1295
 
@@ -1296,12 +1298,14 @@ class PromiseStore(footprints.FootprintBase):
1296
1298
  scheme=self.proxyscheme,
1297
1299
  netloc=self.netloc,
1298
1300
  storetrack=self.storetrack,
1301
+ username=self.username,
1299
1302
  )
1300
1303
  if self.other is None:
1301
1304
  logger.critical(
1302
- "Could not find store scheme <%s> netloc <%s>",
1305
+ "Could not find store scheme <%s> netloc <%s> username <%s>",
1303
1306
  self.proxyscheme,
1304
1307
  self.netloc,
1308
+ self.username,
1305
1309
  )
1306
1310
  raise ValueError("Could not get an Other Store")
1307
1311
 
@@ -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 = paris1s100
1218
+ area = PARIS1S100
1205
1219
  resolution = 0.01
1206
- nlat = 221
1207
- nlon = 336
1220
+ nlat = 187
1221
+ nlon = 279
1208
1222
 
1209
1223
  [medalp1s100]
1210
1224
  info = MEDALP 0.01
1211
1225
  kind = lonlat
1212
- area = medalp1s100
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
- [hycom3dmedoc]
2472
- info = Shom HYCOM3D Med-occidental at 1/60
2496
+ [hycom3dmednowe]
2497
+ info = Shom HYCOM3D Med-NorthWest at 1/60
2473
2498
  kind = lonlat
2474
- area = medoc
2475
- nlat = 331
2476
- nlon = 661
2499
+ area = mednowe
2500
+ nlat = 437
2501
+ nlon = 761
2477
2502
  resolution = 0.017
2478
2503
  runit = deg
2479
2504
 
2480
- [hycom3dmedor]
2481
- info = Shom HYCOM3D Med-oriental at 1/60
2505
+ [hycom3dmedsowe]
2506
+ info = Shom HYCOM3D Med-SouthWest at 1/60
2482
2507
  kind = lonlat
2483
- area = medor
2484
- nlat = 437
2485
- nlon = 645
2508
+ area = medsowe
2509
+ nlat = 481
2510
+ nlon = 1080
2486
2511
  resolution = 0.017
2487
2512
  runit = deg
2488
2513
 
2489
- [hycom3dmedio]
2490
- info = Shom HYCOM3D Med-ionian at 1/60
2514
+ [hycom3dmedea]
2515
+ info = Shom HYCOM3D Med-East at 1/60
2491
2516
  kind = lonlat
2492
- area = medio
2493
- nlat = 557
2494
- nlon = 781
2517
+ area = medea
2518
+ nlat = 706
2519
+ nlon = 855
2495
2520
  resolution = 0.017
2496
2521
  runit = deg
2497
2522
 
2498
- [hycom3dgibal]
2499
- info = Shom HYCOM3D Gibraltair Strait-Alboran Sea at 1/60
2523
+ [hycom3dmedinte]
2524
+ info = Shom HYCOM3D Med-Interior at 1/60
2500
2525
  kind = lonlat
2501
- area = gibal
2502
- nlat = 361
2503
- nlon = 571
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 ===================
@@ -759,13 +759,30 @@ hgeometry_deco = footprints.DecorativeFootprint(
759
759
  # Load default geometries when the module is first imported
760
760
 
761
761
 
762
- def load(inifile="@geometries.ini", refresh=False, verbose=True):
762
+ def _get_user_config_dir():
763
+ """Get the user's vortex configuration directory.
764
+
765
+ This function is separated out to make it easier to mock in tests.
766
+ """
767
+ from pathlib import Path
768
+ from vortex.tools.env import Environment
769
+
770
+ env = Environment(active=False)
771
+ return Path(env.HOME) / ".vortexrc"
772
+
773
+
774
+ def load(
775
+ inifile="@geometries.ini",
776
+ refresh=False,
777
+ verbose=True,
778
+ _user_config_dir=None,
779
+ ):
763
780
  """Load a set of pre-defined geometries from a configuration file.
764
781
 
765
782
  The class that will be instantiated depends on the "kind" keyword..
766
- """
767
- from vortex import sessions
768
783
 
784
+ :param _user_config_dir: Override user config directory (for testing)
785
+ """
769
786
  iniconf = configparser.ConfigParser()
770
787
 
771
788
  # Load from vortex distribution
@@ -776,10 +793,10 @@ def load(inifile="@geometries.ini", refresh=False, verbose=True):
776
793
  iniconf.read_file(fh)
777
794
 
778
795
  # Load from user's config directory if it exists
779
- glove = sessions.current().glove
780
- local = sessions.system()
781
- user_geometries = glove.configrc + "/geometries.ini"
782
- if local.path.exists(user_geometries):
796
+ if _user_config_dir is None:
797
+ _user_config_dir = _get_user_config_dir()
798
+ user_geometries = _user_config_dir / "geometries.ini"
799
+ if user_geometries.exists():
783
800
  with open(user_geometries, encoding="utf-8") as fh:
784
801
  iniconf.read_file(fh)
785
802
 
@@ -485,6 +485,7 @@ class Handler:
485
485
  return footprints.proxy.store(
486
486
  scheme=self._uridata.pop("scheme"),
487
487
  netloc=self._uridata.pop("netloc"),
488
+ username=self._uridata.pop("username"),
488
489
  **stopts,
489
490
  )
490
491
  else: