vortex-nwp 2.0.0b1__py3-none-any.whl → 2.1.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 (141) hide show
  1. vortex/__init__.py +75 -47
  2. vortex/algo/__init__.py +3 -2
  3. vortex/algo/components.py +944 -618
  4. vortex/algo/mpitools.py +802 -497
  5. vortex/algo/mpitools_templates/__init__.py +1 -0
  6. vortex/algo/serversynctools.py +34 -33
  7. vortex/config.py +19 -22
  8. vortex/data/__init__.py +9 -3
  9. vortex/data/abstractstores.py +593 -655
  10. vortex/data/containers.py +217 -162
  11. vortex/data/contents.py +65 -39
  12. vortex/data/executables.py +93 -102
  13. vortex/data/flow.py +40 -34
  14. vortex/data/geometries.py +228 -132
  15. vortex/data/handlers.py +436 -227
  16. vortex/data/outflow.py +15 -15
  17. vortex/data/providers.py +185 -163
  18. vortex/data/resources.py +48 -42
  19. vortex/data/stores.py +540 -417
  20. vortex/data/sync_templates/__init__.py +0 -0
  21. vortex/gloves.py +114 -87
  22. vortex/layout/__init__.py +1 -8
  23. vortex/layout/contexts.py +150 -84
  24. vortex/layout/dataflow.py +353 -202
  25. vortex/layout/monitor.py +264 -128
  26. vortex/nwp/__init__.py +5 -2
  27. vortex/nwp/algo/__init__.py +14 -5
  28. vortex/nwp/algo/assim.py +205 -151
  29. vortex/nwp/algo/clim.py +683 -517
  30. vortex/nwp/algo/coupling.py +447 -225
  31. vortex/nwp/algo/eda.py +437 -229
  32. vortex/nwp/algo/eps.py +403 -231
  33. vortex/nwp/algo/forecasts.py +416 -275
  34. vortex/nwp/algo/fpserver.py +683 -307
  35. vortex/nwp/algo/ifsnaming.py +205 -145
  36. vortex/nwp/algo/ifsroot.py +215 -122
  37. vortex/nwp/algo/monitoring.py +137 -76
  38. vortex/nwp/algo/mpitools.py +330 -190
  39. vortex/nwp/algo/odbtools.py +637 -353
  40. vortex/nwp/algo/oopsroot.py +454 -273
  41. vortex/nwp/algo/oopstests.py +90 -56
  42. vortex/nwp/algo/request.py +287 -206
  43. vortex/nwp/algo/stdpost.py +878 -522
  44. vortex/nwp/data/__init__.py +22 -4
  45. vortex/nwp/data/assim.py +125 -137
  46. vortex/nwp/data/boundaries.py +121 -68
  47. vortex/nwp/data/climfiles.py +193 -211
  48. vortex/nwp/data/configfiles.py +73 -69
  49. vortex/nwp/data/consts.py +426 -401
  50. vortex/nwp/data/ctpini.py +59 -43
  51. vortex/nwp/data/diagnostics.py +94 -66
  52. vortex/nwp/data/eda.py +50 -51
  53. vortex/nwp/data/eps.py +195 -146
  54. vortex/nwp/data/executables.py +440 -434
  55. vortex/nwp/data/fields.py +63 -48
  56. vortex/nwp/data/gridfiles.py +183 -111
  57. vortex/nwp/data/logs.py +250 -217
  58. vortex/nwp/data/modelstates.py +180 -151
  59. vortex/nwp/data/monitoring.py +72 -99
  60. vortex/nwp/data/namelists.py +254 -202
  61. vortex/nwp/data/obs.py +400 -308
  62. vortex/nwp/data/oopsexec.py +22 -20
  63. vortex/nwp/data/providers.py +90 -65
  64. vortex/nwp/data/query.py +71 -82
  65. vortex/nwp/data/stores.py +49 -36
  66. vortex/nwp/data/surfex.py +136 -137
  67. vortex/nwp/syntax/__init__.py +1 -1
  68. vortex/nwp/syntax/stdattrs.py +173 -111
  69. vortex/nwp/tools/__init__.py +2 -2
  70. vortex/nwp/tools/addons.py +22 -17
  71. vortex/nwp/tools/agt.py +24 -12
  72. vortex/nwp/tools/bdap.py +16 -5
  73. vortex/nwp/tools/bdcp.py +4 -1
  74. vortex/nwp/tools/bdm.py +3 -0
  75. vortex/nwp/tools/bdmp.py +14 -9
  76. vortex/nwp/tools/conftools.py +728 -378
  77. vortex/nwp/tools/drhook.py +12 -8
  78. vortex/nwp/tools/grib.py +65 -39
  79. vortex/nwp/tools/gribdiff.py +22 -17
  80. vortex/nwp/tools/ifstools.py +82 -42
  81. vortex/nwp/tools/igastuff.py +167 -143
  82. vortex/nwp/tools/mars.py +14 -2
  83. vortex/nwp/tools/odb.py +234 -125
  84. vortex/nwp/tools/partitioning.py +61 -37
  85. vortex/nwp/tools/satrad.py +27 -12
  86. vortex/nwp/util/async.py +83 -55
  87. vortex/nwp/util/beacon.py +10 -10
  88. vortex/nwp/util/diffpygram.py +174 -86
  89. vortex/nwp/util/ens.py +144 -63
  90. vortex/nwp/util/hooks.py +30 -19
  91. vortex/nwp/util/taskdeco.py +28 -24
  92. vortex/nwp/util/usepygram.py +278 -172
  93. vortex/nwp/util/usetnt.py +31 -17
  94. vortex/sessions.py +72 -39
  95. vortex/syntax/__init__.py +1 -1
  96. vortex/syntax/stdattrs.py +410 -171
  97. vortex/syntax/stddeco.py +31 -22
  98. vortex/toolbox.py +327 -192
  99. vortex/tools/__init__.py +11 -2
  100. vortex/tools/actions.py +110 -121
  101. vortex/tools/addons.py +111 -92
  102. vortex/tools/arm.py +42 -22
  103. vortex/tools/compression.py +72 -69
  104. vortex/tools/date.py +11 -4
  105. vortex/tools/delayedactions.py +242 -132
  106. vortex/tools/env.py +75 -47
  107. vortex/tools/folder.py +342 -171
  108. vortex/tools/grib.py +341 -162
  109. vortex/tools/lfi.py +423 -216
  110. vortex/tools/listings.py +109 -40
  111. vortex/tools/names.py +218 -156
  112. vortex/tools/net.py +655 -299
  113. vortex/tools/parallelism.py +93 -61
  114. vortex/tools/prestaging.py +55 -31
  115. vortex/tools/schedulers.py +172 -105
  116. vortex/tools/services.py +403 -334
  117. vortex/tools/storage.py +293 -358
  118. vortex/tools/surfex.py +24 -24
  119. vortex/tools/systems.py +1234 -643
  120. vortex/tools/targets.py +156 -100
  121. vortex/util/__init__.py +1 -1
  122. vortex/util/config.py +378 -327
  123. vortex/util/empty.py +2 -2
  124. vortex/util/helpers.py +56 -24
  125. vortex/util/introspection.py +18 -12
  126. vortex/util/iosponge.py +8 -4
  127. vortex/util/roles.py +4 -6
  128. vortex/util/storefunctions.py +39 -13
  129. vortex/util/structs.py +3 -3
  130. vortex/util/worker.py +29 -17
  131. vortex_nwp-2.1.0.dist-info/METADATA +67 -0
  132. vortex_nwp-2.1.0.dist-info/RECORD +144 -0
  133. {vortex_nwp-2.0.0b1.dist-info → vortex_nwp-2.1.0.dist-info}/WHEEL +1 -1
  134. vortex/layout/appconf.py +0 -109
  135. vortex/layout/jobs.py +0 -1276
  136. vortex/layout/nodes.py +0 -1424
  137. vortex/layout/subjobs.py +0 -464
  138. vortex_nwp-2.0.0b1.dist-info/METADATA +0 -50
  139. vortex_nwp-2.0.0b1.dist-info/RECORD +0 -146
  140. {vortex_nwp-2.0.0b1.dist-info → vortex_nwp-2.1.0.dist-info/licenses}/LICENSE +0 -0
  141. {vortex_nwp-2.0.0b1.dist-info → vortex_nwp-2.1.0.dist-info}/top_level.txt +0 -0
