vortex-nwp 2.0.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 (144) hide show
  1. vortex/__init__.py +159 -0
  2. vortex/algo/__init__.py +13 -0
  3. vortex/algo/components.py +2462 -0
  4. vortex/algo/mpitools.py +1953 -0
  5. vortex/algo/mpitools_templates/__init__.py +1 -0
  6. vortex/algo/mpitools_templates/envelope_wrapper_default.tpl +27 -0
  7. vortex/algo/mpitools_templates/envelope_wrapper_mpiauto.tpl +29 -0
  8. vortex/algo/mpitools_templates/wrapstd_wrapper_default.tpl +18 -0
  9. vortex/algo/serversynctools.py +171 -0
  10. vortex/config.py +112 -0
  11. vortex/data/__init__.py +19 -0
  12. vortex/data/abstractstores.py +1510 -0
  13. vortex/data/containers.py +835 -0
  14. vortex/data/contents.py +622 -0
  15. vortex/data/executables.py +275 -0
  16. vortex/data/flow.py +119 -0
  17. vortex/data/geometries.ini +2689 -0
  18. vortex/data/geometries.py +799 -0
  19. vortex/data/handlers.py +1230 -0
  20. vortex/data/outflow.py +67 -0
  21. vortex/data/providers.py +487 -0
  22. vortex/data/resources.py +207 -0
  23. vortex/data/stores.py +1390 -0
  24. vortex/data/sync_templates/__init__.py +0 -0
  25. vortex/gloves.py +309 -0
  26. vortex/layout/__init__.py +20 -0
  27. vortex/layout/contexts.py +577 -0
  28. vortex/layout/dataflow.py +1220 -0
  29. vortex/layout/monitor.py +969 -0
  30. vortex/nwp/__init__.py +14 -0
  31. vortex/nwp/algo/__init__.py +21 -0
  32. vortex/nwp/algo/assim.py +537 -0
  33. vortex/nwp/algo/clim.py +1086 -0
  34. vortex/nwp/algo/coupling.py +831 -0
  35. vortex/nwp/algo/eda.py +840 -0
  36. vortex/nwp/algo/eps.py +785 -0
  37. vortex/nwp/algo/forecasts.py +886 -0
  38. vortex/nwp/algo/fpserver.py +1303 -0
  39. vortex/nwp/algo/ifsnaming.py +463 -0
  40. vortex/nwp/algo/ifsroot.py +404 -0
  41. vortex/nwp/algo/monitoring.py +263 -0
  42. vortex/nwp/algo/mpitools.py +694 -0
  43. vortex/nwp/algo/odbtools.py +1258 -0
  44. vortex/nwp/algo/oopsroot.py +916 -0
  45. vortex/nwp/algo/oopstests.py +220 -0
  46. vortex/nwp/algo/request.py +660 -0
  47. vortex/nwp/algo/stdpost.py +1641 -0
  48. vortex/nwp/data/__init__.py +30 -0
  49. vortex/nwp/data/assim.py +380 -0
  50. vortex/nwp/data/boundaries.py +314 -0
  51. vortex/nwp/data/climfiles.py +521 -0
  52. vortex/nwp/data/configfiles.py +153 -0
  53. vortex/nwp/data/consts.py +954 -0
  54. vortex/nwp/data/ctpini.py +149 -0
  55. vortex/nwp/data/diagnostics.py +209 -0
  56. vortex/nwp/data/eda.py +147 -0
  57. vortex/nwp/data/eps.py +432 -0
  58. vortex/nwp/data/executables.py +1045 -0
  59. vortex/nwp/data/fields.py +111 -0
  60. vortex/nwp/data/gridfiles.py +380 -0
  61. vortex/nwp/data/logs.py +584 -0
  62. vortex/nwp/data/modelstates.py +363 -0
  63. vortex/nwp/data/monitoring.py +193 -0
  64. vortex/nwp/data/namelists.py +696 -0
  65. vortex/nwp/data/obs.py +840 -0
  66. vortex/nwp/data/oopsexec.py +74 -0
  67. vortex/nwp/data/providers.py +207 -0
  68. vortex/nwp/data/query.py +206 -0
  69. vortex/nwp/data/stores.py +160 -0
  70. vortex/nwp/data/surfex.py +337 -0
  71. vortex/nwp/syntax/__init__.py +9 -0
  72. vortex/nwp/syntax/stdattrs.py +437 -0
  73. vortex/nwp/tools/__init__.py +10 -0
  74. vortex/nwp/tools/addons.py +40 -0
  75. vortex/nwp/tools/agt.py +67 -0
  76. vortex/nwp/tools/bdap.py +59 -0
  77. vortex/nwp/tools/bdcp.py +41 -0
  78. vortex/nwp/tools/bdm.py +24 -0
  79. vortex/nwp/tools/bdmp.py +54 -0
  80. vortex/nwp/tools/conftools.py +1661 -0
  81. vortex/nwp/tools/drhook.py +66 -0
  82. vortex/nwp/tools/grib.py +294 -0
  83. vortex/nwp/tools/gribdiff.py +104 -0
  84. vortex/nwp/tools/ifstools.py +203 -0
  85. vortex/nwp/tools/igastuff.py +273 -0
  86. vortex/nwp/tools/mars.py +68 -0
  87. vortex/nwp/tools/odb.py +657 -0
  88. vortex/nwp/tools/partitioning.py +258 -0
  89. vortex/nwp/tools/satrad.py +71 -0
  90. vortex/nwp/util/__init__.py +6 -0
  91. vortex/nwp/util/async.py +212 -0
  92. vortex/nwp/util/beacon.py +40 -0
  93. vortex/nwp/util/diffpygram.py +447 -0
  94. vortex/nwp/util/ens.py +279 -0
  95. vortex/nwp/util/hooks.py +139 -0
  96. vortex/nwp/util/taskdeco.py +85 -0
  97. vortex/nwp/util/usepygram.py +697 -0
  98. vortex/nwp/util/usetnt.py +101 -0
  99. vortex/proxy.py +6 -0
  100. vortex/sessions.py +374 -0
  101. vortex/syntax/__init__.py +9 -0
  102. vortex/syntax/stdattrs.py +867 -0
  103. vortex/syntax/stddeco.py +185 -0
  104. vortex/toolbox.py +1117 -0
  105. vortex/tools/__init__.py +20 -0
  106. vortex/tools/actions.py +523 -0
  107. vortex/tools/addons.py +316 -0
  108. vortex/tools/arm.py +96 -0
  109. vortex/tools/compression.py +325 -0
  110. vortex/tools/date.py +27 -0
  111. vortex/tools/ddhpack.py +10 -0
  112. vortex/tools/delayedactions.py +782 -0
  113. vortex/tools/env.py +541 -0
  114. vortex/tools/folder.py +834 -0
  115. vortex/tools/grib.py +738 -0
  116. vortex/tools/lfi.py +953 -0
  117. vortex/tools/listings.py +423 -0
  118. vortex/tools/names.py +637 -0
  119. vortex/tools/net.py +2124 -0
  120. vortex/tools/odb.py +10 -0
  121. vortex/tools/parallelism.py +368 -0
  122. vortex/tools/prestaging.py +210 -0
  123. vortex/tools/rawfiles.py +10 -0
  124. vortex/tools/schedulers.py +480 -0
  125. vortex/tools/services.py +940 -0
  126. vortex/tools/storage.py +996 -0
  127. vortex/tools/surfex.py +61 -0
  128. vortex/tools/systems.py +3976 -0
  129. vortex/tools/targets.py +440 -0
  130. vortex/util/__init__.py +9 -0
  131. vortex/util/config.py +1122 -0
  132. vortex/util/empty.py +24 -0
  133. vortex/util/helpers.py +216 -0
  134. vortex/util/introspection.py +69 -0
  135. vortex/util/iosponge.py +80 -0
  136. vortex/util/roles.py +49 -0
  137. vortex/util/storefunctions.py +129 -0
  138. vortex/util/structs.py +26 -0
  139. vortex/util/worker.py +162 -0
  140. vortex_nwp-2.0.0.dist-info/METADATA +67 -0
  141. vortex_nwp-2.0.0.dist-info/RECORD +144 -0
  142. vortex_nwp-2.0.0.dist-info/WHEEL +5 -0
  143. vortex_nwp-2.0.0.dist-info/licenses/LICENSE +517 -0
  144. vortex_nwp-2.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,325 @@
