Kaynağa Gözat

Now we can use LodelContext with the with statement

Yann Weber 7 yıl önce
ebeveyn
işleme
dbcccb2bbf
1 değiştirilmiş dosya ile 60 ekleme ve 8 silme
  1. 60
    8
      lodel/context.py

+ 60
- 8
lodel/context.py Dosyayı Görüntüle

@@ -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
 

Loading…
İptal
Kaydet