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/nwp/util/ens.py CHANGED
@@ -43,35 +43,44 @@ def drawingfunction(options):
43
43
 
44
44
  :rtype: A file like object
45
45
  """
46
- rhdict = options.get('rhandler', None)
46
+ rhdict = options.get("rhandler", None)
47
47
  if rhdict:
48
- date = rhdict['resource']['date']
48
+ date = rhdict["resource"]["date"]
49
49
  rgen = random.Random()
50
50
  rgen.seed(int(date[:-2]))
51
- nbsample = rhdict['resource'].get('nbsample', 0)
51
+ nbsample = rhdict["resource"].get("nbsample", 0)
52
52
  if not nbsample:
53
- raise FunctionStoreCallbackError('The resource must hold a non-null nbsample attribute')
54
- population = rhdict['resource'].get('population', [])
53
+ raise FunctionStoreCallbackError(
54
+ "The resource must hold a non-null nbsample attribute"
55
+ )
56
+ population = rhdict["resource"].get("population", [])
55
57
  if not population:
56
- raise FunctionStoreCallbackError('The resource must hold a non-empty population attribute')
58
+ raise FunctionStoreCallbackError(
59
+ "The resource must hold a non-empty population attribute"
60
+ )
57
61
  nbset = len(population)
58
62
 
59
- tirage = (rgen.sample(population * (nbsample // nbset), (nbsample // nbset) * nbset) +
60
- rgen.sample(population, nbsample % nbset))
61
- logger.info('List of random elements: %s', ', '.join([str(x) for x in tirage]))
63
+ tirage = rgen.sample(
64
+ population * (nbsample // nbset), (nbsample // nbset) * nbset
65
+ ) + rgen.sample(population, nbsample % nbset)
66
+ logger.info(
67
+ "List of random elements: %s", ", ".join([str(x) for x in tirage])
68
+ )
62
69
  else:
63
70
  raise FunctionStoreCallbackError("no resource handler here :-(")
64
71
  # NB: The result have to be a file like object !
65
- outdict = dict(vapp=rhdict['provider'].get('vapp', None),
66
- vconf=rhdict['provider'].get('vconf', None),
67
- cutoff=rhdict['resource'].get('cutoff', None),
68
- date=rhdict['resource'].get('date', None),
69
- resource_kind=rhdict['resource'].get('kind', None),
70
- drawing=tirage,
71
- population=population)
72
- if rhdict['provider'].get('experiment', None) is not None:
73
- outdict['experiment'] = rhdict['provider']['experiment']
74
- return io.BytesIO(json.dumps(outdict, indent=4).encode(encoding='utf_8'))
72
+ outdict = dict(
73
+ vapp=rhdict["provider"].get("vapp", None),
74
+ vconf=rhdict["provider"].get("vconf", None),
75
+ cutoff=rhdict["resource"].get("cutoff", None),
76
+ date=rhdict["resource"].get("date", None),
77
+ resource_kind=rhdict["resource"].get("kind", None),
78
+ drawing=tirage,
79
+ population=population,
80
+ )
81
+ if rhdict["provider"].get("experiment", None) is not None:
82
+ outdict["experiment"] = rhdict["provider"]["experiment"]
83
+ return io.BytesIO(json.dumps(outdict, indent=4).encode(encoding="utf_8"))
75
84
 
76
85
 
77
86
  def _checkingfunction_dict(options):
@@ -79,38 +88,95 @@ def _checkingfunction_dict(options):
79
88
  Internal function that returns a dictionnary that describes the available
80
89
  inputs.
81
90
  """
82
- rhdict = options.get('rhandler', None)
91
+ rhdict = options.get("rhandler", None)
83
92
  if rhdict:
84
93
  # If no nbsample is provided, easy to achieve...
85
- nbsample = rhdict['resource'].get('nbsample', None)
94
+ nbsample = rhdict["resource"].get("nbsample", None)
86
95
  # ...and if no explicit minimum of resources, nbsample is the minimum
87
- nbmin = int(options.get('min', [(0 if nbsample is None else nbsample), ]).pop())
96
+ nbmin = int(
97
+ options.get(
98
+ "min",
99
+ [
100
+ (0 if nbsample is None else nbsample),
101
+ ],
102
+ ).pop()
103
+ )
88
104
  if nbsample is not None and nbsample < nbmin:
89
- logger.warning('%d resources needed, %d required: sin of gluttony ?', nbsample, nbmin)
105
+ logger.warning(
106
+ "%d resources needed, %d required: sin of gluttony ?",
107
+ nbsample,
108
+ nbmin,
109
+ )
90
110
  # What to look for ?
91
- checkrole = rhdict['resource'].get('checkrole', None)
111
+ checkrole = rhdict["resource"].get("checkrole", None)
92
112
  if not checkrole:
93
- raise FunctionStoreCallbackError('The resource must hold a non-empty checkrole attribute')
94
- rolematch = re.match(r'(\w+)(?:\+(\w+))?$', checkrole)
113
+ raise FunctionStoreCallbackError(
114
+ "The resource must hold a non-empty checkrole attribute"
115
+ )
116
+ rolematch = re.match(r"(\w+)(?:\+(\w+))?$", checkrole)
95
117
  cur_t = sessions.current()
96
118
  if rolematch:
97
119
  ctx = cur_t.context
98
- checklist = [sec.rh for sec in ctx.sequence.filtered_inputs(role=rolematch.group(1))]
99
- mandatorylist = ([sec.rh for sec in ctx.sequence.filtered_inputs(role=rolematch.group(2))]
100
- if rolematch.group(2) else [])
120
+ checklist = [
121
+ sec.rh
122
+ for sec in ctx.sequence.filtered_inputs(
123
+ role=rolematch.group(1)
124
+ )
125
+ ]
126
+ mandatorylist = (
127
+ [
128
+ sec.rh
129
+ for sec in ctx.sequence.filtered_inputs(
130
+ role=rolematch.group(2)
131
+ )
132
+ ]
133
+ if rolematch.group(2)
134
+ else []
135
+ )
101
136
  else:
102
- raise FunctionStoreCallbackError('checkrole is not properly formatted')
137
+ raise FunctionStoreCallbackError(
138
+ "checkrole is not properly formatted"
139
+ )
103
140
  # Other options
104
- nretries = int(options.get('nretries', [0, ]).pop())
105
- retry_wait = Period(options.get('retry_wait', ['PT5M', ]).pop())
106
- comp_delay = Period(options.get('comp_delay', [0, ]).pop())
107
- fakecheck = options.get('fakecheck', [False, ]).pop()
141
+ nretries = int(
142
+ options.get(
143
+ "nretries",
144
+ [
145
+ 0,
146
+ ],
147
+ ).pop()
148
+ )
149
+ retry_wait = Period(
150
+ options.get(
151
+ "retry_wait",
152
+ [
153
+ "PT5M",
154
+ ],
155
+ ).pop()
156
+ )
157
+ comp_delay = Period(
158
+ options.get(
159
+ "comp_delay",
160
+ [
161
+ 0,
162
+ ],
163
+ ).pop()
164
+ )
165
+ fakecheck = options.get(
166
+ "fakecheck",
167
+ [
168
+ False,
169
+ ],
170
+ ).pop()
108
171
 
109
172
  def _retry_cond(the_ntries, the_acceptable_time):
110
- return ((the_acceptable_time is None and
111
- the_ntries <= nretries) or
112
- (the_acceptable_time and
113
- (time.time() - the_acceptable_time) < comp_delay.total_seconds()))
173
+ return (
174
+ the_acceptable_time is None and the_ntries <= nretries
175
+ ) or (
176
+ the_acceptable_time
177
+ and (time.time() - the_acceptable_time)
178
+ < comp_delay.total_seconds()
179
+ )
114
180
 
115
181
  # Ok let's work...
116
182
  ntries = 0
@@ -118,30 +184,41 @@ def _checkingfunction_dict(options):
118
184
  found = []
119
185
  while _retry_cond(ntries, acceptable_time):
120
186
  if ntries:
121
- logger.info("Let's sleep %d sec. before the next check round...",
122
- retry_wait.total_seconds())
187
+ logger.info(
188
+ "Let's sleep %d sec. before the next check round...",
189
+ retry_wait.total_seconds(),
190
+ )
123
191
  cur_t.sh.sleep(retry_wait.total_seconds())
124
192
  ntries += 1
125
193
  try:
126
194
  logger.info("Starting an input check...")
