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/layout/contexts.py
CHANGED
|
@@ -18,10 +18,10 @@ __all__ = []
|
|
|
18
18
|
|
|
19
19
|
logger = loggers.getLogger(__name__)
|
|
20
20
|
|
|
21
|
-
_RHANDLERS_OBSBOARD =
|
|
22
|
-
_STORES_OBSBOARD =
|
|
21
|
+
_RHANDLERS_OBSBOARD = "Resources-Handlers"
|
|
22
|
+
_STORES_OBSBOARD = "Stores-Activity"
|
|
23
23
|
|
|
24
|
-
_PRESTAGE_REQ_ACTION =
|
|
24
|
+
_PRESTAGE_REQ_ACTION = "prestage_req"
|
|
25
25
|
|
|
26
26
|
|
|
27
27
|
# Module Interface
|
|
@@ -105,14 +105,14 @@ class ContextObserverRecorder(observer.Observer):
|
|
|
105
105
|
|
|
106
106
|
def updobsitem(self, item, info):
|
|
107
107
|
if (self._binded_context is not None) and self._binded_context.active:
|
|
108
|
-
logger.debug(
|
|
109
|
-
if info[
|
|
108
|
+
logger.debug("Recording upd item %s", item)
|
|
109
|
+
if info["observerboard"] == _RHANDLERS_OBSBOARD:
|
|
110
110
|
processed_item = item.as_dict()
|
|
111
111
|
self._stages_recorder.append((processed_item, info))
|
|
112
112
|
self._tracker_recorder.update_rh(item, info)
|
|
113
|
-
elif info[
|
|
113
|
+
elif info["observerboard"] == _STORES_OBSBOARD:
|
|
114
114
|
self._tracker_recorder.update_store(item, info)
|
|
115
|
-
if info[
|
|
115
|
+
if info["action"] == _PRESTAGE_REQ_ACTION:
|
|
116
116
|
self._prestaging_recorder.append(info)
|
|
117
117
|
|
|
118
118
|
def replay_in(self, context):
|
|
@@ -122,24 +122,33 @@ class ContextObserverRecorder(observer.Observer):
|
|
|
122
122
|
"""
|
|
123
123
|
# First the stages of the sequence
|
|
124
124
|
if self._stages_recorder:
|
|
125
|
-
logger.info(
|
|
126
|
-
|
|
125
|
+
logger.info(
|
|
126
|
+
"The recorder is replaying stages for context <%s>",
|
|
127
|
+
context.tag,
|
|
128
|
+
)
|
|
129
|
+
for pr_item, info in self._stages_recorder:
|
|
127
130
|
rh_stack = set()
|
|
128
131
|
for section in context.sequence.fastsearch(pr_item):
|
|
129
132
|
if section.rh.as_dict() == pr_item:
|
|
130
133
|
context.sequence.section_updstage(section, info)
|
|
131
134
|
rh_stack.add(section.rh)
|
|
132
135
|
for rh in rh_stack:
|
|
133
|
-
rh.external_stage_update(info.get(
|
|
136
|
+
rh.external_stage_update(info.get("stage"))
|
|
134
137
|
# Then the localtracker
|
|
135
138
|
if self._tracker_recorder is not None:
|
|
136
|
-
logger.info(
|
|
139
|
+
logger.info(
|
|
140
|
+
"The recorder is updating the LocalTracker for context <%s>",
|
|
141
|
+
context.tag,
|
|
142
|
+
)
|
|
137
143
|
context.localtracker.append(self._tracker_recorder)
|
|
138
144
|
# Finally the prestaging requests
|
|
139
145
|
if self._prestaging_recorder:
|
|
140
|
-
logger.info(
|
|
146
|
+
logger.info(
|
|
147
|
+
"The recorder is replaying prestaging requests for context <%s>",
|
|
148
|
+
context.tag,
|
|
149
|
+
)
|
|
141
150
|
for info in self._prestaging_recorder:
|
|
142
|
-
context.prestaging_hub(**
|
|
151
|
+
context.prestaging_hub(**info)
|
|
143
152
|
|
|
144
153
|
|
|
145
154
|
class DiffHistory(PrivateHistory):
|
|
@@ -147,11 +156,17 @@ class DiffHistory(PrivateHistory):
|
|
|
147
156
|
|
|
148
157
|
def append_record(self, rc, localcontainer, remotehandler):
|
|
149
158
|
"""Adds a new diff record in the current DiffHistory."""
|
|
150
|
-
rcmap = {True:
|
|
151
|
-
containerstr = (
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
159
|
+
rcmap = {True: "PASS", False: "FAIL"}
|
|
160
|
+
containerstr = (
|
|
161
|
+
str(localcontainer)
|
|
162
|
+
if localcontainer.is_virtual()
|
|
163
|
+
else localcontainer.localpath()
|
|
164
|
+
)
|
|
165
|
+
self.append(
|
|
166
|
+
"{:s}: {:s} (Ref: {!s})".format(
|
|
167
|
+
rcmap[bool(rc)], containerstr, remotehandler.provider
|
|
168
|
+
)
|
|
169
|
+
)
|
|
155
170
|
|
|
156
171
|
def datastore_inplace_overwrite(self, other):
|
|
157
172
|
"""Used by a DataStore object to refill a DiffHistory."""
|
|
@@ -163,23 +178,26 @@ class DiffHistory(PrivateHistory):
|
|
|
163
178
|
class Context(getbytag.GetByTag, observer.Observer):
|
|
164
179
|
"""Physical layout of a session or task, etc."""
|
|
165
180
|
|
|
166
|
-
_tag_default =
|
|
181
|
+
_tag_default = "ctx"
|
|
167
182
|
|
|
168
|
-
def __init__(
|
|
183
|
+
def __init__(
|
|
184
|
+
self, path=None, topenv=None, sequence=None, localtracker=None
|
|
185
|
+
):
|
|
169
186
|
"""Initiate a new execution context."""
|
|
170
|
-
logger.debug(
|
|
187
|
+
logger.debug("Context initialisation %s", self)
|
|
171
188
|
if path is None:
|
|
172
|
-
logger.critical(
|
|
173
|
-
raise ValueError(
|
|
189
|
+
logger.critical("Try to define a new context without virtual path")
|
|
190
|
+
raise ValueError("No virtual path given to new context.")
|
|
174
191
|
if topenv is None:
|
|
175
|
-
logger.critical(
|
|
176
|
-
raise ValueError(
|
|
177
|
-
self._env = Environment(
|
|
178
|
-
|
|
179
|
-
|
|
192
|
+
logger.critical("Try to define a new context without a topenv.")
|
|
193
|
+
raise ValueError("No top environment given to new context.")
|
|
194
|
+
self._env = Environment(
|
|
195
|
+
env=topenv, verbose=topenv.verbose(), contextlock=self
|
|
196
|
+
)
|
|
197
|
+
self._path = path + "/" + self.tag
|
|
180
198
|
self._session = None
|
|
181
199
|
self._rundir = None
|
|
182
|
-
self._stamp =
|
|
200
|
+
self._stamp = "-".join(("vortex", "stamp", self.tag, str(id(self))))
|
|
183
201
|
self._fstore = dict()
|
|
184
202
|
self._fstamps = set()
|
|
185
203
|
self._wkdir = None
|
|
@@ -196,22 +214,30 @@ class Context(getbytag.GetByTag, observer.Observer):
|
|
|
196
214
|
self._localtracker = localtracker
|
|
197
215
|
else:
|
|
198
216
|
# Create the localtracker within the Session's datastore
|
|
199
|
-
if self.session.datastore.check(
|
|
200
|
-
|
|
201
|
-
|
|
217
|
+
if self.session.datastore.check(
|
|
218
|
+
"context_localtracker", dict(path=self.path)
|
|
219
|
+
):
|
|
220
|
+
self._localtracker = self.session.datastore.get(
|
|
221
|
+
"context_localtracker", dict(path=self.path)
|
|
222
|
+
)
|
|
202
223
|
else:
|
|
203
|
-
self._localtracker = self.session.datastore.insert(
|
|
204
|
-
|
|
205
|
-
|
|
224
|
+
self._localtracker = self.session.datastore.insert(
|
|
225
|
+
"context_localtracker",
|
|
226
|
+
dict(path=self.path),
|
|
227
|
+
dataflow.LocalTracker(),
|
|
228
|
+
)
|
|
206
229
|
|
|
207
230
|
# Create the localtracker within the Session's datastore
|
|
208
|
-
if self.session.datastore.check(
|
|
209
|
-
|
|
210
|
-
|
|
231
|
+
if self.session.datastore.check(
|
|
232
|
+
"context_diffhistory", dict(path=self.path)
|
|
233
|
+
):
|
|
234
|
+
self._dhistory = self.session.datastore.get(
|
|
235
|
+
"context_diffhistory", dict(path=self.path)
|
|
236
|
+
)
|
|
211
237
|
else:
|
|
212
|
-
self._dhistory = self.session.datastore.insert(
|
|
213
|
-
|
|
214
|
-
|
|
238
|
+
self._dhistory = self.session.datastore.insert(
|
|
239
|
+
"context_diffhistory", dict(path=self.path), DiffHistory()
|
|
240
|
+
)
|
|
215
241
|
|
|
216
242
|
observer.get(tag=_RHANDLERS_OBSBOARD).register(self)
|
|
217
243
|
observer.get(tag=_STORES_OBSBOARD).register(self)
|
|
@@ -223,7 +249,9 @@ class Context(getbytag.GetByTag, observer.Observer):
|
|
|
223
249
|
|
|
224
250
|
def _enforce_active(self):
|
|
225
251
|
if not self.active:
|
|
226
|
-
raise RuntimeError(
|
|
252
|
+
raise RuntimeError(
|
|
253
|
+
"It's not allowed to call this method on an inactive Context."
|
|
254
|
+
)
|
|
227
255
|
|
|
228
256
|
def newobsitem(self, item, info):
|
|
229
257
|
"""
|
|
@@ -231,9 +259,14 @@ class Context(getbytag.GetByTag, observer.Observer):
|
|
|
231
259
|
Register a new section in void active context with the resource handler ``item``.
|
|
232
260
|
"""
|
|
233
261
|
if self.active:
|
|
234
|
-
logger.debug(
|
|
235
|
-
|
|
236
|
-
self
|
|
262
|
+
logger.debug(
|
|
263
|
+
"Notified %s new item of class %s and id %s",
|
|
264
|
+
self,
|
|
265
|
+
item.__class__,
|
|
266
|
+
id(item),
|
|
267
|
+
)
|
|
268
|
+
if self._record and info["observerboard"] == _RHANDLERS_OBSBOARD:
|
|
269
|
+
self._sequence.section(rh=item, stage="load")
|
|
237
270
|
|
|
238
271
|
def updobsitem(self, item, info):
|
|
239
272
|
"""
|
|
@@ -241,21 +274,21 @@ class Context(getbytag.GetByTag, observer.Observer):
|
|
|
241
274
|
Track the new stage of the section containing the resource handler ``item``.
|
|
242
275
|
"""
|
|
243
276
|
if self.active:
|
|
244
|
-
logger.debug(
|
|
245
|
-
if info[
|
|
246
|
-
if
|
|
277
|
+
logger.debug("Notified %s upd item %s", self, item)
|
|
278
|
+
if info["observerboard"] == _RHANDLERS_OBSBOARD:
|
|
279
|
+
if "stage" in info:
|
|
247
280
|
# Update the sequence
|
|
248
281
|
for section in self._sequence.fastsearch(item):
|
|
249
282
|
if section.rh is item:
|
|
250
283
|
self._sequence.section_updstage(section, info)
|
|
251
|
-
if (
|
|
284
|
+
if ("stage" in info) or ("clear" in info):
|
|
252
285
|
# Update the local tracker
|
|
253
286
|
self._localtracker.update_rh(item, info)
|
|
254
|
-
elif info[
|
|
287
|
+
elif info["observerboard"] == _STORES_OBSBOARD:
|
|
255
288
|
# Update the local tracker
|
|
256
289
|
self._localtracker.update_store(item, info)
|
|
257
|
-
if info[
|
|
258
|
-
self.prestaging_hub.record(**
|
|
290
|
+
if info["action"] == _PRESTAGE_REQ_ACTION:
|
|
291
|
+
self.prestaging_hub.record(**info)
|
|
259
292
|
|
|
260
293
|
def get_recorder(self):
|
|
261
294
|
"""Return a :obj:`ContextObserverRecorder` object recording the changes in this Context."""
|
|
@@ -275,7 +308,9 @@ class Context(getbytag.GetByTag, observer.Observer):
|
|
|
275
308
|
# It's not possible to activate a Context that lies outside the current
|
|
276
309
|
# session
|
|
277
310
|
if not self.session.active:
|
|
278
|
-
raise RuntimeError(
|
|
311
|
+
raise RuntimeError(
|
|
312
|
+
"It's not allowed to switch to a Context that belongs to an inactive session"
|
|
313
|
+
)
|
|
279
314
|
|
|
280
315
|
def focus_gain_hook(self):
|
|
281
316
|
super().focus_gain_hook()
|
|
@@ -297,7 +332,7 @@ class Context(getbytag.GetByTag, observer.Observer):
|
|
|
297
332
|
obj.catch_focus()
|
|
298
333
|
return obj
|
|
299
334
|
else:
|
|
300
|
-
logger.error(
|
|
335
|
+
logger.error("Try to switch to an undefined context: %s", tag)
|
|
301
336
|
return None
|
|
302
337
|
|
|
303
338
|
def activate(self):
|
|
@@ -314,7 +349,10 @@ class Context(getbytag.GetByTag, observer.Observer):
|
|
|
314
349
|
"""Return the session bound to the current virtual context path."""
|
|
315
350
|
if self._session is None:
|
|
316
351
|
from vortex import sessions
|
|
317
|
-
|
|
352
|
+
|
|
353
|
+
self._session = sessions.get(
|
|
354
|
+
tag=[x for x in self.path.split("/") if x][0]
|
|
355
|
+
)
|
|
318
356
|
return self._session
|
|
319
357
|
|
|
320
358
|
def _get_rundir(self):
|
|
@@ -324,12 +362,20 @@ class Context(getbytag.GetByTag, observer.Observer):
|
|
|
324
362
|
def _set_rundir(self, path):
|
|
325
363
|
"""Set a new rundir."""
|
|
326
364
|
if self._rundir:
|
|
327
|
-
logger.warning(
|
|
365
|
+
logger.warning(
|
|
366
|
+
"Context <%s> is changing its working directory <%s>",
|
|
367
|
+
self.tag,
|
|
368
|
+
self._rundir,
|
|
369
|
+
)
|
|
328
370
|
if self.system.path.isdir(path):
|
|
329
371
|
self._rundir = path
|
|
330
|
-
logger.info(
|
|
372
|
+
logger.info("Context <%s> set rundir <%s>", self.tag, self._rundir)
|
|
331
373
|
else:
|
|
332
|
-
logger.error(
|
|
374
|
+
logger.error(
|
|
375
|
+
"Try to change context <%s> to invalid path <%s>",
|
|
376
|
+
self.tag,
|
|
377
|
+
path,
|
|
378
|
+
)
|
|
333
379
|
|
|
334
380
|
rundir = property(_get_rundir, _set_rundir)
|
|
335
381
|
|
|
@@ -337,7 +383,7 @@ class Context(getbytag.GetByTag, observer.Observer):
|
|
|
337
383
|
"""Change directory to the one associated to that context."""
|
|
338
384
|
self._enforce_active()
|
|
339
385
|
if self.rundir is None:
|
|
340
|
-
subpath = self.path.replace(self.session.path,
|
|
386
|
+
subpath = self.path.replace(self.session.path, "", 1)
|
|
341
387
|
self._rundir = self.session.rundir + subpath
|
|
342
388
|
self.system.cd(self.rundir, create=True)
|
|
343
389
|
self._wkdir = self.rundir
|
|
@@ -357,9 +403,11 @@ class Context(getbytag.GetByTag, observer.Observer):
|
|
|
357
403
|
see :class:`vortex.tools.prestaging` for more details.
|
|
358
404
|
"""
|
|
359
405
|
if self._prestaging_hub is None:
|
|
360
|
-
self._prestaging_hub = vortex.tools.prestaging.get_hub(
|
|
361
|
-
|
|
362
|
-
|
|
406
|
+
self._prestaging_hub = vortex.tools.prestaging.get_hub(
|
|
407
|
+
tag="contextbound_{:s}".format(self.tag),
|
|
408
|
+
sh=self.system,
|
|
409
|
+
email=self.session.glove.email,
|
|
410
|
+
)
|
|
363
411
|
return self._prestaging_hub
|
|
364
412
|
|
|
365
413
|
@property
|
|
@@ -369,8 +417,9 @@ class Context(getbytag.GetByTag, observer.Observer):
|
|
|
369
417
|
see :class:`vortex.tools.delayedactions` for more details.
|
|
370
418
|
"""
|
|
371
419
|
if self._delayedactions_hub is None:
|
|
372
|
-
self._delayedactions_hub = PrivateDelayedActionsHub(
|
|
373
|
-
|
|
420
|
+
self._delayedactions_hub = PrivateDelayedActionsHub(
|
|
421
|
+
sh=self.system, contextrundir=self.rundir
|
|
422
|
+
)
|
|
374
423
|
return self._delayedactions_hub
|
|
375
424
|
|
|
376
425
|
@property
|
|
@@ -395,8 +444,12 @@ class Context(getbytag.GetByTag, observer.Observer):
|
|
|
395
444
|
@property
|
|
396
445
|
def subcontexts(self):
|
|
397
446
|
"""The current contexts virtually included in the current one."""
|
|
398
|
-
rootpath = self.path +
|
|
399
|
-
return [
|
|
447
|
+
rootpath = self.path + "/"
|
|
448
|
+
return [
|
|
449
|
+
x
|
|
450
|
+
for x in self.__class__.tag_values()
|
|
451
|
+
if x.path.startswith(rootpath)
|
|
452
|
+
]
|
|
400
453
|
|
|
401
454
|
def newcontext(self, name, focus=False):
|
|
402
455
|
"""
|
|
@@ -405,17 +458,19 @@ class Context(getbytag.GetByTag, observer.Observer):
|
|
|
405
458
|
as well as the default ``focus``.
|
|
406
459
|
"""
|
|
407
460
|
if name in self.__class__.tag_keys():
|
|
408
|
-
raise RuntimeError(
|
|
461
|
+
raise RuntimeError(
|
|
462
|
+
"A context with tag={!s} already exists.".format(name)
|
|
463
|
+
)
|
|
409
464
|
newctx = self.__class__(tag=name, topenv=self.env, path=self.path)
|
|
410
465
|
if focus:
|
|
411
466
|
self.__class__.set_focus(newctx)
|
|
412
467
|
return newctx
|
|
413
468
|
|
|
414
|
-
def stamp(self, tag=
|
|
469
|
+
def stamp(self, tag="default"):
|
|
415
470
|
"""Return a stamp name that could be used for any generic purpose."""
|
|
416
|
-
return self._stamp +
|
|
471
|
+
return self._stamp + "." + str(tag)
|
|
417
472
|
|
|
418
|
-
def fstrack_stamp(self, tag=
|
|
473
|
+
def fstrack_stamp(self, tag="default"):
|
|
419
474
|
"""Set a stamp to track changes on the filesystem."""
|
|
420
475
|
self._enforce_active()
|
|
421
476
|
stamp = self.stamp(tag)
|
|
@@ -423,7 +478,7 @@ class Context(getbytag.GetByTag, observer.Observer):
|
|
|
423
478
|
self.system.touch(stamp)
|
|
424
479
|
self._fstore[stamp] = set(self.system.ffind())
|
|
425
480
|
|
|
426
|
-
def fstrack_check(self, tag=
|
|
481
|
+
def fstrack_check(self, tag="default"):
|
|
427
482
|
"""
|
|
428
483
|
Return a anonymous dictionary with for the each key, the list of entries
|
|
429
484
|
in the file system that are concerned since the last associated ``tag`` stamp.
|
|
@@ -432,14 +487,18 @@ class Context(getbytag.GetByTag, observer.Observer):
|
|
|
432
487
|
self._enforce_active()
|
|
433
488
|
stamp = self.stamp(tag)
|
|
434
489
|
if not self.system.path.exists(stamp):
|
|
435
|
-
logger.warning(
|
|
490
|
+
logger.warning("Missing stamp %s", stamp)
|
|
436
491
|
return None
|
|
437
492
|
ffinded = set(self.system.ffind())
|
|
438
493
|
bkuptrace = self.system.trace
|
|
439
494
|
self.system.trace = False
|
|
440
495
|
fscheck = Tracker(self._fstore[stamp], ffinded)
|
|
441
496
|
stroot = self.system.stat(stamp)
|
|
442
|
-
fscheck.updated = [
|
|
497
|
+
fscheck.updated = [
|
|
498
|
+
f
|
|
499
|
+
for f in fscheck.unchanged
|
|
500
|
+
if self.system.stat(f).st_mtime > stroot.st_mtime
|
|
501
|
+
]
|
|
443
502
|
self.system.trace = bkuptrace
|
|
444
503
|
return fscheck
|
|
445
504
|
|
|
@@ -456,35 +515,42 @@ class Context(getbytag.GetByTag, observer.Observer):
|
|
|
456
515
|
"""Activate automatic recording of section while loading resource handlers."""
|
|
457
516
|
self._record = True
|
|
458
517
|
|
|
459
|
-
def clear_promises(
|
|
518
|
+
def clear_promises(
|
|
519
|
+
self, netloc="promise.cache.fr", scheme="vortex", storeoptions=None
|
|
520
|
+
):
|
|
460
521
|
"""Remove all promises that have been made in this context.
|
|
461
522
|
|
|
462
523
|
:param netloc: Netloc of the promise's cache store to clean up
|
|
463
524
|
:param scheme: Scheme of the promise's cache store to clean up
|
|
464
525
|
:param storeoptions: Option dictionary passed to the store (may be None)
|
|
465
526
|
"""
|
|
466
|
-
self.system.header(
|
|
527
|
+
self.system.header(
|
|
528
|
+
"Clear promises for {}://{} in context {}".format(
|
|
529
|
+
scheme, netloc, self.path
|
|
530
|
+
)
|
|
531
|
+
)
|
|
467
532
|
skeleton = dict(scheme=scheme, netloc=netloc)
|
|
468
|
-
promises = self.localtracker.grep_uri(
|
|
533
|
+
promises = self.localtracker.grep_uri("put", skeleton)
|
|
469
534
|
if promises:
|
|
470
|
-
logger.info(
|
|
535
|
+
logger.info("Some promises are left pending...")
|
|
471
536
|
if storeoptions is None:
|
|
472
537
|
storeoptions = dict()
|
|
473
|
-
store = footprints.proxy.store(
|
|
474
|
-
|
|
538
|
+
store = footprints.proxy.store(
|
|
539
|
+
scheme=scheme, netloc=netloc, **storeoptions
|
|
540
|
+
)
|
|
475
541
|
for promise in [pr.copy() for pr in promises]:
|
|
476
|
-
del promise[
|
|
477
|
-
del promise[
|
|
542
|
+
del promise["scheme"]
|
|
543
|
+
del promise["netloc"]
|
|
478
544
|
store.delete(promise)
|
|
479
545
|
else:
|
|
480
|
-
logger.info(
|
|
546
|
+
logger.info("No promises were left pending.")
|
|
481
547
|
|
|
482
548
|
def clear_stamps(self):
|
|
483
549
|
"""Remove local context stamps."""
|
|
484
550
|
if self._fstore:
|
|
485
551
|
fstamps = list(self._fstamps)
|
|
486
552
|
self.system.rmall(*fstamps)
|
|
487
|
-
logger.info(
|
|
553
|
+
logger.info("Removing context stamps %s", fstamps)
|
|
488
554
|
self._fstore = dict()
|
|
489
555
|
self._fstamps = set()
|
|
490
556
|
|
|
@@ -503,7 +569,7 @@ class Context(getbytag.GetByTag, observer.Observer):
|
|
|
503
569
|
try:
|
|
504
570
|
self.clear()
|
|
505
571
|
except TypeError:
|
|
506
|
-
logger.error(
|
|
572
|
+
logger.error("Could not clear local context <%s>", self.tag)
|
|
507
573
|
# Nullify some variable to help during garbage collection
|
|
508
574
|
self._prestaging_hub = None
|
|
509
575
|
if self._delayedactions_hub:
|