vortex-nwp 2.0.0__py3-none-any.whl

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 (144) hide show
  1. vortex/__init__.py +159 -0
  2. vortex/algo/__init__.py +13 -0
  3. vortex/algo/components.py +2462 -0
  4. vortex/algo/mpitools.py +1953 -0
  5. vortex/algo/mpitools_templates/__init__.py +1 -0
  6. vortex/algo/mpitools_templates/envelope_wrapper_default.tpl +27 -0
  7. vortex/algo/mpitools_templates/envelope_wrapper_mpiauto.tpl +29 -0
  8. vortex/algo/mpitools_templates/wrapstd_wrapper_default.tpl +18 -0
  9. vortex/algo/serversynctools.py +171 -0
  10. vortex/config.py +112 -0
  11. vortex/data/__init__.py +19 -0
  12. vortex/data/abstractstores.py +1510 -0
  13. vortex/data/containers.py +835 -0
  14. vortex/data/contents.py +622 -0
  15. vortex/data/executables.py +275 -0
  16. vortex/data/flow.py +119 -0
  17. vortex/data/geometries.ini +2689 -0
  18. vortex/data/geometries.py +799 -0
  19. vortex/data/handlers.py +1230 -0
  20. vortex/data/outflow.py +67 -0
  21. vortex/data/providers.py +487 -0
  22. vortex/data/resources.py +207 -0
  23. vortex/data/stores.py +1390 -0
  24. vortex/data/sync_templates/__init__.py +0 -0
  25. vortex/gloves.py +309 -0
  26. vortex/layout/__init__.py +20 -0
  27. vortex/layout/contexts.py +577 -0
  28. vortex/layout/dataflow.py +1220 -0
  29. vortex/layout/monitor.py +969 -0
  30. vortex/nwp/__init__.py +14 -0
  31. vortex/nwp/algo/__init__.py +21 -0
  32. vortex/nwp/algo/assim.py +537 -0
  33. vortex/nwp/algo/clim.py +1086 -0
  34. vortex/nwp/algo/coupling.py +831 -0
  35. vortex/nwp/algo/eda.py +840 -0
  36. vortex/nwp/algo/eps.py +785 -0
  37. vortex/nwp/algo/forecasts.py +886 -0
  38. vortex/nwp/algo/fpserver.py +1303 -0
  39. vortex/nwp/algo/ifsnaming.py +463 -0
  40. vortex/nwp/algo/ifsroot.py +404 -0
  41. vortex/nwp/algo/monitoring.py +263 -0
  42. vortex/nwp/algo/mpitools.py +694 -0
  43. vortex/nwp/algo/odbtools.py +1258 -0
  44. vortex/nwp/algo/oopsroot.py +916 -0
  45. vortex/nwp/algo/oopstests.py +220 -0
  46. vortex/nwp/algo/request.py +660 -0
  47. vortex/nwp/algo/stdpost.py +1641 -0
  48. vortex/nwp/data/__init__.py +30 -0
  49. vortex/nwp/data/assim.py +380 -0
  50. vortex/nwp/data/boundaries.py +314 -0
  51. vortex/nwp/data/climfiles.py +521 -0
  52. vortex/nwp/data/configfiles.py +153 -0
  53. vortex/nwp/data/consts.py +954 -0
  54. vortex/nwp/data/ctpini.py +149 -0
  55. vortex/nwp/data/diagnostics.py +209 -0
  56. vortex/nwp/data/eda.py +147 -0
  57. vortex/nwp/data/eps.py +432 -0
  58. vortex/nwp/data/executables.py +1045 -0
  59. vortex/nwp/data/fields.py +111 -0
  60. vortex/nwp/data/gridfiles.py +380 -0
  61. vortex/nwp/data/logs.py +584 -0
  62. vortex/nwp/data/modelstates.py +363 -0
  63. vortex/nwp/data/monitoring.py +193 -0
  64. vortex/nwp/data/namelists.py +696 -0
  65. vortex/nwp/data/obs.py +840 -0
  66. vortex/nwp/data/oopsexec.py +74 -0
  67. vortex/nwp/data/providers.py +207 -0
  68. vortex/nwp/data/query.py +206 -0
  69. vortex/nwp/data/stores.py +160 -0
  70. vortex/nwp/data/surfex.py +337 -0
  71. vortex/nwp/syntax/__init__.py +9 -0
  72. vortex/nwp/syntax/stdattrs.py +437 -0
  73. vortex/nwp/tools/__init__.py +10 -0
  74. vortex/nwp/tools/addons.py +40 -0
  75. vortex/nwp/tools/agt.py +67 -0
  76. vortex/nwp/tools/bdap.py +59 -0
  77. vortex/nwp/tools/bdcp.py +41 -0
  78. vortex/nwp/tools/bdm.py +24 -0
  79. vortex/nwp/tools/bdmp.py +54 -0
  80. vortex/nwp/tools/conftools.py +1661 -0
  81. vortex/nwp/tools/drhook.py +66 -0
  82. vortex/nwp/tools/grib.py +294 -0
  83. vortex/nwp/tools/gribdiff.py +104 -0
  84. vortex/nwp/tools/ifstools.py +203 -0
  85. vortex/nwp/tools/igastuff.py +273 -0
  86. vortex/nwp/tools/mars.py +68 -0
  87. vortex/nwp/tools/odb.py +657 -0
  88. vortex/nwp/tools/partitioning.py +258 -0
  89. vortex/nwp/tools/satrad.py +71 -0
  90. vortex/nwp/util/__init__.py +6 -0
  91. vortex/nwp/util/async.py +212 -0
  92. vortex/nwp/util/beacon.py +40 -0
  93. vortex/nwp/util/diffpygram.py +447 -0
  94. vortex/nwp/util/ens.py +279 -0
  95. vortex/nwp/util/hooks.py +139 -0
  96. vortex/nwp/util/taskdeco.py +85 -0
  97. vortex/nwp/util/usepygram.py +697 -0
  98. vortex/nwp/util/usetnt.py +101 -0
  99. vortex/proxy.py +6 -0
  100. vortex/sessions.py +374 -0
  101. vortex/syntax/__init__.py +9 -0
  102. vortex/syntax/stdattrs.py +867 -0
  103. vortex/syntax/stddeco.py +185 -0
  104. vortex/toolbox.py +1117 -0
  105. vortex/tools/__init__.py +20 -0
  106. vortex/tools/actions.py +523 -0
  107. vortex/tools/addons.py +316 -0
  108. vortex/tools/arm.py +96 -0
  109. vortex/tools/compression.py +325 -0
  110. vortex/tools/date.py +27 -0
  111. vortex/tools/ddhpack.py +10 -0
  112. vortex/tools/delayedactions.py +782 -0
  113. vortex/tools/env.py +541 -0
  114. vortex/tools/folder.py +834 -0
  115. vortex/tools/grib.py +738 -0
  116. vortex/tools/lfi.py +953 -0
  117. vortex/tools/listings.py +423 -0
  118. vortex/tools/names.py +637 -0
  119. vortex/tools/net.py +2124 -0
  120. vortex/tools/odb.py +10 -0
  121. vortex/tools/parallelism.py +368 -0
  122. vortex/tools/prestaging.py +210 -0
  123. vortex/tools/rawfiles.py +10 -0
  124. vortex/tools/schedulers.py +480 -0
  125. vortex/tools/services.py +940 -0
  126. vortex/tools/storage.py +996 -0
  127. vortex/tools/surfex.py +61 -0
  128. vortex/tools/systems.py +3976 -0
  129. vortex/tools/targets.py +440 -0
  130. vortex/util/__init__.py +9 -0
  131. vortex/util/config.py +1122 -0
  132. vortex/util/empty.py +24 -0
  133. vortex/util/helpers.py +216 -0
  134. vortex/util/introspection.py +69 -0
  135. vortex/util/iosponge.py +80 -0
  136. vortex/util/roles.py +49 -0
  137. vortex/util/storefunctions.py +129 -0
  138. vortex/util/structs.py +26 -0
  139. vortex/util/worker.py +162 -0
  140. vortex_nwp-2.0.0.dist-info/METADATA +67 -0
  141. vortex_nwp-2.0.0.dist-info/RECORD +144 -0
  142. vortex_nwp-2.0.0.dist-info/WHEEL +5 -0
  143. vortex_nwp-2.0.0.dist-info/licenses/LICENSE +517 -0
  144. vortex_nwp-2.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,437 @@