127
- found, candidates = helpers.colorfull_input_checker(nbmin,
128
- checklist,
129
- mandatory=mandatorylist,
130
- fakecheck=fakecheck)
195
+ found, candidates = helpers.colorfull_input_checker(
196
+ nbmin,
197
+ checklist,
198
+ mandatory=mandatorylist,
199
+ fakecheck=fakecheck,
200
+ )
131
201
  if acceptable_time is None and (found or nbmin == 0):
132
202
  acceptable_time = time.time()
133
- if comp_delay.total_seconds() and len(found) != len(candidates):
134
- logger.info("The minimum required size was reached (nbmin=%d). " +
135
- "That's great but we are waiting a little longer " +
136
- "(for at most %d sec.)",
137
- nbmin, comp_delay.total_seconds())
203
+ if comp_delay.total_seconds() and len(found) != len(
204
+ candidates
205
+ ):
206
+ logger.info(
207
+ "The minimum required size was reached (nbmin=%d). "
208
+ + "That's great but we are waiting a little longer "
209
+ + "(for at most %d sec.)",
210
+ nbmin,
211
+ comp_delay.total_seconds(),
212
+ )
138
213
 
139
214
  if len(found) == len(candidates):
140
215
  # No need to wait any longer...
141
216
  break
142
217
  except helpers.InputCheckerError as e:
143
218
  if not _retry_cond(ntries, acceptable_time):
144
- raise FunctionStoreCallbackError('The input checher failed ({!s})'.format(e))
219
+ raise FunctionStoreCallbackError(
220
+ "The input checher failed ({!s})".format(e)
221
+ )
145
222
  return found
146
223
  else:
147
224
  raise FunctionStoreCallbackError("no resource handler here :-(\n")
@@ -163,17 +240,19 @@ def checkingfunction(options):
163
240
 
164
241
  :rtype: A file like object
165
242
  """
166
- rhdict = options.get('rhandler', None)
243
+ rhdict = options.get("rhandler", None)
167
244
  avail_list = _checkingfunction_dict(options)
168
- outdict = dict(vapp=rhdict['provider'].get('vapp', None),
169
- vconf=rhdict['provider'].get('vconf', None),
170
- cutoff=rhdict['resource'].get('cutoff', None),
171
- date=rhdict['resource'].get('date', None),
172
- resource_kind=rhdict['resource'].get('kind', None),
173
- population=avail_list)
174
- if rhdict['provider'].get('experiment', None) is not None:
175
- outdict['experiment'] = rhdict['provider']['experiment']
176
- return io.BytesIO(json.dumps(outdict, indent=4).encode(encoding='utf_8'))
245
+ outdict = dict(
246
+ vapp=rhdict["provider"].get("vapp", None),
247
+ vconf=rhdict["provider"].get("vconf", None),
248
+ cutoff=rhdict["resource"].get("cutoff", None),
249
+ date=rhdict["resource"].get("date", None),
250
+ resource_kind=rhdict["resource"].get("kind", None),
251
+ population=avail_list,
252
+ )
253
+ if rhdict["provider"].get("experiment", None) is not None:
254
+ outdict["experiment"] = rhdict["provider"]["experiment"]
255
+ return io.BytesIO(json.dumps(outdict, indent=4).encode(encoding="utf_8"))
177
256
 
178
257
 
179
258
  def safedrawingfunction(options):
@@ -182,7 +261,7 @@ def safedrawingfunction(options):
182
261
  See the documentation of these two functions for more details.
183
262
  """
184
263
  checkedlist = _checkingfunction_dict(options)
185
- options['rhandler']['resource']['population'] = checkedlist
264
+ options["rhandler"]["resource"]["population"] = checkedlist
186
265
  return drawingfunction(options)
187
266
 
188
267
 
@@ -192,7 +271,9 @@ def unsafedrawingfunction(options):
192
271
 
193
272
  See the documentation of these two functions for more details.
