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.
Files changed (146) hide show
  1. vortex/__init__.py +135 -0
  2. vortex/algo/__init__.py +12 -0
  3. vortex/algo/components.py +2136 -0
  4. vortex/algo/mpitools.py +1648 -0
  5. vortex/algo/mpitools_templates/envelope_wrapper_default.tpl +27 -0
  6. vortex/algo/mpitools_templates/envelope_wrapper_mpiauto.tpl +29 -0
  7. vortex/algo/mpitools_templates/wrapstd_wrapper_default.tpl +18 -0
  8. vortex/algo/serversynctools.py +170 -0
  9. vortex/config.py +115 -0
  10. vortex/data/__init__.py +13 -0
  11. vortex/data/abstractstores.py +1572 -0
  12. vortex/data/containers.py +780 -0
  13. vortex/data/contents.py +596 -0
  14. vortex/data/executables.py +284 -0
  15. vortex/data/flow.py +113 -0
  16. vortex/data/geometries.ini +2689 -0
  17. vortex/data/geometries.py +703 -0
  18. vortex/data/handlers.py +1021 -0
  19. vortex/data/outflow.py +67 -0
  20. vortex/data/providers.py +465 -0
  21. vortex/data/resources.py +201 -0
  22. vortex/data/stores.py +1271 -0
  23. vortex/gloves.py +282 -0
  24. vortex/layout/__init__.py +27 -0
  25. vortex/layout/appconf.py +109 -0
  26. vortex/layout/contexts.py +511 -0
  27. vortex/layout/dataflow.py +1069 -0
  28. vortex/layout/jobs.py +1276 -0
  29. vortex/layout/monitor.py +833 -0
  30. vortex/layout/nodes.py +1424 -0
  31. vortex/layout/subjobs.py +464 -0
  32. vortex/nwp/__init__.py +11 -0
  33. vortex/nwp/algo/__init__.py +12 -0
  34. vortex/nwp/algo/assim.py +483 -0
  35. vortex/nwp/algo/clim.py +920 -0
  36. vortex/nwp/algo/coupling.py +609 -0
  37. vortex/nwp/algo/eda.py +632 -0
  38. vortex/nwp/algo/eps.py +613 -0
  39. vortex/nwp/algo/forecasts.py +745 -0
  40. vortex/nwp/algo/fpserver.py +927 -0
  41. vortex/nwp/algo/ifsnaming.py +403 -0
  42. vortex/nwp/algo/ifsroot.py +311 -0
  43. vortex/nwp/algo/monitoring.py +202 -0
  44. vortex/nwp/algo/mpitools.py +554 -0
  45. vortex/nwp/algo/odbtools.py +974 -0
  46. vortex/nwp/algo/oopsroot.py +735 -0
  47. vortex/nwp/algo/oopstests.py +186 -0
  48. vortex/nwp/algo/request.py +579 -0
  49. vortex/nwp/algo/stdpost.py +1285 -0
  50. vortex/nwp/data/__init__.py +12 -0
  51. vortex/nwp/data/assim.py +392 -0
  52. vortex/nwp/data/boundaries.py +261 -0
  53. vortex/nwp/data/climfiles.py +539 -0
  54. vortex/nwp/data/configfiles.py +149 -0
  55. vortex/nwp/data/consts.py +929 -0
  56. vortex/nwp/data/ctpini.py +133 -0
  57. vortex/nwp/data/diagnostics.py +181 -0
  58. vortex/nwp/data/eda.py +148 -0
  59. vortex/nwp/data/eps.py +383 -0
  60. vortex/nwp/data/executables.py +1039 -0
  61. vortex/nwp/data/fields.py +96 -0
  62. vortex/nwp/data/gridfiles.py +308 -0
  63. vortex/nwp/data/logs.py +551 -0
  64. vortex/nwp/data/modelstates.py +334 -0
  65. vortex/nwp/data/monitoring.py +220 -0
  66. vortex/nwp/data/namelists.py +644 -0
  67. vortex/nwp/data/obs.py +748 -0
  68. vortex/nwp/data/oopsexec.py +72 -0
  69. vortex/nwp/data/providers.py +182 -0
  70. vortex/nwp/data/query.py +217 -0
  71. vortex/nwp/data/stores.py +147 -0
  72. vortex/nwp/data/surfex.py +338 -0
  73. vortex/nwp/syntax/__init__.py +9 -0
  74. vortex/nwp/syntax/stdattrs.py +375 -0
  75. vortex/nwp/tools/__init__.py +10 -0
  76. vortex/nwp/tools/addons.py +35 -0
  77. vortex/nwp/tools/agt.py +55 -0
  78. vortex/nwp/tools/bdap.py +48 -0
  79. vortex/nwp/tools/bdcp.py +38 -0
  80. vortex/nwp/tools/bdm.py +21 -0
  81. vortex/nwp/tools/bdmp.py +49 -0
  82. vortex/nwp/tools/conftools.py +1311 -0
  83. vortex/nwp/tools/drhook.py +62 -0
  84. vortex/nwp/tools/grib.py +268 -0
  85. vortex/nwp/tools/gribdiff.py +99 -0
  86. vortex/nwp/tools/ifstools.py +163 -0
  87. vortex/nwp/tools/igastuff.py +249 -0
  88. vortex/nwp/tools/mars.py +56 -0
  89. vortex/nwp/tools/odb.py +548 -0
  90. vortex/nwp/tools/partitioning.py +234 -0
  91. vortex/nwp/tools/satrad.py +56 -0
  92. vortex/nwp/util/__init__.py +6 -0
  93. vortex/nwp/util/async.py +184 -0
  94. vortex/nwp/util/beacon.py +40 -0
  95. vortex/nwp/util/diffpygram.py +359 -0
  96. vortex/nwp/util/ens.py +198 -0
  97. vortex/nwp/util/hooks.py +128 -0
  98. vortex/nwp/util/taskdeco.py +81 -0
  99. vortex/nwp/util/usepygram.py +591 -0
  100. vortex/nwp/util/usetnt.py +87 -0
  101. vortex/proxy.py +6 -0
  102. vortex/sessions.py +341 -0
  103. vortex/syntax/__init__.py +9 -0
  104. vortex/syntax/stdattrs.py +628 -0
  105. vortex/syntax/stddeco.py +176 -0
  106. vortex/toolbox.py +982 -0
  107. vortex/tools/__init__.py +11 -0
  108. vortex/tools/actions.py +457 -0
  109. vortex/tools/addons.py +297 -0
  110. vortex/tools/arm.py +76 -0
  111. vortex/tools/compression.py +322 -0
  112. vortex/tools/date.py +20 -0
  113. vortex/tools/ddhpack.py +10 -0
  114. vortex/tools/delayedactions.py +672 -0
  115. vortex/tools/env.py +513 -0
  116. vortex/tools/folder.py +663 -0
  117. vortex/tools/grib.py +559 -0
  118. vortex/tools/lfi.py +746 -0
  119. vortex/tools/listings.py +354 -0
  120. vortex/tools/names.py +575 -0
  121. vortex/tools/net.py +1790 -0
  122. vortex/tools/odb.py +10 -0
  123. vortex/tools/parallelism.py +336 -0
  124. vortex/tools/prestaging.py +186 -0
  125. vortex/tools/rawfiles.py +10 -0
  126. vortex/tools/schedulers.py +413 -0
  127. vortex/tools/services.py +871 -0
  128. vortex/tools/storage.py +1061 -0
  129. vortex/tools/surfex.py +61 -0
  130. vortex/tools/systems.py +3396 -0
  131. vortex/tools/targets.py +384 -0
  132. vortex/util/__init__.py +9 -0
  133. vortex/util/config.py +1071 -0
  134. vortex/util/empty.py +24 -0
  135. vortex/util/helpers.py +184 -0
  136. vortex/util/introspection.py +63 -0
  137. vortex/util/iosponge.py +76 -0
  138. vortex/util/roles.py +51 -0
  139. vortex/util/storefunctions.py +103 -0
  140. vortex/util/structs.py +26 -0
  141. vortex/util/worker.py +150 -0
  142. vortex_nwp-2.0.0b1.dist-info/LICENSE +517 -0
  143. vortex_nwp-2.0.0b1.dist-info/METADATA +50 -0
  144. vortex_nwp-2.0.0b1.dist-info/RECORD +146 -0
  145. vortex_nwp-2.0.0b1.dist-info/WHEEL +5 -0
  146. vortex_nwp-2.0.0b1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,628 @@
