vortex-nwp 2.0.0b1__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.
- vortex/__init__.py +135 -0
- vortex/algo/__init__.py +12 -0
- vortex/algo/components.py +2136 -0
- vortex/algo/mpitools.py +1648 -0
- vortex/algo/mpitools_templates/envelope_wrapper_default.tpl +27 -0
- vortex/algo/mpitools_templates/envelope_wrapper_mpiauto.tpl +29 -0
- vortex/algo/mpitools_templates/wrapstd_wrapper_default.tpl +18 -0
- vortex/algo/serversynctools.py +170 -0
- vortex/config.py +115 -0
- vortex/data/__init__.py +13 -0
- vortex/data/abstractstores.py +1572 -0
- vortex/data/containers.py +780 -0
- vortex/data/contents.py +596 -0
- vortex/data/executables.py +284 -0
- vortex/data/flow.py +113 -0
- vortex/data/geometries.ini +2689 -0
- vortex/data/geometries.py +703 -0
- vortex/data/handlers.py +1021 -0
- vortex/data/outflow.py +67 -0
- vortex/data/providers.py +465 -0
- vortex/data/resources.py +201 -0
- vortex/data/stores.py +1271 -0
- vortex/gloves.py +282 -0
- vortex/layout/__init__.py +27 -0
- vortex/layout/appconf.py +109 -0
- vortex/layout/contexts.py +511 -0
- vortex/layout/dataflow.py +1069 -0
- vortex/layout/jobs.py +1276 -0
- vortex/layout/monitor.py +833 -0
- vortex/layout/nodes.py +1424 -0
- vortex/layout/subjobs.py +464 -0
- vortex/nwp/__init__.py +11 -0
- vortex/nwp/algo/__init__.py +12 -0
- vortex/nwp/algo/assim.py +483 -0
- vortex/nwp/algo/clim.py +920 -0
- vortex/nwp/algo/coupling.py +609 -0
- vortex/nwp/algo/eda.py +632 -0
- vortex/nwp/algo/eps.py +613 -0
- vortex/nwp/algo/forecasts.py +745 -0
- vortex/nwp/algo/fpserver.py +927 -0
- vortex/nwp/algo/ifsnaming.py +403 -0
- vortex/nwp/algo/ifsroot.py +311 -0
- vortex/nwp/algo/monitoring.py +202 -0
- vortex/nwp/algo/mpitools.py +554 -0
- vortex/nwp/algo/odbtools.py +974 -0
- vortex/nwp/algo/oopsroot.py +735 -0
- vortex/nwp/algo/oopstests.py +186 -0
- vortex/nwp/algo/request.py +579 -0
- vortex/nwp/algo/stdpost.py +1285 -0
- vortex/nwp/data/__init__.py +12 -0
- vortex/nwp/data/assim.py +392 -0
- vortex/nwp/data/boundaries.py +261 -0
- vortex/nwp/data/climfiles.py +539 -0
- vortex/nwp/data/configfiles.py +149 -0
- vortex/nwp/data/consts.py +929 -0
- vortex/nwp/data/ctpini.py +133 -0
- vortex/nwp/data/diagnostics.py +181 -0
- vortex/nwp/data/eda.py +148 -0
- vortex/nwp/data/eps.py +383 -0
- vortex/nwp/data/executables.py +1039 -0
- vortex/nwp/data/fields.py +96 -0
- vortex/nwp/data/gridfiles.py +308 -0
- vortex/nwp/data/logs.py +551 -0
- vortex/nwp/data/modelstates.py +334 -0
- vortex/nwp/data/monitoring.py +220 -0
- vortex/nwp/data/namelists.py +644 -0
- vortex/nwp/data/obs.py +748 -0
- vortex/nwp/data/oopsexec.py +72 -0
- vortex/nwp/data/providers.py +182 -0
- vortex/nwp/data/query.py +217 -0
- vortex/nwp/data/stores.py +147 -0
- vortex/nwp/data/surfex.py +338 -0
- vortex/nwp/syntax/__init__.py +9 -0
- vortex/nwp/syntax/stdattrs.py +375 -0
- vortex/nwp/tools/__init__.py +10 -0
- vortex/nwp/tools/addons.py +35 -0
- vortex/nwp/tools/agt.py +55 -0
- vortex/nwp/tools/bdap.py +48 -0
- vortex/nwp/tools/bdcp.py +38 -0
- vortex/nwp/tools/bdm.py +21 -0
- vortex/nwp/tools/bdmp.py +49 -0
- vortex/nwp/tools/conftools.py +1311 -0
- vortex/nwp/tools/drhook.py +62 -0
- vortex/nwp/tools/grib.py +268 -0
- vortex/nwp/tools/gribdiff.py +99 -0
- vortex/nwp/tools/ifstools.py +163 -0
- vortex/nwp/tools/igastuff.py +249 -0
- vortex/nwp/tools/mars.py +56 -0
- vortex/nwp/tools/odb.py +548 -0
- vortex/nwp/tools/partitioning.py +234 -0
- vortex/nwp/tools/satrad.py +56 -0
- vortex/nwp/util/__init__.py +6 -0
- vortex/nwp/util/async.py +184 -0
- vortex/nwp/util/beacon.py +40 -0
- vortex/nwp/util/diffpygram.py +359 -0
- vortex/nwp/util/ens.py +198 -0
- vortex/nwp/util/hooks.py +128 -0
- vortex/nwp/util/taskdeco.py +81 -0
- vortex/nwp/util/usepygram.py +591 -0
- vortex/nwp/util/usetnt.py +87 -0
- vortex/proxy.py +6 -0
- vortex/sessions.py +341 -0
- vortex/syntax/__init__.py +9 -0
- vortex/syntax/stdattrs.py +628 -0
- vortex/syntax/stddeco.py +176 -0
- vortex/toolbox.py +982 -0
- vortex/tools/__init__.py +11 -0
- vortex/tools/actions.py +457 -0
- vortex/tools/addons.py +297 -0
- vortex/tools/arm.py +76 -0
- vortex/tools/compression.py +322 -0
- vortex/tools/date.py +20 -0
- vortex/tools/ddhpack.py +10 -0
- vortex/tools/delayedactions.py +672 -0
- vortex/tools/env.py +513 -0
- vortex/tools/folder.py +663 -0
- vortex/tools/grib.py +559 -0
- vortex/tools/lfi.py +746 -0
- vortex/tools/listings.py +354 -0
- vortex/tools/names.py +575 -0
- vortex/tools/net.py +1790 -0
- vortex/tools/odb.py +10 -0
- vortex/tools/parallelism.py +336 -0
- vortex/tools/prestaging.py +186 -0
- vortex/tools/rawfiles.py +10 -0
- vortex/tools/schedulers.py +413 -0
- vortex/tools/services.py +871 -0
- vortex/tools/storage.py +1061 -0
- vortex/tools/surfex.py +61 -0
- vortex/tools/systems.py +3396 -0
- vortex/tools/targets.py +384 -0
- vortex/util/__init__.py +9 -0
- vortex/util/config.py +1071 -0
- vortex/util/empty.py +24 -0
- vortex/util/helpers.py +184 -0
- vortex/util/introspection.py +63 -0
- vortex/util/iosponge.py +76 -0
- vortex/util/roles.py +51 -0
- vortex/util/storefunctions.py +103 -0
- vortex/util/structs.py +26 -0
- vortex/util/worker.py +150 -0
- vortex_nwp-2.0.0b1.dist-info/LICENSE +517 -0
- vortex_nwp-2.0.0b1.dist-info/METADATA +50 -0
- vortex_nwp-2.0.0b1.dist-info/RECORD +146 -0
- vortex_nwp-2.0.0b1.dist-info/WHEEL +5 -0
- vortex_nwp-2.0.0b1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
"""
|
|
2
|
+
TODO: Module documentation.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import re
|
|
6
|
+
|
|
7
|
+
#: No automatic export
|
|
8
|
+
__all__ = []
|
|
9
|
+
|
|
10
|
+
#: Specific tricks for base naming in iga fuzzy namespace.
|
|
11
|
+
fuzzystr = dict(
|
|
12
|
+
histfix=dict(
|
|
13
|
+
historic=dict(
|
|
14
|
+
pearp='prev', arome='AROM', arpege='arpe', arp_court='arpe',
|
|
15
|
+
aearp='arpe', aladin='ALAD', surfex='SURF'
|
|
16
|
+
)
|
|
17
|
+
),
|
|
18
|
+
prefix=dict(
|
|
19
|
+
# LFM 2016/12/30: It was dble='PA' but apparently it's wrong. No idea why...
|
|
20
|
+
gridpoint=dict(oper='PE', dble='PE', mirr='PE', hycom_grb='vent'),
|
|
21
|
+
historic=dict(hycom='s_init0_', mfwam='BLS_', mfwam_BLS='BLS_', mfwam_LAW='LAW_'),
|
|
22
|
+
analysis=dict(hycom='s_init0_', mfwam='LAW_')
|
|
23
|
+
),
|
|
24
|
+
suffix=dict(
|
|
25
|
+
bgstderr=dict(input='in', output='out'),
|
|
26
|
+
analysis=dict(hycom_hycom='.gz', hycom_surcotes='.gz', hycom_surcotes_oi='.gz'),
|
|
27
|
+
historic=dict(surfex_arpege='.sfx', surfex_aearp='.sfx',
|
|
28
|
+
hycom_hycom='.gz', hycom_surcotes='.gz', hycom_surcotes_oi='.gz'),
|
|
29
|
+
gridpoint=dict(hycom_grb='grb'),
|
|
30
|
+
),
|
|
31
|
+
term0003=dict(
|
|
32
|
+
bgstderr=dict(input='', output='_assim'),
|
|
33
|
+
),
|
|
34
|
+
term0009=dict(
|
|
35
|
+
bgstderr=dict(input='', output='_production'),
|
|
36
|
+
),
|
|
37
|
+
term0012=dict(
|
|
38
|
+
bgstderr=dict(input='_production_dsbscr', output='_production_dsbscr'),
|
|
39
|
+
),
|
|
40
|
+
varbcarpege=dict(
|
|
41
|
+
varbc=dict(input='.cycle_arp', output='.cycle'),
|
|
42
|
+
),
|
|
43
|
+
varbcaladin=dict(
|
|
44
|
+
varbc=dict(input='.cycle_alad', output='.cycle'),
|
|
45
|
+
),
|
|
46
|
+
varbcarome=dict(
|
|
47
|
+
varbc=dict(input='.cycle_aro', output='.cycle'),
|
|
48
|
+
),
|
|
49
|
+
surf0000=dict(
|
|
50
|
+
histsurf=dict(input='INIT_SURF', output='INIT_SURF'),
|
|
51
|
+
historic=dict(input='INIT_SURF', output='INIT_SURF'),
|
|
52
|
+
),
|
|
53
|
+
surf0003=dict(
|
|
54
|
+
histsurf=dict(input='PREP', output='AROMOUT_.0003'),
|
|
55
|
+
historic=dict(input='PREP', output='AROMOUT_.0003'),
|
|
56
|
+
),
|
|
57
|
+
surf0006=dict(
|
|
58
|
+
histsurf=dict(input='PREP', output='AROMOUT_.0006'),
|
|
59
|
+
historic=dict(input='PREP', output='AROMOUT_.0006'),
|
|
60
|
+
),
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
arpcourt_vconf = ('courtfr', 'frcourt', 'court')
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def fuzzyname(entry, realkind, key, default=None):
|
|
67
|
+
"""Returns any non-standard naming convention in the operational namespace."""
|
|
68
|
+
try:
|
|
69
|
+
return fuzzystr[entry][realkind][key]
|
|
70
|
+
except KeyError:
|
|
71
|
+
if default is not None:
|
|
72
|
+
return default
|
|
73
|
+
raise
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def archive_suffix(model, cutoff, date, vconf=None):
|
|
77
|
+
"""Returns the suffix for iga filenames according to specified ``model``, ``cutoff`` and ``date`` hour."""
|
|
78
|
+
|
|
79
|
+
hh = range(0, 21, 3)
|
|
80
|
+
hrange = []
|
|
81
|
+
for h in hh:
|
|
82
|
+
hrange.append("%02d" % h)
|
|
83
|
+
|
|
84
|
+
if cutoff == 'assim':
|
|
85
|
+
rr = dict(
|
|
86
|
+
zip(
|
|
87
|
+
zip(
|
|
88
|
+
(cutoff,) * len(hrange),
|
|
89
|
+
hh
|
|
90
|
+
),
|
|
91
|
+
hrange
|
|
92
|
+
)
|
|
93
|
+
)
|
|
94
|
+
else:
|
|
95
|
+
if re.search(r'court|arome', model) or vconf in arpcourt_vconf:
|
|
96
|
+
rr = dict(
|
|
97
|
+
zip(
|
|
98
|
+
zip(
|
|
99
|
+
(cutoff,) * len(hrange),
|
|
100
|
+
hh
|
|
101
|
+
),
|
|
102
|
+
('CM', 'TR', 'SX', 'NF', 'PM', 'QZ', 'DH', 'VU')
|
|
103
|
+
)
|
|
104
|
+
)
|
|
105
|
+
else:
|
|
106
|
+
rr = dict(
|
|
107
|
+
zip(
|
|
108
|
+
zip(
|
|
109
|
+
(cutoff,) * len(hrange),
|
|
110
|
+
hh
|
|
111
|
+
),
|
|
112
|
+
('AM', 'TR', 'SX', 'NF', 'PM', 'QZ', 'DH', 'VU')
|
|
113
|
+
)
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
return str(rr[(cutoff, date.hour)])
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
class _BaseIgakeyFactory(str):
|
|
120
|
+
"""
|
|
121
|
+
Given the vapp/vconf, returns a default value for the igakey attribute.
|
|
122
|
+
|
|
123
|
+
Needs to be subclassed !
|
|
124
|
+
"""
|
|
125
|
+
|
|
126
|
+
_re_appconf = re.compile(r'^(\w+)/([\w@]+)$')
|
|
127
|
+
_keymap = {}
|
|
128
|
+
|
|
129
|
+
def __new__(cls, value):
|
|
130
|
+
"""
|
|
131
|
+
If the input string is something like "vapp/vconf", use a mapping
|
|
132
|
+
between vapp/vconf pairs and the igakey (see _keymap).
|
|
133
|
+
If no mapping is found, it returns vapp.
|
|
134
|
+
"""
|
|
135
|
+
val_split = cls._re_appconf.match(value)
|
|
136
|
+
if val_split:
|
|
137
|
+
value = cls._keymap.get(val_split.group(1),
|
|
138
|
+
{}).get(val_split.group(2),
|
|
139
|
+
val_split.group(1))
|
|
140
|
+
return str.__new__(cls, value)
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
class IgakeyFactoryArchive(_BaseIgakeyFactory):
|
|
144
|
+
"""
|
|
145
|
+
Given the vapp/vconf, returns a default value for the igakey attribute
|
|
146
|
+
"""
|
|
147
|
+
|
|
148
|
+
_keymap = {'arpege': {'4dvarfr': 'arpege',
|
|
149
|
+
'4dvar': 'arpege',
|
|
150
|
+
'pearp': 'pearp',
|
|
151
|
+
'aearp': 'aearp',
|
|
152
|
+
'courtfr': 'arpege',
|
|
153
|
+
'frcourt': 'arpege',
|
|
154
|
+
'court': 'arpege', },
|
|
155
|
+
'mocage': {'camsfcst': 'macc',
|
|
156
|
+
'camsassim': 'macc', },
|
|
157
|
+
'arome': {'3dvarfr': 'arome',
|
|
158
|
+
'france': 'arome',
|
|
159
|
+
'pegase': 'pegase', },
|
|
160
|
+
'aladin': {'antiguy': 'antiguy',
|
|
161
|
+
'caledonie': 'caledonie',
|
|
162
|
+
'nc': 'caledonie',
|
|
163
|
+
'polynesie': 'polynesie',
|
|
164
|
+
'reunion': 'reunion', },
|
|
165
|
+
'hycom': {'atl@anarp': 'surcotes',
|
|
166
|
+
'med@anarp': 'surcotes',
|
|
167
|
+
'atl@fcarp': 'surcotes',
|
|
168
|
+
'med@fcarp': 'surcotes',
|
|
169
|
+
'atl@anaro': 'surcotes',
|
|
170
|
+
'med@anaro': 'surcotes',
|
|
171
|
+
'atl@fcaro': 'surcotes',
|
|
172
|
+
'med@fcaro': 'surcotes',
|
|
173
|
+
'atl@fcaoc': 'surcotes',
|
|
174
|
+
'med@fcaoc': 'surcotes',
|
|
175
|
+
'oin@ancep': 'surcotes_oi',
|
|
176
|
+
'oin@fcaro': 'surcotes_oi', },
|
|
177
|
+
'mfwam': {'globalcep02': 'mfwamglocep02',
|
|
178
|
+
'globalcep01': 'mfwamglocep01',
|
|
179
|
+
'reuaro01': 'mfwamreuaro',
|
|
180
|
+
'polyaro01': 'mfwampolyaro',
|
|
181
|
+
'caledaro01': 'mfwamcaledaro',
|
|
182
|
+
'globalarp02': 'mfwamgloarp02',
|
|
183
|
+
'globalarpc02': 'mfwamgloarpc02',
|
|
184
|
+
'atourxarp01': 'mfwamatourx01arp',
|
|
185
|
+
'euratarpc01': 'mfwameurcourt',
|
|
186
|
+
'frangparo0025': 'mfwamfrangp0025',
|
|
187
|
+
'frangparoifs0025': 'mfwamfrangp0025ifs',
|
|
188
|
+
'assmp1': 'mfwamassmp1',
|
|
189
|
+
'assmp2': 'mfwamassmp2',
|
|
190
|
+
'assms1': 'mfwamassms1',
|
|
191
|
+
'assms2': 'mfwamassms2',
|
|
192
|
+
'angola0025': 'mfwamangola', },
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
class IgakeyFactoryInline(_BaseIgakeyFactory):
|
|
197
|
+
"""
|
|
198
|
+
Given the vapp/vconf, returns a default value for the igakey attribute
|
|
199
|
+
"""
|
|
200
|
+
|
|
201
|
+
_keymap = {'arpege': {'4dvarfr': 'france',
|
|
202
|
+
'4dvar': 'france',
|
|
203
|
+
'pearp': 'pearp',
|
|
204
|
+
'aearp': 'aearp',
|
|
205
|
+
'courtfr': 'frcourt',
|
|
206
|
+
'frcourt': 'frcourt',
|
|
207
|
+
'court': 'frcourt', },
|
|
208
|
+
'arome': {'3dvarfr': 'france',
|
|
209
|
+
'france': 'france',
|
|
210
|
+
'pegase': 'pegase', },
|
|
211
|
+
'aladin': {'antiguy': 'antiguy',
|
|
212
|
+
'caledonie': 'caledonie',
|
|
213
|
+
'nc': 'caledonie',
|
|
214
|
+
'polynesie': 'polynesie',
|
|
215
|
+
'reunion': 'reunion', },
|
|
216
|
+
'hycom': {'atl@anarp': 'surcotes',
|
|
217
|
+
'med@anarp': 'surcotes',
|
|
218
|
+
'atl@fcarp': 'surcotes',
|
|
219
|
+
'med@fcarp': 'surcotes',
|
|
220
|
+
'atl@ancep': 'surcotes',
|
|
221
|
+
'med@ancep': 'surcotes',
|
|
222
|
+
'atl@fccep': 'surcotes',
|
|
223
|
+
'med@fccep': 'surcotes',
|
|
224
|
+
'atl@anaro': 'surcotes',
|
|
225
|
+
'med@anaro': 'surcotes',
|
|
226
|
+
'atl@fcaro': 'surcotes',
|
|
227
|
+
'med@fcaro': 'surcotes',
|
|
228
|
+
'atl@red': 'surcotes',
|
|
229
|
+
'med@red': 'surcotes',
|
|
230
|
+
'oin@ancep': 'surcotes_oi',
|
|
231
|
+
'oin@fcaro': 'surcotes_oi',
|
|
232
|
+
'oin@red': 'surcotes_oi', },
|
|
233
|
+
'mfwam': {'globalcep02': 'mfwamglocep02',
|
|
234
|
+
'globalcep01': 'mfwamglocep01',
|
|
235
|
+
'reuaro01': 'mfwamreuaro',
|
|
236
|
+
'polyaro01': 'mfwampolyaro',
|
|
237
|
+
'caledaro01': 'mfwamcaledaro',
|
|
238
|
+
'globalarp02': 'mfwamgloarp02',
|
|
239
|
+
'globalarpc02': 'mfwamgloarpc02',
|
|
240
|
+
'atourxarp01': 'mfwamatourx01arp',
|
|
241
|
+
'euratarpc01': 'mfwameurcourt',
|
|
242
|
+
'frangparo0025': 'mfwamfrangp0025',
|
|
243
|
+
'frangparoifs0025': 'mfwamfrangp0025ifs',
|
|
244
|
+
'assmp1': 'mfwamassmp1',
|
|
245
|
+
'assmp2': 'mfwamassmp2',
|
|
246
|
+
'assms1': 'mfwamassms1',
|
|
247
|
+
'assms2': 'mfwamassms2',
|
|
248
|
+
'angola0025': 'mfwamangola', },
|
|
249
|
+
}
|
vortex/nwp/tools/mars.py
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Utility classes and function to work with the Mars database.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from bronx.fancies import loggers
|
|
6
|
+
|
|
7
|
+
from vortex.util.config import GenericConfigParser
|
|
8
|
+
|
|
9
|
+
#: No automatic export
|
|
10
|
+
__all__ = []
|
|
11
|
+
|
|
12
|
+
logger = loggers.getLogger(__name__)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class MarsError(Exception):
|
|
16
|
+
"""General Mars error."""
|
|
17
|
+
pass
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class MarsConfigurationError(MarsError):
|
|
21
|
+
"""Specific Mars configuration error."""
|
|
22
|
+
pass
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class MarsGetError(MarsError):
|
|
26
|
+
"""Generic Mars get error."""
|
|
27
|
+
pass
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def findMarsExtractCommand(sh, inifile=None, command=None):
|
|
31
|
+
actual_command = command
|
|
32
|
+
if actual_command is None:
|
|
33
|
+
actual_inifile = inifile
|
|
34
|
+
if actual_inifile is None:
|
|
35
|
+
actual_command = sh.default_target.get("mars:command", None)
|
|
36
|
+
else:
|
|
37
|
+
actual_config = GenericConfigParser(inifile=actual_inifile)
|
|
38
|
+
if actual_config.has_section('mars') and actual_config.has_option('mars', 'command'):
|
|
39
|
+
actual_command = actual_config.get("mars", "command")
|
|
40
|
+
if actual_command is None:
|
|
41
|
+
raise MarsConfigurationError("Could not find a proper command.")
|
|
42
|
+
return actual_command
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def callMarsExtract(sh, query_file, command=None, fatal=True):
|
|
46
|
+
"""
|
|
47
|
+
Build the command line used to execute the Mars query and launch it.
|
|
48
|
+
|
|
49
|
+
:param: sh: the system object used
|
|
50
|
+
:param query_file: The file containing the Mars query.
|
|
51
|
+
:param command: The command to be used to launch the Mars extraction.
|
|
52
|
+
:param fatal: Parameter indicating whether the fail of the request should be fatal or not
|
|
53
|
+
:return: The return code of the Mars extraction.
|
|
54
|
+
"""
|
|
55
|
+
command_line = " ".join([command, query_file])
|
|
56
|
+
return sh.spawn([command_line, ], shell=True, output=False, fatal=fatal)
|