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/tools/folder.py CHANGED
@@ -19,23 +19,38 @@ __all__ = []
19
19
 
20
20
  logger = loggers.getLogger(__name__)
21
21
 
22
- _folder_exposed_methods = {'cp', 'mv', 'forcepack', 'forceunpack',
23
- 'anyft_remote_rewrite',
24
- 'ftget', 'rawftget', 'batchrawftget', 'ftput', 'rawftput',
25
- 'scpget', 'scpput',
26
- 'ecfsget', 'ecfsput', 'ectransget', 'ectransput'}
22
+ _folder_exposed_methods = {
23
+ "cp",
24
+ "mv",
25
+ "forcepack",
26
+ "forceunpack",
27
+ "anyft_remote_rewrite",
28
+ "ftget",
29
+ "rawftget",
30
+ "batchrawftget",
31
+ "ftput",
32
+ "rawftput",
33
+ "scpget",
34
+ "scpput",
35
+ "ecfsget",
36
+ "ecfsput",
37
+ "ectransget",
38
+ "ectransput",
39
+ }
27
40
 
28
41
 
29
42
  def folderize(cls):
30
43
  """Create the necessary methods in a class that inherits from :class:`FolderShell`."""
31
- addon_kind = cls.footprint_retrieve().get_values('kind')
44
+ addon_kind = cls.footprint_retrieve().get_values("kind")
32
45
  if len(addon_kind) != 1:
33
- raise SyntaxError("Authorised values for a given Addon's kind must be unique")
46
+ raise SyntaxError(
47
+ "Authorised values for a given Addon's kind must be unique"
48
+ )
34
49
  addon_kind = addon_kind[0]
35
50
  for basic_mtdname in _folder_exposed_methods:
36
- expected_mtdname = '{:s}_{:s}'.format(addon_kind, basic_mtdname)
51
+ expected_mtdname = "{:s}_{:s}".format(addon_kind, basic_mtdname)
37
52
  if not hasattr(cls, expected_mtdname):
38
- parent_mtd = getattr(cls, '_folder_{:s}'.format(basic_mtdname))
53
+ parent_mtd = getattr(cls, "_folder_{:s}".format(basic_mtdname))
39
54
  setattr(cls, expected_mtdname, parent_mtd)
40
55
  return cls
41
56
 
@@ -45,41 +60,53 @@ class FolderShell(addons.FtrawEnableAddon):
45
60
  This abstract class defines methods to manipulate folders.
