|
@@ -6,6 +6,7 @@ import types
|
6
|
6
|
import os
|
7
|
7
|
import os.path
|
8
|
8
|
import re
|
|
9
|
+import copy
|
9
|
10
|
|
10
|
11
|
import warnings #For the moment no way to use the logger in this file (I guess)
|
11
|
12
|
|
|
@@ -107,10 +108,16 @@ class LodelContext(object):
|
107
|
108
|
##@brief Create a new context
|
108
|
109
|
#@see LodelContext.new()
|
109
|
110
|
def __init__(self, site_id, instance_path = None):
|
110
|
|
- print("New context instanciation named '%s'" % site_id)
|
|
111
|
+ if site_id is None and self.multisite():
|
|
112
|
+ site_id = LOAD_CTX
|
|
113
|
+ if self.multisite() and site_id is not LOAD_CTX:
|
|
114
|
+ with LodelContext.with_context(None) as ctx:
|
|
115
|
+ ctx.expose_modules(globals(), {'lodel.logger': 'logger'})
|
|
116
|
+ logger.info("New context instanciation named '%s'" % site_id)
|
111
|
117
|
if site_id is None:
|
|
118
|
+ self.__id = None
|
112
|
119
|
#Monosite instanciation
|
113
|
|
- if self.__class__._type != self.__class__.MONOSITE:
|
|
120
|
+ if self.multisite():
|
114
|
121
|
raise ContextError("Cannot instanciate a context with \
|
115
|
122
|
site_id set to None when we are in MULTISITE beahavior")
|
116
|
123
|
else:
|
|
@@ -121,7 +128,7 @@ site_id set to None when we are in MULTISITE beahavior")
|
121
|
128
|
return
|
122
|
129
|
else:
|
123
|
130
|
#Multisite instanciation
|
124
|
|
- if self.__class__._type != self.__class__.MULTISITE:
|
|
131
|
+ if not self.multisite():
|
125
|
132
|
raise ContextError("Cannot instanciate a context with a \
|
126
|
133
|
site_id when we are in MONOSITE beahvior")
|
127
|
134
|
if not self.validate_identifier(site_id):
|
|
@@ -145,6 +152,8 @@ a context without a path......")
|
145
|
152
|
#Importing the site package to trigger its creation
|
146
|
153
|
self.__package = importlib.import_module(self.__pkg_name)
|
147
|
154
|
self.__class__._contexts[site_id] = self
|
|
155
|
+ #Designed to be use by with statement
|
|
156
|
+ self.__previous_ctx = None
|
148
|
157
|
|
149
|
158
|
##@brief Expose a module from the context
|
150
|
159
|
#@param globs globals : globals where we have to expose the module
|
|
@@ -165,6 +174,14 @@ length == 2 but got : %s" % spec)
|
165
|
174
|
sys.path.append(self.__instance_path)
|
166
|
175
|
dyncode = importlib.import_module('leapi_dyncode')
|
167
|
176
|
self.safe_exposure(globs, dyncode, alias)
|
|
177
|
+
|
|
178
|
+ @classmethod
|
|
179
|
+ def multisite(cls):
|
|
180
|
+ return cls._type == cls.MULTISITE
|
|
181
|
+
|
|
182
|
+ @classmethod
|
|
183
|
+ def with_context(cls, target_ctx_id):
|
|
184
|
+ return cls.get(target_ctx_id)
|
168
|
185
|
|
169
|
186
|
##@brief Utility method to expose a module with an alias name in globals
|
170
|
187
|
#@param globs globals() : concerned globals dict
|
|
@@ -220,13 +237,29 @@ submodule : '%s'" % module_fullname)
|
220
|
237
|
if site_id not in cls._contexts:
|
221
|
238
|
raise ContextError("No context named '%s' found." % site_id)
|
222
|
239
|
cls._current = cls._contexts[site_id]
|
|
240
|
+ return cls._current
|
|
241
|
+
|
|
242
|
+ ##@brief Getter for contexts
|
|
243
|
+ #@param ctx_id str | None | False : if False return the current context
|
|
244
|
+ #@return A LodelContext instance
|
|
245
|
+ @classmethod
|
|
246
|
+ def get(cls, ctx_id = False):
|
|
247
|
+ if ctx_id is False:
|
|
248
|
+ if cls._current is None:
|
|
249
|
+ raise ContextError("No context loaded")
|
|
250
|
+ return cls._current
|
|
251
|
+ ctx_id = LOAD_CTX if ctx_id is None else ctx_id
|
|
252
|
+ if ctx_id not in cls._contexts:
|
|
253
|
+ raise ContextError("No context identified by '%s'" % ctx_id)
|
|
254
|
+ return cls._contexts[ctx_id]
|
223
|
255
|
|
224
|
|
- ##@brief Helper method that returns the current context
|
|
256
|
+ ##@brief Returns the name of the loaded context
|
225
|
257
|
@classmethod
|
226
|
|
- def get(cls):
|
|
258
|
+ def get_name(cls):
|
227
|
259
|
if cls._current is None:
|
228
|
260
|
raise ContextError("No context loaded")
|
229
|
|
- return cls._current
|
|
261
|
+ return copy.copy(cls._current.__id)
|
|
262
|
+
|
230
|
263
|
|
231
|
264
|
##@brief Create a new context given a context name
|
232
|
265
|
#
|
|
@@ -349,7 +382,7 @@ MONOSITE mode")
|
349
|
382
|
"Unable to create a context named '%s'" % site_id)
|
350
|
383
|
cls.new(site_id, path)
|
351
|
384
|
return site_id
|
352
|
|
-
|
|
385
|
+
|
353
|
386
|
##@brief Delete a site's context
|
354
|
387
|
#@param site_id str : the site's name to remove the context
|
355
|
388
|
def remove(cls, site_id):
|
|
@@ -367,5 +400,24 @@ site_id set to None when we are in MULTISITE beahavior")
|
367
|
400
|
else:
|
368
|
401
|
raise ContextError("Cannot have a context with \
|
369
|
402
|
site_id set when we are in MONOSITE beahavior")
|
370
|
|
-
|
|
403
|
+
|
|
404
|
+ ##@brief Implements the with statement behavior
|
|
405
|
+ def __enter__(self):
|
|
406
|
+ if self.__previous_ctx is not None:
|
|
407
|
+ raise ContextError("__enter__ called but a previous context \
|
|
408
|
+is allready registered !!! Bailout")
|
|
409
|
+ current = LodelContext.get().__id
|
|
410
|
+ if current != self.__id:
|
|
411
|
+ #Only switch if necessary
|
|
412
|
+ self.__previous_ctx = LodelContext.get().__id
|
|
413
|
+ LodelContext.set(self.__id)
|
|
414
|
+ return self
|
|
415
|
+
|
|
416
|
+ ##@brief Implements the with statement behavior
|
|
417
|
+ def __exit__(self, exc_type, exc_val, exc_tb):
|
|
418
|
+ prev = self.__previous_ctx
|
|
419
|
+ self.__previous_ctx = None
|
|
420
|
+ if prev is not None:
|
|
421
|
+ #Only restore if needed
|
|
422
|
+ LodelContext.set(self.__previous_ctx)
|
371
|
423
|
|