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.
- vortex/__init__.py +159 -0
- vortex/algo/__init__.py +13 -0
- vortex/algo/components.py +2462 -0
- vortex/algo/mpitools.py +1953 -0
- vortex/algo/mpitools_templates/__init__.py +1 -0
- vortex/algo/mpitools_templates/envelope_wrapper_default.tpl +27 -0
- vortex/algo/mpitools_templates/envelope_wrapper_mpiauto.tpl +29 -0
- vortex/algo/mpitools_templates/wrapstd_wrapper_default.tpl +18 -0
- vortex/algo/serversynctools.py +171 -0
- vortex/config.py +112 -0
- vortex/data/__init__.py +19 -0
- vortex/data/abstractstores.py +1510 -0
- vortex/data/containers.py +835 -0
- vortex/data/contents.py +622 -0
- vortex/data/executables.py +275 -0
- vortex/data/flow.py +119 -0
- vortex/data/geometries.ini +2689 -0
- vortex/data/geometries.py +799 -0
- vortex/data/handlers.py +1230 -0
- vortex/data/outflow.py +67 -0
- vortex/data/providers.py +487 -0
- vortex/data/resources.py +207 -0
- vortex/data/stores.py +1390 -0
- vortex/data/sync_templates/__init__.py +0 -0
- vortex/gloves.py +309 -0
- vortex/layout/__init__.py +20 -0
- vortex/layout/contexts.py +577 -0
- vortex/layout/dataflow.py +1220 -0
- vortex/layout/monitor.py +969 -0
- vortex/nwp/__init__.py +14 -0
- vortex/nwp/algo/__init__.py +21 -0
- vortex/nwp/algo/assim.py +537 -0
- vortex/nwp/algo/clim.py +1086 -0
- vortex/nwp/algo/coupling.py +831 -0
- vortex/nwp/algo/eda.py +840 -0
- vortex/nwp/algo/eps.py +785 -0
- vortex/nwp/algo/forecasts.py +886 -0
- vortex/nwp/algo/fpserver.py +1303 -0
- vortex/nwp/algo/ifsnaming.py +463 -0
- vortex/nwp/algo/ifsroot.py +404 -0
- vortex/nwp/algo/monitoring.py +263 -0
- vortex/nwp/algo/mpitools.py +694 -0
- vortex/nwp/algo/odbtools.py +1258 -0
- vortex/nwp/algo/oopsroot.py +916 -0
- vortex/nwp/algo/oopstests.py +220 -0
- vortex/nwp/algo/request.py +660 -0
- vortex/nwp/algo/stdpost.py +1641 -0
- vortex/nwp/data/__init__.py +30 -0
- vortex/nwp/data/assim.py +380 -0
- vortex/nwp/data/boundaries.py +314 -0
- vortex/nwp/data/climfiles.py +521 -0
- vortex/nwp/data/configfiles.py +153 -0
- vortex/nwp/data/consts.py +954 -0
- vortex/nwp/data/ctpini.py +149 -0
- vortex/nwp/data/diagnostics.py +209 -0
- vortex/nwp/data/eda.py +147 -0
- vortex/nwp/data/eps.py +432 -0
- vortex/nwp/data/executables.py +1045 -0
- vortex/nwp/data/fields.py +111 -0
- vortex/nwp/data/gridfiles.py +380 -0
- vortex/nwp/data/logs.py +584 -0
- vortex/nwp/data/modelstates.py +363 -0
- vortex/nwp/data/monitoring.py +193 -0
- vortex/nwp/data/namelists.py +696 -0
- vortex/nwp/data/obs.py +840 -0
- vortex/nwp/data/oopsexec.py +74 -0
- vortex/nwp/data/providers.py +207 -0
- vortex/nwp/data/query.py +206 -0
- vortex/nwp/data/stores.py +160 -0
- vortex/nwp/data/surfex.py +337 -0
- vortex/nwp/syntax/__init__.py +9 -0
- vortex/nwp/syntax/stdattrs.py +437 -0
- vortex/nwp/tools/__init__.py +10 -0
- vortex/nwp/tools/addons.py +40 -0
- vortex/nwp/tools/agt.py +67 -0
- vortex/nwp/tools/bdap.py +59 -0
- vortex/nwp/tools/bdcp.py +41 -0
- vortex/nwp/tools/bdm.py +24 -0
- vortex/nwp/tools/bdmp.py +54 -0
- vortex/nwp/tools/conftools.py +1661 -0
- vortex/nwp/tools/drhook.py +66 -0
- vortex/nwp/tools/grib.py +294 -0
- vortex/nwp/tools/gribdiff.py +104 -0
- vortex/nwp/tools/ifstools.py +203 -0
- vortex/nwp/tools/igastuff.py +273 -0
- vortex/nwp/tools/mars.py +68 -0
- vortex/nwp/tools/odb.py +657 -0
- vortex/nwp/tools/partitioning.py +258 -0
- vortex/nwp/tools/satrad.py +71 -0
- vortex/nwp/util/__init__.py +6 -0
- vortex/nwp/util/async.py +212 -0
- vortex/nwp/util/beacon.py +40 -0
- vortex/nwp/util/diffpygram.py +447 -0
- vortex/nwp/util/ens.py +279 -0
- vortex/nwp/util/hooks.py +139 -0
- vortex/nwp/util/taskdeco.py +85 -0
- vortex/nwp/util/usepygram.py +697 -0
- vortex/nwp/util/usetnt.py +101 -0
- vortex/proxy.py +6 -0
- vortex/sessions.py +374 -0
- vortex/syntax/__init__.py +9 -0
- vortex/syntax/stdattrs.py +867 -0
- vortex/syntax/stddeco.py +185 -0
- vortex/toolbox.py +1117 -0
- vortex/tools/__init__.py +20 -0
- vortex/tools/actions.py +523 -0
- vortex/tools/addons.py +316 -0
- vortex/tools/arm.py +96 -0
- vortex/tools/compression.py +325 -0
- vortex/tools/date.py +27 -0
- vortex/tools/ddhpack.py +10 -0
- vortex/tools/delayedactions.py +782 -0
- vortex/tools/env.py +541 -0
- vortex/tools/folder.py +834 -0
- vortex/tools/grib.py +738 -0
- vortex/tools/lfi.py +953 -0
- vortex/tools/listings.py +423 -0
- vortex/tools/names.py +637 -0
- vortex/tools/net.py +2124 -0
- vortex/tools/odb.py +10 -0
- vortex/tools/parallelism.py +368 -0
- vortex/tools/prestaging.py +210 -0
- vortex/tools/rawfiles.py +10 -0
- vortex/tools/schedulers.py +480 -0
- vortex/tools/services.py +940 -0
- vortex/tools/storage.py +996 -0
- vortex/tools/surfex.py +61 -0
- vortex/tools/systems.py +3976 -0
- vortex/tools/targets.py +440 -0
- vortex/util/__init__.py +9 -0
- vortex/util/config.py +1122 -0
- vortex/util/empty.py +24 -0
- vortex/util/helpers.py +216 -0
- vortex/util/introspection.py +69 -0
- vortex/util/iosponge.py +80 -0
- vortex/util/roles.py +49 -0
- vortex/util/storefunctions.py +129 -0
- vortex/util/structs.py +26 -0
- vortex/util/worker.py +162 -0
- vortex_nwp-2.0.0.dist-info/METADATA +67 -0
- vortex_nwp-2.0.0.dist-info/RECORD +144 -0
- vortex_nwp-2.0.0.dist-info/WHEEL +5 -0
- vortex_nwp-2.0.0.dist-info/licenses/LICENSE +517 -0
- vortex_nwp-2.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Usage of the TNT package.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import codecs
|
|
6
|
+
import io
|
|
7
|
+
|
|
8
|
+
from bronx.fancies import loggers
|
|
9
|
+
from bronx.syntax.externalcode import ExternalCodeImportChecker
|
|
10
|
+
|
|
11
|
+
from vortex import sessions
|
|
12
|
+
from vortex.data.stores import FunctionStoreCallbackError
|
|
13
|
+
from vortex.util.roles import setrole
|
|
14
|
+
|
|
15
|
+
logger = loggers.getLogger(__name__)
|
|
16
|
+
|
|
17
|
+
tnt_checker = ExternalCodeImportChecker("thenamelisttool")
|
|
18
|
+
with tnt_checker as tnt_register:
|
|
19
|
+
import thenamelisttool
|
|
20
|
+
|
|
21
|
+
__all__ = []
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@tnt_checker.disabled_if_unavailable
|
|
25
|
+
def compose_nam(options):
|
|
26
|
+
"""Use a TNT recipe in order to build a namelist file.
|
|
27
|
+
|
|
28
|
+
This function is designed to be executed by a
|
|
29
|
+
:obj:`vortex.data.stores.FunctionStore` object.
|
|
30
|
+
|
|
31
|
+
In order to "execute" the TNT recipe, this function requires a namelist
|
|
32
|
+
pack to be available in the inputs sequence. By default, this namelist
|
|
33
|
+
pack should have the "MainNamelistPack" role. This default value can
|
|
34
|
+
be overriden using the `nampack` attribute of the URI query.
|
|
35
|
+
|
|
36
|
+
The recipe file should be named `[source].yaml` where `[source]` stands
|
|
37
|
+
for the `source` attribute of the obj:`~nwp.data.namelists.Namelist`
|
|
38
|
+
resource object.
|
|
39
|
+
|
|
40
|
+
By defaut, the recipe file is looked for in the namelist pack mentioned
|
|
41
|
+
above. The role of an alternative pack can be designated using the
|
|
42
|
+
`dirpack` attribute of the URI.
|
|
43
|
+
|
|
44
|
+
:param dict options: All the options passed to the store plus anything from
|
|
45
|
+
the query part of the URI.
|
|
46
|
+
|
|
47
|
+
:return: Content of a :obj:`nwp.data.namelists.Namelist` resource
|
|
48
|
+
|
|
49
|
+
:rtype: A file like object
|
|
50
|
+
"""
|
|
51
|
+
rhdict = options.get("rhandler", None)
|
|
52
|
+
source = rhdict["resource"].get("source", None)
|
|
53
|
+
if source is None:
|
|
54
|
+
logger.error("Inapropriate type of resource. Got:\n%s", rhdict)
|
|
55
|
+
raise FunctionStoreCallbackError("Inapropriate type of resources.")
|
|
56
|
+
|
|
57
|
+
t = sessions.current()
|
|
58
|
+
|
|
59
|
+
def _get_pack_adress(role):
|
|
60
|
+
role = setrole(role)
|
|
61
|
+
packlist = [
|
|
62
|
+
sec.rh for sec in t.context.sequence.filtered_inputs(role=role)
|
|
63
|
+
]
|
|
64
|
+
if len(packlist) != 1:
|
|
65
|
+
logger.error("The number of namelist packs with role=%s is not 1.")
|
|
66
|
+
raise FunctionStoreCallbackError(
|
|
67
|
+
"Incorrect number of namelist packs."
|
|
68
|
+
)
|
|
69
|
+
packrh = packlist[0]
|
|
70
|
+
if packrh.resource.realkind != "namelistpack":
|
|
71
|
+
logger.error(
|
|
72
|
+
"Incorrect resource type for role %s. Resource handler:\n%s",
|
|
73
|
+
role,
|
|
74
|
+
packrh.icdard(),
|
|
75
|
+
)
|
|
76
|
+
raise FunctionStoreCallbackError("Incorrect resource type.")
|
|
77
|
+
if not packrh.container.filled:
|
|
78
|
+
logger.error(
|
|
79
|
+
"The resource handler's container is not filled for role %s",
|
|
80
|
+
role,
|
|
81
|
+
)
|
|
82
|
+
raise FunctionStoreCallbackError("RH container is not filled.")
|
|
83
|
+
return packrh.container.abspath
|
|
84
|
+
|
|
85
|
+
nampack_path = _get_pack_adress(
|
|
86
|
+
options.get("nampack", "Main Namelist Pack")
|
|
87
|
+
)
|
|
88
|
+
dirpack_role = options.get("dirpack", None)
|
|
89
|
+
dirpack_path = (
|
|
90
|
+
_get_pack_adress(dirpack_role) if dirpack_role else nampack_path
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
out_io = io.BytesIO()
|
|
94
|
+
thenamelisttool.util.compose_namelist(
|
|
95
|
+
t.sh.path.join(dirpack_path, source + ".yaml"),
|
|
96
|
+
sourcenam_directory=nampack_path,
|
|
97
|
+
sorting=thenamelisttool.namadapter.FIRST_ORDER_SORTING,
|
|
98
|
+
squeeze=False,
|
|
99
|
+
fhoutput=codecs.getwriter("utf-8")(out_io),
|
|
100
|
+
)
|
|
101
|
+
return out_io
|
vortex/proxy.py
ADDED
vortex/sessions.py
ADDED
|
@@ -0,0 +1,374 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Vortex Sessions Handling
|
|
3
|
+
|
|
4
|
+
A :mod:`vortex` session is a virtual identifier gathering information on the current
|
|
5
|
+
#usage of the toolbox. A session has a starting time, and possibly a closing
|
|
6
|
+
time. A session also defines the level of the internal logging used in all
|
|
7
|
+
the vortex modules.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import logging
|
|
11
|
+
|
|
12
|
+
from bronx.fancies import loggers
|
|
13
|
+
from bronx.datagrip.datastore import DataStore
|
|
14
|
+
from bronx.patterns import getbytag
|
|
15
|
+
from bronx.stdtypes import date
|
|
16
|
+
import footprints
|
|
17
|
+
|
|
18
|
+
from vortex.tools.env import Environment
|
|
19
|
+
|
|
20
|
+
from vortex import gloves as gloves # footprints import
|
|
21
|
+
from vortex.layout import contexts
|
|
22
|
+
|
|
23
|
+
#: No automatic export
|
|
24
|
+
__all__ = []
|
|
25
|
+
|
|
26
|
+
logger = loggers.getLogger(__name__)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
# Module Interface
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def get(**kw):
|
|
33
|
+
"""Return actual session ticket object matching description."""
|
|
34
|
+
if (
|
|
35
|
+
kw.get("tag", "current") == "current"
|
|
36
|
+
and Ticket.tag_focus() is not None
|
|
37
|
+
):
|
|
38
|
+
return current()
|
|
39
|
+
else:
|
|
40
|
+
return Ticket(**kw)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def keys():
|
|
44
|
+
"""Return the list of current session tickets names collected."""
|
|
45
|
+
return Ticket.tag_keys()
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def values():
|
|
49
|
+
"""Return the list of current session ticket values collected."""
|
|
50
|
+
return Ticket.tag_values()
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def items():
|
|
54
|
+
"""Return the items of the session tickets table."""
|
|
55
|
+
return Ticket.tag_items()
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def current():
|
|
59
|
+
"""Return the current active session."""
|
|
60
|
+
return get(tag=Ticket.tag_focus())
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def prompt():
|
|
64
|
+
"""Returns a built string that could be used as a prompt for reporting."""
|
|
65
|
+
return current().prompt
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def switch(tag=None):
|
|
69
|
+
"""Set the session associated to the actual ``tag`` as active."""
|
|
70
|
+
return current().switch(tag=tag)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def getglove(**kw):
|
|
74
|
+
"""Proxy to :mod:`gloves` collector."""
|
|
75
|
+
return footprints.proxy.gloves.default(**kw)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def system(**kw):
|
|
79
|
+
"""Returns the system associated to the current ticket."""
|
|
80
|
+
return get(tag=kw.pop("tag", Ticket.tag_focus())).system(**kw)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
# noinspection PyShadowingBuiltins
|
|
84
|
+
def exit():
|
|
85
|
+
"""Ask all inactive sessions to close, then close the active one."""
|
|
86
|
+
tags = keys()
|
|
87
|
+
xtag = Ticket.tag_focus()
|
|
88
|
+
tags.remove(xtag)
|
|
89
|
+
tags.append(xtag)
|
|
90
|
+
ok = True
|
|
91
|
+
for s in [get(tag=x) for x in tags]:
|
|
92
|
+
ok = s.exit() and ok
|
|
93
|
+
return ok
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
class Ticket(getbytag.GetByTag):
|
|
97
|
+
"""
|
|
98
|
+
Default session ticket class, defined by tag.
|
|
99
|
+
"""
|
|
100
|
+
|
|
101
|
+
_tag_default = "root"
|
|
102
|
+
|
|
103
|
+
def __init__(
|
|
104
|
+
self,
|
|
105
|
+
active=False,
|
|
106
|
+
topenv=None,
|
|
107
|
+
glove=None,
|
|
108
|
+
context=None,
|
|
109
|
+
datastore=None,
|
|
110
|
+
prompt="Vortex:",
|
|
111
|
+
):
|
|
112
|
+
self.prompt = prompt
|
|
113
|
+
self.line = "\n" + "-" * 100 + "\n"
|
|
114
|
+
|
|
115
|
+
self._started = date.now()
|
|
116
|
+
self._closed = 0
|
|
117
|
+
self._system = None
|
|
118
|
+
|
|
119
|
+
if topenv:
|
|
120
|
+
self._topenv = topenv
|
|
121
|
+
else:
|
|
122
|
+
self._topenv = Environment()
|
|
123
|
+
|
|
124
|
+
if glove:
|
|
125
|
+
self._glove = glove
|
|
126
|
+
else:
|
|
127
|
+
self._glove = getglove()
|
|
128
|
+
|
|
129
|
+
logger.debug("New session system is %s", self.system())
|
|
130
|
+
|
|
131
|
+
self._rundir = self.sh.getcwd()
|
|
132
|
+
|
|
133
|
+
logger.debug("Open session %s %s", self.tag, self)
|
|
134
|
+
|
|
135
|
+
if datastore is None:
|
|
136
|
+
datastore = DataStore(
|
|
137
|
+
default_picklefile="{:s}_session_datastore.pickled".format(
|
|
138
|
+
self.tag
|
|
139
|
+
)
|
|
140
|
+
)
|
|
141
|
+
self._dstore = datastore
|
|
142
|
+
|
|
143
|
+
if context is None:
|
|
144
|
+
context = contexts.Context(
|
|
145
|
+
tag=self.tag, topenv=self._topenv, path=self.path
|
|
146
|
+
)
|
|
147
|
+
self._last_context = context
|
|
148
|
+
|
|
149
|
+
if active:
|
|
150
|
+
self.catch_focus()
|
|
151
|
+
|
|
152
|
+
def _get_rundir(self):
|
|
153
|
+
"""Return the path of the directory associated to current session."""
|
|
154
|
+
return self._rundir
|
|
155
|
+
|
|
156
|
+
def _set_rundir(self, path):
|
|
157
|
+
"""Set a new default rundir for this session."""
|
|
158
|
+
if self._rundir:
|
|
159
|
+
logger.warning(
|
|
160
|
+
"Session <%s> is changing its working directory <%s>",
|
|
161
|
+
self.tag,
|
|
162
|
+
self._rundir,
|
|
163
|
+
)
|
|
164
|
+
if self.sh.path.isdir(path):
|
|
165
|
+
self._rundir = path
|
|
166
|
+
logger.info("Session <%s> set rundir <%s>", self.tag, self._rundir)
|
|
167
|
+
else:
|
|
168
|
+
logger.error(
|
|
169
|
+
"Try to change session <%s> to invalid path <%s>",
|
|
170
|
+
self.tag,
|
|
171
|
+
path,
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
rundir = property(_get_rundir, _set_rundir)
|
|
175
|
+
|
|
176
|
+
@property
|
|
177
|
+
def active(self):
|
|
178
|
+
"""Return whether this session is active or not."""
|
|
179
|
+
return self.has_focus()
|
|
180
|
+
|
|
181
|
+
@property
|
|
182
|
+
def started(self):
|
|
183
|
+
"""Return opening time stamp."""
|
|
184
|
+
return self._started
|
|
185
|
+
|
|
186
|
+
@property
|
|
187
|
+
def closed(self):
|
|
188
|
+
"""Return closing time stamp if any."""
|
|
189
|
+
return self._closed
|
|
190
|
+
|
|
191
|
+
@property
|
|
192
|
+
def opened(self):
|
|
193
|
+
"""Boolean. True if the session is not closed."""
|
|
194
|
+
return not bool(self.closed)
|
|
195
|
+
|
|
196
|
+
@property
|
|
197
|
+
def topenv(self):
|
|
198
|
+
"""Return top environment binded to this session."""
|
|
199
|
+
return self._topenv
|
|
200
|
+
|
|
201
|
+
@property
|
|
202
|
+
def env(self):
|
|
203
|
+
"""Return environment binded to current active context."""
|
|
204
|
+
return self.context.env
|
|
205
|
+
|
|
206
|
+
@property
|
|
207
|
+
def sh(self):
|
|
208
|
+
"""Return shell interface binded to current active context."""
|
|
209
|
+
return self._system
|
|
210
|
+
|
|
211
|
+
@property
|
|
212
|
+
def glove(self):
|
|
213
|
+
"""Return the default glove associated to this session."""
|
|
214
|
+
return self._glove
|
|
215
|
+
|
|
216
|
+
@property
|
|
217
|
+
def context(self):
|
|
218
|
+
"""Returns the active or latest context binded to this section."""
|
|
219
|
+
if self.active:
|
|
220
|
+
return contexts.current()
|
|
221
|
+
else:
|
|
222
|
+
return self._last_context
|
|
223
|
+
|
|
224
|
+
@property
|
|
225
|
+
def datastore(self):
|
|
226
|
+
return self._dstore
|
|
227
|
+
|
|
228
|
+
def system(self, **kw):
|
|
229
|
+
"""
|
|
230
|
+
Returns the current OS handler used or set a new one according
|
|
231
|
+
to ``kw`` dictionary-like arguments.
|
|
232
|
+
"""
|
|
233
|
+
refill = kw.pop("refill", False)
|
|
234
|
+
if not self._system or kw or refill:
|
|
235
|
+
self._system = footprints.proxy.system(glove=self.glove, **kw)
|
|
236
|
+
if not self._system:
|
|
237
|
+
logger.critical(
|
|
238
|
+
"Could not load a system object with description %s",
|
|
239
|
+
str(kw),
|
|
240
|
+
)
|
|
241
|
+
return self._system
|
|
242
|
+
|
|
243
|
+
def duration(self):
|
|
244
|
+
"""
|
|
245
|
+
Time since the opening of the session if still opened
|
|
246
|
+
or complete duration time if closed.
|
|
247
|
+
"""
|
|
248
|
+
if self.closed:
|
|
249
|
+
return self.closed - self.started
|
|
250
|
+
else:
|
|
251
|
+
return date.now() - self.started
|
|
252
|
+
|
|
253
|
+
def activate(self):
|
|
254
|
+
"""Force the current session as active."""
|
|
255
|
+
if self.opened:
|
|
256
|
+
return self.switch(self.tag)
|
|
257
|
+
else:
|
|
258
|
+
return False
|
|
259
|
+
|
|
260
|
+
def close(self):
|
|
261
|
+
"""Closes the current session."""
|
|
262
|
+
if self.closed:
|
|
263
|
+
logger.warning(
|
|
264
|
+
"Session %s already closed at %s", self.tag, self.closed
|
|
265
|
+
)
|
|
266
|
+
else:
|
|
267
|
+
self._closed = date.now()
|
|
268
|
+
logger.debug(
|
|
269
|
+
"Close session %s ( time = %s )", self.tag, self.duration()
|
|
270
|
+
)
|
|
271
|
+
|
|
272
|
+
@property
|
|
273
|
+
def path(self):
|
|
274
|
+
return "/" + self.tag
|
|
275
|
+
|
|
276
|
+
@property
|
|
277
|
+
def subcontexts(self):
|
|
278
|
+
"""The current contexts binded to this session."""
|
|
279
|
+
rootpath = self.path + "/"
|
|
280
|
+
return [x for x in contexts.values() if x.path.startswith(rootpath)]
|
|
281
|
+
|
|
282
|
+
def exit(self):
|
|
283
|
+
"""Exit from the current session."""
|
|
284
|
+
ok = True
|
|
285
|
+
logger.debug("Exit session %s %s", self.tag, self)
|
|
286
|
+
for kid in self.subcontexts:
|
|
287
|
+
logger.debug("Exit from context %s", kid)
|
|
288
|
+
ok = ok and kid.exit()
|
|
289
|
+
if self.opened:
|
|
290
|
+
self.close()
|
|
291
|
+
return ok
|
|
292
|
+
|
|
293
|
+
def warning(self):
|
|
294
|
+
"""Switch current loglevel to WARNING."""
|
|
295
|
+
self.setloglevel(logging.WARNING)
|
|
296
|
+
|
|
297
|
+
def debug(self):
|
|
298
|
+
"""Switch current loglevel to DEBUG."""
|
|
299
|
+
self.setloglevel(logging.DEBUG)
|
|
300
|
+
|
|
301
|
+
def info(self):
|
|
302
|
+
"""Switch current loglevel to INFO."""
|
|
303
|
+
self.setloglevel(logging.INFO)
|
|
304
|
+
|
|
305
|
+
def error(self):
|
|
306
|
+
"""Switch current loglevel to ERROR."""
|
|
307
|
+
self.setloglevel(logging.ERROR)
|
|
308
|
+
|
|
309
|
+
def critical(self):
|
|
310
|
+
"""Switch current loglevel to CRITICAL."""
|
|
311
|
+
self.setloglevel(logging.CRITICAL)
|
|
312
|
+
|
|
313
|
+
def setloglevel(self, level):
|
|
314
|
+
"""
|
|
315
|
+
Explicitly sets the logging level to the ``level`` value.
|
|
316
|
+
Shortcuts such as :method::`debug' or :method:`error` should be used.
|
|
317
|
+
"""
|
|
318
|
+
loggers.setGlobalLevel(level)
|
|
319
|
+
|
|
320
|
+
@property
|
|
321
|
+
def loglevel(self):
|
|
322
|
+
"""
|
|
323
|
+
Returns the logging level.
|
|
324
|
+
"""
|
|
325
|
+
v_logger = loggers.getLogger("vortex")
|
|
326
|
+
return logging.getLevelName(v_logger.getEffectiveLevel())
|
|
327
|
+
|
|
328
|
+
def idcard(self, indent="+ "):
|
|
329
|
+
"""Returns a printable description of the current session."""
|
|
330
|
+
card = "\n".join(
|
|
331
|
+
(
|
|
332
|
+
"{0}Name = {1:s}",
|
|
333
|
+
"{0}Started = {2!s}",
|
|
334
|
+
"{0}Opened = {3!s}",
|
|
335
|
+
"{0}Duration = {4!s}",
|
|
336
|
+
"{0}Loglevel = {5:s}",
|
|
337
|
+
)
|
|
338
|
+
).format(
|
|
339
|
+
indent,
|
|
340
|
+
self.tag,
|
|
341
|
+
self.started,
|
|
342
|
+
self.opened,
|
|
343
|
+
self.duration(),
|
|
344
|
+
self.loglevel,
|
|
345
|
+
)
|
|
346
|
+
return card
|
|
347
|
+
|
|
348
|
+
def focus_gain_hook(self):
|
|
349
|
+
"""Activate the appropriate context."""
|
|
350
|
+
super().focus_gain_hook()
|
|
351
|
+
self._last_context.catch_focus()
|
|
352
|
+
|
|
353
|
+
def focus_loose_hook(self):
|
|
354
|
+
"""Keep track of the latest context."""
|
|
355
|
+
super().focus_loose_hook()
|
|
356
|
+
self._last_context = self.context
|
|
357
|
+
|
|
358
|
+
@classmethod
|
|
359
|
+
def switch(cls, tag=None):
|
|
360
|
+
"""
|
|
361
|
+
Allows the user to switch to an other session,
|
|
362
|
+
assuming that the provided tag is already known.
|
|
363
|
+
"""
|
|
364
|
+
if tag in cls.tag_keys():
|
|
365
|
+
obj = Ticket(tag=tag)
|
|
366
|
+
obj.catch_focus()
|
|
367
|
+
return obj
|
|
368
|
+
else:
|
|
369
|
+
logger.error("Try to switch to an undefined session: %s", tag)
|
|
370
|
+
return None
|
|
371
|
+
|
|
372
|
+
def __del__(self):
|
|
373
|
+
if self.opened:
|
|
374
|
+
self.close()
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"""
|
|
2
|
+
The :mod:`vortex` syntax mostly deals with attributes resolution and arguments expansion.
|
|
3
|
+
The most important usage is done by :class:`FootprintBase` derivated objects.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
#: No automatic export
|
|
7
|
+
__all__ = []
|
|
8
|
+
|
|
9
|
+
__tocinfoline__ = "VORTEX package where standard attributes are defined."
|