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/nwp/data/logs.py CHANGED
@@ -24,77 +24,84 @@ class FlowLogsStack(Resource):
24
24
  date_deco,
25
25
  cutoff_deco,
26
26
  dict(
27
- info = 'Stack of miscellaneous log files.',
28
- attr = dict(
29
- kind = dict(
30
- values = ['flow_logs']
31
- ),
32
- nativefmt = dict(
33
- values = ['filespack', ],
34
- default = 'filespack',
27
+ info="Stack of miscellaneous log files.",
28
+ attr=dict(
29
+ kind=dict(values=["flow_logs"]),
30
+ nativefmt=dict(
31
+ values=[
32
+ "filespack",
33
+ ],
34
+ default="filespack",
35
35
  ),
36
36
  ),
37
- )
37
+ ),
38
38
  ]
39
39
 
40
40
  @property
41
41
  def realkind(self):
42
- return 'flow_logs'
42
+ return "flow_logs"
43
43
 
44
44
 
45
45
  def use_flow_logs_stack(cls):
46
46
  """Setup the decorated class to work with the FlowLogsStack resource."""
47
47
  fpattrs = set(cls.footprint_retrieve().attr.keys())
48
- fpcheck = all([k in fpattrs for k in ('date', 'cutoff')])
48
+ fpcheck = all([k in fpattrs for k in ("date", "cutoff")])
49
49
  if not fpcheck:
50
- raise ImportError('The "{!s}" class is not compatible with the FlowLogsStack class.'
51
- .format(cls))
50
+ raise ImportError(
51
+ 'The "{!s}" class is not compatible with the FlowLogsStack class.'.format(
52
+ cls
53
+ )
54
+ )
52
55
 
53
56
  def stackedstorage_resource(self):
54
57
  """Use the FlowLogsStack resource for stacked storage."""
55
- return FlowLogsStack(kind='flow_logs', date=self.date, cutoff=self.cutoff), False
58
+ return FlowLogsStack(
59
+ kind="flow_logs", date=self.date, cutoff=self.cutoff
60
+ ), False
56
61
 
57
62
  cls.stackedstorage_resource = stackedstorage_resource
58
63
  return cls
59
64
 
60
65
 
61
66
  @use_flow_logs_stack
62
- @namebuilding_insert('src', lambda s: [s.binary, '-'.join(s.task.split('/')[s.task_start:s.task_stop])])
63
- @namebuilding_insert('compute', lambda s: s.part)
64
- @namebuilding_delete('fmt')
67
+ @namebuilding_insert(
68
+ "src",
69
+ lambda s: [
70
+ s.binary,
71
+ "-".join(s.task.split("/")[s.task_start : s.task_stop]),
72
+ ],
73
+ )
74
+ @namebuilding_insert("compute", lambda s: s.part)
75
+ @namebuilding_delete("fmt")
65
76
  class Listing(FlowResource):
66
77
  """Miscellaneous application output from a task processing."""