46
61
  """
47
62
 
48
- _COMPRESSED = 'gz'
63
+ _COMPRESSED = "gz"
49
64
 
50
65
  _abstract = True
51
66
  _footprint = dict(
52
- info = 'Tools for manipulating folders',
53
- attr = dict(
54
- kind = dict(
55
- values = ['folder'],
67
+ info="Tools for manipulating folders",
68
+ attr=dict(
69
+ kind=dict(
70
+ values=["folder"],
56
71
  ),
57
- tmpname = dict(
58
- optional = True,
59
- default = 'folder_tmpunpack',
72
+ tmpname=dict(
73
+ optional=True,
74
+ default="folder_tmpunpack",
60
75
  ),
61
- pipeget = dict(
62
- type = bool,
63
- optional = True,
64
- default = False,
76
+ pipeget=dict(
77
+ type=bool,
78
+ optional=True,
79
+ default=False,
65
80
  ),
66
- supportedfmt = dict(
67
- optional = True,
68
- default = '[kind]',
81
+ supportedfmt=dict(
82
+ optional=True,
83
+ default="[kind]",
69
84
  ),
70
- )
85
+ ),
71
86
  )
72
87
 
73
- def _folder_cp(self, source, destination,
74
- smartcp_threshold=0, intent='in', silent=False):
88
+ def _folder_cp(
89
+ self,
90
+ source,
91
+ destination,
92
+ smartcp_threshold=0,
93
+ intent="in",
94
+ silent=False,
95
+ ):
75
96
  """Extended copy for a folder repository."""
76
97
  rc, source, destination = self._folder_tarfix_out(source, destination)
77
- rc = rc and self.sh.cp(source, destination,
78
- smartcp_threshold=smartcp_threshold, intent=intent)
98
+ rc = rc and self.sh.cp(
99
+ source,
100
+ destination,
101
+ smartcp_threshold=smartcp_threshold,
102
+ intent=intent,
103
+ )
79
104
  if rc:
80
- rc, source, destination = self._folder_tarfix_in(source, destination)
81
- if rc and intent == 'inout':
82
- self.sh.stderr('chmod', 0o644, destination)
105
+ rc, source, destination = self._folder_tarfix_in(
106
+ source, destination
107
+ )
108
+ if rc and intent == "inout":
109
+ self.sh.stderr("chmod", 0o644, destination)
83
110
  with self.sh.mute_stderr():
84
111
  for infile in self.sh.ffind(destination):
85
112
  self.sh.chmod(infile, 0o644)
@@ -92,18 +119,27 @@ class FolderShell(addons.FtrawEnableAddon):
92
119
  if isinstance(source, str):
93
120
  rc = rc and self.sh.remove(source)
94
121
  else:
95
- rc, source, destination = self._folder_tarfix_out(source, destination)
122
+ rc, source, destination = self._folder_tarfix_out(
123
+ source, destination
124
+ )
96
125
  rc = rc and self.sh.move(source, destination)
97
126
  if rc:
98
- rc, source, destination = self._folder_tarfix_in(source, destination)
127
+ rc, source, destination = self._folder_tarfix_in(
128
+ source, destination
129
+ )
99
130
  return rc
100
131
 
101
132
  def _folder_forcepack(self, source, destination=None):
102
133
  """Returned a path to a packed data."""
103
134
  if not self.sh.is_tarname(source):
104
- destination = (destination if destination else
105
- "{:s}.{:s}".format(self.sh.safe_fileaddsuffix(source),
106
- self._folder_tarfix_extension))
135
+ destination = (
136
+ destination
137
+ if destination
138
+ else "{:s}.{:s}".format(
139
+ self.sh.safe_fileaddsuffix(source),
140
+ self._folder_tarfix_extension,
141
+ )
142
+ )
107
143
  if not self.sh.path.exists(destination):
108
144
  absdestination = self.sh.path.abspath(destination)
109
145
  with self.sh.cdcontext(self.sh.path.dirname(source)):
@@ -114,24 +150,33 @@ class FolderShell(addons.FtrawEnableAddon):
114
150
 
115
151
  def _folder_forceunpack(self, source):
116
152
  """Unpack the data "inplace"."""
117
- fakesource = '{:s}.{:s}'.format(self.sh.safe_fileaddsuffix(source),
118
- self._folder_tarfix_extension)
153
+ fakesource = "{:s}.{:s}".format(
154
+ self.sh.safe_fileaddsuffix(source), self._folder_tarfix_extension
155
+ )
119
156
  rc, _, _ = self._folder_tarfix_in(fakesource, source)
120
157
  return rc
121
158
 
122
159
  def _folder_pack_stream(self, source, stdout=True):
123
160
  source_name = self.sh.path.basename(source)
124
161
  source_dirname = self.sh.path.dirname(source)
125
- compression_map = {'gz': 'z', 'bz2': 'j'}
126
- compression_opt = compression_map.get(self._COMPRESSED, '')
127
- cmd = ['tar', '--directory', source_dirname,
128
- '-c' + compression_opt, source_name]
162
+ compression_map = {"gz": "z", "bz2": "j"}
163
+ compression_opt = compression_map.get(self._COMPRESSED, "")
164
+ cmd = [
165
+ "tar",
166
+ "--directory",
167
+ source_dirname,
168
+ "-c" + compression_opt,
169
+ source_name,
170
+ ]
129
171
  return self.sh.popen(cmd, stdout=stdout, bufsize=8192)
130
172
 
131
- def _folder_unpack_stream(self, stdin=True, options='xvf'):
173
+ def _folder_unpack_stream(self, stdin=True, options="xvf"):
132
174
  return self.sh.popen(
133
175
  # the z option is omitted consequently it also works if the file is not compressed
134
- ['tar', options, '-'], stdin=stdin, bufsize=8192)
176
+ ["tar", options, "-"],
177
+ stdin=stdin,
178
+ bufsize=8192,
179
+ )
135
180
 
136
181
  def _packed_size(self, source):
137
182
  """Size of the final file, must be exact or be an overestimation.
@@ -150,17 +195,20 @@ class FolderShell(addons.FtrawEnableAddon):
150
195
 
151
196
  def _folder_preftget(self, source, destination):
152
197
  """Prepare source and destination"""