1
+ """
2
+ Stream/File compression tools.
3
+
4
+ The user interface for such tools is the :class:`CompressionPipeline`.
5
+ """
6
+
7
+ from contextlib import contextmanager
8
+ import io
9
+ import functools
10
+ import operator
11
+
12
+ import footprints
13
+ from bronx.fancies import loggers
14
+ from vortex.util.iosponge import IoSponge
15
+
16
+
17
+ #: No automatic export
18
+ __all__ = []
19
+
20
+ logger = loggers.getLogger(__name__)
21
+
22
+
23
+ class CompressionPipeline:
24
+ """Main interface to data compression algorithms."""
25
+
26
+ def __init__(self, system, compression=""):
27
+ """
28
+ :param System system: The system object that will be used to carry out
29
+ the task.
30
+ :param str compression: The description of the compression tools that
31
+ will be used in this compression pipeline.
32
+ (e.g. 'gzip' will just compress/uncompress using the gzip software,
33
+ 'gzip|bzip2' will use the gzip software piped to the bzip2 software
34
+ (which is useless), 'gzip&complevel=5' will use the gzip software
35
+ with a compression factor of 5.)
36
+
37
+ :note: See the subclasses of :class:`CompressionUnit` for a description
38
+ of available compression tools (and their options).
39
+ """
40
+ self._units = list()
41
+ self._sh = system
42
+ self.description_string = compression
43
+ for c in [c for c in compression.split("|") if c]:
44
+ c_raw = c.split("&")
45
+ ckind = c_raw.pop(0)
46
+ cargs = dict([arg.split("=", 1) for arg in c_raw])
47
+ self.add_compression_unit(ckind, **cargs)
48
+
49
+ def add_compression_unit(self, unit, **kwargs):
50
+ """Add a new compression tool to the compression pipeline.
51
+
52
+ :param str unit: The kind of the compression tool (see :class:`CompressionUnit`
53
+ subclases
54
+ :param kwargs: Options that will be used during the compression tool
55
+ initialisation
56
+ """
57
+ c_unit = footprints.proxy.compression_unit(kind=unit, **kwargs)
58
+ if c_unit is None:
59
+ raise ValueError(
60
+ "The {:s} compression unit could not be found.".format(unit)
61
+ )
62
+ self._units.append(c_unit)
63
+
64
+ @property
65
+ def units(self):
66
+ """The list of compression tools forming the compression pipeline."""
67
+ return self._units
68
+
69
+ @property
70
+ def _rawftp_shell(self):
71
+ """The name of the corresponding rawftp specialshell (if relevant)."""
72
+ if len(self.units) == 1:
73
+ return self.units[0].rawftp_shell(self._sh)
74
+ else:
75
+ return None
76
+
77
+ @property
78
+ def suffix(self):
79
+ """The suffix usualy associated with this compression pipeline."""
80
+ s = ".".join([s.suffix for s in self.units])
81
+ return "." + s if s else ""
82
+
83
+ @property
84
+ def compression_factor(self):
85
+ """The minimal compression factor expected with such a compression pipeline."""
86
+ return functools.reduce(
87
+ operator.mul, [s.cfactor for s in self.units], 1.0
88
+ )
89
+
90
+ @staticmethod
91
+ def _inputstream_size(stream):
92
+ """Find out the size of a seekable input stream."""
93
+ estimated_size = 0
94
+ try:
95
+ stream.seek(0, io.SEEK_END)
96
+ estimated_size = stream.tell()
97
+ stream.seek(0)
98
+ except AttributeError:
99
+ logger.warning("Could not rewind <source:%s>", str(stream))
100
+ except OSError:
101
+ logger.debug("Seek trouble <source:%s>", str(stream))
102
+ return estimated_size
103
+
104
+ @contextmanager
105
+ def _openstream(self, local, mode="rb"):
106
+ """If *local* is not an opened file, open it..."""
107
+ if isinstance(local, str):
108
+ localfh = open(local, mode)
109
+ yield localfh
110
+ localfh.close()
111
+ elif isinstance(local, io.IOBase):
112
+ yield local
113
+ else:
114
+ raise ValueError("Unknown type for {!s}".format(local))
115
+
116
+ def _genericstream_close(self, processes):
117
+ """Close a list of Popen objects (and look for the returncode)."""
118
+ for i, p in enumerate(processes):
119
+ if not self._sh.pclose(p):
120
+ logger.error(
121
+ "Abnormal return code for one of the processes (#%d)", i
122
+ )
123
+
124
+ @contextmanager
125
+ def compress2stream(self, local, iosponge=False):
126
+ """Compress *local* into a pipe or an :class:`IoSponge` object.
127
+
128
+ *local* can be an opened file-like object or a filename.
129
+
130
+ This method creates a context manager. Example::
131
+
132
+ source='myfile'
133
+ cp = CompressionPipeline(systemobj, 'gzip')
134
+ ftp = systemobj.ftp('hendrix.meteo.fr')
135
+ with cp.compress2stream(source) as csource:
136
+ ftp.put(csource, 'remote_compressedfile')
137
+
138
+ When leaving the context, the gzip process that compresses the data will
139
+ be properly closed
140
+ """
141
+ with self._openstream(local) as stream:
142
+ estimated_size = (
143
+ self._inputstream_size(stream) * self.compression_factor
144
+ )
145
+ processes = list()
146
+ lstream = stream
147
+ for unit in self.units:
148
+ p = unit.compress(self._sh, lstream)
149
+ lstream = p.stdout
150
+ processes.append(p)
151
+ if iosponge:
152
+ yield IoSponge(lstream, guessed_size=estimated_size)
153
+ else:
154
+ yield lstream
155
+ self._genericstream_close(processes)
156
+
157
+ def _xcopyfileobj(self, in_fh, out_fh):
158
+ try:
159
+ self._sh.copyfileobj(in_fh, out_fh)
160
+ except OSError:
161
+ return False
162
+ else:
163
+ return True
164
+
165
+ def compress2file(self, local, destination):
166
+ """Compress *local* into a file (named *destination*)
167
+
168
+ *local* can be an opened file-like object or a filename.
169
+ *destination* is a filename.
170
+ """
171
+ with open(destination, "wb") as fhout:
172
+ with self.compress2stream(local) as fhcompressed:
173
+ return self._xcopyfileobj(fhcompressed, fhout)
174
+
175
+ def compress2rawftp(self, local):
176
+ """
177
+ Return the name of the rawftp's specialshell that can be used to
178
+ compress the *local* data. It might return None.
179
+ """
180
+ return self._rawftp_shell
181
+
182
+ @contextmanager
183
+ def stream2uncompress(self, destination):
184
+ """Uncompress piped data to *destination*.
185
+
186
+ *destination* can be an opened file-like object or a filename.
187
+
188
+ This method creates a context manager. Example::
189
+
190
+ destination='mydownloadedfile'
191
+ cp = CompressionPipeline(systemobj, 'gzip')
192
+ ftp = systemobj.ftp('hendrix.meteo.fr')
193
+ with cp.stream2uncompress(destination) as cdestination:
194
+ ftp.get('remote_compressedfile', cdestination)
195
+
196
+ When leaving the context, the gunzip process that uncompresses the data
197
+ will be properly closed.
198
+ """
199
+ with self._openstream(destination, "wb") as dstream:
200
+ processes = list()
201
+ instream = True
202
+ nunits = len(self.units)
203
+ for i, unit in enumerate(reversed(self.units)):
204
+ outstream = dstream if i == nunits - 1 else True
205
+ p = unit.uncompress(self._sh, instream, outstream)
206
+ instream = p.stdout
207
+ processes.append(p)
208
+ yield processes[0].stdin
209
+ self._genericstream_close(processes)
210
+
211
+ def file2uncompress(self, local, destination):
212
+ """Uncompress *local* into *destination*.
213
+
214
+ *local* is a filename.
215
+ *destination* can be an opened file-like object or a filename.
216
+ """
217
+ with self.stream2uncompress(destination) as fhuncompressed:
218
+ with open(local, "rb") as fhcompressed:
219
+ return self._xcopyfileobj(fhcompressed, fhuncompressed)
220
+
221
+
222
+ class CompressionUnit(footprints.FootprintBase):
223
+ """Defines compress/uncompress methods for a given compression tool."""
224
+
225
+ _abstract = True
226
+ _collector = ("compression_unit",)
227
+ _footprint = dict(
228
+ info="Abstract Compression Unit",
229
+ attr=dict(
230
+ kind=dict(
231
+ info="The name of the compression tool.",
232
+ ),
233
+ suffix=dict(
234
+ info="The usual file extension for this compression tool.",
235
+ optional=True,
236
+ ),
237
+ cfactor=dict(
238
+ info="The usual compression factor for this compression tool.",
239
+ type=float,
240
+ default=1.0,
241
+ optional=True,
242
+ ),
243
+ ),
244
+ )
245
+
246
+ def rawftp_shell(self, sh):
247
+ """The rawftp's speciall shell that may carry out a comparable compression."""
248
+ return None
249
+
250
+ def _run_in_pipe(self, sh, cmd, stream, outstream=True):
251
+ """Run *cmd* with the piped input *stream*."""
252
+ p = sh.popen(cmd, stdin=stream, stdout=outstream, bufsize=8192)
253
+ return p
254
+
255
+ def compress(self, sh, stream):
256
+ """Compress the input *stream*. Returns a Popen object."""
257
+ raise NotImplementedError()
258
+
259
+ def uncompress(self, sh, stream, outstream=True):
260
+ """Uncompress the input *stream*. Returns a Popen object."""
261
+ raise NotImplementedError()
262
+
263
+
264
+ class GzipCompressionUnit(CompressionUnit):
265
+ _footprint = dict(
266
+ info="Compress/Uncompress a stream using gzip",
267
+ attr=dict(
268
+ kind=dict(values=["gzip", "gz"]),
269
+ suffix=dict(
270
+ default="gz",
271
+ ),
272
+ complevel=dict(
273
+ info="The gzip algorithm compression level (see 'man gzip')",
274
+ type=int,
275
+ values=range(1, 10),
276
+ default=6,
277
+ optional=True,
278
+ ),
279
+ cfactor=dict(default=0.9),
280
+ ),
281
+ )
282
+
283
+ def compress(self, sh, stream):
284
+ """Compress the input *stream*. Returns a Popen object."""
285
+ return self._run_in_pipe(
286
+ sh, ["gzip", "--stdout", "-{!s}".format(self.complevel)], stream
287
+ )
288
+
289
+ def uncompress(self, sh, stream, outstream=True):
290
+ """Uncompress the input *stream*. Returns a Popen object."""
291
+ return self._run_in_pipe(sh, ["gunzip", "--stdout"], stream, outstream)
292
+
293
+
294
+ class Bzip2CompressionUnit(CompressionUnit):
295
+ _footprint = dict(
296
+ info="Compress/Uncompress a stream using bzip2",
297
+ attr=dict(
298
+ kind=dict(values=["bzip2", "bz2"]),
299
+ suffix=dict(
300
+ default="bz2",
301
+ ),
302
+ complevel=dict(
303
+ info="The bzip2 algorithm compression level (see 'man bzip2')",
304
+ type=int,
305
+ values=range(1, 10),
306
+ default=9,
307
+ optional=True,
308
+ ),
309
+ cfactor=dict(
310
+ default=0.85,
311
+ ),
312
+ ),
313
+ )
314
+
315
+ def compress(self, sh, stream):
316
+ """Compress the input *stream*. Returns a Popen object."""
317
+ return self._run_in_pipe(
318
+ sh, ["bzip2", "--stdout", "-{!s}".format(self.complevel)], stream
319
+ )
320
+
321
+ def uncompress(self, sh, stream, outstream=True):
322
+ """Uncompress the input *stream*. Returns a Popen object."""
323
+ return self._run_in_pipe(
324
+ sh, ["bunzip2", "--stdout"], stream, outstream
325
+ )
vortex/tools/date.py ADDED
@@ -0,0 +1,27 @@
1
+ """
2
+ Classes and functions form this module are dedicated to the manipulation of
3
+ date and time quantities.
4
+
5
+ It is kept for backward compatibility, however :mod:`bronx.stdtypes.date` should
6
+ be used now and on.
7
+ """
8
+
9
+ import sys
10
+
11
+ from bronx.stdtypes import date as _b_date
12
+
13
+ _ALIASES = _b_date.local_date_functions.copy()
14
+ _ALIASES.update(
15
+ dict(
16
+ guess=_b_date.guess,
17
+ daterange=_b_date.daterange,
18
+ stamp=_b_date.stamp,
19
+ Period=_b_date.Period,
20
+ Date=_b_date.Date,
21
+ Time=_b_date.Time,
22
+ Month=_b_date.Month,
23
+ )
24
+ )
25
+
26
+ for n, obj in _ALIASES.items():
27
+ sys.modules[__name__].__dict__.update(_ALIASES)
@@ -0,0 +1,10 @@
1
+ """
2
+ Module needed to interact with subdirectories of DDH files.
3
+
4
+ :warning: Do not use this module. It is deprecated
5
+ """
6
+
7
+ # Backward compatibility...
8
+ from . import folder
9
+
10
+ DdhPackShell = folder.DdhPackShell