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.
- vortex/__init__.py +59 -45
- vortex/algo/__init__.py +3 -2
- vortex/algo/components.py +940 -614
- vortex/algo/mpitools.py +802 -497
- vortex/algo/serversynctools.py +34 -33
- vortex/config.py +19 -22
- vortex/data/__init__.py +9 -3
- vortex/data/abstractstores.py +593 -655
- vortex/data/containers.py +217 -162
- vortex/data/contents.py +65 -39
- vortex/data/executables.py +93 -102
- vortex/data/flow.py +40 -34
- vortex/data/geometries.py +228 -132
- vortex/data/handlers.py +428 -225
- vortex/data/outflow.py +15 -15
- vortex/data/providers.py +185 -163
- vortex/data/resources.py +48 -42
- vortex/data/stores.py +544 -413
- vortex/gloves.py +114 -87
- vortex/layout/__init__.py +1 -8
- vortex/layout/contexts.py +150 -84
- vortex/layout/dataflow.py +353 -202
- vortex/layout/monitor.py +264 -128
- vortex/nwp/__init__.py +5 -2
- vortex/nwp/algo/__init__.py +14 -5
- vortex/nwp/algo/assim.py +205 -151
- vortex/nwp/algo/clim.py +683 -517
- vortex/nwp/algo/coupling.py +447 -225
- vortex/nwp/algo/eda.py +437 -229
- vortex/nwp/algo/eps.py +403 -231
- vortex/nwp/algo/forecasts.py +420 -271
- vortex/nwp/algo/fpserver.py +683 -307
- vortex/nwp/algo/ifsnaming.py +205 -145
- vortex/nwp/algo/ifsroot.py +210 -122
- vortex/nwp/algo/monitoring.py +132 -76
- vortex/nwp/algo/mpitools.py +321 -191
- vortex/nwp/algo/odbtools.py +617 -353
- vortex/nwp/algo/oopsroot.py +449 -273
- vortex/nwp/algo/oopstests.py +90 -56
- vortex/nwp/algo/request.py +287 -206
- vortex/nwp/algo/stdpost.py +878 -522
- vortex/nwp/data/__init__.py +22 -4
- vortex/nwp/data/assim.py +125 -137
- vortex/nwp/data/boundaries.py +121 -68
- vortex/nwp/data/climfiles.py +193 -211
- vortex/nwp/data/configfiles.py +73 -69
- vortex/nwp/data/consts.py +426 -401
- vortex/nwp/data/ctpini.py +59 -43
- vortex/nwp/data/diagnostics.py +94 -66
- vortex/nwp/data/eda.py +50 -51
- vortex/nwp/data/eps.py +195 -146
- vortex/nwp/data/executables.py +440 -434
- vortex/nwp/data/fields.py +63 -48
- vortex/nwp/data/gridfiles.py +183 -111
- vortex/nwp/data/logs.py +250 -217
- vortex/nwp/data/modelstates.py +180 -151
- vortex/nwp/data/monitoring.py +72 -99
- vortex/nwp/data/namelists.py +254 -202
- vortex/nwp/data/obs.py +400 -308
- vortex/nwp/data/oopsexec.py +22 -20
- vortex/nwp/data/providers.py +90 -65
- vortex/nwp/data/query.py +71 -82
- vortex/nwp/data/stores.py +49 -36
- vortex/nwp/data/surfex.py +136 -137
- vortex/nwp/syntax/__init__.py +1 -1
- vortex/nwp/syntax/stdattrs.py +173 -111
- vortex/nwp/tools/__init__.py +2 -2
- vortex/nwp/tools/addons.py +22 -17
- vortex/nwp/tools/agt.py +24 -12
- vortex/nwp/tools/bdap.py +16 -5
- vortex/nwp/tools/bdcp.py +4 -1
- vortex/nwp/tools/bdm.py +3 -0
- vortex/nwp/tools/bdmp.py +14 -9
- vortex/nwp/tools/conftools.py +728 -378
- vortex/nwp/tools/drhook.py +12 -8
- vortex/nwp/tools/grib.py +65 -39
- vortex/nwp/tools/gribdiff.py +22 -17
- vortex/nwp/tools/ifstools.py +82 -42
- vortex/nwp/tools/igastuff.py +167 -143
- vortex/nwp/tools/mars.py +14 -2
- vortex/nwp/tools/odb.py +234 -125
- vortex/nwp/tools/partitioning.py +61 -37
- vortex/nwp/tools/satrad.py +27 -12
- vortex/nwp/util/async.py +83 -55
- vortex/nwp/util/beacon.py +10 -10
- vortex/nwp/util/diffpygram.py +174 -86
- vortex/nwp/util/ens.py +144 -63
- vortex/nwp/util/hooks.py +30 -19
- vortex/nwp/util/taskdeco.py +28 -24
- vortex/nwp/util/usepygram.py +278 -172
- vortex/nwp/util/usetnt.py +31 -17
- vortex/sessions.py +72 -39
- vortex/syntax/__init__.py +1 -1
- vortex/syntax/stdattrs.py +410 -171
- vortex/syntax/stddeco.py +31 -22
- vortex/toolbox.py +327 -192
- vortex/tools/__init__.py +11 -2
- vortex/tools/actions.py +125 -59
- vortex/tools/addons.py +111 -92
- vortex/tools/arm.py +42 -22
- vortex/tools/compression.py +72 -69
- vortex/tools/date.py +11 -4
- vortex/tools/delayedactions.py +242 -132
- vortex/tools/env.py +75 -47
- vortex/tools/folder.py +342 -171
- vortex/tools/grib.py +311 -149
- vortex/tools/lfi.py +423 -216
- vortex/tools/listings.py +109 -40
- vortex/tools/names.py +218 -156
- vortex/tools/net.py +632 -298
- vortex/tools/parallelism.py +93 -61
- vortex/tools/prestaging.py +55 -31
- vortex/tools/schedulers.py +172 -105
- vortex/tools/services.py +402 -333
- vortex/tools/storage.py +293 -358
- vortex/tools/surfex.py +24 -24
- vortex/tools/systems.py +1211 -631
- vortex/tools/targets.py +156 -100
- vortex/util/__init__.py +1 -1
- vortex/util/config.py +377 -327
- vortex/util/empty.py +2 -2
- vortex/util/helpers.py +56 -24
- vortex/util/introspection.py +18 -12
- vortex/util/iosponge.py +8 -4
- vortex/util/roles.py +4 -6
- vortex/util/storefunctions.py +39 -13
- vortex/util/structs.py +3 -3
- vortex/util/worker.py +29 -17
- vortex_nwp-2.0.0b2.dist-info/METADATA +66 -0
- vortex_nwp-2.0.0b2.dist-info/RECORD +142 -0
- {vortex_nwp-2.0.0b1.dist-info → vortex_nwp-2.0.0b2.dist-info}/WHEEL +1 -1
- vortex/layout/appconf.py +0 -109
- vortex/layout/jobs.py +0 -1276
- vortex/layout/nodes.py +0 -1424
- vortex/layout/subjobs.py +0 -464
- vortex_nwp-2.0.0b1.dist-info/METADATA +0 -50
- vortex_nwp-2.0.0b1.dist-info/RECORD +0 -146
- {vortex_nwp-2.0.0b1.dist-info → vortex_nwp-2.0.0b2.dist-info}/LICENSE +0 -0
- {vortex_nwp-2.0.0b1.dist-info → vortex_nwp-2.0.0b2.dist-info}/top_level.txt +0 -0
vortex/syntax/stdattrs.py
CHANGED
|
@@ -13,46 +13,159 @@ from bronx.syntax.decorators import secure_getattr
|
|
|
13
13
|
from bronx.system import hash as hashutils
|
|
14
14
|
from vortex.tools import env
|
|
15
15
|
|
|
16
|
-
from .stddeco import
|
|
16
|
+
from .stddeco import (
|
|
17
|
+
generic_pathname_insert,
|
|
18
|
+
namebuilding_append,
|
|
19
|
+
namebuilding_insert,
|
|
20
|
+
)
|
|
17
21
|
|
|
18
22
|
#: Export a set of attributes :data:`a_model`, :data:`a_date`, etc..
|
|
19
23
|
__all__ = [
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
24
|
+
"a_xpid",
|
|
25
|
+
"a_month",
|
|
26
|
+
"a_domain",
|
|
27
|
+
"a_truncation",
|
|
28
|
+
"a_model",
|
|
29
|
+
"a_member",
|
|
30
|
+
"a_date",
|
|
31
|
+
"a_cutoff",
|
|
32
|
+
"a_term",
|
|
33
|
+
"a_nativefmt",
|
|
34
|
+
"a_actualfmt",
|
|
35
|
+
"a_suite",
|
|
36
|
+
"a_namespace",
|
|
37
|
+
"a_hashalgo",
|
|
38
|
+
"a_compressionpipeline",
|
|
39
|
+
"a_block",
|
|
40
|
+
"a_number",
|
|
23
41
|
]
|
|
24
42
|
|
|
25
43
|
#: Possible values for the *model* attribute.
|
|
26
44
|
models = {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
45
|
+
"arpege",
|
|
46
|
+
"arp",
|
|
47
|
+
"arp_court",
|
|
48
|
+
"aladin",
|
|
49
|
+
"ald",
|
|
50
|
+
"arome",
|
|
51
|
+
"aro",
|
|
52
|
+
"aearp",
|
|
53
|
+
"pearp",
|
|
54
|
+
"mocage",
|
|
55
|
+
"mesonh",
|
|
56
|
+
"surfex",
|
|
57
|
+
"hycom",
|
|
58
|
+
"psy4",
|
|
59
|
+
"mercator_global",
|
|
60
|
+
"glo12",
|
|
61
|
+
"safran",
|
|
62
|
+
"ifs",
|
|
63
|
+
"aroifs",
|
|
64
|
+
"cifs",
|
|
65
|
+
"mfwam",
|
|
66
|
+
"pg1",
|
|
67
|
+
"alpha",
|
|
68
|
+
"eps",
|
|
69
|
+
"postproc",
|
|
70
|
+
"ww3",
|
|
71
|
+
"sympo",
|
|
72
|
+
"psym",
|
|
73
|
+
"petaroute",
|
|
74
|
+
"promethee",
|
|
75
|
+
"hycom3d",
|
|
76
|
+
"croco",
|
|
77
|
+
"alaro",
|
|
78
|
+
"harmoniearome",
|
|
79
|
+
"nemo",
|
|
80
|
+
"oasis",
|
|
31
81
|
}
|
|
32
82
|
|
|
33
83
|
#: Possible values for the most common binaries.
|
|
34
84
|
binaries = {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
85
|
+
"arpege",
|
|
86
|
+
"aladin",
|
|
87
|
+
"arome",
|
|
88
|
+
"aromeom_common",
|
|
89
|
+
"batodb",
|
|
90
|
+
"peace",
|
|
91
|
+
"mocage",
|
|
92
|
+
"sumo",
|
|
93
|
+
"corromegasurf",
|
|
94
|
+
"mesonh",
|
|
95
|
+
"safran",
|
|
96
|
+
"surfex",
|
|
97
|
+
"macc",
|
|
98
|
+
"mktopbd",
|
|
99
|
+
"ifs",
|
|
100
|
+
"oops",
|
|
101
|
+
"assistance",
|
|
102
|
+
"arpifs",
|
|
103
|
+
"mfwam",
|
|
104
|
+
"mfwam_interp",
|
|
105
|
+
"mfwam_interpbc",
|
|
106
|
+
"ww3",
|
|
107
|
+
"ww3_prnc",
|
|
108
|
+
"ww3_bound",
|
|
109
|
+
"ww3_ncgrb",
|
|
110
|
+
"ial",
|
|
111
|
+
"alaro",
|
|
112
|
+
"harmoniearome",
|
|
113
|
+
"nemo",
|
|
114
|
+
"oasis",
|
|
115
|
+
"arobase",
|
|
116
|
+
"xios",
|
|
40
117
|
}
|
|
41
118
|
|
|
42
119
|
#: Possible values for the most common utility programs.
|
|
43
|
-
utilities = {
|
|
120
|
+
utilities = {"batodb"}
|
|
44
121
|
|
|
45
122
|
#: Known formats
|
|
46
123
|
knownfmt = {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
124
|
+
"auto",
|
|
125
|
+
"autoconfig",
|
|
126
|
+
"unknown",
|
|
127
|
+
"foo",
|
|
128
|
+
"arpifslist",
|
|
129
|
+
"bdmbufr_listing",
|
|
130
|
+
"ascii",
|
|
131
|
+
"txt",
|
|
132
|
+
"json",
|
|
133
|
+
"fa",
|
|
134
|
+
"lfi",
|
|
135
|
+
"lfa",
|
|
136
|
+
"netcdf",
|
|
137
|
+
"grib",
|
|
138
|
+
"grib1",
|
|
139
|
+
"grib2",
|
|
140
|
+
"bufr",
|
|
141
|
+
"hdf5",
|
|
142
|
+
"obsoul",
|
|
143
|
+
"odb",
|
|
144
|
+
"ecma",
|
|
145
|
+
"ccma",
|
|
146
|
+
"bullx",
|
|
147
|
+
"sx",
|
|
148
|
+
"ddhpack",
|
|
149
|
+
"tar",
|
|
150
|
+
"tgz",
|
|
151
|
+
"rawfiles",
|
|
152
|
+
"binary",
|
|
153
|
+
"bin",
|
|
154
|
+
"obslocationpack",
|
|
155
|
+
"obsfirepack",
|
|
156
|
+
"wbcpack",
|
|
157
|
+
"geo",
|
|
158
|
+
"nam",
|
|
159
|
+
"png",
|
|
160
|
+
"pdf",
|
|
161
|
+
"dir/hdr",
|
|
162
|
+
"yml",
|
|
163
|
+
"yaml",
|
|
164
|
+
"ini",
|
|
52
165
|
}
|
|
53
166
|
|
|
54
167
|
#: Default attributes excluded from `repr` display
|
|
55
|
-
notinrepr = {
|
|
168
|
+
notinrepr = {"kind", "unknown", "clscontents", "gvar", "nativefmt"}
|
|
56
169
|
|
|
57
170
|
|
|
58
171
|
class DelayedEnvValue:
|
|
@@ -69,7 +182,7 @@ class DelayedEnvValue:
|
|
|
69
182
|
self._frozen = False
|
|
70
183
|
|
|
71
184
|
def as_dump(self):
|
|
72
|
-
return
|
|
185
|
+
return "varname={},default={}".format(self.varname, self.default)
|
|
73
186
|
|
|
74
187
|
def footprint_value(self):
|
|
75
188
|
"""
|
|
@@ -104,10 +217,13 @@ class DelayedInit:
|
|
|
104
217
|
return getattr(self.__proxied, name)
|
|
105
218
|
|
|
106
219
|
def __repr__(self):
|
|
107
|
-
orig = re.sub(
|
|
108
|
-
return
|
|
109
|
-
|
|
110
|
-
|
|
220
|
+
orig = re.sub("^<(.*)>$", r"\1", super().__repr__())
|
|
221
|
+
return "<{:s} | proxied={:s}>".format(
|
|
222
|
+
orig,
|
|
223
|
+
"Not yet Initialised"
|
|
224
|
+
if self.__proxied is None
|
|
225
|
+
else repr(self.__proxied),
|
|
226
|
+
)
|
|
111
227
|
|
|
112
228
|
def __str__(self):
|
|
113
229
|
return repr(self) if self.__proxied is None else str(self.__proxied)
|
|
@@ -116,13 +232,13 @@ class DelayedInit:
|
|
|
116
232
|
class FmtInt(int):
|
|
117
233
|
"""Formated integer."""
|
|
118
234
|
|
|
119
|
-
def __new__(cls, value, fmt=
|
|
235
|
+
def __new__(cls, value, fmt="02"):
|
|
120
236
|
obj = int.__new__(cls, value)
|
|
121
237
|
obj._fmt = fmt
|
|
122
238
|
return obj
|
|
123
239
|
|
|
124
240
|
def __str__(self):
|
|
125
|
-
return
|
|
241
|
+
return "{0:{fmt}d}".format(self.__int__(), fmt=self._fmt)
|
|
126
242
|
|
|
127
243
|
def export_dict(self):
|
|
128
244
|
"""The pure dict/json output is the raw integer"""
|
|
@@ -130,11 +246,12 @@ class FmtInt(int):
|
|
|
130
246
|
|
|
131
247
|
def nice(self, value):
|
|
132
248
|
"""Returns the specified ``value`` with the format of the current object."""
|
|
133
|
-
return
|
|
249
|
+
return "{0:{fmt}d}".format(value, fmt=self._fmt)
|
|
134
250
|
|
|
135
251
|
|
|
136
252
|
class XPid(str):
|
|
137
253
|
"""Basestring wrapper for experiment ids (abstract)."""
|
|
254
|
+
|
|
138
255
|
pass
|
|
139
256
|
|
|
140
257
|
|
|
@@ -142,8 +259,8 @@ class LegacyXPid(XPid):
|
|
|
142
259
|
"""Basestring wrapper for experiment ids (Olive/Oper convention)."""
|
|
143
260
|
|
|
144
261
|
def __new__(cls, value):
|
|
145
|
-
if len(value) != 4 or
|
|
146
|
-
raise ValueError(
|
|
262
|
+
if len(value) != 4 or "@" in value:
|
|
263
|
+
raise ValueError("XPid should be a 4 digits string")
|
|
147
264
|
return str.__new__(cls, value.upper())
|
|
148
265
|
|
|
149
266
|
def isoper(self):
|
|
@@ -154,21 +271,24 @@ class LegacyXPid(XPid):
|
|
|
154
271
|
class FreeXPid(XPid):
|
|
155
272
|
"""Basestring wrapper for experiment ids (User defined)."""
|
|
156
273
|
|
|
157
|
-
_re_valid = re.compile(r
|
|
274
|
+
_re_valid = re.compile(r"^\S+@[-\w]+$")
|
|
158
275
|
|
|
159
276
|
def __new__(cls, value):
|
|
160
277
|
if not cls._re_valid.match(value):
|
|
161
|
-
raise ValueError(
|
|
162
|
-
|
|
278
|
+
raise ValueError(
|
|
279
|
+
'XPid should be something like "id@location" (not "{:s}")'.format(
|
|
280
|
+
value
|
|
281
|
+
)
|
|
282
|
+
)
|
|
163
283
|
return str.__new__(cls, value)
|
|
164
284
|
|
|
165
285
|
@property
|
|
166
286
|
def id(self):
|
|
167
|
-
return self.split(
|
|
287
|
+
return self.split("@")[0]
|
|
168
288
|
|
|
169
289
|
@property
|
|
170
290
|
def location(self):
|
|
171
|
-
return self.split(
|
|
291
|
+
return self.split("@")[1]
|
|
172
292
|
|
|
173
293
|
|
|
174
294
|
def any_vortex_xpid(xpidguess):
|
|
@@ -179,16 +299,23 @@ def any_vortex_xpid(xpidguess):
|
|
|
179
299
|
except ValueError:
|
|
180
300
|
xp = FreeXPid(xpidguess)
|
|
181
301
|
except ValueError:
|
|
182
|
-
raise ValueError(
|
|
302
|
+
raise ValueError(
|
|
303
|
+
"'{:s}' could not be reclassed as a LegacyXPid or a FreeXPid"
|
|
304
|
+
)
|
|
183
305
|
return xp
|
|
184
306
|
|
|
185
307
|
|
|
186
308
|
#: The list of operational experiment names.
|
|
187
|
-
opsuites = {
|
|
188
|
-
|
|
309
|
+
opsuites = {
|
|
310
|
+
LegacyXPid(x)
|
|
311
|
+
for x in (
|
|
312
|
+
["OPER", "DBLE", "TEST", "MIRR"]
|
|
313
|
+
+ ["OP{:02d}".format(i) for i in range(100)]
|
|
314
|
+
)
|
|
315
|
+
}
|
|
189
316
|
|
|
190
317
|
#: The list of experiemnt names dedicated to Vortex' demos
|
|
191
|
-
demosuites = {LegacyXPid(
|
|
318
|
+
demosuites = {LegacyXPid("DEMO"), LegacyXPid("DREF")}
|
|
192
319
|
|
|
193
320
|
|
|
194
321
|
class Namespace(str):
|
|
@@ -197,20 +324,22 @@ class Namespace(str):
|
|
|
197
324
|
def __new__(cls, value):
|
|
198
325
|
value = value.lower()
|
|
199
326
|
full = value
|
|
200
|
-
if
|
|
201
|
-
netuser, value = value.split(
|
|
202
|
-
if
|
|
203
|
-
netuser, netpass = netuser.split(
|
|
327
|
+
if "@" in value:
|
|
328
|
+
netuser, value = value.split("@")
|
|
329
|
+
if ":" in netuser:
|
|
330
|
+
netuser, netpass = netuser.split(":")
|
|
204
331
|
else:
|
|
205
332
|
netpass = None
|
|
206
333
|
else:
|
|
207
334
|
netuser, netpass = None, None
|
|
208
|
-
if
|
|
209
|
-
value, port = value.split(
|
|
335
|
+
if ":" in value:
|
|
336
|
+
value, port = value.split(":")
|
|
210
337
|
else:
|
|
211
338
|
port = None
|
|
212
|
-
if 0 < value.count(
|
|
213
|
-
raise ValueError(
|
|
339
|
+
if 0 < value.count(".") < 2:
|
|
340
|
+
raise ValueError(
|
|
341
|
+
"Namespace should contain one or at least 3 fields"
|
|
342
|
+
)
|
|
214
343
|
thisns = str.__new__(cls, value)
|
|
215
344
|
thisns._port = int(port) if port else None
|
|
216
345
|
thisns._user = netuser
|
|
@@ -220,12 +349,12 @@ class Namespace(str):
|
|
|
220
349
|
|
|
221
350
|
@property
|
|
222
351
|
def firstname(self):
|
|
223
|
-
return self.split(
|
|
352
|
+
return self.split(".", 1)[0]
|
|
224
353
|
|
|
225
354
|
@property
|
|
226
355
|
def domain(self):
|
|
227
|
-
if
|
|
228
|
-
return self.split(
|
|
356
|
+
if "." in self.netloc:
|
|
357
|
+
return self.split(".", 1)[1]
|
|
229
358
|
else:
|
|
230
359
|
return self.netloc
|
|
231
360
|
|
|
@@ -251,23 +380,23 @@ class Latitude(float):
|
|
|
251
380
|
|
|
252
381
|
def __new__(cls, value):
|
|
253
382
|
value = str(value).lower()
|
|
254
|
-
if value.endswith(
|
|
383
|
+
if value.endswith("n"):
|
|
255
384
|
value = value[:-1]
|
|
256
|
-
elif value.endswith(
|
|
385
|
+
elif value.endswith("s"):
|
|
257
386
|
value = value[:-1]
|
|
258
|
-
if not value.startswith(
|
|
259
|
-
value =
|
|
387
|
+
if not value.startswith("-"):
|
|
388
|
+
value = "-" + value
|
|
260
389
|
if not -90 <= float(value) <= 90:
|
|
261
|
-
raise ValueError(
|
|
390
|
+
raise ValueError("Latitude out of bounds: " + value)
|
|
262
391
|
return float.__new__(cls, value)
|
|
263
392
|
|
|
264
393
|
def nice(self):
|
|
265
|
-
ns =
|
|
266
|
-
return str(self).strip(
|
|
394
|
+
ns = "N" if self >= 0 else "S"
|
|
395
|
+
return str(self).strip("-") + ns
|
|
267
396
|
|
|
268
397
|
@property
|
|
269
398
|
def hemisphere(self):
|
|
270
|
-
return
|
|
399
|
+
return "North" if self >= 0 else "South"
|
|
271
400
|
|
|
272
401
|
|
|
273
402
|
class Longitude(float):
|
|
@@ -275,23 +404,23 @@ class Longitude(float):
|
|
|
275
404
|
|
|
276
405
|
def __new__(cls, value):
|
|
277
406
|
value = str(value).lower()
|
|
278
|
-
if value.endswith(
|
|
407
|
+
if value.endswith("e"):
|
|
279
408
|
value = value[:-1]
|
|
280
|
-
elif value.endswith(
|
|
409
|
+
elif value.endswith("w"):
|
|
281
410
|
value = value[:-1]
|
|
282
|
-
if not value.startswith(
|
|
283
|
-
value =
|
|
411
|
+
if not value.startswith("-"):
|
|
412
|
+
value = "-" + value
|
|
284
413
|
if not -180 <= float(value) <= 180:
|
|
285
|
-
raise ValueError(
|
|
414
|
+
raise ValueError("Longitude out of bounds: " + value)
|
|
286
415
|
return float.__new__(cls, value)
|
|
287
416
|
|
|
288
417
|
def nice(self):
|
|
289
|
-
ns =
|
|
290
|
-
return str(self).strip(
|
|
418
|
+
ns = "E" if self >= 0 else "W"
|
|
419
|
+
return str(self).strip("-") + ns
|
|
291
420
|
|
|
292
421
|
@property
|
|
293
422
|
def hemisphere(self):
|
|
294
|
-
return
|
|
423
|
+
return "East" if self >= 0 else "West"
|
|
295
424
|
|
|
296
425
|
|
|
297
426
|
# predefined attributes
|
|
@@ -303,46 +432,52 @@ a_xpid = dict(
|
|
|
303
432
|
optional=False,
|
|
304
433
|
)
|
|
305
434
|
|
|
306
|
-
xpid = footprints.Footprint(
|
|
307
|
-
|
|
435
|
+
xpid = footprints.Footprint(
|
|
436
|
+
info="Abstract experiment id", attr=dict(experiment=a_xpid)
|
|
437
|
+
)
|
|
308
438
|
|
|
309
439
|
#: Usual definition for an Olive/Oper ``xpid`` (*e.g.* experiment name).
|
|
310
440
|
a_legacy_xpid = copy.copy(a_xpid)
|
|
311
|
-
a_legacy_xpid[
|
|
441
|
+
a_legacy_xpid["type"] = LegacyXPid
|
|
312
442
|
|
|
313
|
-
legacy_xpid = footprints.Footprint(
|
|
314
|
-
|
|
443
|
+
legacy_xpid = footprints.Footprint(
|
|
444
|
+
info="Abstract experiment id", attr=dict(experiment=a_legacy_xpid)
|
|
445
|
+
)
|
|
315
446
|
|
|
316
447
|
#: Usual definition for a user-defined ``xpid`` (*e.g.* experiment name).
|
|
317
448
|
a_free_xpid = copy.copy(a_xpid)
|
|
318
|
-
a_free_xpid[
|
|
449
|
+
a_free_xpid["type"] = FreeXPid
|
|
319
450
|
|
|
320
|
-
free_xpid = footprints.Footprint(
|
|
321
|
-
|
|
451
|
+
free_xpid = footprints.Footprint(
|
|
452
|
+
info="Abstract experiment id", attr=dict(experiment=a_free_xpid)
|
|
453
|
+
)
|
|
322
454
|
|
|
323
455
|
#: Usual definition of the ``nativefmt`` attribute.
|
|
324
456
|
a_nativefmt = dict(
|
|
325
457
|
info="The resource's storage format.",
|
|
326
458
|
optional=True,
|
|
327
|
-
default=
|
|
459
|
+
default="foo",
|
|
328
460
|
values=knownfmt,
|
|
329
|
-
remap=dict(auto=
|
|
461
|
+
remap=dict(auto="foo"),
|
|
330
462
|
)
|
|
331
463
|
|
|
332
|
-
nativefmt = footprints.Footprint(
|
|
464
|
+
nativefmt = footprints.Footprint(
|
|
465
|
+
info="Native format", attr=dict(nativefmt=a_nativefmt)
|
|
466
|
+
)
|
|
333
467
|
|
|
334
468
|
|
|
335
469
|
def _namebuilding_insert_nativefmt(cls):
|
|
336
|
-
|
|
337
|
-
if hasattr(cls, 'namebuilding_info'):
|
|
470
|
+
if hasattr(cls, "namebuilding_info"):
|
|
338
471
|
original_namebuilding_info = cls.namebuilding_info
|
|
339
472
|
|
|
340
473
|
def namebuilding_info(self):
|
|
341
474
|
vinfo = original_namebuilding_info(self)
|
|
342
|
-
ext_remap = getattr(self,
|
|
475
|
+
ext_remap = getattr(self, "_extension_remap", dict())
|
|
343
476
|
ext_value = ext_remap.get(self.nativefmt, self.nativefmt)
|
|
344
477
|
if ext_value is not None:
|
|
345
|
-
vinfo.setdefault(
|
|
478
|
+
vinfo.setdefault(
|
|
479
|
+
"fmt", ext_remap.get(self.nativefmt, self.nativefmt)
|
|
480
|
+
)
|
|
346
481
|
return vinfo
|
|
347
482
|
|
|
348
483
|
namebuilding_info.__doc__ = original_namebuilding_info.__doc__
|
|
@@ -353,67 +488,97 @@ def _namebuilding_insert_nativefmt(cls):
|
|
|
353
488
|
|
|
354
489
|
nativefmt_deco = footprints.DecorativeFootprint(
|
|
355
490
|
nativefmt,
|
|
356
|
-
decorator=[
|
|
357
|
-
|
|
491
|
+
decorator=[
|
|
492
|
+
_namebuilding_insert_nativefmt,
|
|
493
|
+
generic_pathname_insert(
|
|
494
|
+
"nativefmt", lambda self: self.nativefmt, setdefault=True
|
|
495
|
+
),
|
|
496
|
+
],
|
|
497
|
+
)
|
|
358
498
|
|
|
359
499
|
#: Usual definition of the ``actualfmt`` attribute.
|
|
360
500
|
a_actualfmt = dict(
|
|
361
501
|
info="The resource's format.",
|
|
362
502
|
optional=True,
|
|
363
|
-
default=
|
|
364
|
-
alias=(
|
|
503
|
+
default="[nativefmt#unknown]",
|
|
504
|
+
alias=("format",),
|
|
365
505
|
values=knownfmt,
|
|
366
|
-
remap=dict(auto=
|
|
506
|
+
remap=dict(auto="foo"),
|
|
367
507
|
)
|
|
368
508
|
|
|
369
|
-
actualfmt = footprints.Footprint(
|
|
509
|
+
actualfmt = footprints.Footprint(
|
|
510
|
+
info="Actual data format", attr=dict(actualfmt=a_actualfmt)
|
|
511
|
+
)
|
|
370
512
|
|
|
371
513
|
#: Usual definition of the ``cutoff`` attribute.
|
|
372
514
|
a_cutoff = dict(
|
|
373
515
|
info="The cutoff type of the generating process.",
|
|
374
516
|
optional=False,
|
|
375
|
-
alias=(
|
|
517
|
+
alias=("cut",),
|
|
376
518
|
values=[
|
|
377
|
-
|
|
378
|
-
|
|
519
|
+
"a",
|
|
520
|
+
"assim",
|
|
521
|
+
"assimilation",
|
|
522
|
+
"long",
|
|
523
|
+
"p",
|
|
524
|
+
"prod",
|
|
525
|
+
"production",
|
|
526
|
+
"short",
|
|
379
527
|
],
|
|
380
528
|
remap=dict(
|
|
381
|
-
a=
|
|
382
|
-
p=
|
|
383
|
-
prod=
|
|
384
|
-
long=
|
|
385
|
-
assimilation=
|
|
386
|
-
)
|
|
529
|
+
a="assim",
|
|
530
|
+
p="production",
|
|
531
|
+
prod="production",
|
|
532
|
+
long="assim",
|
|
533
|
+
assimilation="assim",
|
|
534
|
+
),
|
|
387
535
|
)
|
|
388
536
|
|
|
389
|
-
cutoff = footprints.Footprint(
|
|
537
|
+
cutoff = footprints.Footprint(
|
|
538
|
+
info="Abstract cutoff", attr=dict(cutoff=a_cutoff)
|
|
539
|
+
)
|
|
390
540
|
|
|
391
541
|
cutoff_deco = footprints.DecorativeFootprint(
|
|
392
542
|
cutoff,
|
|
393
|
-
decorator=[
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
543
|
+
decorator=[
|
|
544
|
+
namebuilding_append(
|
|
545
|
+
"flow",
|
|
546
|
+
lambda self: None
|
|
547
|
+
if self.cutoff is None
|
|
548
|
+
else {"shortcutoff": self.cutoff},
|
|
549
|
+
none_discard=True,
|
|
550
|
+
),
|
|
551
|
+
generic_pathname_insert(
|
|
552
|
+
"cutoff", lambda self: self.cutoff, setdefault=True
|
|
553
|
+
),
|
|
554
|
+
],
|
|
555
|
+
)
|
|
397
556
|
|
|
398
557
|
#: Usual definition of the ``model`` attribute.
|
|
399
558
|
a_model = dict(
|
|
400
559
|
info="The model name (from a source code perspective).",
|
|
401
|
-
alias=(
|
|
560
|
+
alias=("turtle",),
|
|
402
561
|
optional=False,
|
|
403
562
|
values=models,
|
|
404
|
-
remap=dict(
|
|
405
|
-
arp='arpege',
|
|
406
|
-
ald='aladin',
|
|
407
|
-
aro='arome'
|
|
408
|
-
),
|
|
563
|
+
remap=dict(arp="arpege", ald="aladin", aro="arome"),
|
|
409
564
|
)
|
|
410
565
|
|
|
411
|
-
model = footprints.Footprint(info=
|
|
566
|
+
model = footprints.Footprint(info="Abstract model", attr=dict(model=a_model))
|
|
412
567
|
|
|
413
568
|
model_deco = footprints.DecorativeFootprint(
|
|
414
569
|
model,
|
|
415
|
-
decorator=[
|
|
416
|
-
|
|
570
|
+
decorator=[
|
|
571
|
+
namebuilding_append(
|
|
572
|
+
"src",
|
|
573
|
+
lambda self: [
|
|
574
|
+
self.model,
|
|
575
|
+
],
|
|
576
|
+
),
|
|
577
|
+
generic_pathname_insert(
|
|
578
|
+
"model", lambda self: self.model, setdefault=True
|
|
579
|
+
),
|
|
580
|
+
],
|
|
581
|
+
)
|
|
417
582
|
|
|
418
583
|
#: Usual definition of the ``date`` attribute.
|
|
419
584
|
a_date = dict(
|
|
@@ -422,31 +587,50 @@ a_date = dict(
|
|
|
422
587
|
optional=False,
|
|
423
588
|
)
|
|
424
589
|
|
|
425
|
-
date = footprints.Footprint(info=
|
|
590
|
+
date = footprints.Footprint(info="Abstract date", attr=dict(date=a_date))
|
|
426
591
|
|
|
427
592
|
date_deco = footprints.DecorativeFootprint(
|
|
428
593
|
date,
|
|
429
|
-
decorator=[
|
|
430
|
-
|
|
594
|
+
decorator=[
|
|
595
|
+
namebuilding_append("flow", lambda self: {"date": self.date}),
|
|
596
|
+
generic_pathname_insert(
|
|
597
|
+
"date", lambda self: self.date, setdefault=True
|
|
598
|
+
),
|
|
599
|
+
],
|
|
600
|
+
)
|
|
431
601
|
|
|
432
602
|
#: Usual definition of the ``begindate`` and ``enddate`` attributes.
|
|
433
603
|
|
|
434
|
-
dateperiod = footprints.Footprint(
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
604
|
+
dateperiod = footprints.Footprint(
|
|
605
|
+
info="Abstract date period",
|
|
606
|
+
attr=dict(
|
|
607
|
+
begindate=dict(
|
|
608
|
+
info="The resource's begin date.", type=Date, optional=False
|
|
609
|
+
),
|
|
610
|
+
enddate=dict(
|
|
611
|
+
info="The resource's end date.", type=Date, optional=False
|
|
612
|
+
),
|
|
613
|
+
),
|
|
614
|
+
)
|
|
442
615
|
|
|
443
616
|
dateperiod_deco = footprints.DecorativeFootprint(
|
|
444
617
|
dateperiod,
|
|
445
|
-
decorator=[
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
618
|
+
decorator=[
|
|
619
|
+
namebuilding_append(
|
|
620
|
+
"flow",
|
|
621
|
+
lambda self: [
|
|
622
|
+
{"begindate": self.begindate},
|
|
623
|
+
{"enddate": self.enddate},
|
|
624
|
+
],
|
|
625
|
+
),
|
|
626
|
+
generic_pathname_insert(
|
|
627
|
+
"begindate", lambda self: self.begindate, setdefault=True
|
|
628
|
+
),
|
|
629
|
+
generic_pathname_insert(
|
|
630
|
+
"enddate", lambda self: self.enddate, setdefault=True
|
|
631
|
+
),
|
|
632
|
+
],
|
|
633
|
+
)
|
|
450
634
|
|
|
451
635
|
#: Usual definition of the ``month`` attribute.
|
|
452
636
|
a_month = dict(
|
|
@@ -454,21 +638,23 @@ a_month = dict(
|
|
|
454
638
|
type=Month,
|
|
455
639
|
args=dict(year=0),
|
|
456
640
|
optional=False,
|
|
457
|
-
values=range(1, 13)
|
|
641
|
+
values=range(1, 13),
|
|
458
642
|
)
|
|
459
643
|
|
|
460
|
-
month = footprints.Footprint(info=
|
|
644
|
+
month = footprints.Footprint(info="Abstract month", attr=dict(month=a_month))
|
|
461
645
|
|
|
462
646
|
|
|
463
647
|
def _add_month2gget_basename(cls):
|
|
464
648
|
"""Decorator that appends the month's number at the end of the gget_basename"""
|
|
465
|
-
original_gget_basename = getattr(cls,
|
|
649
|
+
original_gget_basename = getattr(cls, "gget_basename", None)
|
|
466
650
|
if original_gget_basename is not None:
|
|
467
651
|
|
|
468
652
|
def gget_basename(self):
|
|
469
653
|
"""GGET specific naming convention."""
|
|
470
654
|
b_dict = original_gget_basename(self)
|
|
471
|
-
b_dict[
|
|
655
|
+
b_dict["suffix"] = b_dict.get("suffix", "") + ".m{!s}".format(
|
|
656
|
+
self.month
|
|
657
|
+
)
|
|
472
658
|
return b_dict
|
|
473
659
|
|
|
474
660
|
cls.gget_basename = gget_basename
|
|
@@ -477,12 +663,12 @@ def _add_month2gget_basename(cls):
|
|
|
477
663
|
|
|
478
664
|
def _add_month2olive_basename(cls):
|
|
479
665
|
"""Decorator that appends the month's number at the end of the olive_basename."""
|
|
480
|
-
original_olive_basename = getattr(cls,
|
|
666
|
+
original_olive_basename = getattr(cls, "olive_basename", None)
|
|
481
667
|
if original_olive_basename is not None:
|
|
482
668
|
|
|
483
669
|
def olive_basename(self):
|
|
484
670
|
"""GGET specific naming convention."""
|
|
485
|
-
return original_olive_basename(self) +
|
|
671
|
+
return original_olive_basename(self) + ".{!s}".format(self.month)
|
|
486
672
|
|
|
487
673
|
cls.olive_basename = olive_basename
|
|
488
674
|
return cls
|
|
@@ -490,8 +676,12 @@ def _add_month2olive_basename(cls):
|
|
|
490
676
|
|
|
491
677
|
month_deco = footprints.DecorativeFootprint(
|
|
492
678
|
month,
|
|
493
|
-
decorator=[
|
|
494
|
-
|
|
679
|
+
decorator=[
|
|
680
|
+
namebuilding_append("suffix", lambda self: {"month": self.month}),
|
|
681
|
+
_add_month2gget_basename,
|
|
682
|
+
_add_month2olive_basename,
|
|
683
|
+
],
|
|
684
|
+
)
|
|
495
685
|
|
|
496
686
|
#: Usual definition of the ``truncation`` attribute.
|
|
497
687
|
a_truncation = dict(
|
|
@@ -500,7 +690,9 @@ a_truncation = dict(
|
|
|
500
690
|
optional=False,
|
|
501
691
|
)
|
|
502
692
|
|
|
503
|
-
truncation = footprints.Footprint(
|
|
693
|
+
truncation = footprints.Footprint(
|
|
694
|
+
info="Abstract truncation", attr=dict(truncation=a_truncation)
|
|
695
|
+
)
|
|
504
696
|
|
|
505
697
|
#: Usual definition of the ``domain`` attribute.
|
|
506
698
|
a_domain = dict(
|
|
@@ -508,7 +700,9 @@ a_domain = dict(
|
|
|
508
700
|
optional=False,
|
|
509
701
|
)
|
|
510
702
|
|
|
511
|
-
domain = footprints.Footprint(
|
|
703
|
+
domain = footprints.Footprint(
|
|
704
|
+
info="Abstract domain", attr=dict(domain=a_domain)
|
|
705
|
+
)
|
|
512
706
|
|
|
513
707
|
#: Usual definition of the ``term`` attribute.
|
|
514
708
|
a_term = dict(
|
|
@@ -517,39 +711,57 @@ a_term = dict(
|
|
|
517
711
|
optional=False,
|
|
518
712
|
)
|
|
519
713
|
|
|
520
|
-
term = footprints.Footprint(info=
|
|
714
|
+
term = footprints.Footprint(info="Abstract term", attr=dict(term=a_term))
|
|
521
715
|
|
|
522
716
|
term_deco = footprints.DecorativeFootprint(
|
|
523
717
|
term,
|
|
524
|
-
decorator=[
|
|
525
|
-
|
|
526
|
-
|
|
718
|
+
decorator=[
|
|
719
|
+
namebuilding_insert(
|
|
720
|
+
"term",
|
|
721
|
+
lambda self: None if self.term is None else self.term.fmthm,
|
|
722
|
+
none_discard=True,
|
|
723
|
+
setdefault=True,
|
|
724
|
+
),
|
|
725
|
+
],
|
|
726
|
+
)
|
|
527
727
|
|
|
528
728
|
#: Usual definition of the ``begintime`` and ``endtime`` attributes.
|
|
529
729
|
|
|
530
|
-
timeperiod = footprints.Footprint(
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
730
|
+
timeperiod = footprints.Footprint(
|
|
731
|
+
info="Abstract Time Period",
|
|
732
|
+
attr=dict(
|
|
733
|
+
begintime=dict(
|
|
734
|
+
info="The resource's begin forecast term.",
|
|
735
|
+
type=Time,
|
|
736
|
+
optional=False,
|
|
737
|
+
),
|
|
738
|
+
endtime=dict(
|
|
739
|
+
info="The resource's end forecast term.", type=Time, optional=False
|
|
740
|
+
),
|
|
741
|
+
),
|
|
742
|
+
)
|
|
538
743
|
|
|
539
744
|
timeperiod_deco = footprints.DecorativeFootprint(
|
|
540
745
|
timeperiod,
|
|
541
|
-
decorator=[
|
|
542
|
-
|
|
543
|
-
|
|
746
|
+
decorator=[
|
|
747
|
+
namebuilding_insert(
|
|
748
|
+
"period",
|
|
749
|
+
lambda self: [
|
|
750
|
+
{"begintime": self.begintime},
|
|
751
|
+
{"endtime": self.endtime},
|
|
752
|
+
],
|
|
753
|
+
),
|
|
754
|
+
],
|
|
755
|
+
)
|
|
544
756
|
|
|
545
757
|
#: Usual definition of operational suite
|
|
546
758
|
a_suite = dict(
|
|
547
759
|
info="The operational suite identifier.",
|
|
548
|
-
values=[
|
|
760
|
+
values=["oper", "dble", "dbl", "test", "mirr", "miroir"],
|
|
549
761
|
remap=dict(
|
|
550
|
-
dbl=
|
|
551
|
-
miroir=
|
|
552
|
-
)
|
|
762
|
+
dbl="dble",
|
|
763
|
+
miroir="mirr",
|
|
764
|
+
),
|
|
553
765
|
)
|
|
554
766
|
|
|
555
767
|
#: Usual definition of the ``member`` attribute
|
|
@@ -559,7 +771,9 @@ a_member = dict(
|
|
|
559
771
|
optional=True,
|
|
560
772
|
)
|
|
561
773
|
|
|
562
|
-
member = footprints.Footprint(
|
|
774
|
+
member = footprints.Footprint(
|
|
775
|
+
info="Abstract member", attr=dict(member=a_member)
|
|
776
|
+
)
|
|
563
777
|
|
|
564
778
|
#: Usual definition of the ``scenario`` attribute
|
|
565
779
|
a_scenario = dict(
|
|
@@ -567,27 +781,36 @@ a_scenario = dict(
|
|
|
567
781
|
optional=True,
|
|
568
782
|
)
|
|
569
783
|
|
|
570
|
-
scenario = footprints.Footprint(
|
|
784
|
+
scenario = footprints.Footprint(
|
|
785
|
+
info="Abstract scenario", attr=dict(scenario=a_scenario)
|
|
786
|
+
)
|
|
571
787
|
|
|
572
788
|
#: Usual definition of the ``number`` attribute (e.g. a perturbation number)
|
|
573
789
|
a_number = dict(
|
|
574
790
|
info="Any kind of numbering...",
|
|
575
791
|
type=FmtInt,
|
|
576
|
-
args=dict(fmt=
|
|
792
|
+
args=dict(fmt="03"),
|
|
577
793
|
)
|
|
578
794
|
|
|
579
|
-
number = footprints.Footprint(
|
|
795
|
+
number = footprints.Footprint(
|
|
796
|
+
info="Abstract number", attr=dict(number=a_number)
|
|
797
|
+
)
|
|
580
798
|
|
|
581
799
|
number_deco = footprints.DecorativeFootprint(
|
|
582
800
|
number,
|
|
583
|
-
decorator=[
|
|
801
|
+
decorator=[
|
|
802
|
+
namebuilding_insert(
|
|
803
|
+
"number", lambda self: self.number, setdefault=True
|
|
804
|
+
),
|
|
805
|
+
],
|
|
806
|
+
)
|
|
584
807
|
|
|
585
808
|
#: Usual definition of the ``block`` attribute
|
|
586
809
|
a_block = dict(
|
|
587
|
-
info=
|
|
810
|
+
info="The subpath where to store the data.",
|
|
588
811
|
)
|
|
589
812
|
|
|
590
|
-
block = footprints.Footprint(info=
|
|
813
|
+
block = footprints.Footprint(info="Abstract block", attr=dict(block=a_block))
|
|
591
814
|
|
|
592
815
|
#: Usual definition of the ``namespace`` attribute
|
|
593
816
|
a_namespace = dict(
|
|
@@ -596,17 +819,22 @@ a_namespace = dict(
|
|
|
596
819
|
optional=True,
|
|
597
820
|
)
|
|
598
821
|
|
|
599
|
-
namespacefp = footprints.Footprint(
|
|
600
|
-
|
|
822
|
+
namespacefp = footprints.Footprint(
|
|
823
|
+
info="Abstract namespace", attr=dict(namespace=a_namespace)
|
|
824
|
+
)
|
|
601
825
|
|
|
602
826
|
#: Usual definition of the ``storehash`` attribute
|
|
603
827
|
a_hashalgo = dict(
|
|
604
828
|
info="The hash algorithm used to check data integrity",
|
|
605
829
|
optional=True,
|
|
606
|
-
values=[
|
|
830
|
+
values=[
|
|
831
|
+
None,
|
|
832
|
+
],
|
|
607
833
|
)
|
|
608
834
|
|
|
609
|
-
hashalgo = footprints.Footprint(
|
|
835
|
+
hashalgo = footprints.Footprint(
|
|
836
|
+
info="Abstract Hash Algo", attr=dict(storehash=a_hashalgo)
|
|
837
|
+
)
|
|
610
838
|
|
|
611
839
|
hashalgo_avail_list = hashutils.HashAdapter.algorithms()
|
|
612
840
|
|
|
@@ -616,13 +844,24 @@ a_compressionpipeline = dict(
|
|
|
616
844
|
optional=True,
|
|
617
845
|
)
|
|
618
846
|
|
|
619
|
-
compressionpipeline = footprints.Footprint(
|
|
620
|
-
|
|
847
|
+
compressionpipeline = footprints.Footprint(
|
|
848
|
+
info="Abstract Compression Pipeline",
|
|
849
|
+
attr=dict(store_compressed=a_compressionpipeline),
|
|
850
|
+
)
|
|
621
851
|
|
|
622
852
|
|
|
623
853
|
def show():
|
|
624
854
|
"""Returns available items and their type."""
|
|
625
855
|
dmod = globals()
|
|
626
|
-
for stda in sorted(
|
|
627
|
-
|
|
628
|
-
|
|
856
|
+
for stda in sorted(
|
|
857
|
+
filter(
|
|
858
|
+
lambda x: x.startswith("a_")
|
|
859
|
+
or isinstance(dmod[x], footprints.Footprint),
|
|
860
|
+
dmod.keys(),
|
|
861
|
+
)
|
|
862
|
+
):
|
|
863
|
+
print(
|
|
864
|
+
"{} ( {} ) :\n {}\n".format(
|
|
865
|
+
stda, type(dmod[stda]).__name__, dmod[stda]
|
|
866
|
+
)
|
|
867
|
+
)
|