vortex-nwp 2.0.0b1__py3-none-any.whl → 2.0.0b2__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 (139) hide show
  1. vortex/__init__.py +59 -45
  2. vortex/algo/__init__.py +3 -2
  3. vortex/algo/components.py +940 -614
  4. vortex/algo/mpitools.py +802 -497
  5. vortex/algo/serversynctools.py +34 -33
  6. vortex/config.py +19 -22
  7. vortex/data/__init__.py +9 -3
  8. vortex/data/abstractstores.py +593 -655
  9. vortex/data/containers.py +217 -162
  10. vortex/data/contents.py +65 -39
  11. vortex/data/executables.py +93 -102
  12. vortex/data/flow.py +40 -34
  13. vortex/data/geometries.py +228 -132
  14. vortex/data/handlers.py +428 -225
  15. vortex/data/outflow.py +15 -15
  16. vortex/data/providers.py +185 -163
  17. vortex/data/resources.py +48 -42
  18. vortex/data/stores.py +544 -413
  19. vortex/gloves.py +114 -87
  20. vortex/layout/__init__.py +1 -8
  21. vortex/layout/contexts.py +150 -84
  22. vortex/layout/dataflow.py +353 -202
  23. vortex/layout/monitor.py +264 -128
  24. vortex/nwp/__init__.py +5 -2
  25. vortex/nwp/algo/__init__.py +14 -5
  26. vortex/nwp/algo/assim.py +205 -151
  27. vortex/nwp/algo/clim.py +683 -517
  28. vortex/nwp/algo/coupling.py +447 -225
  29. vortex/nwp/algo/eda.py +437 -229
  30. vortex/nwp/algo/eps.py +403 -231
  31. vortex/nwp/algo/forecasts.py +420 -271
  32. vortex/nwp/algo/fpserver.py +683 -307
  33. vortex/nwp/algo/ifsnaming.py +205 -145
  34. vortex/nwp/algo/ifsroot.py +210 -122
  35. vortex/nwp/algo/monitoring.py +132 -76
  36. vortex/nwp/algo/mpitools.py +321 -191
  37. vortex/nwp/algo/odbtools.py +617 -353
  38. vortex/nwp/algo/oopsroot.py +449 -273
  39. vortex/nwp/algo/oopstests.py +90 -56
  40. vortex/nwp/algo/request.py +287 -206
  41. vortex/nwp/algo/stdpost.py +878 -522
  42. vortex/nwp/data/__init__.py +22 -4
  43. vortex/nwp/data/assim.py +125 -137
  44. vortex/nwp/data/boundaries.py +121 -68
  45. vortex/nwp/data/climfiles.py +193 -211
  46. vortex/nwp/data/configfiles.py +73 -69
  47. vortex/nwp/data/consts.py +426 -401
  48. vortex/nwp/data/ctpini.py +59 -43
  49. vortex/nwp/data/diagnostics.py +94 -66
  50. vortex/nwp/data/eda.py +50 -51
  51. vortex/nwp/data/eps.py +195 -146
  52. vortex/nwp/data/executables.py +440 -434
  53. vortex/nwp/data/fields.py +63 -48
  54. vortex/nwp/data/gridfiles.py +183 -111
  55. vortex/nwp/data/logs.py +250 -217
  56. vortex/nwp/data/modelstates.py +180 -151
  57. vortex/nwp/data/monitoring.py +72 -99
  58. vortex/nwp/data/namelists.py +254 -202
  59. vortex/nwp/data/obs.py +400 -308
  60. vortex/nwp/data/oopsexec.py +22 -20
  61. vortex/nwp/data/providers.py +90 -65
  62. vortex/nwp/data/query.py +71 -82
  63. vortex/nwp/data/stores.py +49 -36
  64. vortex/nwp/data/surfex.py +136 -137
  65. vortex/nwp/syntax/__init__.py +1 -1
  66. vortex/nwp/syntax/stdattrs.py +173 -111
  67. vortex/nwp/tools/__init__.py +2 -2
  68. vortex/nwp/tools/addons.py +22 -17
  69. vortex/nwp/tools/agt.py +24 -12
  70. vortex/nwp/tools/bdap.py +16 -5
  71. vortex/nwp/tools/bdcp.py +4 -1
  72. vortex/nwp/tools/bdm.py +3 -0
  73. vortex/nwp/tools/bdmp.py +14 -9
  74. vortex/nwp/tools/conftools.py +728 -378
  75. vortex/nwp/tools/drhook.py +12 -8
  76. vortex/nwp/tools/grib.py +65 -39
  77. vortex/nwp/tools/gribdiff.py +22 -17
  78. vortex/nwp/tools/ifstools.py +82 -42
  79. vortex/nwp/tools/igastuff.py +167 -143
  80. vortex/nwp/tools/mars.py +14 -2
  81. vortex/nwp/tools/odb.py +234 -125
  82. vortex/nwp/tools/partitioning.py +61 -37
  83. vortex/nwp/tools/satrad.py +27 -12
  84. vortex/nwp/util/async.py +83 -55
  85. vortex/nwp/util/beacon.py +10 -10
  86. vortex/nwp/util/diffpygram.py +174 -86
  87. vortex/nwp/util/ens.py +144 -63
  88. vortex/nwp/util/hooks.py +30 -19
  89. vortex/nwp/util/taskdeco.py +28 -24
  90. vortex/nwp/util/usepygram.py +278 -172
  91. vortex/nwp/util/usetnt.py +31 -17
  92. vortex/sessions.py +72 -39
  93. vortex/syntax/__init__.py +1 -1
  94. vortex/syntax/stdattrs.py +410 -171
  95. vortex/syntax/stddeco.py +31 -22
  96. vortex/toolbox.py +327 -192
  97. vortex/tools/__init__.py +11 -2
  98. vortex/tools/actions.py +125 -59
  99. vortex/tools/addons.py +111 -92
  100. vortex/tools/arm.py +42 -22
  101. vortex/tools/compression.py +72 -69
  102. vortex/tools/date.py +11 -4
  103. vortex/tools/delayedactions.py +242 -132
  104. vortex/tools/env.py +75 -47
  105. vortex/tools/folder.py +342 -171
  106. vortex/tools/grib.py +311 -149
  107. vortex/tools/lfi.py +423 -216
  108. vortex/tools/listings.py +109 -40
  109. vortex/tools/names.py +218 -156
  110. vortex/tools/net.py +632 -298
  111. vortex/tools/parallelism.py +93 -61
  112. vortex/tools/prestaging.py +55 -31
  113. vortex/tools/schedulers.py +172 -105
  114. vortex/tools/services.py +402 -333
  115. vortex/tools/storage.py +293 -358
  116. vortex/tools/surfex.py +24 -24
  117. vortex/tools/systems.py +1211 -631
  118. vortex/tools/targets.py +156 -100
  119. vortex/util/__init__.py +1 -1
  120. vortex/util/config.py +377 -327
  121. vortex/util/empty.py +2 -2
  122. vortex/util/helpers.py +56 -24
  123. vortex/util/introspection.py +18 -12
  124. vortex/util/iosponge.py +8 -4
  125. vortex/util/roles.py +4 -6
  126. vortex/util/storefunctions.py +39 -13
  127. vortex/util/structs.py +3 -3
  128. vortex/util/worker.py +29 -17
  129. vortex_nwp-2.0.0b2.dist-info/METADATA +66 -0
  130. vortex_nwp-2.0.0b2.dist-info/RECORD +142 -0
  131. {vortex_nwp-2.0.0b1.dist-info → vortex_nwp-2.0.0b2.dist-info}/WHEEL +1 -1
  132. vortex/layout/appconf.py +0 -109
  133. vortex/layout/jobs.py +0 -1276
  134. vortex/layout/nodes.py +0 -1424
  135. vortex/layout/subjobs.py +0 -464
  136. vortex_nwp-2.0.0b1.dist-info/METADATA +0 -50
  137. vortex_nwp-2.0.0b1.dist-info/RECORD +0 -146
  138. {vortex_nwp-2.0.0b1.dist-info → vortex_nwp-2.0.0b2.dist-info}/LICENSE +0 -0
  139. {vortex_nwp-2.0.0b1.dist-info → vortex_nwp-2.0.0b2.dist-info}/top_level.txt +0 -0