153
- destination = self.sh.path.abspath(self.sh.path.expanduser(destination))
198
+ destination = self.sh.path.abspath(
199
+ self.sh.path.expanduser(destination)
200
+ )
154
201
  self.sh.rm(destination)
155
202
  return source, destination
156
203
 
157
204
  def _folder_postftget(self, destination):
158
205
  """Move the untared stuff to the destination and clean-up things."""
159
206
  try:
160
- unpacked = self.sh.glob('*')
207
+ unpacked = self.sh.glob("*")
161
208
  if unpacked:
162
- if (len(unpacked) == 1 and
163
- self.sh.path.isdir(self.sh.path.join(unpacked[-1]))):
209
+ if len(unpacked) == 1 and self.sh.path.isdir(
210
+ self.sh.path.join(unpacked[-1])
211
+ ):
164
212
  # This is the most usual case... (ODB, DDH packs produced by Vortex)
165
213
  self.sh.wpermtree(unpacked[-1], force=True)
166
214
  if self.sh.path.isdir(unpacked[-1]):
@@ -174,17 +222,21 @@ class FolderShell(addons.FtrawEnableAddon):
174
222
  self.sh.mkdir(destination)
175
223
  for item in unpacked:
176
224
  self.sh.wpermtree(item, force=True)
177
- self.sh.mv(item, self.sh.path.join(destination, item))
225
+ self.sh.mv(
226
+ item, self.sh.path.join(destination, item)
227
+ )
178
228
  else:
179
- logger.error('Nothing to unpack')
229
+ logger.error("Nothing to unpack")
180
230
  except Exception as trouble:
181
- logger.critical('Unable to proceed folder post-ftget step')
231
+ logger.critical("Unable to proceed folder post-ftget step")
182
232
  raise trouble
183
233
 
184
234
  @contextlib.contextmanager
185
235
  def _folder_postftget_context(self, destination):
186
236
  """Move the untared stuff to the destination and clean-up things."""
187
- with self.sh.temporary_dir_cdcontext(prefix='folder_', dir=self.sh.getcwd()):
237
+ with self.sh.temporary_dir_cdcontext(
238
+ prefix="folder_", dir=self.sh.getcwd()
239
+ ):
188
240
  try:
189
241
  yield
190
242
  finally:
@@ -209,8 +261,11 @@ class FolderShell(addons.FtrawEnableAddon):
209
261
 
210
262
  @contextlib.contextmanager
211
263
  def _folder_ftput_file_compress(self, source):
212
- c_source = (self.sh.safe_fileaddsuffix(source) +
213
- '.' + self._folder_tarfix_extension)
264
+ c_source = (
265
+ self.sh.safe_fileaddsuffix(source)
266
+ + "."
267
+ + self._folder_tarfix_extension
268
+ )
214
269
  try:
215
270
  self.sh.tar(c_source, source)
216
271
  yield c_source
@@ -226,36 +281,54 @@ class FolderShell(addons.FtrawEnableAddon):
226
281
  def _folder_anyft_remote_rewrite(self, remote):
227
282
  """Add the folder suffix before using file transfert protocols."""
228
283
  if not self.sh.is_tarname(self.sh.path.basename(remote)):
229
- return '{:s}.{:s}'.format(remote, self._folder_tarfix_extension)
284
+ return "{:s}.{:s}".format(remote, self._folder_tarfix_extension)
230
285
  else:
231
286
  return remote
232
287
 
233
- def _folder_ftget(self, source, destination, hostname=None, logname=None,
234
- port=DEFAULT_FTP_PORT, cpipeline=None):
288
+ def _folder_ftget(
289
+ self,
290
+ source,
291
+ destination,
292
+ hostname=None,
293
+ logname=None,
294
+ port=DEFAULT_FTP_PORT,
295
+ cpipeline=None,
296
+ ):
235
297
  """Proceed direct ftp get on the specified target."""
236
298
  if cpipeline is not None:
237
299
  raise OSError("It's not allowed to compress folder like data.")
238
300
  hostname = self.sh.fix_fthostname(hostname)
239
301
  with self.sh.ftpcontext(hostname, logname, port=port) as ftp:
240
302
  if ftp:
241
- source, destination = self._folder_preftget(source, destination)
303
+ source, destination = self._folder_preftget(
304
+ source, destination
305
+ )
242
306
  with self._folder_postftget_context(destination):
243
307
  try:
244
308
  if self.pipeget:
245
309
  with self._folder_ftget_pipe_extract() as p:
246
310
  rc = ftp.get(source, p.stdin)
247
311
  else:
248
- with self._folder_ftget_file_extract(source) as tmp_target:
312
+ with self._folder_ftget_file_extract(
313
+ source
314
+ ) as tmp_target:
249
315
  rc = ftp.get(source, tmp_target)
250
316
  except ftplib.all_errors as e:
251
- logger.warning('An FTP error occurred: %s', str(e))
317
+ logger.warning("An FTP error occurred: %s", str(e))
252
318
  rc = False
253
319
  return rc
254
320
  else:
255
321
  return False
256
322
 
257
- def _folder_rawftget(self, source, destination, hostname=None, logname=None,
258
- port=None, cpipeline=None):
323
+ def _folder_rawftget(
324
+ self,
325
+ source,
326
+ destination,
327
+ hostname=None,
328
+ logname=None,
329
+ port=None,
330
+ cpipeline=None,
331
+ ):
259
332
  """Use ftserv as much as possible."""
260
333
  if cpipeline is not None:
261
334
  raise OSError("It's not allowed to compress folder like data.")
@@ -263,17 +336,30 @@ class FolderShell(addons.FtrawEnableAddon):
263
336
  source, destination = self._folder_preftget(source, destination)
264
337
  with self._folder_postftget_context(destination):
265
338
  with self._folder_ftget_file_extract(source) as tmp_target:
266
- rc = self.sh.ftserv_get(source, tmp_target,
267
- hostname=hostname, logname=logname,
268
- port=port)
339
+ rc = self.sh.ftserv_get(
340
+ source,
341
+ tmp_target,
342
+ hostname=hostname,
343
+ logname=logname,
344
+ port=port,
345
+ )
269
346
  return rc
270
347
  else:
271
348
  if port is None:
272
349
  port = DEFAULT_FTP_PORT
273
- return self._folder_ftget(source, destination, hostname, logname, port=port)
274
-
275
- def _folder_batchrawftget(self, source, destination, hostname=None, logname=None,
276
- port=None, cpipeline=None):
350
+ return self._folder_ftget(
351
+ source, destination, hostname, logname, port=port
352
+ )
353
+
354
+ def _folder_batchrawftget(
355
+ self,
356
+ source,
357
+ destination,
358
+ hostname=None,
359
+ logname=None,
360
+ port=None,
361
+ cpipeline=None,
362
+ ):
277
363
  """Use ftserv to fetch several folder-like resources."""
278
364
  if cpipeline is not None:
279
365
  raise OSError("It's not allowed to compress folder like data.")
@@ -288,20 +374,35 @@ class FolderShell(addons.FtrawEnableAddon):
288
374
  actualdestinations.append(actual_d)
289
375
  d_dirname = self.sh.path.dirname(actual_d)
290
376
  self.sh.mkdir(d_dirname)
291
- d_tmpdir = tempfile.mkdtemp(prefix='folder_', dir=d_dirname)
377
+ d_tmpdir = tempfile.mkdtemp(
378
+ prefix="folder_", dir=d_dirname
379
+ )
292
380
  d_extname = self.sh.tarname_splitext(actual_s)[1]
293
- tmpdestinations.append(self.sh.path.join(d_tmpdir, self.tmpname + d_extname))
294
-
295
- rc = self.sh.ftserv_batchget(actualsources, tmpdestinations, hostname,
296
- logname, port=port)
297
-
298
- for i, (d, t) in enumerate(zip(actualdestinations, tmpdestinations)):
381
+ tmpdestinations.append(
382
+ self.sh.path.join(d_tmpdir, self.tmpname + d_extname)
383
+ )
384
+
385
+ rc = self.sh.ftserv_batchget(
386
+ actualsources,
387
+ tmpdestinations,
388
+ hostname,
389
+ logname,
390
+ port=port,
391
+ )
392
+
393
+ for i, (d, t) in enumerate(
394
+ zip(actualdestinations, tmpdestinations)
395
+ ):
299
396
  if rc[i]:
300
397
  with self.sh.cdcontext(self.sh.path.dirname(t)):
301
398
  try:
302
399
  try:
303
- rc[i] = rc[i] and bool(self.sh.untar(self.sh.path.basename(t),
304
- autocompress=False))
400
+ rc[i] = rc[i] and bool(
401
+ self.sh.untar(
402
+ self.sh.path.basename(t),
403
+ autocompress=False,
404
+ )
405
+ )
305
406
  finally:
306
407
  self.sh.rm(t)
307
408
  finally:
@@ -311,10 +412,18 @@ class FolderShell(addons.FtrawEnableAddon):
311
412
  self.sh.rm(self.sh.path.dirname(t))
312
413
  return rc
313
414
  else:
314
- raise RuntimeError('You are not supposed to land here !')
315
-
316
- def _folder_ftput(self, source, destination, hostname=None, logname=None,
317
- port=DEFAULT_FTP_PORT, cpipeline=None, sync=False):
415
+ raise RuntimeError("You are not supposed to land here !")
416
+
417
+ def _folder_ftput(
418
+ self,
419
+ source,
420
+ destination,
421
+ hostname=None,
422
+ logname=None,
423
+ port=DEFAULT_FTP_PORT,
424
+ cpipeline=None,
425
+ sync=False,
426
+ ):
318
427
  """Proceed direct ftp put on the specified target."""
319
428
  if cpipeline is not None:
320
429
  raise OSError("It's not allowed to compress folder like data.")
@@ -326,42 +435,64 @@ class FolderShell(addons.FtrawEnableAddon):
326
435
  with self._folder_ftput_pipe_compress(source) as p:
327
436
  sponge = IoSponge(p.stdout, guessed_size=packed_size)
328
437
  try:
329
- rc = ftp.put(sponge, destination, size=sponge.size, exact=False)
438
+ rc = ftp.put(
439
+ sponge, destination, size=sponge.size, exact=False
440
+ )
330
441
  except ftplib.all_errors as e:
331
- logger.warning('An FTP error occurred: %s', str(e))
442
+ logger.warning("An FTP error occurred: %s", str(e))
332
443
  rc = False
333
444
  return rc
334
445
  else:
335
446
  return False
336
447
 
337
- def _folder_rawftput(self, source, destination, hostname=None, logname=None,
338
- port=None, cpipeline=None, sync=False):
448
+ def _folder_rawftput(
449
+ self,
450
+ source,
451
+ destination,
452
+ hostname=None,
453
+ logname=None,
454
+ port=None,
455
+ cpipeline=None,
456
+ sync=False,
457
+ ):
339
458
  """Use ftserv as much as possible."""
340
459
  if cpipeline is not None:
341
460
  raise OSError("It's not allowed to compress folder like data.")
342
461
  if self.sh.ftraw and self.rawftshell is not None:
343
- newsource = self.sh.copy2ftspool(source, nest=True,
344
- fmt=self.supportedfmt)
345
- request = self.sh.path.dirname(newsource) + '.request'
346
- with open(request, 'w') as request_fh:
462
+ newsource = self.sh.copy2ftspool(
463
+ source, nest=True, fmt=self.supportedfmt
464
+ )
465
+ request = self.sh.path.dirname(newsource) + ".request"
466
+ with open(request, "w") as request_fh:
347
467
  request_fh.write(str(self.sh.path.dirname(newsource)))
348
468
  self.sh.readonly(request)
349
- rc = self.sh.ftserv_put(request, destination,
350
- hostname=hostname, logname=logname, port=port,
351
- specialshell=self.rawftshell, sync=sync)
469
+ rc = self.sh.ftserv_put(
470
+ request,
471
+ destination,
472
+ hostname=hostname,
473
+ logname=logname,
474
+ port=port,
475
+ specialshell=self.rawftshell,
476
+ sync=sync,
477
+ )
352
478
  self.sh.rm(request)
353
479
  return rc
354
480
  else:
355
481
  if port is None:
356
482
  port = DEFAULT_FTP_PORT
357
- return self._folder_ftput(source, destination, hostname, logname,
358
- port=port, sync=sync)
483
+ return self._folder_ftput(
484
+ source, destination, hostname, logname, port=port, sync=sync
485
+ )
359
486
 
360
- def _folder_scpget(self, source, destination, hostname, logname=None, cpipeline=None):
487
+ def _folder_scpget(
488
+ self, source, destination, hostname, logname=None, cpipeline=None
489
+ ):
361
490
  """Retrieve a folder using scp."""
362
491
  if cpipeline is not None:
363
492
  raise OSError("It's not allowed to compress folder like data.")