194
273
  """
195
- options['fakecheck'] = [True, ]
274
+ options["fakecheck"] = [
275
+ True,
276
+ ]
196
277
  checkedlist = _checkingfunction_dict(options)
197
- options['rhandler']['resource']['population'] = checkedlist
278
+ options["rhandler"]["resource"]["population"] = checkedlist
198
279
  return drawingfunction(options)
vortex/nwp/util/hooks.py CHANGED
@@ -21,10 +21,15 @@ def update_namelist(t, rh, *completive_rh):
21
21
  touched = False
22
22
  for crh in completive_rh:
23
23
  if not isinstance(crh, (list, tuple)):
24
- crh = [crh, ]
24
+ crh = [
25
+ crh,
26
+ ]
25
27
  for arh in crh:
26
- logger.info('Merging: {!r} :\n{:s}'.format(arh.container,
27
- arh.contents.dumps()))
28
+ logger.info(
29
+ "Merging: {!r} :\n{:s}".format(
30
+ arh.container, arh.contents.dumps()
31
+ )
32
+ )
28
33
  rh.contents.merge(arh.contents)
29
34
  touched = True
30
35
  if touched:
@@ -36,14 +41,16 @@ def concatenate(t, rh, *rhlist):
36
41
  blocksize = 32 * 1024 * 1024 # 32Mb
37
42
  rh.container.close()
38
43
  with rh.container.iod_context():
39
- myfh = rh.container.iodesc(mode='ab')
44
+ myfh = rh.container.iodesc(mode="ab")
40
45
  for crh in rhlist:
41
46
  if not isinstance(crh, (list, tuple)):
42
- crh = [crh, ]
47
+ crh = [
48
+ crh,
49
+ ]
43
50
  for arh in crh:
44
- logger.info('Appending %s to self.', str(arh.container))
51
+ logger.info("Appending %s to self.", str(arh.container))
45
52
  with arh.container.iod_context():
46
- afh = arh.container.iodesc(mode='rb')
53
+ afh = arh.container.iodesc(mode="rb")
47
54
  stuff = afh.read(blocksize)
48
55
  while stuff:
49
56
  myfh.write(stuff)
@@ -64,14 +71,17 @@ def insert_cutoffs(t, rh, rh_cutoff_source, fuse_per_obstype=False):
64
71
  ValueError("The resource handler's list is empty.")
65
72
  # Get the CutoffDispenser
66
73
  import vortex.tools.listings
74
+
67
75
  assert vortex.tools.listings
68
- if rh_cutoff_source.container.actualfmt == 'bdmbufr_listing':
76
+ if rh_cutoff_source.container.actualfmt == "bdmbufr_listing":
69
77
  c_disp_callback = functools.partial(
70
78
  rh_cutoff_source.contents.data.cutoffs_dispenser,
71
- fuse_per_obstype=fuse_per_obstype
79
+ fuse_per_obstype=fuse_per_obstype,
72
80
  )
73
81
  else:
74
- raise RuntimeError("Incompatible < {!s} > ressource handler".format(rh_cutoff_source))
82
+ raise RuntimeError(
83
+ "Incompatible < {!s} > ressource handler".format(rh_cutoff_source)
84
+ )
75
85
  # Fill the gaps in the original request
76
86
  rh.contents.add_cutoff_info(c_disp_callback())
77
87
  # Actually save the result to file
@@ -79,7 +89,6 @@ def insert_cutoffs(t, rh, rh_cutoff_source, fuse_per_obstype=False):
79
89
 
80
90
 
81
91
  def _new_static_cutoff_dispencer(base_date, cutoffs_def):
82
-
83
92
  def x_period(p):
84
93
  try:
85
94
  return Period(p)
@@ -89,8 +98,10 @@ def _new_static_cutoff_dispencer(base_date, cutoffs_def):
89
98
  if not isinstance(base_date, Date):
90
99
  base_date = Date(base_date)
91
100
  if isinstance(cutoffs_def, collections.abc.Mapping):
92
- cutoffs_def = {(k if isinstance(k, Period) else x_period(k)): v
93
- for k, v in cutoffs_def.items()}
101
+ cutoffs_def = {
102
+ (k if isinstance(k, Period) else x_period(k)): v
103
+ for k, v in cutoffs_def.items()
104
+ }
94
105
  cutoffs = {base_date + k: v for k, v in cutoffs_def.items()}
95
106
  c_disp = StaticCutoffDispenser(max(cutoffs.keys()), cutoffs)
96
107
  else:
@@ -110,19 +121,19 @@ def insert_static_cutoffs(t, rh, base_date, cutoffs_def):
110
121
  associates a cutoff with a list of `obstypes`.
111
122
  """