vortex/layout/subjobs.py DELETED
@@ -1,464 +0,0 @@
1
- """
2
- This module defines classes in charge of launching sub-jobs. This allow for a
3
- rough parallelisation at job's level.
4
- """
5
-
6
- import collections
7
- import contextlib
8
- import locale
9
- import re
10
- import sys
11
- import time
12
-
13
- from bronx.datagrip import datastore
14
- from bronx.fancies import loggers
15
- from bronx.syntax.parsing import xlist_strings
16
- from bronx.patterns import observer
17
- import footprints as fp
18
-
19
- logger = loggers.getLogger(__name__)
20
-
21
- _LOG_CAPTURE_START = '>>>> subjob stdeo start <<<<\n'
22
- _LOG_CAPTURE_END = '>>>> subjob stdeo end <<<<\n'
23
-
24
- _DSTORE_IN = '{:s}_datastore.in'
25
- _DSTORE_OUT = '{:s}_{:s}_datastore.out'
26
- _JOB_STDEO = '{:s}_{:s}.stdeo'
27
-
28
- _SUBJOB_NODES_CHATTER = 'subjob_nodes_observerboard_chatter'
29
-
30
-
31
- class NodesObserverboardRecorder(observer.Observer):
32
- """Listen on the 'Layout-Nodes' observer board and record everything."""
33
-
34
- def __init__(self, observer_tag):
35
- """
36
- :param observer_tag: The name of the observer board
37
- """
38
- self._obsboard = observer.get(tag=observer_tag)
39
- self._obsboard.register(self)
40
- self._messages = list()
41
-
42
- def stop_listening(self):
43
- """Stop listening on the observer board."""
44
- self._obsboard.unregister(self)
45
-
46
- def updobsitem(self, item, info):
47
- """Store the observer board messages"""
48
- self._messages.append({k: v for k, v in info.items()
49
- if k != 'observerboard'})
50
-
51
- @property
52
- def messages(self):
53
- """The list of collected messages"""
54
- return self._messages
55
-
56
-
57
- @contextlib.contextmanager
58
- def subjob_handling(node, observer_tag):
59
- """
60
- Insert markup strings in stdout in order to frame its "usefull" part and
61
- record the Layout-Nodes observer board.
62
- """
63
- sys.stdout.write(_LOG_CAPTURE_START)
64
- sys.stdout.flush()
65
- recorder = NodesObserverboardRecorder(observer_tag)
66
- try:
67
- yield
68
- finally:
69
- recorder.stop_listening()
70
- sys.stdout.flush()
71
- sys.stdout.write(_LOG_CAPTURE_END)
72
- sys.stdout.flush()
73
- node.ticket.datastore.insert(_SUBJOB_NODES_CHATTER,
74
- dict(tag=node.tag), recorder.messages)
75
-
76
-
77
- class SubJobLauncherError(Exception):
78
- """Raise whenever an error occurred in at least on of the subjobs."""
79
- pass
80
-
81
-
82
- class AbstractSubJobLauncher(fp.FootprintBase):
83
- """Abstract subjob launcher class."""
84
-
85
- _collector = ('subjobslauncher',)
86
- _abstract = True
87
- _footprint = dict(
88
- info = 'Abstract SubJob launcher.',
89
- attr = dict(
90
- kind = dict(
91
- ),
92
- nodes_obsboard_tag = dict(
93
- info = "The name of the Layout-Nodes observer board.",
94
- ),
95
- limit = dict(
96
- info = "The maximum number of parallel subjobs.",
97
- type = int,
98
- optional = True
99
- ),
100
- scriptpath = dict(
101
- info = "The path to the current job script.",
102
- )
103
- ),
104
- )
105
-
106
- def __init__(self, *kargs, **kwargs):
107
- super().__init__(*kargs, **kwargs)
108
- self._ticket = None
109
- self._watermark = 0
110
- self._running = dict()
111
- logger.info('"%s" subjob launcher created (limit=%s, scriptpath=%s)',
112
- self.kind, str(self.limit), self.scriptpath)
113
-
114
- @property
115
- def actual_limit(self):
116
- """The maximum number of subjobs allowed in parallel."""
117
- return self.limit
118
-
119
- def _new_ticket_hook(self, t):
120
- """Any additional actions to be performed when a next session ticket is provided."""
121
- pass
122
-
123
- def _set_ticket(self, t):
124
- self._ticket = t
125
- self.fsid = self.ticket.sh.path.join(self.ticket.sh.pwd(), 'sjob_fs')
126
- self._ticket.datastore.pickle_dump(_DSTORE_IN.format(self.fsid))
127
- self._new_ticket_hook(t)
128
-
129
- def _get_ticket(self):
130
- assert self._ticket is not None
131
- return self._ticket
132
-
133
- ticket = property(_get_ticket, _set_ticket, doc="The current Session's ticket")
134
-
135
- def __call__(self, tag, subtags):
136
- """Launch the subjob that will be in charge of processing the **tag** node."""
137
- if self.actual_limit is not None and self._watermark == self.actual_limit:
138
- logger.info("The subjobs limit is reached (%d). Waiting for some subjobs to finish.",
139
- self.actual_limit)
140
- self.wait()
141
- self._running[tag] = subtags
142
- self._watermark += 1
143
- with self.ticket.env.delta_context(VORTEX_SUBJOB_ACTIVATED='{:s}:{:s}'.format(tag, self.fsid)):
144
- logger.info("Launching subjob with VORTEX_SUBJOB_ACTIVATED='%s'",
145
- self.ticket.env.VORTEX_SUBJOB_ACTIVATED)
146
- self._actual_launch(tag)
147
-
148
- def wait(self):
149
- """Wait for at least one subjob to complete."""
150
- done, ko = self._actual_wait()
151
- for tag in done | ko:
152
- self._stdeo_dump(tag, 'succeeded' if tag in done else 'failed')
153
- self._update_context(tag)
154
- del self._running[tag]
155
- self._watermark -= 1
156
- return done, ko
157
-
158
- def waitall(self):
159
- """Wait for all subjob to complete."""
160
- logger.info("Waiting for all subjobs to terminate.")
161
- done = set()
162
- ko = set()
163
- while self._running:
164
- new_done, new_ko = self.wait()
165
- done.update(new_done)
166
- ko.update(new_ko)
167
- return done, ko
168
-
169
- def _stdeo_dump(self, tag, outcome='succeeded', ignore_end=False):
170
- """Dump the standard output of the subjob refered by **tag**.
171
-
172
- :param tag: The subjob's tag
173
- :param outcome: Some indication on how the subjob ended
174
- :param ignore_end: Print the entire standard output (usefull for debuging)
175
- """
176
- plocale = locale.getlocale()[1] or 'ascii'
177
- self.ticket.sh.title('subjob "{:s}" {:s}. Here is the output:'.format(tag, outcome))
178
- with open(_JOB_STDEO.format(self.fsid, tag), encoding=plocale) as fhst:
179
- started = False
180
- for lst in fhst:
181
- if started:
182
- if lst == _LOG_CAPTURE_END:
183
- if not ignore_end:
184
- break
185
- else:
186
- sys.stdout.write(lst)
187
- else:
188
- started = lst == _LOG_CAPTURE_START
189
- print()
190
- print('Full Log available at: {:s}_{:s}.stdeo'.format(self.fsid, tag))
191
- print()
192
-
193
- def _update_context(self, tag):
194
- """Update the context using the **tag** subjob datastore's dump."""
195
- stags = self._running[tag]
196
- ds = datastore.DataStore()
197
- ds.pickle_load(_DSTORE_OUT.format(self.fsid, tag))
198
- for k in ds.keys():
199
- if re.match('context_', k.kind):
200
- xpath = k.extras.get('path', '').split('/')
201
- for stag in stags:
202
- # Only update relevant entries
203
- if xpath[-1] == stag:
204
- logger.info('Updating "%s, path=%s" in the datastore',
205
- k.kind, '/'.join(xpath))
206
- curv = self.ticket.datastore.get(k.kind, k.extras)
207
- if hasattr(curv, 'datastore_inplace_overwrite'):
208
- curv.datastore_inplace_overwrite(ds.get(k.kind, k.extras))
209
- else:
210
- self.ticket.datastore.insert(k.kind, k.extras,
211
- ds.get(k.kind, k.extras))
212
- break
213
- if k.kind == _SUBJOB_NODES_CHATTER and k.extras['tag'] == tag:
214
- messages = ds.get(k.kind, k.extras)
215
- if messages:
216
- oboard = observer.get(tag=self.nodes_obsboard_tag)
217
- oboard.notify_new(self, dict(tag=tag, subjob_replay=True))
218
- for message in messages:
219
- message['subjob_replay'] = True
220
- oboard.notify_upd(self, message)
221
- logger.debug('Relaying status change: %s', message)
222
- oboard.notify_del(self, dict(tag=tag, subjob_replay=False))
223
-
224
- def _actual_launch(self, tag):
225
- """Launch the **tag** subjob: to be overwritten in the subclass!"""
226
- raise NotImplementedError()
227
-
228
- def _actual_wait(self):
229
- """Wait for the **tag** subjob: to be overwritten in the subclass!"""
230
- raise NotImplementedError()
231
-
232
-
233
- class SpawnSubJobLauncher(AbstractSubJobLauncher):
234
- """A very simple subjob launcher: just starts a new process."""
235
-
236
- _footprint = dict(
237
- attr = dict(
238
- kind =dict(
239
- values = ['spawn', ]
240
- )
241
- )
242
- )
243
-
244
- def __init__(self, *kargs, **kwargs):
245
- super().__init__(*kargs, **kwargs)
246
- self._outfhs = dict()
247
- self._processes = dict()
248
- self._nvcores = None
249
-
250
- @property
251
- def actual_limit(self):
252
- """The maximum number of subjobs allowed in parallel."""
253
- if self.limit is not None:
254
- return self.limit
255
- elif self.limit is None and self._nvcores is not None:
256
- return self._nvcores
257
- else:
258
- raise ValueError('No limit could be found for the number of subprocesses.')
259
-
260
- def _new_ticket_hook(self, t):
261
- """Tries to find out the number of virtual cores available."""
262
- super()._new_ticket_hook(t)
263
- if self.limit is None and t.sh.cpus_info is not None:
264
- self._nvcores = t.sh.cpus_info.nphysical_cores
265
- logger.info('"spawn" subjob launcher set to %d (i.e the number of virtual cores)',
266
- self._nvcores)
267
-
268
- def _actual_launch(self, tag):
269
- """Just launch the subjob using a subprocess... easy!"""
270
- sh = self.ticket.sh
271
- ofh = open(_JOB_STDEO.format(self.fsid, tag), mode='wb')
272
- p = sh.popen([sys.executable, self.scriptpath], stdout=ofh, stderr=ofh)
273
- self._outfhs[tag] = ofh
274
- self._processes[tag] = p
275
-
276
- def _actual_wait(self):
277
- """Wait for at least one subprocess to terminate.
278
-
279
- If none of the subjob failed, returns the list of tags of the successful
280
- subjobs. If at least one of the subjob fails, wait for every process to
281
- terminate and raise a :class:`SubJobLauncherError` exception.
282
- """
283
- sh = self.ticket.sh
284
- oktags = set()
285
- kotags = set()
286
- while self._processes and (not oktags or kotags):
287
- for tag, p in self._processes.items():
288
- if p.poll() is not None:
289
- if sh.pclose(p):
290
- oktags.add(tag)
291
- else:
292
- kotags.add(tag)
293
- for tag in oktags | kotags:
294
- if tag in self._processes:
295
- del self._processes[tag]
296
- del self._outfhs[tag]
297
- if self._processes and (not oktags or kotags):
298
- time.sleep(0.5)
299
- return oktags, kotags
300
-
301
-
302
- class AbstractSshSubJobLauncher(AbstractSubJobLauncher):
303
- """Use SSH to launch a remote subjob."""
304
-
305
- _abstract = True
306
- _footprint = dict(
307
- attr = dict(
308
- taskspn = dict(
309
- type = int,
310
- default = 1,
311
- optional = True,
312
- ),
313
- )
314
- )
315
-
316
- def __init__(self, *kargs, **kwargs):
317
- super().__init__(*kargs, **kwargs)
318
- self.nodes = list()
319
- self._avnodes = collections.deque()
320
- self._outfhs = dict()
321
- self._hosts = dict()
322
- self._processes = dict()
323
-
324
- @property
325
- def actual_limit(self):
326
- """The maximum number of subjobs allowed in parallel."""
327
- if self.limit is None:
328
- return len(self.nodes)
329
- else:
330
- return self.limit
331
-
332
- def _find_raw_nodes_list(self, t):
333
- """This method should be overwritten and return a list of target hostnames."""
334
- raise NotImplementedError()
335
-
336
- def _env_variables_iterator(self, t):
337
- """Return the environment variables that will be used."""
338
- return t.topenv.items()
339
-
340
- def _new_ticket_hook(self, t):
341
- """Common initialisations."""
342
- super()._new_ticket_hook(t)
343
- self.nodes = self._find_raw_nodes_list(t)
344
- # Several tasks may be launched on a single node
345
- self.nodes = self.nodes * self.taskspn
346
- if self.limit is not None and len(self.nodes) < self.limit:
347
- raise RuntimeError('The are not enough compute nodes (available:{:s}/requested={:d})'
348
- .format(len(self.nodes), self.limit))
349
- # Summary
350
- logger.info("%d task(s) per node will be launched. Nodes list: %s",
351
- self.taskspn, ",".join(sorted(set(self.nodes))))
352
- # Available nodes
353
- self._avnodes = collections.deque(self.nodes)
354
- # Freeze the root environment in a wrapper
355
- self._lwrapper = '{:s}.wrap.sh'.format(self.fsid)
356
- with open(self._lwrapper, 'w', encoding='utf-8') as fhwrap:
357
- fhwrap.write('#! /bin/bash\n')
358
- fhwrap.write('set -x\n')
359
- fhwrap.write('set -e\n')
360
- fhwrap.write('echo "I am running on $(hostname) !"\n')
361
- for k, v in self._env_variables_iterator(t):
362
- if re.match(r'[-_\w]+$', k): # Get rid of weird variable names
363
- fhwrap.write("export {:s}='{!s}'\n".format(k.upper(), v))
364
- fhwrap.write('exec $*\n')
365
- t.sh.xperm(self._lwrapper, force=True)
366
- # Put the script on the parallel file-system (otherwise it won't be accessible
367
- # from other nodes)
368
- self._pfs_scriptpath = '{:s}.script.py'.format(self.fsid)
369
- t.sh.cp(self.scriptpath, self._pfs_scriptpath)
370
-
371
- def _env_lastminute_update(self, tag, thost):
372
- """Add some lastminute environment variables."""
373
- return dict().items()
374
-
375
- def _actual_launch(self, tag):
376
- """Just launch the subjob using an SSH command."""
377
- sh = self.ticket.sh
378
- thost = self._avnodes.popleft()
379
- logger.info('"%s" will be used (through SSH).', thost)
380
- ofh = open(_JOB_STDEO.format(self.fsid, tag), mode='wb')
381
- cmd = "export VORTEX_SUBJOB_ACTIVATED='{:s}'; ".format(sh.env.VORTEX_SUBJOB_ACTIVATED)
382
- cmd += ' '.join(["export {:s}='{!s}'; ".format(k, v)
383
- for k, v in self._env_lastminute_update(tag, thost)])
384
- cmd += ' '.join([self._lwrapper, sys.executable, self._pfs_scriptpath])
385
- print(cmd)
386
- p = sh.ssh(thost).background_execute(cmd, sshopts='-o CheckHostIP=no',
387
- stdout=ofh, stderr=ofh)
388
- self._outfhs[tag] = ofh
389
- self._hosts[tag] = thost
390
- self._processes[tag] = p
391
-
392
- def _actual_wait(self):
393
- """Wait for at least one subprocess to terminate.
394
-
395
- If none of the subjob failed, returns the list of tags of the successful
396
- subjobs. If at least one of the subjob fails, wait for every process to
397
- terminate and raise a :class:`SubJobLauncherError` exception.
398
- """
399
- sh = self.ticket.sh
400
- oktags = set()
401
- kotags = set()
402
- while self._processes and (not oktags or kotags):
403
- for tag, p in self._processes.items():
404
- if p.poll() is not None:
405
- if sh.pclose(p):
406
- oktags.add(tag)
407
- else:
408
- kotags.add(tag)
409
- for tag in oktags | kotags:
410
- if tag in self._processes:
411
- self._avnodes.append(self._hosts.pop(tag))
412
- del self._processes[tag]
413
- del self._outfhs[tag]
414
- if self._processes and (not oktags or kotags):
415
- time.sleep(0.5)
416
- return oktags, kotags
417
-
418
-
419
- class SlurmSshSubJobLauncher(AbstractSshSubJobLauncher):
420
- """
421
- Find the list of availlable compute nodes thanks to SLURM and use SSH to
422
- launch subjobs.
423
- """
424
-
425
- _footprint = dict(
426
- attr = dict(
427
- kind = dict(
428
- values = ['slurm:ssh', ]
429
- ),
430
- )
431
- )
432
-
433
- def _env_variables_iterator(self, t):
434
- """Return the environment variables that will be used."""
435
- blacklist = {"SLURM_{:s}".format(s)
436
- for s in ('NNODES', 'JOB_NNODES', 'JOB_NUM_NODES',
437
- 'NODELIST', 'JOB_NODELIST')}
438
- slurmnodes_ids = re.compile(r'(\(x\d+\))$')
439
- for k, v in t.topenv.items():
440
- if k not in blacklist:
441
- if k.startswith('SLURM') and slurmnodes_ids.search(v):
442
- yield k, slurmnodes_ids.sub('(x1)', v)
443
- else:
444
- yield k, v
445
- for k in ('SLURM_NNODES', 'SLURM_JOB_NNODES', 'SLURM_JOB_NUM_NODES'):
446
- yield k, "1"
447
-
448
- def _env_lastminute_update(self, tag, thost): # @UnusedVariable
449
- """Add some lastminute environment variables."""
450
- return dict(SLURM_NODELIST=thost,
451
- SLURM_JOB_NODELIST=thost).items()
452
-
453
- def _find_raw_nodes_list(self, t):
454
- """Find out what is the nodes list.
455
-
456
- To do so, the SLURM_JOB_NODELIST environment variable is processed.
457
- """
458
- # Process SLURM's nodes list
459
- nlist = t.env.get('SLURM_JOB_NODELIST',
460
- t.env.get('SLURM_NODELIST', None))
461
- if nlist:
462
- return xlist_strings(nlist)
463
- else:
464
- raise RuntimeError('The "SLURM_JOB_NODELIST" environment variable is not defined.')
@@ -1,50 +0,0 @@
1
- Metadata-Version: 2.2
2
- Name: vortex-nwp
3
- Version: 2.0.0b1
4
- Summary: A Python library to write Numerical Weather Prediction pipelines components
5
- Author-email: The Vortex Team <vortex.support@meteo.fr>
6
- License: CECILL-C
7
- Classifier: Development Status :: 4 - Beta
8
- Classifier: License :: CeCILL-C Free Software License Agreement (CECILL-C)
9
- Requires-Python: >=3.7
10
- Description-Content-Type: text/markdown
11
- License-File: LICENSE
12
- Requires-Dist: bronx
13
- Requires-Dist: footprints
14
- Requires-Dist: taylorism
15
- Requires-Dist: tomli
16
- Requires-Dist: arpifs_listings
17
- Provides-Extra: dev
18
- Requires-Dist: sphinx; extra == "dev"
19
- Requires-Dist: sphinx-book-theme; extra == "dev"
20
- Requires-Dist: sphinx-copybutton; extra == "dev"
21
-
22
- ## VORTEX
23
-
24
- Versatile Objects Rounded-Up in a Toolbox for Environmental eXperiments
25
-
26
- ### Documentation
27
-
28
- Documentation is available at
29
-
30
- http://cnrm-gmap.gitlab.meteo.fr/vortex-nwp/
31
-
32
- currently only reachable from Météo-France's internal network.
33
-
34
- ### Installation
35
-
36
- Vortex can be installed using `pip`. Not taht it is not yet available
37
- on pypi.org, but can be installed by specifying the path to the GitLab
38
- repository:
39
-
40
- ```bash
41
- pip install git+http://gitlab.meteo.fr/cnrm-gmap/vortex-nwp.git
42
- ```
43
-
44
- ### Contributing
45
-
46
- See [CONTRIBUTING.md](CONTRIBUTING.md).
47
-
48
-
49
-
50
-
@@ -1,146 +0,0 @@
1
- vortex/__init__.py,sha256=Uu956WgN7e225V0zub71tadib6MgF6IM7MbcW_T9Oik,3807
2
- vortex/config.py,sha256=a_ZpjE27PcWBVwCM-eiSKwQyzkgcGaUqnqkcxiR2soo,2830
3
- vortex/gloves.py,sha256=NWRKYfacmPKcMjABdVCBejQwIY4dFoKIWveE3iae7OE,8263
4
- vortex/proxy.py,sha256=OlPrVUJS5FoKt5pX8ApN1crFFDj8RJAqhDEilwvfrYU,127
5
- vortex/sessions.py,sha256=x0WTFJO0NqUdy_Sj4HsgmEmacL6wfmaXCP-BssbwGU0,9549
6
- vortex/toolbox.py,sha256=mAhcksIwauUbZtDOYyzaszLrEBGyQok9YdI-I3cVmW0,38479
7
- vortex/algo/__init__.py,sha256=Kb6ExLWP_9htwPKYIMEX6duPnQe6JauN4LEYJs3m9As,313
8
- vortex/algo/components.py,sha256=dmLwvEwCGpMQjdIyPScvn_JaBTQRqxyE06_cvdHWy64,86775
9
- vortex/algo/mpitools.py,sha256=20nGMn8jXx84lkWB4hIY_voCOv-WLzRttutOuAsghws,69520
10
- vortex/algo/serversynctools.py,sha256=kB2igwHGEmDe6AZ2v4xVY6XjX57d-SmoZF1okddzVDo,5554
11
- vortex/algo/mpitools_templates/envelope_wrapper_default.tpl,sha256=4VhkDx_YbOYywKQ82HIxRJXGcDpLuOgqcY7Edx9Rxyw,453
12
- vortex/algo/mpitools_templates/envelope_wrapper_mpiauto.tpl,sha256=iB4_4jz-7QDqpl6AxrlCACsotJnEMG75dtazuGfkCb4,514
13
- vortex/algo/mpitools_templates/wrapstd_wrapper_default.tpl,sha256=hh1Um95FIuvXAhUTMifAfixtfGgyjF1vEaF1nmbqMLw,502
14
- vortex/data/__init__.py,sha256=0YSZQv6f3N9stevG74ESg6GMagDL0_8B_zqTQIZh7sY,372
15
- vortex/data/abstractstores.py,sha256=Re4nWZbH60WxNrz-unhwhVBDHw2ild6Uian1e24gbiw,64973
16
- vortex/data/containers.py,sha256=9MSABgd9B777ilYH91mewLUfclCI81mco8JOdfeBer4,25721
17
- vortex/data/contents.py,sha256=aUFo5gI_eDwfPNOXRAIZesJdGt0HCKOr8DDW0O51LiU,18722
18
- vortex/data/executables.py,sha256=PN60aCm2VvCldx8JMOc83F5J0JbK4iirflk0ajLE_DM,7125
19
- vortex/data/flow.py,sha256=mHcrpf0KVKeUPy8KfCDNsggcg8KUU0oRz2IEGXRuO68,3053
20
- vortex/data/geometries.ini,sha256=J7hX5hYWqwBjdUAul6q8j10U6b3I-QEHrFJ98LBTQXM,52805
21
- vortex/data/geometries.py,sha256=gfmvtC44sgwqjVFZzj7LV1itSTNskJQ2eavNVcFO-wk,26817
22
- vortex/data/handlers.py,sha256=MOvQbzWqlNqF0M2uUS6BVh_FevfyrhWNq9he4GZ6Hro,43469
23
- vortex/data/outflow.py,sha256=mNTgT5bl4-ctfb5BDpYE89tixVN6v3llJtgasRtzW0Y,1490
24
- vortex/data/providers.py,sha256=wpPa1_0kHQL4Zn5lM9EwJsTgv3yS7FtVGcKVjS4766U,15844
25
- vortex/data/resources.py,sha256=MtzmGqzDltPTPiZx-03Vzgzj5sgLOSNhyNExiAqqzP0,6407
26
- vortex/data/stores.py,sha256=cS3V5eQBBINotEUfxCEUGOnlYq232w1M4fcEJbUYRYc,44098
27
- vortex/layout/__init__.py,sha256=fbWOrUvCCdHdYcvcAweE55tGDi7Jc9dD3Wk1iZRVKg8,1129
28
- vortex/layout/appconf.py,sha256=-Y5yJTlDDhegDE0u5r-Q1I2jeG-wRcQyJK766ZsJJF8,3856
29
- vortex/layout/contexts.py,sha256=CiSxNxkZBC0aFfqFoh2qDzWrQ5KzUDq9G-wQvOKAx-E,19977
30
- vortex/layout/dataflow.py,sha256=g7ze55DwnWa7gMT1-bVa477vq9tHDORACCx4EMkoLYA,42871
31
- vortex/layout/jobs.py,sha256=Oj51CJUdEJ8h25KF88hv_trRRgWOtO4GJhaYreg9TfI,47982
32
- vortex/layout/monitor.py,sha256=t0rtc9zfxwB0JTEZwOJiGvM2XZP1hA2UU0lyfyT09fY,32736
33
- vortex/layout/nodes.py,sha256=AT32a6YOA4accFtxNvzZ8TeiG3_SBQpZEBJSP5eiIqg,59319
34
- vortex/layout/subjobs.py,sha256=yTqSLnON20Md-Ljhhwm9ybF3N7XCzOs5bay-SFULAh0,17475
35
- vortex/nwp/__init__.py,sha256=481VGHxujr_ke-nIBcVlsuWlXxXf-xg-W3GcC5K0FFM,237
36
- vortex/nwp/algo/__init__.py,sha256=ZwHvgKZJlJ4hldXng2sqSaGNvWgr4sxxVhUsWEjP_o0,298
37
- vortex/nwp/algo/assim.py,sha256=73t2S3eDq1xbrxLFYsNrW1U13o2qlMRm5vwOKzoG_rQ,15424
38
- vortex/nwp/algo/clim.py,sha256=pgcJwCg0vH35MPC0JGtMk_iF25zwGo-rOmJzxGm87B4,37643
39
- vortex/nwp/algo/coupling.py,sha256=xNhy0ORu50RDqik7iPiULRyj_oDTJKQURQpw2Odsxow,26311
40
- vortex/nwp/algo/eda.py,sha256=FrS2PPPYfXyD-zfTaZl__c72uA5H0uqbuVLCwqgeDLQ,27886
41
- vortex/nwp/algo/eps.py,sha256=Im6p6-F0FCFNwm2gvVGNsv8ZkZ-uqMLCq4vGxArgdoY,24581
42
- vortex/nwp/algo/forecasts.py,sha256=DP5foN7KbSJ711Ne6oagAJoSh-a9mzPzwKx3F2ht9mo,28556
43
- vortex/nwp/algo/fpserver.py,sha256=yImWjPbZJ12VtSeWKsWn0g7jM4j8Bjijo_sd9eJF4rM,44232
44
- vortex/nwp/algo/ifsnaming.py,sha256=TOfVy8OsRYq3z6aGpki1jtCGNPuAqy5mEzqn1kVaYZg,10340
45
- vortex/nwp/algo/ifsroot.py,sha256=LeJNC26EJAIZOVIg24P2I1ghpZmyzS8qmzm-XJ3gogc,13372
46
- vortex/nwp/algo/monitoring.py,sha256=MhKY16wqOAJrJbDpwjBIAAPevk6IFa3W5KAT9tlUrzk,7903
47
- vortex/nwp/algo/mpitools.py,sha256=odCjrLWsPPv-cbmR4ES5cKN9FI4B3N-ppbPBjz1gZDA,22871
48
- vortex/nwp/algo/odbtools.py,sha256=EZ35LVM09JNgnb0vrYgZyjT81KeSBAf9921sxu-3gA8,39970
49
- vortex/nwp/algo/oopsroot.py,sha256=w0bnAcFSmShAlSaCgjBO7TBtI2f8wFCO1MIHIItiA0k,31536
50
- vortex/nwp/algo/oopstests.py,sha256=ipvzm0vUWfVqjb6mMn5DCjwYSIFlsidz5qVRdcnS7gg,6487
51
- vortex/nwp/algo/request.py,sha256=buVhGbaAtNOyq7Vza5UMi7_yhCXvMGaUeeoG2jE2nEs,21738
52
- vortex/nwp/algo/stdpost.py,sha256=pn38o-6YY41Mnktswvb8j8WQnKam01XdVNpp-Xm0e8o,51306
53
- vortex/nwp/data/__init__.py,sha256=tyrEiPYpQ39LLcEIEVYCgchixjkcsqGV3WaZiWFvLt4,403
54
- vortex/nwp/data/assim.py,sha256=RxwsRw1-sIhD0jZVTMWizNJ9TzlL0oOMfIrfyyLJXV8,10587
55
- vortex/nwp/data/boundaries.py,sha256=oCODeosY5cxZysEDcEk9gL3EQfz2lr6XdEnNkSeDG3k,7540
56
- vortex/nwp/data/climfiles.py,sha256=YsuTivWvfv2hDWQZx5uYRv8ll9ReE2Bq3XuaM3T2Nw0,13478
57
- vortex/nwp/data/configfiles.py,sha256=C-qwPw8W0ziGvQzMuBb3itcMZ3Wh1tFg6uJQrJ53YnY,3891
58
- vortex/nwp/data/consts.py,sha256=OTKrxPv85HjrRF8eRoAiLwQGbs3fT2Mn5fQTZXUlWYs,22596
59
- vortex/nwp/data/ctpini.py,sha256=ZmO0FfNfLq_P83lK2VTxKHfXe5e06lS5Q6D1oSEC6wo,3281
60
- vortex/nwp/data/diagnostics.py,sha256=fFL1ipv4i_OrqbvrACGeliRm02XQC_P9PIXVi5MEi4c,4819
61
- vortex/nwp/data/eda.py,sha256=2i9ISHApPLHABTJ4pINnSCtN2P3mN8B127Ua-FTQjLw,4268
62
- vortex/nwp/data/eps.py,sha256=v9VT4YBGy1HOuN49yObQsrDBuqV3ytJwJ2HBhbTMbfg,11475
63
- vortex/nwp/data/executables.py,sha256=esQoEKtbg3R4JW8TYqx5E5oTnXNUFHkt5HwvcQShAQ4,25764
64
- vortex/nwp/data/fields.py,sha256=S-zdlc0YLg7dY1aYlPO9UFSrzzJz0NFlvQNm1V6_EDk,2796
65
- vortex/nwp/data/gridfiles.py,sha256=sLV9VdvLisdZsChbw75Gtv_GA2TXQWNY3ZlZwdjkSGQ,10008
66
- vortex/nwp/data/logs.py,sha256=y9KfVu6wNk_5b98elTwERBRDQyHsMcL0R9cJCy_bb0E,17930
67
- vortex/nwp/data/modelstates.py,sha256=sTCJ8ACYQVq4qdxJ4kAKmEWf9AStU6VFed-9j54fHKo,10217
68
- vortex/nwp/data/monitoring.py,sha256=-5zeDS7TYaTaP_XHeFqg3yli93XzNCX2ZAyKvAB730E,5227
69
- vortex/nwp/data/namelists.py,sha256=frcRnhvBGs4En4rd42EDvdZONoh1Yqvph3Teec6yKN0,20649
70
- vortex/nwp/data/obs.py,sha256=rYDclj_2hXmAZ4y20YkV7YT5xvSuXgSUp_nB58-wnLg,24588
71
- vortex/nwp/data/oopsexec.py,sha256=ebEvRzA9buMylajvUUVmA6k6SAQKe3_bU2SWkRzhVSM,1977
72
- vortex/nwp/data/providers.py,sha256=1vEBqQ6iALg4NgrBmNaS4W6KBq2VPVwAzpRzs8PaNDI,7043
73
- vortex/nwp/data/query.py,sha256=U1jkWzSJA5gQvJJBvAULkQivFXaaMXDVc6GqsV2MgYw,5764
74
- vortex/nwp/data/stores.py,sha256=cDTUCW0kBsBeCa1PvVcwmvK44A7sIjea51lEpNwtdvY,5185
75
- vortex/nwp/data/surfex.py,sha256=8WZWXycV1n-lcFjBVvWzfefB26jaiudzEBSLQjZvaCU,8072
76
- vortex/nwp/syntax/__init__.py,sha256=Sj2dtsmFxX_Z4PosLq_nNfJRKlyQYinPOt-m5VaUJF0,281
77
- vortex/nwp/syntax/stdattrs.py,sha256=6_gGZynGvphboJEVcKDWgveBBzPAr4WivcYfEnyXWTo,12886
78
- vortex/nwp/tools/__init__.py,sha256=bd5vtyq74iH1udwv4ed1lJkF1EEVWRIBm9Uu8cFtWYo,205
79
- vortex/nwp/tools/addons.py,sha256=7yeAvDDtMgwY5ufx_T7C9d68wHX4xQV5mmmJ-5B1cgI,937
80
- vortex/nwp/tools/agt.py,sha256=GhKYEj1dJBuE7IV9qAU1IBfjL0YZ8sRb9d97At4aMGY,2279
81
- vortex/nwp/tools/bdap.py,sha256=Bb_c3Ntc8BgZcPGuSYkc3HxUlIHiRjUfhMMEBUotfsQ,1630
82
- vortex/nwp/tools/bdcp.py,sha256=FA9-pOKlGJcuIJ5bIMFLc5-bkgX8c6yU_3Azi7zwH14,983
83
- vortex/nwp/tools/bdm.py,sha256=ChFaLNWiZ3oYQMyFvgnQo4CEWWV8d0Ut3v3kcSAQdog,357
84
- vortex/nwp/tools/bdmp.py,sha256=xidg7JVxxW-o2jur2fVLdlKmIpNMGS2ZRw2MVo6o2mI,1489
85
- vortex/nwp/tools/conftools.py,sha256=IV7qxEfITosfNm9qvMqWrxUajljxl6RhyXE7RYLEfG4,56464
86
- vortex/nwp/tools/drhook.py,sha256=WsHQO7l_tGroHuO15d1zKG6Is_SgotCzxoi2B2-k5fo,1952
87
- vortex/nwp/tools/grib.py,sha256=jvr2J4CsjFdh7A2FIw_hIFq4A0Fowk07TEwv0U9UcYY,9851
88
- vortex/nwp/tools/gribdiff.py,sha256=Q5-As8WvDBssP3kMvHIyRAm2EoUi829RJ_OOzLhdM6A,3128
89
- vortex/nwp/tools/ifstools.py,sha256=Vk0LOKBsQUZdyt6xfpR7eCBdpC3IoNYdTKwh-xh05S8,6419
90
- vortex/nwp/tools/igastuff.py,sha256=Kqm7pMhKCg6bFr8knxvhcuOfgmpdtbSs5msXMsPgUKc,9331
91
- vortex/nwp/tools/mars.py,sha256=-slz1iQgLKqwK2rxHIg0BrKpQ7ykththeniy4VOeBWg,1730
92
- vortex/nwp/tools/odb.py,sha256=pnS4OYKM_sw4wXc8FbXnN6Gbn_7Zs57MF0r8VL9kDKg,21970
93
- vortex/nwp/tools/partitioning.py,sha256=hLM3H47avVH5_R9eTpO20i39oaEiV4xkSj7MGAoEKuo,9138
94
- vortex/nwp/tools/satrad.py,sha256=Fyc7N0Bfv6yLYm-srvlihGBq3zeFNy-DOjmmW0herQA,2199
95
- vortex/nwp/util/__init__.py,sha256=Weqz6S6ZTwjtveSMD1poZYDAKvnsZFjq172VrAq221Q,71
96
- vortex/nwp/util/async.py,sha256=cQJLtMk3a_quXXlpZ33vOKBezZA3-GAhrAdOtgUKz9U,6633
97
- vortex/nwp/util/beacon.py,sha256=Y3Iv4OuW1k8QDd_H52lm7PkIXOgfOSy5KQVpHLaNQ3w,1181
98
- vortex/nwp/util/diffpygram.py,sha256=y3U5AQvSRIv888J7uQ8IznhoumXzatQ9jyV0f0c5Sqg,13500
99
- vortex/nwp/util/ens.py,sha256=QTBKAImd1oNVtYI0CjxwPuFfRMA-wTdgnXfvkOISotc,8590
100
- vortex/nwp/util/hooks.py,sha256=Fd_qJLnW5OpsAnrnqZOjyS81F3NE5uz3SkgZ_lYiwrk,4573
101
- vortex/nwp/util/taskdeco.py,sha256=xbVBhSNLiNrspEvDM7bRZ2c4yJKqWzSITHAG6dlKQeQ,2446
102
- vortex/nwp/util/usepygram.py,sha256=aI99WVCcqxRZE0d6XMZxQV9cvxxN6z9VIKoDGY1opXg,23771
103
- vortex/nwp/util/usetnt.py,sha256=7sIRQtnI4iBJYMgZtDt_e0y6cVpJOyjVt4pdghRXIZE,3294
104
- vortex/syntax/__init__.py,sha256=ZtP-2pVIWyxvDQUg1ESCwqS77InAa1v3rqRZBXNk8ZY,288
105
- vortex/syntax/stdattrs.py,sha256=VyE9Y058CC2YQH8A5ZOqC0cVpd_8apMfGDFmPM3TLZ0,20538
106
- vortex/syntax/stddeco.py,sha256=Pt4eQPKG3Ryv1W785tzl5dFoeLdqHXMpnjkeRwSzo6s,6270
107
- vortex/tools/__init__.py,sha256=WvFMltMO9ZhOvzyBMwmVCytEHCsCjmwJ8_3FE8Ru_1A,300
108
- vortex/tools/actions.py,sha256=1QxFQvBmfyvbqqUVdNFgVIIiRySwTOKa666c0ZdAIJY,15430
109
- vortex/tools/addons.py,sha256=TRObpUB__V7SP_RtN4KsvMcNt5n9yOE8xfnhNUn8-Xc,10367
110
- vortex/tools/arm.py,sha256=UA0MUhjC79Msp_EEBHhIdGnh5zNPx0rIQRRrqNLI8BY,2947
111
- vortex/tools/compression.py,sha256=Bhr_nim1FEUe5KOCjtc1IFIST_kBpBqeJertu0rGnr0,11296
112
- vortex/tools/date.py,sha256=ca_jHH0H2siWp8R71pbjFzNYJP6OnjGOVhOiZOIvEZ0,639
113
- vortex/tools/ddhpack.py,sha256=tOcQ5XQ7yTFBlisyjANDPMPQPijvHwz8yWY1eBfZMAs,206
114
- vortex/tools/delayedactions.py,sha256=o0VdMloWUdeEshJVJB-WT9J37eJvh4RuGEO0_RpElVM,26002
115
- vortex/tools/env.py,sha256=DoztoomXAUNH0Wpyvbqn7UJ9GUBNc6qQ-QK_3M4JIc8,18145
116
- vortex/tools/folder.py,sha256=7O7nIDa_NQF2i2pV12phd_Izhz2KTU6sET0UuIwBt0k,26568
117
- vortex/tools/grib.py,sha256=0TL3H3fEyOGZQRsb85slV9oukLYRPeaAUY_moWbgUQc,23862
118
- vortex/tools/lfi.py,sha256=b_muz1_K5_k40uZXP5QfuR1mo4RhQwVLeSPVH2O1BWc,27430
119
- vortex/tools/listings.py,sha256=0bAPI2k8sW0F0lRa82y5QM0tvpj-QmNDwTOKsjluRss,13629
120
- vortex/tools/names.py,sha256=mUj2R7HpAD4TRUGPrYio4zavMc_gmsepOfOEiUDKWM4,20885
121
- vortex/tools/net.py,sha256=eezxGn1F9Y6jBWltVviyE4qIYSezdASAPndaL09i6tw,70279
122
- vortex/tools/odb.py,sha256=TZ1Qq8QmFIh3OP-bsgnwPuHPdfMKNXUAfhc-KSx9tZQ,193
123
- vortex/tools/parallelism.py,sha256=b6IeSpxFmek8d9sOEWRUGZKk6KK0JlsOPxWNZniGixI,12089
124
- vortex/tools/prestaging.py,sha256=SLzHojUWZ3EyekcF2UfLSBeHIu66FLDUy2kUd85fuRw,6755
125
- vortex/tools/rawfiles.py,sha256=keUI6QtEZQrWQ7H_Sg_TY9SY32anfb-suqJkrDmdXN0,215
126
- vortex/tools/schedulers.py,sha256=tJK13wNsSiEldWdUlYYaTBkKijhXm0zNKJKKiDCJ4mU,14763
127
- vortex/tools/services.py,sha256=hihaI4jM_L6eYYrHup40yrFthnALOXdT127945SVEaE,28915
128
- vortex/tools/storage.py,sha256=9WO86T8Zjr0mvPvOGtk5nlDOntj2cMjdjUnCVwiRyjQ,38087
129
- vortex/tools/surfex.py,sha256=cxpWfrYYlaek2gmKFnrC0qaScIY6ow1oou2MQB7aGQc,1506
130
- vortex/tools/systems.py,sha256=PPhuK5a6KX-A7xtG78JWJ-VEMPPL8Veoki8YwjPzgno,140905
131
- vortex/tools/targets.py,sha256=c6eGEDmPr4gi8ssmd6yRpC1wbXL-uZQe4WAClQzany8,14278
132
- vortex/util/__init__.py,sha256=bJcMkIOoGmieREiiIe7y60rYGNqKAqFBCb3aHUl0bJk,198
133
- vortex/util/config.py,sha256=F0dqculVttX7LcvEoISbE159tmIs3KsoQ5cl2vi7lxs,43284
134
- vortex/util/empty.py,sha256=ic9ZkJRJA5ArGMyyinWd3AqiSkEXNFil1IlnZGCg_no,535
135
- vortex/util/helpers.py,sha256=lzuoYHKYSb-uGeUt2Rlzwe-xSn8pAJGhuj8Y02LzcjI,7310
136
- vortex/util/introspection.py,sha256=ai3rATbuC8xHINfYBNbrvWzfEq0zax4eWYvc3QHD6jU,2061
137
- vortex/util/iosponge.py,sha256=4XGirHQuWhMCOhq9Kr09h6HcYNJ-pDuf4N1LUc-odOs,2539
138
- vortex/util/roles.py,sha256=NatnoeaxycpRw8lnPJZcMle7HEk2oPpYDAZlz9WLu10,1156
139
- vortex/util/storefunctions.py,sha256=vgvXzL4FBpkcwYouhWZx4OXI-G3PRWA9gZubbfbFMLc,3332
140
- vortex/util/structs.py,sha256=O6FpUOsByO4eUgZVuQ9nPaaRNcC1X_exEthynqaaW-c,683
141
- vortex/util/worker.py,sha256=t4UNvl_ZIJIcN8ZtkWtNMkSsV-id1JY_1OxfepgLnuY,4624
142
- vortex_nwp-2.0.0b1.dist-info/LICENSE,sha256=ewBJPmWAcQqtBPrydH10tt6ECkcYP3b1o2RfH85pJF0,21863
143
- vortex_nwp-2.0.0b1.dist-info/METADATA,sha256=EnHZjY2UUfkkt37RdQ91KWG8zSRXRdlXEN3xHzr0nqQ,1257
144
- vortex_nwp-2.0.0b1.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
145
- vortex_nwp-2.0.0b1.dist-info/top_level.txt,sha256=3xfbSD7kw8xKl0jk4GNHsOPKbhubstfWHPl6bxHciRQ,7
146
- vortex_nwp-2.0.0b1.dist-info/RECORD,,