364
- logname = self.sh.fix_ftuser(hostname, logname, fatal=False, defaults_to_user=False)
493
+ logname = self.sh.fix_ftuser(
494
+ hostname, logname, fatal=False, defaults_to_user=False
495
+ )
365
496
  ssh = self.sh.ssh(hostname, logname)
366
497
  rc = False
367
498
  source, destination = self._folder_preftget(source, destination)
@@ -370,18 +501,22 @@ class FolderShell(addons.FtrawEnableAddon):
370
501
  rc = ssh.scpget_stream(source, p.stdin)
371
502
  return rc
372
503
 
373
- def _folder_scpput(self, source, destination, hostname, logname=None, cpipeline=None):
504
+ def _folder_scpput(
505
+ self, source, destination, hostname, logname=None, cpipeline=None
506
+ ):
374
507
  """Upload a folder using scp."""
375
508
  if cpipeline is not None:
376
509
  raise OSError("It's not allowed to compress folder like data.")
377
510
  source = self.sh.path.abspath(source)
378
- logname = self.sh.fix_ftuser(hostname, logname, fatal=False, defaults_to_user=False)
511
+ logname = self.sh.fix_ftuser(
512
+ hostname, logname, fatal=False, defaults_to_user=False
513
+ )
379
514
  ssh = self.sh.ssh(hostname, logname)
380
515
  with self._folder_ftput_pipe_compress(source) as p:
381
516
  rc = ssh.scpput_stream(p.stdout, destination)
382
517
  return rc
383
518
 
384
- @addons.require_external_addon('ecfs')
519
+ @addons.require_external_addon("ecfs")
385
520
  def _folder_ecfsget(self, source, target, cpipeline=None, options=None):
386
521
  """Get a folder resource using ECfs.
387
522
 
@@ -397,10 +532,12 @@ class FolderShell(addons.FtrawEnableAddon):
397
532
  source, target = self._folder_preftget(source, target)
398
533
  with self._folder_postftget_context(target):
399
534
  with self._folder_ftget_file_extract(source) as tmp_target:
400
- rc = self.sh.ecfsget(source=source, target=tmp_target, options=options)
535
+ rc = self.sh.ecfsget(
536
+ source=source, target=tmp_target, options=options
537
+ )
401
538
  return rc
402
539
 
403
- @addons.require_external_addon('ecfs')
540
+ @addons.require_external_addon("ecfs")
404
541
  def _folder_ecfsput(self, source, target, cpipeline=None, options=None):
405
542
  """Put a folder resource using ECfs.
406
543
 
@@ -414,11 +551,15 @@ class FolderShell(addons.FtrawEnableAddon):
414
551
  raise OSError("It's not allowed to compress folder like data.")
415
552
  source = self.sh.path.abspath(source)
416
553
  with self._folder_ftput_file_compress(source) as c_source:
417
- rc = self.sh.ecfsput(source=c_source, target=target, options=options)
554
+ rc = self.sh.ecfsput(
555
+ source=c_source, target=target, options=options
556
+ )
418
557
  return rc
419
558
 
420
- @addons.require_external_addon('ectrans')
421
- def _folder_ectransget(self, source, target, gateway=None, remote=None, cpipeline=None):
559
+ @addons.require_external_addon("ectrans")
560
+ def _folder_ectransget(
561
+ self, source, target, gateway=None, remote=None, cpipeline=None
562
+ ):
422
563
  """Get a folder resource using ECtrans.
423
564
 
424
565
  :param source: source file
@@ -434,15 +575,24 @@ class FolderShell(addons.FtrawEnableAddon):
434
575
  source, target = self._folder_preftget(source, target)
435
576
  with self._folder_postftget_context(target):
436
577
  with self._folder_ftget_file_extract(source) as tmp_target:
437
- rc = self.sh.raw_ectransget(source=source,
438
- target=tmp_target,
439
- gateway=gateway,
440
- remote=remote)
578
+ rc = self.sh.raw_ectransget(
579
+ source=source,
580
+ target=tmp_target,
581
+ gateway=gateway,
582
+ remote=remote,
583
+ )
441
584
  return rc
442
585
 
443
- @addons.require_external_addon('ectrans')
444
- def _folder_ectransput(self, source, target, gateway=None, remote=None,
445
- cpipeline=None, sync=False):
586
+ @addons.require_external_addon("ectrans")
587
+ def _folder_ectransput(
588
+ self,
589
+ source,
590
+ target,
591
+ gateway=None,
592
+ remote=None,
593
+ cpipeline=None,
594
+ sync=False,
595
+ ):
446
596
  """Put a folder resource using ECtrans.