78
+
67
79
  _footprint = [
68
80
  dict(
69
- info = 'Listing',
70
- attr = dict(
71
- task = dict(
72
- optional = True,
73
- default = 'anonymous'
74
- ),
75
- task_start = dict(
76
- optional = True,
77
- type = int,
78
- default = -1,
79
- ),
80
- task_stop = dict(
81
- optional = True,
82
- type = int,
83
- default = None,
84
- ),
85
- kind = dict(
86
- values = ['listing']
87
- ),
88
- part = dict(
89
- optional = True,
90
- default = 'all',
91
- ),
92
- binary = dict(
93
- optional = True,
94
- default = '[model]',
95
- ),
96
- clscontents = dict(
97
- default = FormatAdapter,
81
+ info="Listing",
82
+ attr=dict(
83
+ task=dict(optional=True, default="anonymous"),
84
+ task_start=dict(
85
+ optional=True,
86
+ type=int,
87
+ default=-1,
88
+ ),
89
+ task_stop=dict(
90
+ optional=True,
91
+ type=int,
92
+ default=None,
93
+ ),
94
+ kind=dict(values=["listing"]),
95
+ part=dict(
96
+ optional=True,
97
+ default="all",
98
+ ),
99
+ binary=dict(
100
+ optional=True,
101
+ default="[model]",
102
+ ),
103
+ clscontents=dict(
104
+ default=FormatAdapter,
98
105
  ),
99
106
  ),
100
107
  )
@@ -102,11 +109,11 @@ class Listing(FlowResource):
102
109
 
103
110
  @property
104
111
  def realkind(self):
105
- return 'listing'
112
+ return "listing"
106
113
 
107
114
  def olive_basename(self):
108
115
  """Fake basename for getting olive listings"""
109
- if hasattr(self, '_listingpath'):
116
+ if hasattr(self, "_listingpath"):
110
117
  return self._listingpath
111
118
  else:
112
119
  return "NOT_IMPLEMENTED"
@@ -117,39 +124,40 @@ class Listing(FlowResource):
117
124
 
118
125
  class ParallelListing(Listing):
119
126
  """Multi output for parallel MPI and/or OpenMP processing."""
127
+
120
128
  _footprint = [
121
129
  dict(
122
- attr = dict(
123
- kind = dict(
124
- values = ['listing', 'plisting', 'mlisting'],
125
- remap = dict(
126
- listing = 'plisting',
127
- mlisting = 'plisting',
128
- )
129
- ),
130
- mpi = dict(
131
- optional = True,
132
- default = None,
133
- type = FmtInt,
134
- args = dict(fmt = '03'),
135
- ),
136
- openmp = dict(
137
- optional = True,
138
- default = None,
139
- type = FmtInt,
140
- args = dict(fmt = '02'),
141
- ),
142
- seta = dict(
143
- optional = True,
144
- default = None,
145
- type = FmtInt,
146
- args = dict(fmt = '03'),
147
- ),
148
- setb = dict(
149
- optional = True,
150
- default = None,
151
- type = FmtInt,
152
- args = dict(fmt = '02'),
130
+ attr=dict(
131
+ kind=dict(
132
+ values=["listing", "plisting", "mlisting"],
133
+ remap=dict(
134
+ listing="plisting",
135
+ mlisting="plisting",
136
+ ),
137
+ ),
138
+ mpi=dict(
139
+ optional=True,
140
+ default=None,
141
+ type=FmtInt,
142
+ args=dict(fmt="03"),
143
+ ),
144
+ openmp=dict(
145
+ optional=True,
146
+ default=None,
147
+ type=FmtInt,
148
+ args=dict(fmt="02"),
149
+ ),
150
+ seta=dict(
151
+ optional=True,
152
+ default=None,
153
+ type=FmtInt,
154
+ args=dict(fmt="03"),
155
+ ),
156
+ setb=dict(
157
+ optional=True,
158
+ default=None,
159
+ type=FmtInt,
160
+ args=dict(fmt="02"),
153
161
  ),
154
162
  )
155
163
  )
@@ -159,38 +167,34 @@ class ParallelListing(Listing):
159
167
  """From base information of ``listing`` add mpi and openmp values."""
160
168
  info = super().namebuilding_info()
161
169
  if self.mpi and self.openmp:
162
- info['compute'] = [{'mpi': self.mpi}, {'openmp': self.openmp}]
170
+ info["compute"] = [{"mpi": self.mpi}, {"openmp": self.openmp}]
163
171
  if self.seta and self.setb:
164
- info['compute'] = [{'seta': self.seta}, {'setb': self.setb}]
172
+ info["compute"] = [{"seta": self.seta}, {"setb": self.setb}]
165
173
  return info
166
174
 
167
175
 
168
- @namebuilding_insert('src', lambda s: [s.binary, s.task.split('/').pop()])
169
- @namebuilding_insert('compute', lambda s: s.part)
170
- @namebuilding_delete('fmt')
176
+ @namebuilding_insert("src", lambda s: [s.binary, s.task.split("/").pop()])
177
+ @namebuilding_insert("compute", lambda s: s.part)
178
+ @namebuilding_delete("fmt")
171
179
  class StaticListing(Resource):
172
180
  """Miscelanous application output from a task processing, out-of-flow."""
181
+
173
182
  _footprint = [
174
183
  dict(
175
- info = 'Listing',
176
- attr = dict(
177
- task = dict(
178
- optional = True,
179
- default = 'anonymous'
180
- ),
181
- kind = dict(
182
- values = ['staticlisting']
183
- ),
184
- part = dict(
185
- optional = True,
186
- default = 'all',
184
+ info="Listing",
185
+ attr=dict(
186
+ task=dict(optional=True, default="anonymous"),
187
+ kind=dict(values=["staticlisting"]),
188
+ part=dict(
189
+ optional=True,
190
+ default="all",
187
191
  ),
188
- binary = dict(
189
- optional = True,
190
- default = '[model]',
192
+ binary=dict(
193
+ optional=True,
194
+ default="[model]",
191
195
  ),
192
- clscontents = dict(
193
- default = FormatAdapter,
196
+ clscontents=dict(
197
+ default=FormatAdapter,
194
198
  ),
195
199
  ),
196
200
  )
@@ -198,23 +202,33 @@ class StaticListing(Resource):
198
202
 
199
203
  @property
200
204
  def realkind(self):
201
- return 'staticlisting'
202
-
203
-
204
- @namebuilding_insert('compute', lambda s: None if s.mpi is None else [{'mpi': s.mpi}, ],
205
- none_discard=True)
205
+ return "staticlisting"
206
+
207
+
208
+ @namebuilding_insert(
209
+ "compute",
210
+ lambda s: None
211
+ if s.mpi is None
212
+ else [
213
+ {"mpi": s.mpi},
214
+ ],
215
+ none_discard=True,
216
+ )
206
217
  class DrHookListing(Listing):
207
218
  """Output produced by DrHook"""
219
+
208
220
  _footprint = [
209
221
  dict(
210
- attr = dict(
211
- kind = dict(
212
- values = ['drhook', ],
222
+ attr=dict(
223
+ kind=dict(
224
+ values=[
225
+ "drhook",
226
+ ],
213
227
  ),
214
- mpi = dict(
215
- optional = True,
216
- type = FmtInt,
217
- args = dict(fmt = '03'),
228
+ mpi=dict(
229
+ optional=True,
230
+ type=FmtInt,
231
+ args=dict(fmt="03"),
218
232
  ),
219
233
  )
220
234
  )
@@ -222,116 +236,107 @@ class DrHookListing(Listing):
222
236
 
223
237
  @property
224
238
  def realkind(self):
225
- return 'drhookprof'
239
+ return "drhookprof"
226
240
 
227
241
 
228
242
  @use_flow_logs_stack
229
243
  class Beacon(FlowResource):
230
244
  """Output indicating the end of a model run."""
245
+
231
246
  _footprint = [
232
247
  dict(
233
- info = 'Beacon',
234
- attr = dict(
235
- kind = dict(
236
- values = ['beacon']
237
- ),
238
- clscontents = dict(
239
- default = JsonDictContent,
248
+ info="Beacon",
249
+ attr=dict(
250
+ kind=dict(values=["beacon"]),
251
+ clscontents=dict(
252
+ default=JsonDictContent,
240
253
  ),
241
- nativefmt = dict(
242
- default = 'json',
254
+ nativefmt=dict(
255
+ default="json",
243
256
  ),
244
- )
257
+ ),
245
258
  )
246
259
  ]
247
260
 
248
261
  @property
249
262
  def realkind(self):
250
- return 'beacon'
263
+ return "beacon"
251
264
 
252
265
 
253
266
  @use_flow_logs_stack
254
- @namebuilding_insert('src', lambda s: s.task.split('/').pop())
255
- @namebuilding_insert('compute', lambda s: s.scope)
267
+ @namebuilding_insert("src", lambda s: s.task.split("/").pop())
268
+ @namebuilding_insert("compute", lambda s: s.scope)
256
269
  class TaskInfo(FlowResource):
257
270
  """Task informations."""
271
+
258
272
  _footprint = [
259
273
  dict(
260
- info = 'Task informations',
261
- attr = dict(
262
- task = dict(
263
- optional = True,
264
- default = 'anonymous'
274
+ info="Task informations",
275
+ attr=dict(
276
+ task=dict(optional=True, default="anonymous"),
277
+ kind=dict(values=["taskinfo"]),
278
+ scope=dict(
279
+ optional=True,
280
+ default="void",
265
281
  ),
266
- kind = dict(
267
- values = ['taskinfo']
282
+ clscontents=dict(
283
+ default=JsonDictContent,
268
284
  ),
269
- scope = dict(
270
- optional = True,
271
- default = 'void',
285
+ nativefmt=dict(
286
+ default="json",
272
287
  ),
273
- clscontents = dict(
274
- default = JsonDictContent,
275
- ),
276
- nativefmt = dict(
277
- default = 'json',
278
- ),
279
- )
288
+ ),
280
289
  )
281
290
  ]
282
291
 
283
292
  @property
284
293
  def realkind(self):
285
- return 'taskinfo'
294
+ return "taskinfo"
286
295
 
287
296
 
288
- @namebuilding_insert('src', lambda s: s.task.split('/').pop())
289
- @namebuilding_insert('compute', lambda s: s.scope)
290
- @namebuilding_delete('fmt')
297
+ @namebuilding_insert("src", lambda s: s.task.split("/").pop())
298
+ @namebuilding_insert("compute", lambda s: s.scope)
299
+ @namebuilding_delete("fmt")
291
300
  class StaticTaskInfo(Resource):
292
301
  """Task informations."""
302
+
293
303
  _footprint = [
294
304
  dict(
295
- info = 'Task informations',
296
- attr = dict(
297
- task = dict(
298
- optional = True,
299
- default = 'anonymous'
305
+ info="Task informations",
306
+ attr=dict(
307
+ task=dict(optional=True, default="anonymous"),
308
+ kind=dict(values=["statictaskinfo"]),
309
+ scope=dict(
310
+ optional=True,
311
+ default="void",
300
312
  ),
301
- kind = dict(
302
- values = ['statictaskinfo']
313
+ clscontents=dict(
314
+ default=JsonDictContent,
303
315
  ),
304
- scope = dict(
305
- optional = True,
306
- default = 'void',
316
+ nativefmt=dict(
317
+ default="json",
307
318
  ),
308
- clscontents = dict(
309
- default = JsonDictContent,
310
- ),
311
- nativefmt = dict(
312
- default = 'json',
313
- ),
314
- )
319
+ ),
315
320
  )
316
321
  ]
317
322
 
318
323
  @property
319
324
  def realkind(self):
320
- return 'statictaskinfo'
325
+ return "statictaskinfo"
321
326
 
322
327
 
323
328
  class SectionsSlice(collections.abc.Sequence):
324
329
  """Hold a list of dictionaries representing Sections."""
325
330
 
326
- _INDEX_PREFIX = 'sslice'
327
- _INDEX_ATTR = 'sliceindex'
331
+ _INDEX_PREFIX = "sslice"
332
+ _INDEX_ATTR = "sliceindex"
328
333
 
329
334
  def __init__(self, sequence):
330
335
  self._data = sequence
331
336
 
332
337
  def __getitem__(self, i):
333
338
  if isinstance(i, str) and i.startswith(self._INDEX_PREFIX):
334
- i = int(i[len(self._INDEX_PREFIX):])
339
+ i = int(i[len(self._INDEX_PREFIX) :])
335
340
  return self._data[i]
336
341
 
337
342
  def __eq__(self, other):
@@ -361,23 +366,26 @@ class SectionsSlice(collections.abc.Sequence):
361
366
  'resource', 'provider' and 'container' parts of the 'rh'sub-dictionary
362
367
  are also looked for.
363
368
  """
364
- if k == 'role':
365
- return item[k] or item['alternate']
366
- elif k == 'kind' and k in item.get('rh', dict()).get('resource', dict()):
367
- return item['rh']['resource'][k]
368
- elif k == 'section_kind' and 'kind' in item:
369
- return item['kind']
369
+ if k == "role":
370
+ return item[k] or item["alternate"]
371
+ elif k == "kind" and k in item.get("rh", dict()).get(
372
+ "resource", dict()
373
+ ):
374
+ return item["rh"]["resource"][k]
375
+ elif k == "section_kind" and "kind" in item:
376
+ return item["kind"]
370
377
  elif k in item:
371
378
  return item[k]
372
- elif k in item.get('rh', dict()).get('resource', dict()):
373
- return item['rh']['resource'][k]
374
- elif k in item.get('rh', dict()).get('provider', dict()):
375
- return item['rh']['provider'][k]
376
- elif k in item.get('rh', dict()).get('container', dict()):
377
- return item['rh']['container'][k]
379
+ elif k in item.get("rh", dict()).get("resource", dict()):
380
+ return item["rh"]["resource"][k]
381
+ elif k in item.get("rh", dict()).get("provider", dict()):
382
+ return item["rh"]["provider"][k]
383
+ elif k in item.get("rh", dict()).get("container", dict()):
384
+ return item["rh"]["container"][k]
378
385
  else:
379
- raise KeyError("'{:s}' wasn't found in the designated dictionary"
380
- .format(k))
386
+ raise KeyError(
387
+ "'{:s}' wasn't found in the designated dictionary".format(k)
388
+ )
381
389
 
382
390
  @staticmethod
383
391
  def _sloppy_compare(json_v, v):
@@ -398,20 +406,22 @@ class SectionsSlice(collections.abc.Sequence):
398
406
 
399
407
  def _sloppy_ckeck(self, item, k, v, extras):
400
408
  """Perform a _sloppy_lookup and check the result against *v*."""
401
- if k in ('role', 'alternate'):
409
+ if k in ("role", "alternate"):
402
410
  v = setrole(v)
403
411
  try:
404
- if k == 'baseterm':
405
- found = self._sloppy_lookup(item, 'term')
406
- foundbis = self._sloppy_lookup(item, 'date')
412
+ if k == "baseterm":
413
+ found = self._sloppy_lookup(item, "term")
414
+ foundbis = self._sloppy_lookup(item, "date")
407
415
  else:
408
416
  found = self._sloppy_lookup(item, k)
409
417
  except KeyError:
410
418
  return False
411
419
  if not isinstance(v, (list, tuple, set)):
412
- v = [v, ]
413
- if k == 'baseterm' and extras.get('basedate', None):
414
- delta = (Date(extras['basedate']) - Date(foundbis))
420
+ v = [
421
+ v,
422
+ ]
423
+ if k == "baseterm" and extras.get("basedate", None):
424
+ delta = Date(extras["basedate"]) - Date(foundbis)
415
425
  found = Time(found) - delta
416
426
  return any([self._sloppy_compare(found, a_v) for a_v in v])
417
427
 
@@ -423,10 +433,17 @@ class SectionsSlice(collections.abc.Sequence):
423
433
  >>> self.filter(role='Guess', member=1)
424
434
  """
425
435
  extras = dict()
426
- extras['basedate'] = kwargs.pop('basedate', None)
427
- newslice = [s for s in self
428
- if all([self._sloppy_ckeck(s, k, v, extras)
429
- for k, v in kwargs.items()])]
436
+ extras["basedate"] = kwargs.pop("basedate", None)
437
+ newslice = [
438
+ s
439
+ for s in self
440
+ if all(
441
+ [
442
+ self._sloppy_ckeck(s, k, v, extras)
443
+ for k, v in kwargs.items()
444
+ ]
445
+ )
446
+ ]
430
447
  return self.__class__(newslice)
431
448
 
432
449
  def uniquefilter(self, **kwargs):
@@ -442,7 +459,9 @@ class SectionsSlice(collections.abc.Sequence):
442
459
  @property
443
460
  def indexes(self):
444
461
  """Returns an index list of all the element contained if the present object."""
445
- return [self._INDEX_PREFIX + '{:d}'.format(i) for i in range(len(self))]
462
+ return [
463
+ self._INDEX_PREFIX + "{:d}".format(i) for i in range(len(self))
464
+ ]
446
465
 
447
466
  def __deepcopy__(self, memo):
448
467
  newslice = self.__class__(self._data)
@@ -465,27 +484,40 @@ class SectionsSlice(collections.abc.Sequence):
465
484
  be generated using the :meth:`indexes` property), the corresponding element
466
485
  will be searched using :meth:`_sloppy_lookup`.
467
486
  """.format(idx_attr=self._INDEX_ATTR)
468
- if attr.startswith('__'):
487
+ if attr.startswith("__"):
469
488
  raise AttributeError(attr)
470
489
  if len(self) == 1:
471
490
  try:
472
491
  return self._sloppy_lookup(self[0], attr)
473
492
  except KeyError:
474
- raise AttributeError("'{:s}' wasn't found in the unique dictionary"
475
- .format(attr))
493
+ raise AttributeError(
494
+ "'{:s}' wasn't found in the unique dictionary".format(attr)
495
+ )
476
496
  elif len(self) == 0:
477
- raise AttributeError("The current SectionsSlice is empty. No attribute lookup allowed !")
497
+ raise AttributeError(
498
+ "The current SectionsSlice is empty. No attribute lookup allowed !"
499
+ )
478
500
  else:
501
+
479
502
  def _attr_lookup(g, x):
480
- if len(self) > 1 and (self._INDEX_ATTR in g or self._INDEX_ATTR in x):
503
+ if len(self) > 1 and (
504
+ self._INDEX_ATTR in g or self._INDEX_ATTR in x
505
+ ):
481
506
  idx = g.get(self._INDEX_ATTR, x.get(self._INDEX_ATTR))
482
507
  try:
483
508
  return self._sloppy_lookup(self[idx], attr)
484
509
  except KeyError:
485
- raise AttributeError("'{:s}' wasn't found in the {!s}-th dictionary"
486
- .format(attr, idx))
510
+ raise AttributeError(
511
+ "'{:s}' wasn't found in the {!s}-th dictionary".format(
512
+ attr, idx
513
+ )
514
+ )
487
515
  else:
488
- raise AttributeError("A '{:s}' attribute must be there !".format(self._INDEX_ATTR))
516
+ raise AttributeError(
517
+ "A '{:s}' attribute must be there !".format(
518
+ self._INDEX_ATTR
519
+ )
520
+ )
489
521
 
490
522
  return _attr_lookup
491
523
 
@@ -518,7 +550,7 @@ class SectionsJsonListContent(DataContent):
518
550
 
519
551
 
520
552
  @use_flow_logs_stack
521
- @namebuilding_insert('src', lambda s: s.task.split('/').pop())
553
+ @namebuilding_insert("src", lambda s: s.task.split("/").pop())
522
554
  class SectionsList(FlowResource):
523
555
  """Class to handle a resource that contains a list of Sections in JSON format.
524
556
 
@@ -527,23 +559,24 @@ class SectionsList(FlowResource):
527
559
  """
528
560
 
529
561
  _footprint = dict(
530
- info = 'A Sections List',
531
- attr = dict(
562
+ info="A Sections List",
563
+ attr=dict(
532
564
  kind=dict(
533
- values=['sectionslist', ],
565
+ values=[
566
+ "sectionslist",
567
+ ],
534
568
  ),
535
- task = dict(
536
- optional = True,
537
- default = 'anonymous'
569
+ task=dict(optional=True, default="anonymous"),
570
+ clscontents=dict(
571
+ default=SectionsJsonListContent,
538
572
  ),
539
- clscontents = dict(
540
- default = SectionsJsonListContent,
573
+ nativefmt=dict(
574
+ values=[
575
+ "json",
576
+ ],
577
+ default="json",
541
578
  ),
542
- nativefmt = dict(
543
- values = ['json', ],
544
- default = 'json',
545
- )
546
- )
579
+ ),
547
580
  )
548
581
 
549
582
  @property