112
123
  # Fill the gaps in the original request
113
- rh.contents.add_cutoff_info(_new_static_cutoff_dispencer(base_date, cutoffs_def))
124
+ rh.contents.add_cutoff_info(
125
+ _new_static_cutoff_dispencer(base_date, cutoffs_def)
126
+ )
114
127
  # Actually save the result to files
115
128
  rh.save()
116
129
 
117
130
 
118
131
  def arpifs_obs_error_correl_legacy2oops(t, rh):
119
132
  """Convert a constant file that contains observation errors correlations."""
120
- if rh.resource.realkind != 'correlations':
121
- raise ValueError('Incompatible resource: {!s}'.format(rh))
133
+ if rh.resource.realkind != "correlations":
134
+ raise ValueError("Incompatible resource: {!s}".format(rh))
122
135
  if rh.contents[0].startswith("SIGMAO"):
123
136
  logger.warning("Non conversion is needed...")
124
137
  else:
125
- rh.contents[:0] = ["SIGMAO unused\n",
126
- "1 1.2\n",
127
- "CORRELATIONS\n"]
138
+ rh.contents[:0] = ["SIGMAO unused\n", "1 1.2\n", "CORRELATIONS\n"]
128
139
  rh.save()
@@ -34,15 +34,17 @@ def process_needs_lfi_stuff(*kargs, **kwargs):
34
34
  pass
35
35
 
36
36
  """
37
- cyclekey = kwargs.pop('cyclekey', 'cycle')
37
+ cyclekey = kwargs.pop("cyclekey", "cycle")
38
38
 
39
39
  def decorate_process(cls):
40
40
  """Decorator for Task: get LFI stuff before calling process."""
41
- original_process = getattr(cls, 'process', None)
41
+ original_process = getattr(cls, "process", None)
42
42
  if original_process is not None:
43
+
43
44
  def process(self, *args, **kwargs):
44
45
  _get_lfi_stuff(self, cyclekey)
45
46
  original_process(self, *args, **kwargs)
47
+
46
48
  process.__doc__ = original_process.__doc__
47
49
  cls.process = process
48
50
  return cls
@@ -55,27 +57,29 @@ def process_needs_lfi_stuff(*kargs, **kwargs):
55
57
 
56
58
  def _get_lfi_stuff(self, cyclekey):
57
59
  """Get LFI stuff method (called from process)."""
58
- if 'early-fetch' in self.steps or 'fetch' in self.steps:
59
-
60
+ if "early-fetch" in self.steps or "fetch" in self.steps:
60
61
  actualcycle = getattr(self.conf, cyclekey)
61
62
 
62
- self.sh.title('Toolbox input tblfiscripts')
63
- toolbox.input(role='LFIScripts',
64
- genv=actualcycle,
65
- kind='lfiscripts',
66
- local='usualtools/tools.lfi.tgz',
67
- )
68
- self.sh.title('Toolbox input tbiopoll')
69
- toolbox.input(role='IOPoll',
70
- format='unknown',
71
- genv=actualcycle,
72
- kind='iopoll',
73
- language='perl',
74
- local='usualtools/io_poll',
75
- )
76
- self.sh.title('Toolbox input tblfitools')
77
- toolbox.input(role='LFITOOLS',
78
- genv=actualcycle,
79
- kind='lfitools',
80
- local='usualtools/lfitools'
81
- )
63
+ self.sh.title("Toolbox input tblfiscripts")
64
+ toolbox.input(
65
+ role="LFIScripts",
66
+ genv=actualcycle,
67
+ kind="lfiscripts",
68
+ local="usualtools/tools.lfi.tgz",
69
+ )
70
+ self.sh.title("Toolbox input tbiopoll")
71
+ toolbox.input(
72
+ role="IOPoll",
73
+ format="unknown",
74
+ genv=actualcycle,
75
+ kind="iopoll",
76
+ language="perl",
77
+ local="usualtools/io_poll",
78
+ )
79
+ self.sh.title("Toolbox input tblfitools")
80
+ toolbox.input(
81
+ role="LFITOOLS",
82
+ genv=actualcycle,
83
+ kind="lfitools",
84
+ local="usualtools/lfitools",
85
+ )