1
+ """
2
+ This module provides some pre-defined attributes descriptions or combined sets
3
+ of attributes description that could be used in the footprint definition of any
4
+ class which follow the :class:`footprints.Footprint` syntax.
5
+ """
6
+
7
+ import re
8
+ from functools import total_ordering
9
+
10
+ import footprints
11
+ from bronx.stdtypes.date import Time
12
+
13
+ from vortex.syntax.stddeco import namebuilding_append
14
+
15
+ #: Export some new class for attributes in footprint objects, eg : GenvKey
16
+ __all__ = ["GenvKey", "GenvDomain"]
17
+
18
+ #: Usual Footprint for a single member (in an algo Component)
19
+ a_algo_member = dict(
20
+ info=(
21
+ "The current member's number "
22
+ + "(may be omitted in deterministic configurations)."
23
+ ),
24
+ optional=True,
25
+ type=int,
26
+ )
27
+
28
+ #: Usual Footprint of the ``outputid`` attribute.
29
+ algo_member = footprints.Footprint(attr=dict(member=a_algo_member))
30
+
31
+ #: Known OOPS testcomponent ``run``
32
+ known_oops_testcomponent_runs = ["ootestcomponent", "testcomponent", "testvar"]
33
+
34
+ #: Usual definition of the ``run`` attribute for OOPS binaries.
35
+ a_oops_run = dict(
36
+ info="The OOPS run (== task).",
37
+ optional=False,
38
+ )
39
+ #: Usual Footprint of the ``run`` attribute for OOPS binaries.
40
+ oops_run = footprints.Footprint(
41
+ info="OOPS kind of run", attr=dict(run=a_oops_run)
42
+ )
43
+
44
+ #: Usual definition of the ``test_type`` attribute.
45
+ a_oops_test_type = dict(
46
+ info="Sub-test or family of sub-tests to be ran.",
47
+ optional=False,
48
+ )
49
+ #: Usual Footprint of the ``test_type`` attribute.
50
+ oops_test_type = footprints.Footprint(
51
+ info="OOPS type of test", attr=dict(test_type=a_oops_test_type)
52
+ )
53
+
54
+ #: Usual definition of the ``expected_target`` attribute.
55
+ an_oops_expected_target = dict(
56
+ info=("Expected target for the test success"),
57
+ type=footprints.FPDict,
58
+ optional=True,
59
+ default=None,
60
+ )
61
+ #: Usual Footprint of the ``expected_target`` attribute.
62
+ oops_expected_target = footprints.Footprint(
63
+ attr=dict(expected_target=an_oops_expected_target)
64
+ )
65
+
66
+ #: Usual Footprint of a combined lists of members and terms
67
+ oops_members_terms_lists = footprints.Footprint(
68
+ info="Abstract footprint for a members/terms list.",
69
+ attr=dict(
70
+ members=dict(
71
+ info="A list of members.",
72
+ type=footprints.FPList,
73
+ ),
74
+ terms=dict(
75
+ info="A list of effective terms.",
76
+ type=footprints.FPList,
77
+ optional=True,
78
+ default=footprints.FPList(
79
+ [
80
+ Time(0),
81
+ ]
82
+ ),
83
+ ),
84
+ ),
85
+ )
86
+
87
+ #: Usual definition of the ``outputid`` attribute
88
+ a_outputid = dict(
89
+ info="The identifier for the encoding of post-processed fields.",
90
+ optional=True,
91
+ )
92
+
93
+ #: Usual Footprint of the ``outputid`` attribute.
94
+ outputid = footprints.Footprint(attr=dict(outputid=a_outputid))
95
+
96
+
97
+ def _apply_outputid(cls):
98
+ """Decorator that tweak the class in order to add OUTPUTID on the namelist"""
99
+ orig_pnd = getattr(cls, "prepare_namelist_delta", None)
100
+ if orig_pnd is None:
101
+ raise ImportError(
102
+ "_apply_outputid can not be applied on {!s}".format(cls)
103
+ )
104
+
105
+ def prepare_namelist_delta(self, rh, namcontents, namlocal):
106
+ namw = orig_pnd(self, rh, namcontents, namlocal)
107
+ if self.outputid is not None and any(
108
+ ["OUTPUTID" in nam_b.macros() for nam_b in namcontents.values()]
109
+ ):
110
+ self._set_nam_macro(
111
+ namcontents, namlocal, "OUTPUTID", self.outputid
112
+ )
113
+ namw = True
114
+ return namw
115
+
116
+ cls.prepare_namelist_delta = prepare_namelist_delta
117
+ return cls
118
+
119
+
120
+ #: Decorated footprint for the ``outputid`` attribute
121
+ outputid_deco = footprints.DecorativeFootprint(
122
+ outputid,
123
+ decorator=[
124
+ _apply_outputid,
125
+ ],
126
+ )
127
+
128
+
129
+ def show():
130
+ """Returns available items and their type."""
131
+ dmod = globals()
132
+ for stda in sorted(
133
+ filter(
134
+ lambda x: x.startswith("a_")
135
+ or isinstance(dmod[x], footprints.Footprint),
136
+ dmod.keys(),
137
+ )
138
+ ):
139
+ print(
140
+ "{} ( {} ) :\n {}\n".format(
141
+ stda, type(dmod[stda]).__name__, dmod[stda]
142
+ )
143
+ )
144
+
145
+
146
+ domain_remap = dict()
147
+
148
+
149
+ def _lowerattr(matchobj):
150
+ """Internal and technical function returning lower case value of the complete match item."""
151
+ return matchobj.group(0).lower()
152
+
153
+
154
+ class GenvKey(str):
155
+ """
156
+ Attribute for a GEnv cycle name.
157
+ Implicit attributes inside brackets are translated to lower case.
158
+ See also :mod:`vortex_gco.tools.genv`.
159
+ """
160
+
161
+ def __new__(cls, value):
162
+ """Proxy to ``str.__new___`` with attributes inside brackets translated to lower case."""
163
+ return str.__new__(cls, re.sub(r"\[\w+\]", _lowerattr, value.upper()))
164
+
165
+
166
+ a_gvar = dict(
167
+ info="The key that identifies the resource in the Genv database.",
168
+ type=GenvKey,
169
+ optional=True,
170
+ doc_visibility=footprints.doc.visibility.ADVANCED,
171
+ )
172
+
173
+ #: Usual definition of the ``genv`` attribute.
174
+ gvar = footprints.Footprint(info="A GENV access key", attr=dict(gvar=a_gvar))
175
+
176
+
177
+ class GenvDomain(str):
178
+ """
179
+ Remap plain area names to specific Genv short domain names.
180
+ See also :mod:`vortex_gco.tools.genv`.
181
+ """
182
+
183
+ def __new__(cls, value):
184
+ """Proxy to ``str.__new___`` with on the fly remapping of domain names to short values."""
185
+ return str.__new__(cls, domain_remap.get(value, value))
186
+
187
+
188
+ a_gdomain = dict(
189
+ info="The resource's geographical domain name in the Genv database.",
190
+ type=GenvDomain,
191
+ optional=True,
192
+ default="[geometry::area]",
193
+ doc_visibility=footprints.doc.visibility.ADVANCED,
194
+ )
195
+
196
+ #: Usual definition of the ``gdomain`` attribute.
197
+ gdomain = footprints.Footprint(
198
+ info="A domain name in GCO convention", attr=dict(gdomain=a_gdomain)
199
+ )
200
+
201
+
202
+ @total_ordering
203
+ class ArpIfsSimplifiedCycle:
204
+ """
205
+ Type that holds a simplified representation of an ArpegeIFS cycle.
206
+
207
+ It provides basic comparison operators to determine if a given cycle is more recent or not
208
+ compared to another one.
209
+
210
+ It can be used in a footprint specification.
211
+ """
212
+
213
+ _cy_re = re.compile(
214
+ r"(?:u(?:env|get):)?(?:cy|al)(\d+)(?:t(\d{1,3}))?(?=_|@|\.|$)(?:.*?(?:[_-]op(\d{1,3})))?"
215
+ )
216
+ _hash_shift = 10000
217
+
218
+ def __init__(self, cyclestr):
219
+ cy_match = self._cy_re.match(cyclestr)
220
+ if cy_match:
221
+ self._number = int(cy_match.group(1))
222
+ self._toulouse = (
223
+ int(cy_match.group(2)) + 1
224
+ if cy_match.group(2) is not None
225
+ else 0
226
+ )
227
+ self._op = (
228
+ int(cy_match.group(3)) + 1
229
+ if cy_match.group(3) is not None
230
+ else 0
231
+ )
232
+ else:
233
+ raise ValueError("Malformed cycle: {}".format(cyclestr))
234
+
235
+ def __hash__(self):
236
+ return (
237
+ self._number * self._hash_shift + self._toulouse
238
+ ) * self._hash_shift + self._op
239
+
240
+ def __eq__(self, other):
241
+ if not isinstance(other, ArpIfsSimplifiedCycle):
242
+ try:
243
+ other = ArpIfsSimplifiedCycle(other)
244
+ except (ValueError, TypeError):
245
+ return False
246
+ return hash(self) == hash(other)
247
+
248
+ def __gt__(self, other):
249
+ if not isinstance(other, ArpIfsSimplifiedCycle):
250
+ other = ArpIfsSimplifiedCycle(other)
251
+ return hash(self) > hash(other)
252
+
253
+ def __str__(self):
254
+ return (
255
+ "cy{:d}".format(self._number)
256
+ + ("t{:d}".format(self._toulouse - 1) if self._toulouse else "")
257
+ + ("_op{:d}".format(self._op - 1) if self._op else "")
258
+ )
259
+
260
+ def __repr__(self):
261
+ return "<{} | {!s}>".format(
262
+ object.__repr__(self).lstrip("<").rstrip(">"), self
263
+ )
264
+
265
+ def export_dict(self):
266
+ """The pure dict/json output is the raw integer"""
267
+ return str(self)
268
+
269
+
270
+ a_arpifs_cycle = dict(
271
+ info="An Arpege/IFS cycle name",
272
+ type=ArpIfsSimplifiedCycle,
273
+ optional=True,
274
+ default="cy40", # For "old" Olive configurations to keep working
275
+ )
276
+
277
+ #: Usual definition of the ``cycle`` attribute.
278
+ arpifs_cycle = footprints.Footprint(
279
+ info="An abstract arpifs_cycle in GCO convention",
280
+ attr=dict(cycle=a_arpifs_cycle),
281
+ )
282
+
283
+ uget_sloppy_id_regex = re.compile(
284
+ r"(?P<shortuget>(?P<id>\S+)@(?P<location>[-\w]+))"
285
+ )
286
+ uget_id_regex = (
287
+ r"(?P<fulluget>u(?:get|env):" + uget_sloppy_id_regex.pattern + ")"
288
+ )
289
+ uget_id_regex_only = re.compile("^" + uget_id_regex + "$")
290
+ uget_id_regex = re.compile(r"\b" + uget_id_regex + r"\b")
291
+
292
+
293
+ class GgetId(str):
294
+ """Basestring wrapper for Gget Ids."""
295
+
296
+ def __new__(cls, value):
297
+ if uget_id_regex_only.match(value):
298
+ raise ValueError("A GgetId cannot look like a UgetId !")
299
+ return str.__new__(cls, value)
300
+
301
+
302
+ class AbstractUgetId(str):
303
+ """Basestring wrapper for Uget Ids."""
304
+
305
+ _ALLOWED_LOCATIONS = ()
306
+ _OUTCAST_LOCATIONS = ()
307
+
308
+ def __new__(cls, value):
309
+ vmatch = uget_id_regex_only.match(value)
310
+ if not vmatch:
311
+ raise ValueError('Invalid UgetId (got "{:s}")'.format(value))
312
+ me = str.__new__(cls, value)
313
+ me._id = vmatch.group("id")
314
+ me._location = vmatch.group("location")
315
+ if me._location in set(cls._OUTCAST_LOCATIONS):
316
+ raise ValueError(
317
+ 'Invalid UgetId (got "{:s}"). Outcast Location.'.format(value)
318
+ )
319
+ if cls._ALLOWED_LOCATIONS and me._location not in set(
320
+ cls._ALLOWED_LOCATIONS
321
+ ):
322
+ raise ValueError(
323
+ 'Invalid UgetId (got "{:s}"). Disallowed location'.format(
324
+ value
325
+ )
326
+ )
327
+ return me
328
+
329
+ @property
330
+ def id(self):
331
+ return self._id
332
+
333
+ @property
334
+ def location(self):
335
+ return self._location
336
+
337
+ @property
338
+ def short(self):
339
+ return self._id + "@" + self._location
340
+
341
+ def monthlyshort(self, month):
342
+ return self._id + ".m{:02d}".format(month) + "@" + self._location
343
+
344
+
345
+ class UgetId(AbstractUgetId):
346
+ _OUTCAST_LOCATIONS = ("demo",)
347
+
348
+
349
+ def genv_ifs_compiler_convention(cls):
350
+ """Add the necessary method to handle compiler version/option in Genv."""
351
+ original_gget_basename = getattr(cls, "gget_basename", None)
352
+ if original_gget_basename is not None:
353
+
354
+ def gget_basename(self):
355
+ """GGET specific naming convention."""
356
+ b_dict = original_gget_basename(self)
357
+ if getattr(self, "compiler_version", None):
358
+ b_dict["compiler_version"] = self.compiler_version
359
+ if getattr(self, "compiler_option", None):
360
+ b_dict["compiler_option"] = self.compiler_option
361
+ if getattr(self, "cycle", None):
362
+ b_dict["cycle"] = self.cycle
363
+ return b_dict
364
+
365
+ cls.gget_basename = gget_basename
366
+ return cls
367
+
368
+
369
+ #: Usual definition of the ``compiler_version`` and ``compiler_option`` attributes.
370
+ gmkpack_compiler_identification = footprints.Footprint(
371
+ info="Add the compiler version/option in the footprint",
372
+ attr=dict(
373
+ compiler_version=dict(
374
+ info="The compiler version in gmkpack convention.", optional=True
375
+ ),
376
+ compiler_option=dict(
377
+ info="The compiler option in gmkpack convention.", optional=True
378
+ ),
379
+ ),
380
+ )
381
+
382
+
383
+ #: Usual definition of the ``compiler_version`` and ``compiler_option`` attributes + genv integration.
384
+ gmkpack_compiler_identification_deco = footprints.DecorativeFootprint(
385
+ gmkpack_compiler_identification,
386
+ decorator=[
387
+ genv_ifs_compiler_convention,
388
+ ],
389
+ )
390
+
391
+
392
+ def genv_executable_flavour(cls):
393
+ """Add the necessary method to the "flavour" in Genv."""
394
+ original_genv_basename = getattr(cls, "genv_basename", None)
395
+ if original_genv_basename is not None:
396
+
397
+ def genv_basename(self):
398
+ """Just retrieve a potential gvar attribute."""
399
+ gvar = original_genv_basename(self)
400
+ if getattr(self, "flavour", None):
401
+ gvar += (
402
+ "_"
403
+ + {"singleprecision": "SP"}.get(
404
+ self.flavour, self.flavour
405
+ ).upper()
406
+ )
407
+ return gvar
408
+
409
+ cls.genv_basename = genv_basename
410
+ return cls
411
+
412
+
413
+ #: Usual definition of the ``flavour`` attribute.
414
+ executable_flavour = footprints.Footprint(
415
+ info="Add the executable flavour attribute to the resource",
416
+ attr=dict(
417
+ flavour=dict(
418
+ info="The executable flavour (This may influence the Genv's key choice).",
419
+ values=[
420
+ "singleprecision",
421
+ ],
422
+ optional=True,
423
+ ),
424
+ ),
425
+ )
426
+
427
+
428
+ #: Usual definition of the ``flavour``.
429
+ executable_flavour_deco = footprints.DecorativeFootprint(
430
+ executable_flavour,
431
+ decorator=[
432
+ genv_executable_flavour,
433
+ namebuilding_append(
434
+ "src", lambda self: [self.flavour], none_discard=True
435
+ ),
436
+ ],
437
+ )
@@ -0,0 +1,10 @@
1
+ """
2
+ Standalone tools for NWP
3
+ """
4
+
5
+ # Recursive inclusion of packages with potential FootprintBase classes
6
+ from . import conftools as conftools
7
+ from . import ifstools as ifstools
8
+
9
+ #: Automatic export of data subpackage
10
+ __all__ = []
@@ -0,0 +1,40 @@
1
+ """
2
+ Various System needed for NWP applications.
3
+ """
4
+
5
+ from vortex.tools.addons import AddonGroup
6
+
7
+ # Import the proper Addon modules for footprints
8
+ from vortex.tools import folder as folder
9
+ from vortex.tools import lfi as lfi
10
+ from vortex.tools import grib as grib
11
+ from vortex.tools import listings as listings
12
+ from vortex.tools import surfex as surfex
13
+
14
+ #: No automatic export
15
+ __all__ = []
16
+
17
+
18
+ class NWPAddonsGroup(AddonGroup):
19
+ """A set of usual NWP Addons."""
20
+
21
+ _footprint = dict(
22
+ info="Default NWP Addons",
23
+ attr=dict(
24
+ kind=dict(
25
+ values=[
26
+ "nwp",
27
+ ],
28
+ ),
29
+ ),
30
+ )
31
+
32
+ _addonslist = (
33
+ "allfolders", # Folder like...
34
+ "lfi",
35
+ "iopoll", # Wonderful FA/LFI world...
36
+ "grib",
37
+ "gribapi", # GRIB stuff...
38
+ "arpifs_listings", # Obscure IFS/Arpege listings...
39
+ "sfx", # Surfex...
40
+ )
@@ -0,0 +1,67 @@
1
+ """
2
+ TODO: Module documentation.
3
+ """
4
+
5
+ import collections
6
+
7
+
8
+ class AgtConfigurationError(Exception):
9
+ """Specific Transfer Agent configuration error."""
10
+
11
+ pass
12
+
13
+
14
+ def agt_volatile_path(sh):
15
+ """Prefix path to use for the Transfer Agent to consider a file as being "volatile"
16
+ and hard-linking to it instead of expecting it to be present "later".
17
+ """
18
+ config = sh.default_target.config
19
+ if not config.has_section("agt"):
20
+ fmt = 'Missing section "agt" in configuration file\n"{}"'
21
+ raise AgtConfigurationError(fmt.format(config.file))
22
+ return config.get("agt", "agt_volatile")
23
+
24
+
25
+ def agt_actual_command(sh, binary_name, args, extraenv=None):
26
+ """Build the command able to execute a Transfer Agent binary.
27
+
28
+ The context, the execution path and the command name are
29
+ provided by the configuration file of the target.
30
+
31
+ The resulting command should be executed on a transfer node.
32
+
33
+ :param sh: The vortex shell that will be used
34
+ :param binary_name: Key in the configuration file that holds the binary name
35
+ :param args: Argument to the AGT binary
36
+ :param extraenv: Additional environment variables to export (dictionary)
37
+ """
38
+ config = sh.default_target.config
39
+ if not config.has_section("agt"):
40
+ fmt = 'Missing section "agt" in configuration file\n"{}"'
41
+ raise AgtConfigurationError(fmt.format(config.file))
42
+
43
+ agt_path = sh.default_target.get("agt_path", default=None)
44
+ agt_bin = sh.default_target.get(binary_name, default=None)
45
+ if not all([agt_path, agt_bin]):
46
+ fmt = 'Missing key "agt_path" or "{}" in configuration file\n"{}"'
47
+ raise AgtConfigurationError(fmt.format(binary_name, config.file))
48
+ cfgkeys = [
49
+ "HOME_SOPRA",
50
+ "LD_LIBRARY_PATH",
51
+ "base_transfert_agent",
52
+ "DIAP_AGENT_NUMPROG_AGENT",
53
+ ]
54
+ context = " ; ".join(
55
+ ["export {}={}".format(key, config.get("agt", key)) for key in cfgkeys]
56
+ )
57
+ if extraenv is not None and isinstance(extraenv, collections.abc.Mapping):
58
+ context = " ; ".join(
59
+ [
60
+ context,
61
+ ]
62
+ + [
63
+ "export {}={}".format(key.upper(), value)
64
+ for (key, value) in extraenv.items()
65
+ ]
66
+ )
67
+ return "{} ; {} {}".format(context, sh.path.join(agt_path, agt_bin), args)
@@ -0,0 +1,59 @@
1
+ """
2
+ Utility classes and function to work with the BDAP database.
3
+ """
4
+
5
+ #: No automatic export
6
+ __all__ = []
7
+
8
+
9
+ class BDAPError(Exception):
10
+ """General BDAP error."""
11
+
12
+ pass
13
+
14
+
15
+ class BDAPRequestConfigurationError(BDAPError):
16
+ """Specific Transfer Agent configuration error."""
17
+
18
+ pass
19
+
20
+
21
+ class BDAPGetError(BDAPError):
22
+ """Generic BDAP get error."""
23
+
24
+ pass
25
+
26
+
27
+ def BDAPrequest_actual_command(command, date, term, query, int_extraenv=False):
28
+ """Build the command able to execute a BDAP request.
29
+
30
+ The context, the execution path and the command name are
31
+ provided by the configuration file of the target.
32
+
33
+ The resulting command should be executed on a transfer node.
34
+
35
+ :param command: name of the BDAP request command to be used
36
+ :param date: the date of the file requested
37
+ :param term: the term of the file requested
38
+ :param query: the query file used for the request
39
+ :param int_extraenv: boolean to know if the integration BDAP is used or not
40
+ (an additional environment variable has to be exported in this case).
41
+ """
42
+
43
+ # Environment variable to specify the date of the file
44
+ context = " ; ".join(
45
+ ["export {}={}".format("dmt_date_pivot".upper(), date.ymdhms)]
46
+ )
47
+ # Extra environment variables (integration BDAP)
48
+ if int_extraenv:
49
+ context = " ; ".join(
50
+ [context]
51
+ + [
52
+ "export {}={}".format(
53
+ "db_file_bdap".upper(),
54
+ "/usr/local/sopra/neons_db_bdap.intgr",
55
+ )
56
+ ]
57
+ )
58
+ # Return the command to be launched
59
+ return "{} ; {} {:d} {}".format(context, command, term.hour, query)
@@ -0,0 +1,41 @@
1
+ """
2
+ Utility classes and function to work with the BDCP database.
3
+ """
4
+
5
+ #: No automatic export
6
+ __all__ = []
7
+
8
+
9
+ class BDCPError(Exception):
10
+ """General BDMP error."""
11
+
12
+ pass
13
+
14
+
15
+ class BDCPRequestConfigurationError(BDCPError):
16
+ """Specific Transfer Agent configuration error."""
17
+
18
+ pass
19
+
20
+
21
+ class BDCPGetError(BDCPError):
22
+ """Generic BDCP get error."""
23
+
24
+ pass
25
+
26
+
27
+ def BDCPrequest_actual_command(command, query_file, output_file):
28
+ """Build the command able to execute a BDCP request.
29
+
30
+ The context, the execution path and the command name are
31
+ provided by the configuration file of the target.
32
+
33
+ The resulting command should be executed on a transfer node.
34
+
35
+ :param command: name of the BDMP request command to be used
36
+ :param query_file: the query file used for the request
37
+ :param output_file: the file in which the result will be written
38
+ """
39
+
40
+ # Return the command to be launched
41
+ return "{} -D {} -f {}".format(command, query_file, output_file)
@@ -0,0 +1,24 @@
1
+ """
2
+ Utility classes and function to work with the BDM database.
3
+ """
4
+
5
+ #: No automatic export
6
+ __all__ = []
7
+
8
+
9
+ class BDMError(Exception):
10
+ """General BDM error."""
11
+
12
+ pass
13
+
14
+
15
+ class BDMRequestConfigurationError(BDMError):
16
+ """Specific Transfer Agent configuration error."""
17
+
18
+ pass
19
+
20
+
21
+ class BDMGetError(BDMError):
22
+ """Generic BDM get error."""
23
+
24
+ pass