447
597
 
448
598
  :param source: source file
@@ -457,24 +607,29 @@ class FolderShell(addons.FtrawEnableAddon):
457
607
  raise OSError("It's not allowed to compress folder like data.")
458
608
  source = self.sh.path.abspath(source)
459
609
  with self._folder_ftput_file_compress(source) as c_source:
460
- rc = self.sh.raw_ectransput(source=c_source,
461
- target=target,
462
- gateway=gateway,
463
- remote=remote,
464
- sync=sync)
610
+ rc = self.sh.raw_ectransput(
611
+ source=c_source,
612
+ target=target,
613
+ gateway=gateway,
614
+ remote=remote,
615
+ sync=sync,
616
+ )
465
617
  return rc
466
618
 
467
619
  @property
468
620
  def _folder_tarfix_extension(self):
469
621
  """Return the extension of tar file associated with this extension."""
470
622
  if self._COMPRESSED:
471
- if self._COMPRESSED == 'gz':
623
+ if self._COMPRESSED == "gz":
472
624
  return "tgz"
473
- elif self._COMPRESSED == 'bz2':
625
+ elif self._COMPRESSED == "bz2":
474
626
  return "tar.bz2"
475
627
  else:
476
- raise ValueError("Unsupported compression type: {:s}"
477
- .format(self._COMPRESSED))
628
+ raise ValueError(
629
+ "Unsupported compression type: {:s}".format(
630
+ self._COMPRESSED
631
+ )
632
+ )
478
633
  else:
479
634
  return "tar"
480
635
 
@@ -487,17 +642,23 @@ class FolderShell(addons.FtrawEnableAddon):
487
642
  ok = True
488
643
  sh = self.sh
489
644
  if sh.is_tarname(source) and not sh.is_tarname(destination):
490
- logger.info('tarfix_in: untar from get <%s> to <%s>', source, destination)
645
+ logger.info(
646
+ "tarfix_in: untar from get <%s> to <%s>", source, destination
647
+ )
491
648
  (destdir, destfile) = sh.path.split(sh.path.abspath(destination))
492
649
  tar_ext = sh.tarname_splitext(source)[1]
493
650
  desttar = sh.path.abspath(destination + tar_ext)
494
651
  sh.remove(desttar)
495
652
  ok = ok and sh.move(destination, desttar)
496
- with sh.temporary_dir_cdcontext(prefix='untar_', dir=destdir):
653
+ with sh.temporary_dir_cdcontext(prefix="untar_", dir=destdir):
497
654
  ok = ok and sh.untar(desttar, output=False)
498
- unpacked = sh.glob('*')
499
- ok = ok and len(unpacked) == 1 # Only one element allowed in this kind of tarfiles
500
- ok = ok and sh.move(unpacked[0], sh.path.join(destdir, destfile))
655
+ unpacked = sh.glob("*")
656
+ ok = (
657
+ ok and len(unpacked) == 1
658
+ ) # Only one element allowed in this kind of tarfiles
659
+ ok = ok and sh.move(
660
+ unpacked[0], sh.path.join(destdir, destfile)
661
+ )
501
662
  ok = ok and sh.remove(desttar)
502
663
  return (ok, source, destination)
503
664
 
@@ -511,7 +672,9 @@ class FolderShell(addons.FtrawEnableAddon):
511
672
  ok = True
512
673
  sh = self.sh
513
674
  if sh.is_tarname(destination) and not sh.is_tarname(source):
514
- logger.info('tarfix_out: tar before put <%s> to <%s>', source, destination)
675
+ logger.info(
676
+ "tarfix_out: tar before put <%s> to <%s>", source, destination
677
+ )
515
678
  tar_ext = sh.tarname_splitext(destination)[1]
516
679
  sourcetar = sh.path.abspath(source + tar_ext)
517
680
  source_rel = sh.path.basename(source)
@@ -532,12 +695,12 @@ class OdbShell(FolderShell):
532
695
  """
533
696
 
534
697
  _footprint = dict(
535
- info = 'Default ODB system interface',
536
- attr = dict(
537
- kind = dict(
538
- values = ['odb'],
698
+ info="Default ODB system interface",
699
+ attr=dict(
700
+ kind=dict(
701
+ values=["odb"],
539
702
  ),
540
- )
703
+ ),
541
704
  )
542
705
 
543
706
 
@@ -549,12 +712,12 @@ class DdhPackShell(FolderShell):
549
712
  """