vortex/tools/targets.py CHANGED
@@ -44,55 +44,55 @@ class Target(fp.FootprintBase):
44
44
 
45
45
  _abstract = True
46
46
  _explicit = False
47
- _collector = ('target',)
47
+ _collector = ("target",)
48
48
  _footprint = dict(
49
- info = 'Default target description',
50
- attr = dict(
51
- hostname = dict(
52
- optional = True,
53
- default = platform.node(),
54
- alias = ('nodename', 'computer')
49
+ info="Default target description",
50
+ attr=dict(
51
+ hostname=dict(
52
+ optional=True,
53
+ default=platform.node(),
54
+ alias=("nodename", "computer"),
55
55
  ),
56
- inetname = dict(
57
- optional = True,
58
- default = platform.node(),
56
+ inetname=dict(
57
+ optional=True,
58
+ default=platform.node(),
59
59
  ),
60
- fqdn = dict(
61
- optional = True,
62
- default = default_fqdn(),
60
+ fqdn=dict(
61
+ optional=True,
62
+ default=default_fqdn(),
63
63
  ),
64
- sysname = dict(
65
- optional = True,
66
- default = platform.system(),
64
+ sysname=dict(
65
+ optional=True,
66
+ default=platform.system(),
67
67
  ),
68
- userconfig = dict(
69
- type = GenericConfigParser,
70
- optional = True,
71
- default = None,
68
+ userconfig=dict(
69
+ type=GenericConfigParser,
70
+ optional=True,
71
+ default=None,
72
72
  ),
73
- inifile = dict(
74
- optional = True,
75
- default = '@target-[hostname].ini',
73
+ inifile=dict(
74
+ optional=True,
75
+ default="@target-[hostname].ini",
76
76
  ),
77
- defaultinifile = dict(
78
- optional = True,
79
- default = 'target-commons.ini',
77
+ defaultinifile=dict(
78
+ optional=True,
79
+ default="target-commons.ini",
80
80
  ),
81
- iniauto = dict(
82
- type = bool,
83
- optional = True,
84
- default = True,
85
- )
86
- )
81
+ iniauto=dict(
82
+ type=bool,
83
+ optional=True,
84
+ default=True,
85
+ ),
86
+ ),
87
87
  )
88
88
 
89
- _re_nodes_property = re.compile(r'(\w+)(nodes)$')
90
- _re_proxies_property = re.compile(r'(\w+)(proxies)$')
91
- _re_isnode_property = re.compile(r'is(\w+)node$')
92
- _re_glove_rk_id = re.compile(r'^(.*)@\w+$')
89
+ _re_nodes_property = re.compile(r"(\w+)(nodes)$")
90
+ _re_proxies_property = re.compile(r"(\w+)(proxies)$")
91
+ _re_isnode_property = re.compile(r"is(\w+)node$")
92
+ _re_glove_rk_id = re.compile(r"^(.*)@\w+$")
93
93
 
94
94
  def __init__(self, *args, **kw):
95
- logger.debug('Abstract target computer init %s', self.__class__)
95
+ logger.debug("Abstract target computer init %s", self.__class__)
96
96
  super().__init__(*args, **kw)
97
97
  self._actualconfig = self.userconfig
98
98
  self._specialnodes = None
@@ -101,7 +101,7 @@ class Target(fp.FootprintBase):
101
101
 
102
102
  @property
103
103
  def realkind(self):
104
- return 'target'
104
+ return "target"
105
105
 
106
106
  @property
107
107
  def config(self):
@@ -135,23 +135,35 @@ class Target(fp.FootprintBase):
135
135
  The :meth:`get` method called whith ``key='sectionname:myoption'`` will
136
136
  return 'operations'.
137
137
  """
138
- my_glove_rk = '@' + sessions.current().glove.realkind
139
- if ':' in key:
140
- section, option = (x.strip() for x in key.split(':', 1))
138
+ my_glove_rk = "@" + sessions.current().glove.realkind
139
+ if ":" in key:
140
+ section, option = (x.strip() for x in key.split(":", 1))
141
141
  # Check if an override section exists
142
- sections = [x for x in (section + my_glove_rk, section)
143
- if x in self.config.sections()]
142
+ sections = [
143
+ x
144
+ for x in (section + my_glove_rk, section)
145
+ if x in self.config.sections()
146
+ ]
144
147
  else:
145
148
  option = key
146
149
  # First look in override sections, then in default one
147
- sections = ([s for s in self.config.sections() if s.endswith(my_glove_rk)] +
148
- [s for s in self.config.sections() if not self._re_glove_rk_id.match(s)])
150
+ sections = [
151
+ s for s in self.config.sections() if s.endswith(my_glove_rk)
152
+ ] + [
153
+ s
154
+ for s in self.config.sections()
155
+ if not self._re_glove_rk_id.match(s)
156
+ ]
149
157
  # Return the first matching section/option
150
- for section in [x for x in sections if self.config.has_option(x, option)]:
158
+ for section in [
159
+ x for x in sections if self.config.has_option(x, option)
160
+ ]:
151
161
  return self.config.get(section, option)
152
162
  return default
153
163
 
154
- def getx(self, key, default=None, env_key=None, silent=False, aslist=False):
164
+ def getx(
165
+ self, key, default=None, env_key=None, silent=False, aslist=False
166
+ ):
155
167
  r"""Return a value from several sources.
156
168
 
157
169
  In turn, the following sources are considered:
@@ -179,10 +191,12 @@ class Target(fp.FootprintBase):
179
191
  value = None
180
192
 
181
193
  if value is None:
182
- if ':' not in key:
194
+ if ":" not in key:
183
195
  if silent:
184
196
  return None
185
- msg = 'Configuration key should be "section:option" not "{}"'.format(key)
197
+ msg = 'Configuration key should be "section:option" not "{}"'.format(
198
+ key
199
+ )
186
200
  raise KeyError(msg)
187
201
  value = self.get(key, default)
188
202
 
@@ -196,17 +210,28 @@ class Target(fp.FootprintBase):
196
210
  raise KeyError(msg)
197
211
 
198
212
  if aslist:
199
- value = value.replace('\n', ' ').replace('\\', ' ').replace(',', ' ').split()
213
+ value = (
214
+ value.replace("\n", " ")
215
+ .replace("\\", " ")
216
+ .replace(",", " ")
217
+ .split()
218
+ )
200
219
 
201
220
  return value
202
221
 
203
222
  def sections(self):
204
223
  """Returns the list of sections contained in the config file."""
205
- my_glove_rk = '@' + sessions.current().glove.realkind
206
- return sorted({self._re_glove_rk_id.sub(r'\1', x)
207
- for x in self.config.sections()
208
- if ((not self._re_glove_rk_id.match(x)) or
209
- x.endswith(my_glove_rk))})
224
+ my_glove_rk = "@" + sessions.current().glove.realkind
225
+ return sorted(
226
+ {
227
+ self._re_glove_rk_id.sub(r"\1", x)
228
+ for x in self.config.sections()
229
+ if (
230
+ (not self._re_glove_rk_id.match(x))
231
+ or x.endswith(my_glove_rk)
232
+ )
233
+ }
234
+ )
210
235
 
211
236
  def options(self, key):
212
237
  """For a given section, returns the list of available options.
@@ -214,9 +239,10 @@ class Target(fp.FootprintBase):
214
239
  The result may depend on the current glove (see the :meth:`get`
215
240
  method documentation).
216
241
  """
217
- my_glove_rk = '@' + sessions.current().glove.realkind
218
- sections = [x for x in (key, key + my_glove_rk)
219
- if x in self.config.sections()]
242
+ my_glove_rk = "@" + sessions.current().glove.realkind
243
+ sections = [
244
+ x for x in (key, key + my_glove_rk) if x in self.config.sections()
245
+ ]
220
246
  options = set()
221
247
  for section in sections:
222
248
  options.update(self.config.options(section))
@@ -230,9 +256,12 @@ class Target(fp.FootprintBase):
230
256
  """
231
257
  items = dict()
232
258
  if key is not None:
233
- my_glove_rk = '@' + sessions.current().glove.realkind
234
- sections = [x for x in (key, key + my_glove_rk)
235
- if x in self.config.sections()]
259
+ my_glove_rk = "@" + sessions.current().glove.realkind
260
+ sections = [
261
+ x
262
+ for x in (key, key + my_glove_rk)
263
+ if x in self.config.sections()
264
+ ]
236
265
  for section in sections:
237
266
  items.update(self.config.items(section))
238
267
  return items
@@ -241,7 +270,7 @@ class Target(fp.FootprintBase):
241
270
  def is_anonymous(cls):
242
271
  """Return a boolean either the current footprint define or not a mandatory set of hostname values."""
243
272
  fp = cls.footprint_retrieve()
244
- return not bool(fp.attr['hostname']['values'])
273
+ return not bool(fp.attr["hostname"]["values"])
245
274
 
246
275
  def spawn_hook(self, sh):
247
276
  """Specific target hook before any serious execution."""
@@ -252,7 +281,12 @@ class Target(fp.FootprintBase):
252
281
  """Specific target hook before any component run."""
253
282
  yield
254
283
 
255
- def _init_supernodes(self, main_re, rangeid='range', baseid='base',):
284
+ def _init_supernodes(
285
+ self,
286
+ main_re,
287
+ rangeid="range",
288
+ baseid="base",
289
+ ):
256
290
  """Read the configuration file in order to initialize the specialnodes
257
291
  and specialproxies lists.
258
292
 
@@ -261,40 +295,55 @@ class Target(fp.FootprintBase):
261
295
  *generic_nodes* keyword. In such a case, the node list will be
262
296
  auto-generated using the XXXrange and XXXbase configuration keys.
263
297
  """
264
- confsection = 'generic_nodes'
298
+ confsection = "generic_nodes"
265
299
  confoptions = self.options(confsection)
266
- nodetypes = [(m.group(1), m.group(2))
267
- for m in [main_re.match(k) for k in confoptions]
268
- if m is not None]
300
+ nodetypes = [
301
+ (m.group(1), m.group(2))
302
+ for m in [main_re.match(k) for k in confoptions]
303
+ if m is not None
304
+ ]
269
305
  outdict = dict()
270
306
  for nodetype, nodelistid in nodetypes:
271
- nodelist = self.get(confsection + ':' + nodetype + nodelistid)
272
- if nodelist == 'no_generic':
273
- noderanges = self.get(confsection + ':' + nodetype + rangeid, None)
307
+ nodelist = self.get(confsection + ":" + nodetype + nodelistid)
308
+ if nodelist == "no_generic":
309
+ noderanges = self.get(
310
+ confsection + ":" + nodetype + rangeid, None
311
+ )
274
312
  if noderanges is None:
275
- raise ValueError('when {0:s}{1:s} == no_generic, {0:s}{2:s} must be provided'
276
- .format(nodetype, nodelistid, rangeid))
277
- nodebases = self.get(confsection + ':' + nodetype + baseid,
278
- self.inetname + nodetype + '{:d}')
313
+ raise ValueError(
314
+ "when {0:s}{1:s} == no_generic, {0:s}{2:s} must be provided".format(
315
+ nodetype, nodelistid, rangeid
316
+ )
317
+ )
318
+ nodebases = self.get(
319
+ confsection + ":" + nodetype + baseid,
320
+ self.inetname + nodetype + "{:d}",
321
+ )
279
322
  outdict[nodetype] = list()
280
- for (r, b) in zip(noderanges.split('+'), nodebases.split('+')):
281
- outdict[nodetype].extend([b.format(int(i)) for i in r.split(',')])
323
+ for r, b in zip(noderanges.split("+"), nodebases.split("+")):
324
+ outdict[nodetype].extend(
325
+ [b.format(int(i)) for i in r.split(",")]
326
+ )
282
327
  else:
283
- outdict[nodetype] = nodelist.split(',')
328
+ outdict[nodetype] = nodelist.split(",")
284
329
  return outdict
285
330
 
286
331
  @property
287
332
  def specialnodesaliases(self):
288
333
  """Return the list of known aliases."""
289
334
  if self._sepcialnodesaliases is None:
290
- confsection = 'generic_nodes'
335
+ confsection = "generic_nodes"
291
336
  confoptions = self.options(confsection)
292
- aliases_re = re.compile(r'(\w+)(aliases)')
293
- nodetypes = [(m.group(1), m.group(2))
294
- for m in [aliases_re.match(k) for k in confoptions]
295
- if m is not None]
296
- rdict = {ntype: self.get(confsection + ':' + ntype + key, '').split(',')
297
- for ntype, key in nodetypes}
337
+ aliases_re = re.compile(r"(\w+)(aliases)")
338
+ nodetypes = [
339
+ (m.group(1), m.group(2))
340
+ for m in [aliases_re.match(k) for k in confoptions]
341
+ if m is not None
342
+ ]
343
+ rdict = {
344
+ ntype: self.get(confsection + ":" + ntype + key, "").split(",")
345
+ for ntype, key in nodetypes
346
+ }
298
347
  self._sepcialnodesaliases = rdict
299
348
  return self._sepcialnodesaliases
300
349
 
@@ -320,7 +369,9 @@ class Target(fp.FootprintBase):
320
369
  equal to the specialnodes list.
321
370
  """
322
371
  if self._specialproxies is None:
323
- self._specialproxies = self._init_supernodes(self._re_proxies_property, 'proxiesrange', 'proxiesbase')
372
+ self._specialproxies = self._init_supernodes(
373
+ self._re_proxies_property, "proxiesrange", "proxiesbase"
374
+ )
324
375
  for nodetype, nodelist in self.specialnodes.items():
325
376
  if nodetype not in self._specialproxies:
326
377
  self._specialproxies[nodetype] = nodelist
@@ -346,39 +397,44 @@ class Target(fp.FootprintBase):
346
397
  """
347
398
  kmatch = self._re_nodes_property.match(key)
348
399
  if kmatch is not None:
349
- return fp.stdtypes.FPList(self.specialnodes.get(kmatch.group(1), []))
400
+ return fp.stdtypes.FPList(
401
+ self.specialnodes.get(kmatch.group(1), [])
402
+ )
350
403
  kmatch = self._re_proxies_property.match(key)
351
404
  if kmatch is not None:
352
- return fp.stdtypes.FPList(self.specialproxies.get(kmatch.group(1), []))
405
+ return fp.stdtypes.FPList(
406
+ self.specialproxies.get(kmatch.group(1), [])
407
+ )
353
408
  kmatch = self._re_isnode_property.match(key)
354
409
  if kmatch is not None:
355
- return ((kmatch.group(1) not in self.specialnodes) or
356
- any([self.hostname.startswith(s)
357
- for s in self.specialnodes[kmatch.group(1)]]))
410
+ return (kmatch.group(1) not in self.specialnodes) or any(
411
+ [
412
+ self.hostname.startswith(s)
413
+ for s in self.specialnodes[kmatch.group(1)]
414
+ ]
415
+ )
358
416
  raise AttributeError('The key "{:s}" does not exist.'.format(key))
359
417
 
360
418
  @property
361
419
  def ftraw_default(self):
362
420
  """The default value for the System object ftraw attribute."""
363
- return ('ftraw' in self.specialnodes and
364
- any([self.hostname.startswith(s)
365
- for s in self.specialnodes['ftraw']]))
421
+ return "ftraw" in self.specialnodes and any(
422
+ [self.hostname.startswith(s) for s in self.specialnodes["ftraw"]]
423
+ )
366
424
 
367
425
 
368
426
  class LocalTarget(Target):
369
427
  """A very generic class usable for most computers."""
370
428
 
371
429
  _footprint = dict(
372
- info = 'Nice local target',
373
- attr = dict(
374
- sysname = dict(
375
- values = ['Linux', 'Darwin', 'Local', 'Localhost']
376
- ),
377
- )
430
+ info="Nice local target",
431
+ attr=dict(
432
+ sysname=dict(values=["Linux", "Darwin", "Local", "Localhost"]),
433
+ ),
378
434
  )
379
435
 
380
436
 
381
437
  # Disable priority warnings on the target collector
382
- fcollect = fp.collectors.get(tag='target')
438
+ fcollect = fp.collectors.get(tag="target")
383
439
  fcollect.non_ambiguous_loglevel = logging.DEBUG
384
440
  del fcollect
vortex/util/__init__.py CHANGED
@@ -6,4 +6,4 @@ capabilities.
6
6
  #: No automatic export
7
7
  __all__ = []
8
8
 
9
- __tocinfoline__ = 'VORTEX generic utility classes and methods'
9
+ __tocinfoline__ = "VORTEX generic utility classes and methods"