1
+ """
2
+ This module provides some pre-defined attributes descriptions or combined sets
3
+ of attributes description that could be used in the footprint definition of any
4
+ class which follow the :class:`footprints.Footprint` syntax.
5
+ """
6
+
7
+ import copy
8
+ import re
9
+
10
+ import footprints
11
+ from bronx.stdtypes.date import Date, Month, Time
12
+ from bronx.syntax.decorators import secure_getattr
13
+ from bronx.system import hash as hashutils
14
+ from vortex.tools import env
15
+
16
+ from .stddeco import generic_pathname_insert, namebuilding_append, namebuilding_insert
17
+
18
+ #: Export a set of attributes :data:`a_model`, :data:`a_date`, etc..
19
+ __all__ = [
20
+ 'a_xpid', 'a_month', 'a_domain', 'a_truncation', 'a_model', 'a_member',
21
+ 'a_date', 'a_cutoff', 'a_term', 'a_nativefmt', 'a_actualfmt', 'a_suite',
22
+ 'a_namespace', 'a_hashalgo', 'a_compressionpipeline', 'a_block', 'a_number'
23
+ ]
24
+
25
+ #: Possible values for the *model* attribute.
26
+ models = {
27
+ 'arpege', 'arp', 'arp_court', 'aladin', 'ald', 'arome', 'aro', 'aearp', 'pearp', 'mocage',
28
+ 'mesonh', 'surfex', 'hycom', 'psy4', 'mercator_global', 'glo12', 'safran', 'ifs', 'aroifs', 'cifs',
29
+ 'mfwam', 'pg1', 'alpha', 'eps', 'postproc', 'ww3', 'sympo', 'psym', 'petaroute', 'promethee',
30
+ 'hycom3d', 'croco', 'alaro', 'harmoniearome', 'nemo', 'oasis',
31
+ }
32
+
33
+ #: Possible values for the most common binaries.
34
+ binaries = {
35
+ 'arpege', 'aladin', 'arome', 'aromeom_common', 'batodb', 'peace', 'mocage', 'sumo',
36
+ 'corromegasurf', 'mesonh', 'safran', 'surfex', 'macc', 'mktopbd', 'ifs', 'oops',
37
+ 'assistance', 'arpifs', 'mfwam', 'mfwam_interp', 'mfwam_interpbc', 'ww3', 'ww3_prnc',
38
+ 'ww3_bound', 'ww3_ncgrb', 'ial', 'alaro', 'harmoniearome', 'nemo', 'oasis', 'arobase',
39
+ 'xios',
40
+ }
41
+
42
+ #: Possible values for the most common utility programs.
43
+ utilities = {'batodb'}
44
+
45
+ #: Known formats
46
+ knownfmt = {
47
+ 'auto', 'autoconfig', 'unknown', 'foo', 'arpifslist', 'bdmbufr_listing', 'ascii', 'txt',
48
+ 'json', 'fa', 'lfi', 'lfa', 'netcdf', 'grib', 'grib1', 'grib2', 'bufr', 'hdf5', 'obsoul',
49
+ 'odb', 'ecma', 'ccma', 'bullx', 'sx', 'ddhpack', 'tar', 'tgz', 'rawfiles', 'binary', 'bin',
50
+ 'obslocationpack', 'obsfirepack', 'wbcpack', 'geo', 'nam', 'png', 'pdf', 'dir/hdr', 'yml',
51
+ 'yaml', 'ini'
52
+ }
53
+
54
+ #: Default attributes excluded from `repr` display
55
+ notinrepr = {'kind', 'unknown', 'clscontents', 'gvar', 'nativefmt'}
56
+
57
+
58
+ class DelayedEnvValue:
59
+ """
60
+ Store an environment variable name and compute its value when needed,
61
+ *e.g.* in a footprint evaluation.
62
+ """
63
+
64
+ def __init__(self, varname, default=None, refresh=False):
65
+ self.varname = varname
66
+ self.default = default
67
+ self.refresh = refresh
68
+ self._value = None
69
+ self._frozen = False
70
+
71
+ def as_dump(self):
72
+ return 'varname={},default={}'.format(self.varname, self.default)
73
+
74
+ def footprint_value(self):
75
+ """
76
+ Return the actual env value of the ``varname`` variable.
77
+ Optional argument ``refresh`` set to ``True`` do not store this value.
78
+ """
79
+ if not self._frozen:
80
+ self._value = env.current().get(self.varname, self.default)
81
+ if not self.refresh:
82
+ self._frozen = True
83
+ return self._value
84
+
85
+ def export_dict(self):
86
+ """The pure dict/json value is the actual value."""
87
+ return self.footprint_value()
88
+
89
+
90
+ class DelayedInit:
91
+ """
92
+ Delays the proxied object creation until it's actually accessed.
93
+ *e.g.* in a footprint evaluation.
94
+ """
95
+
96
+ def __init__(self, proxied, initializer):
97
+ self.__proxied = proxied
98
+ self.__initializer = initializer
99
+
100
+ @secure_getattr
101
+ def __getattr__(self, name):
102
+ if self.__proxied is None:
103
+ self.__proxied = self.__initializer()
104
+ return getattr(self.__proxied, name)
105
+
106
+ def __repr__(self):
107
+ orig = re.sub('^<(.*)>$', r'\1', super().__repr__())
108
+ return '<{:s} | proxied={:s}>'.format(orig,
109
+ 'Not yet Initialised' if self.__proxied is None
110
+ else repr(self.__proxied))
111
+
112
+ def __str__(self):
113
+ return repr(self) if self.__proxied is None else str(self.__proxied)
114
+
115
+
116
+ class FmtInt(int):
117
+ """Formated integer."""
118
+
119
+ def __new__(cls, value, fmt='02'):
120
+ obj = int.__new__(cls, value)
121
+ obj._fmt = fmt
122
+ return obj
123
+
124
+ def __str__(self):
125
+ return '{0:{fmt}d}'.format(self.__int__(), fmt=self._fmt)
126
+
127
+ def export_dict(self):
128
+ """The pure dict/json output is the raw integer"""
129
+ return int(self)
130
+
131
+ def nice(self, value):
132
+ """Returns the specified ``value`` with the format of the current object."""
133
+ return '{0:{fmt}d}'.format(value, fmt=self._fmt)
134
+
135
+
136
+ class XPid(str):
137
+ """Basestring wrapper for experiment ids (abstract)."""
138
+ pass
139
+
140
+
141
+ class LegacyXPid(XPid):
142
+ """Basestring wrapper for experiment ids (Olive/Oper convention)."""
143
+
144
+ def __new__(cls, value):
145
+ if len(value) != 4 or '@' in value:
146
+ raise ValueError('XPid should be a 4 digits string')
147
+ return str.__new__(cls, value.upper())
148
+
149
+ def isoper(self):
150
+ """Return true if current value looks like an op id."""
151
+ return str(self) in opsuites
152
+
153
+
154
+ class FreeXPid(XPid):
155
+ """Basestring wrapper for experiment ids (User defined)."""
156
+
157
+ _re_valid = re.compile(r'^\S+@[-\w]+$')
158
+
159
+ def __new__(cls, value):
160
+ if not cls._re_valid.match(value):
161
+ raise ValueError('XPid should be something like "id@location" (not "{:s}")'
162
+ .format(value))
163
+ return str.__new__(cls, value)
164
+
165
+ @property
166
+ def id(self):
167
+ return self.split('@')[0]
168
+
169
+ @property
170
+ def location(self):
171
+ return self.split('@')[1]
172
+
173
+
174
+ def any_vortex_xpid(xpidguess):
175
+ """Try to reclass *xpidquess* as a Legacy or Free XPid"""
176
+ try:
177
+ try:
178
+ xp = LegacyXPid(xpidguess)
179
+ except ValueError:
180
+ xp = FreeXPid(xpidguess)
181
+ except ValueError:
182
+ raise ValueError("'{:s}' could not be reclassed as a LegacyXPid or a FreeXPid")
183
+ return xp
184
+
185
+
186
+ #: The list of operational experiment names.
187
+ opsuites = {LegacyXPid(x) for x in (['OPER', 'DBLE', 'TEST', 'MIRR'] +
188
+ ['OP{:02d}'.format(i) for i in range(100)])}
189
+
190
+ #: The list of experiemnt names dedicated to Vortex' demos
191
+ demosuites = {LegacyXPid('DEMO'), LegacyXPid('DREF')}
192
+
193
+
194
+ class Namespace(str):
195
+ """Basestring wrapper for namespaces (as net domains)."""
196
+
197
+ def __new__(cls, value):
198
+ value = value.lower()
199
+ full = value
200
+ if '@' in value:
201
+ netuser, value = value.split('@')
202
+ if ':' in netuser:
203
+ netuser, netpass = netuser.split(':')
204
+ else:
205
+ netpass = None
206
+ else:
207
+ netuser, netpass = None, None
208
+ if ':' in value:
209
+ value, port = value.split(':')
210
+ else:
211
+ port = None
212
+ if 0 < value.count('.') < 2:
213
+ raise ValueError('Namespace should contain one or at least 3 fields')
214
+ thisns = str.__new__(cls, value)
215
+ thisns._port = int(port) if port else None
216
+ thisns._user = netuser
217
+ thisns._pass = netpass
218
+ thisns._full = full
219
+ return thisns
220
+
221
+ @property
222
+ def firstname(self):
223
+ return self.split('.', 1)[0]
224
+
225
+ @property
226
+ def domain(self):
227
+ if '.' in self.netloc:
228
+ return self.split('.', 1)[1]
229
+ else:
230
+ return self.netloc
231
+
232
+ @property
233
+ def netuser(self):
234
+ return self._user
235
+
236
+ @property
237
+ def netpass(self):
238
+ return self._pass
239
+
240
+ @property
241
+ def netport(self):
242
+ return self._port
243
+
244
+ @property
245
+ def netloc(self):
246
+ return self._full
247
+
248
+
249
+ class Latitude(float):
250
+ """Bounded floating point value with N-S nice representation."""
251
+
252
+ def __new__(cls, value):
253
+ value = str(value).lower()
254
+ if value.endswith('n'):
255
+ value = value[:-1]
256
+ elif value.endswith('s'):
257
+ value = value[:-1]
258
+ if not value.startswith('-'):
259
+ value = '-' + value
260
+ if not -90 <= float(value) <= 90:
261
+ raise ValueError('Latitude out of bounds: ' + value)
262
+ return float.__new__(cls, value)
263
+
264
+ def nice(self):
265
+ ns = 'N' if self >= 0 else 'S'
266
+ return str(self).strip('-') + ns
267
+
268
+ @property
269
+ def hemisphere(self):
270
+ return 'North' if self >= 0 else 'South'
271
+
272
+
273
+ class Longitude(float):
274
+ """Bounded floating point value with E-W nice representation."""
275
+
276
+ def __new__(cls, value):
277
+ value = str(value).lower()
278
+ if value.endswith('e'):
279
+ value = value[:-1]
280
+ elif value.endswith('w'):
281
+ value = value[:-1]
282
+ if not value.startswith('-'):
283
+ value = '-' + value
284
+ if not -180 <= float(value) <= 180:
285
+ raise ValueError('Longitude out of bounds: ' + value)
286
+ return float.__new__(cls, value)
287
+
288
+ def nice(self):
289
+ ns = 'E' if self >= 0 else 'W'
290
+ return str(self).strip('-') + ns
291
+
292
+ @property
293
+ def hemisphere(self):
294
+ return 'East' if self >= 0 else 'West'
295
+
296
+
297
+ # predefined attributes
298
+
299
+ #: Usual definition for the ``xpid`` (*e.g.* experiment name).
300
+ a_xpid = dict(
301
+ info="The experiment's identifier.",
302
+ type=XPid,
303
+ optional=False,
304
+ )
305
+
306
+ xpid = footprints.Footprint(info='Abstract experiment id',
307
+ attr=dict(experiment=a_xpid))
308
+
309
+ #: Usual definition for an Olive/Oper ``xpid`` (*e.g.* experiment name).
310
+ a_legacy_xpid = copy.copy(a_xpid)
311
+ a_legacy_xpid['type'] = LegacyXPid
312
+
313
+ legacy_xpid = footprints.Footprint(info='Abstract experiment id',
314
+ attr=dict(experiment=a_legacy_xpid))
315
+
316
+ #: Usual definition for a user-defined ``xpid`` (*e.g.* experiment name).
317
+ a_free_xpid = copy.copy(a_xpid)
318
+ a_free_xpid['type'] = FreeXPid
319
+
320
+ free_xpid = footprints.Footprint(info='Abstract experiment id',
321
+ attr=dict(experiment=a_free_xpid))
322
+
323
+ #: Usual definition of the ``nativefmt`` attribute.
324
+ a_nativefmt = dict(
325
+ info="The resource's storage format.",
326
+ optional=True,
327
+ default='foo',
328
+ values=knownfmt,
329
+ remap=dict(auto='foo'),
330
+ )
331
+
332
+ nativefmt = footprints.Footprint(info='Native format', attr=dict(nativefmt=a_nativefmt))
333
+
334
+
335
+ def _namebuilding_insert_nativefmt(cls):
336
+
337
+ if hasattr(cls, 'namebuilding_info'):
338
+ original_namebuilding_info = cls.namebuilding_info
339
+
340
+ def namebuilding_info(self):
341
+ vinfo = original_namebuilding_info(self)
342
+ ext_remap = getattr(self, '_extension_remap', dict())
343
+ ext_value = ext_remap.get(self.nativefmt, self.nativefmt)
344
+ if ext_value is not None:
345
+ vinfo.setdefault('fmt', ext_remap.get(self.nativefmt, self.nativefmt))
346
+ return vinfo
347
+
348
+ namebuilding_info.__doc__ = original_namebuilding_info.__doc__
349
+ cls.namebuilding_info = namebuilding_info
350
+
351
+ return cls
352
+
353
+
354
+ nativefmt_deco = footprints.DecorativeFootprint(
355
+ nativefmt,
356
+ decorator=[_namebuilding_insert_nativefmt,
357
+ generic_pathname_insert('nativefmt', lambda self: self.nativefmt, setdefault=True)])
358
+
359
+ #: Usual definition of the ``actualfmt`` attribute.
360
+ a_actualfmt = dict(
361
+ info="The resource's format.",
362
+ optional=True,
363
+ default='[nativefmt#unknown]',
364
+ alias=('format',),
365
+ values=knownfmt,
366
+ remap=dict(auto='foo'),
367
+ )
368
+
369
+ actualfmt = footprints.Footprint(info='Actual data format', attr=dict(actualfmt=a_actualfmt))
370
+
371
+ #: Usual definition of the ``cutoff`` attribute.
372
+ a_cutoff = dict(
373
+ info="The cutoff type of the generating process.",
374
+ optional=False,
375
+ alias=('cut',),
376
+ values=[
377
+ 'a', 'assim', 'assimilation', 'long',
378
+ 'p', 'prod', 'production', 'short'
379
+ ],
380
+ remap=dict(
381
+ a='assim',
382
+ p='production',
383
+ prod='production',
384
+ long='assim',
385
+ assimilation='assim'
386
+ )
387
+ )
388
+
389
+ cutoff = footprints.Footprint(info='Abstract cutoff', attr=dict(cutoff=a_cutoff))
390
+
391
+ cutoff_deco = footprints.DecorativeFootprint(
392
+ cutoff,
393
+ decorator=[namebuilding_append('flow',
394
+ lambda self: None if self.cutoff is None else {'shortcutoff': self.cutoff},
395
+ none_discard=True),
396
+ generic_pathname_insert('cutoff', lambda self: self.cutoff, setdefault=True)])
397
+
398
+ #: Usual definition of the ``model`` attribute.
399
+ a_model = dict(
400
+ info="The model name (from a source code perspective).",
401
+ alias=('turtle',),
402
+ optional=False,
403
+ values=models,
404
+ remap=dict(
405
+ arp='arpege',
406
+ ald='aladin',
407
+ aro='arome'
408
+ ),
409
+ )
410
+
411
+ model = footprints.Footprint(info='Abstract model', attr=dict(model=a_model))
412
+
413
+ model_deco = footprints.DecorativeFootprint(
414
+ model,
415
+ decorator=[namebuilding_append('src', lambda self: [self.model, ]),
416
+ generic_pathname_insert('model', lambda self: self.model, setdefault=True)])
417
+
418
+ #: Usual definition of the ``date`` attribute.
419
+ a_date = dict(
420
+ info="The generating process run date.",
421
+ type=Date,
422
+ optional=False,
423
+ )
424
+
425
+ date = footprints.Footprint(info='Abstract date', attr=dict(date=a_date))
426
+
427
+ date_deco = footprints.DecorativeFootprint(
428
+ date,
429
+ decorator=[namebuilding_append('flow', lambda self: {'date': self.date}),
430
+ generic_pathname_insert('date', lambda self: self.date, setdefault=True)])
431
+
432
+ #: Usual definition of the ``begindate`` and ``enddate`` attributes.
433
+
434
+ dateperiod = footprints.Footprint(info='Abstract date period',
435
+ attr=dict(begindate=dict(info="The resource's begin date.",
436
+ type=Date,
437
+ optional=False),
438
+ enddate=dict(info="The resource's end date.",
439
+ type=Date,
440
+ optional=False),
441
+ ))
442
+
443
+ dateperiod_deco = footprints.DecorativeFootprint(
444
+ dateperiod,
445
+ decorator=[namebuilding_append('flow',
446
+ lambda self: [{'begindate': self.begindate},
447
+ {'enddate': self.enddate}]),
448
+ generic_pathname_insert('begindate', lambda self: self.begindate, setdefault=True),
449
+ generic_pathname_insert('enddate', lambda self: self.enddate, setdefault=True)])
450
+
451
+ #: Usual definition of the ``month`` attribute.
452
+ a_month = dict(
453
+ info="The generating process run month.",
454
+ type=Month,
455
+ args=dict(year=0),
456
+ optional=False,
457
+ values=range(1, 13)
458
+ )
459
+
460
+ month = footprints.Footprint(info='Abstract month', attr=dict(month=a_month))
461
+
462
+
463
+ def _add_month2gget_basename(cls):
464
+ """Decorator that appends the month's number at the end of the gget_basename"""
465
+ original_gget_basename = getattr(cls, 'gget_basename', None)
466
+ if original_gget_basename is not None:
467
+
468
+ def gget_basename(self):
469
+ """GGET specific naming convention."""
470
+ b_dict = original_gget_basename(self)
471
+ b_dict['suffix'] = b_dict.get('suffix', '') + '.m{!s}'.format(self.month)
472
+ return b_dict
473
+
474
+ cls.gget_basename = gget_basename
475
+ return cls
476
+
477
+
478
+ def _add_month2olive_basename(cls):
479
+ """Decorator that appends the month's number at the end of the olive_basename."""
480
+ original_olive_basename = getattr(cls, 'olive_basename', None)
481
+ if original_olive_basename is not None:
482
+
483
+ def olive_basename(self):
484
+ """GGET specific naming convention."""
485
+ return original_olive_basename(self) + '.{!s}'.format(self.month)
486
+
487
+ cls.olive_basename = olive_basename
488
+ return cls
489
+
490
+
491
+ month_deco = footprints.DecorativeFootprint(
492
+ month,
493
+ decorator=[namebuilding_append('suffix', lambda self: {'month': self.month}),
494
+ _add_month2gget_basename, _add_month2olive_basename])
495
+
496
+ #: Usual definition of the ``truncation`` attribute.
497
+ a_truncation = dict(
498
+ info="The resource's truncation.",
499
+ type=int,
500
+ optional=False,
501
+ )
502
+
503
+ truncation = footprints.Footprint(info='Abstract truncation', attr=dict(truncation=a_truncation))
504
+
505
+ #: Usual definition of the ``domain`` attribute.
506
+ a_domain = dict(
507
+ info="The resource's geographical domain.",
508
+ optional=False,
509
+ )
510
+
511
+ domain = footprints.Footprint(info='Abstract domain', attr=dict(domain=a_domain))
512
+
513
+ #: Usual definition of the ``term`` attribute.
514
+ a_term = dict(
515
+ info="The resource's forecast term.",
516
+ type=Time,
517
+ optional=False,
518
+ )
519
+
520
+ term = footprints.Footprint(info='Abstract term', attr=dict(term=a_term))
521
+
522
+ term_deco = footprints.DecorativeFootprint(
523
+ term,
524
+ decorator=[namebuilding_insert('term',
525
+ lambda self: None if self.term is None else self.term.fmthm,
526
+ none_discard=True, setdefault=True), ])
527
+
528
+ #: Usual definition of the ``begintime`` and ``endtime`` attributes.
529
+
530
+ timeperiod = footprints.Footprint(info='Abstract Time Period',
531
+ attr=dict(begintime=dict(info="The resource's begin forecast term.",
532
+ type=Time,
533
+ optional=False),
534
+ endtime=dict(info="The resource's end forecast term.",
535
+ type=Time,
536
+ optional=False),
537
+ ))
538
+
539
+ timeperiod_deco = footprints.DecorativeFootprint(
540
+ timeperiod,
541
+ decorator=[namebuilding_insert('period',
542
+ lambda self: [{'begintime': self.begintime},
543
+ {'endtime': self.endtime}]), ])
544
+
545
+ #: Usual definition of operational suite
546
+ a_suite = dict(
547
+ info="The operational suite identifier.",
548
+ values=['oper', 'dble', 'dbl', 'test', 'mirr', 'miroir'],
549
+ remap=dict(
550
+ dbl='dble',
551
+ miroir='mirr',
552
+ )
553
+ )
554
+
555
+ #: Usual definition of the ``member`` attribute
556
+ a_member = dict(
557
+ info="The member's number (`None` for a deterministic configuration).",
558
+ type=int,
559
+ optional=True,
560
+ )
561
+
562
+ member = footprints.Footprint(info='Abstract member', attr=dict(member=a_member))
563
+
564
+ #: Usual definition of the ``scenario`` attribute
565
+ a_scenario = dict(
566
+ info="The scenario identifier of the climate simulation (optional, especially in an NWP context).",
567
+ optional=True,
568
+ )
569
+
570
+ scenario = footprints.Footprint(info='Abstract scenario', attr=dict(scenario=a_scenario))
571
+
572
+ #: Usual definition of the ``number`` attribute (e.g. a perturbation number)
573
+ a_number = dict(
574
+ info="Any kind of numbering...",
575
+ type=FmtInt,
576
+ args=dict(fmt='03'),
577
+ )
578
+
579
+ number = footprints.Footprint(info='Abstract number', attr=dict(number=a_number))
580
+
581
+ number_deco = footprints.DecorativeFootprint(
582
+ number,
583
+ decorator=[namebuilding_insert('number', lambda self: self.number, setdefault=True), ])
584
+
585
+ #: Usual definition of the ``block`` attribute
586
+ a_block = dict(
587
+ info='The subpath where to store the data.',
588
+ )
589
+
590
+ block = footprints.Footprint(info='Abstract block', attr=dict(block=a_block))
591
+
592
+ #: Usual definition of the ``namespace`` attribute
593
+ a_namespace = dict(
594
+ info="The namespace where to store the data.",
595
+ type=Namespace,
596
+ optional=True,
597
+ )
598
+
599
+ namespacefp = footprints.Footprint(info='Abstract namespace',
600
+ attr=dict(namespace=a_namespace))
601
+
602
+ #: Usual definition of the ``storehash`` attribute
603
+ a_hashalgo = dict(
604
+ info="The hash algorithm used to check data integrity",
605
+ optional=True,
606
+ values=[None, ],
607
+ )
608
+
609
+ hashalgo = footprints.Footprint(info='Abstract Hash Algo', attr=dict(storehash=a_hashalgo))
610
+
611
+ hashalgo_avail_list = hashutils.HashAdapter.algorithms()
612
+
613
+ #: Usual definition of the ``store_compressed`` attribute
614
+ a_compressionpipeline = dict(
615
+ info="The compression pipeline used for this store",
616
+ optional=True,
617
+ )
618
+
619
+ compressionpipeline = footprints.Footprint(info='Abstract Compression Pipeline',
620
+ attr=dict(store_compressed=a_compressionpipeline))
621
+
622
+
623
+ def show():
624
+ """Returns available items and their type."""
625
+ dmod = globals()
626
+ for stda in sorted(filter(lambda x: x.startswith('a_') or isinstance(dmod[x], footprints.Footprint),
627
+ dmod.keys())):
628
+ print('{} ( {} ) :\n {}\n'.format(stda, type(dmod[stda]).__name__, dmod[stda]))