550
713
 
551
714
  _footprint = dict(
552
- info = 'Default DDHpack system interface',
553
- attr = dict(
554
- kind = dict(
555
- values = ['ddhpack'],
715
+ info="Default DDHpack system interface",
716
+ attr=dict(
717
+ kind=dict(
718
+ values=["ddhpack"],
556
719
  ),
557
- )
720
+ ),
558
721
  )
559
722
 
560
723
 
@@ -566,12 +729,12 @@ class RawFilesShell(FolderShell):
566
729
  """
567
730
 
568
731
  _footprint = dict(
569
- info = 'Default (g)RRRRawfiles system interface',
570
- attr = dict(
571
- kind = dict(
572
- values = ['rawfiles'],
732
+ info="Default (g)RRRRawfiles system interface",
733
+ attr=dict(
734
+ kind=dict(
735
+ values=["rawfiles"],
573
736
  ),
574
- )
737
+ ),
575
738
  )
576
739
 
577
740
 
@@ -583,12 +746,12 @@ class ObsLocationPackShell(FolderShell):
583
746
  """
584
747
 
585
748
  _footprint = dict(
586
- info = 'Default Obs Location packs system interface',
587
- attr = dict(
588
- kind = dict(
589
- values = ['obslocationpack'],
749
+ info="Default Obs Location packs system interface",
750
+ attr=dict(
751
+ kind=dict(
752
+ values=["obslocationpack"],
590
753
  ),
591
- )
754
+ ),
592
755
  )
593
756
 
594
757
 
@@ -600,12 +763,12 @@ class ObsFirePackShell(FolderShell):
600
763
  """
601
764
 
602
765
  _footprint = dict(
603
- info = 'Default Obs Location packs system interface',
604
- attr = dict(
605
- kind = dict(
606
- values = ['obsfirepack'],
766
+ info="Default Obs Location packs system interface",
767
+ attr=dict(
768
+ kind=dict(
769
+ values=["obsfirepack"],
607
770
  ),
608
- )
771
+ ),
609
772
  )
610
773
 
611
774
 
@@ -617,12 +780,12 @@ class WavesBCShell(FolderShell):
617
780
  """
618
781
 
619
782
  _footprint = dict(
620
- info = 'Default waves BC system interface',
621
- attr = dict(
622
- kind = dict(
623
- values = ['wbcpack'],
783
+ info="Default waves BC system interface",
784
+ attr=dict(
785
+ kind=dict(
786
+ values=["wbcpack"],
624
787
  ),
625
- )
788
+ ),
626
789
  )
627
790
 
628
791
 
@@ -634,30 +797,38 @@ class FilesPackShell(FolderShell):
634
797
  """
635
798
 
636
799
  _footprint = dict(
637
- info = 'Default Files packs system interface',
638
- attr = dict(
639
- kind = dict(
640
- values = ['filespack'],
800
+ info="Default Files packs system interface",
801
+ attr=dict(
802
+ kind=dict(
803
+ values=["filespack"],
641
804
  ),
642
- )
805
+ ),
643
806
  )
644
807
 
645
808
 
646
- available_foldershells = [e.footprint_values('kind')[0] for e in locals().values()
647
- if (isinstance(e, type) and issubclass(e, FolderShell) and
648
- not e.footprint_abstract())]
809
+ available_foldershells = [
810
+ e.footprint_values("kind")[0]
811
+ for e in locals().values()
812
+ if (
813
+ isinstance(e, type)
814
+ and issubclass(e, FolderShell)
815
+ and not e.footprint_abstract()
816
+ )
817
+ ]
649
818
 
650
819
 
651
820
  class FolderShellsGroup(addons.AddonGroup):
652
821
  """The whole bunch of folder shells."""
653
822
 
654
823
  _footprint = dict(
655
- info = 'The whole bunch of folder shells',
656
- attr = dict(
657
- kind = dict(
658
- values = ['allfolders', ],
824
+ info="The whole bunch of folder shells",
825
+ attr=dict(
826
+ kind=dict(
827
+ values=[
828
+ "allfolders",
829
+ ],
659
830
  ),
660
- )
831
+ ),
661
832
  )
662
833
 
663
834
  _addonslist = available_foldershells