Browse Source

Bugfix + forgotten file for lodelsites implementation

Yann Weber 7 years ago
parent
commit
26f586ad84
3 changed files with 179 additions and 5 deletions
  1. 8
    3
      lodel/context.py
  2. 0
    2
      lodel/plugins/multisite/loader.py
  3. 171
    0
      lodel/plugins/multisite/loader_utils.py

+ 8
- 3
lodel/context.py View File

@@ -206,6 +206,9 @@ a context without a path......")
206 206
             self.__class__._contexts[site_id] = self
207 207
         #Designed to be use by with statement
208 208
         self.__previous_ctx = None
209
+
210
+    def __repr__(self):
211
+        return '<LodelContext name="%s">' % self.__id
209 212
     
210 213
     ##@brief Expose a module from the context
211 214
     #@param globs globals : globals where we have to expose the module
@@ -285,7 +288,7 @@ site_id set to None when we are in MULTISITE beahavior")
285 288
 : '%s'" % site_id)
286 289
         if site_id not in cls._contexts:
287 290
             raise ContextError("No context named '%s' found." % site_id)
288
-        if cls.current_id != LOAD_CTX and site_id != LOAD_CTX:
291
+        if cls.current_id() != LOAD_CTX and site_id != LOAD_CTX:
289 292
             raise ContextError("Not allowed to switch into a site context \
290 293
 from another site context. You have to switch back to LOAD_CTX before")
291 294
         wanted_ctx = cls._contexts[site_id]
@@ -316,7 +319,7 @@ from another site context. You have to switch back to LOAD_CTX before")
316 319
         return copy.copy(cls._current.__id)
317 320
         
318 321
 
319
-    ##@brief Create a new context given a context name
322
+    ##@brief Create a new context given a context name and switch in it
320 323
     #
321 324
     #@note It's just an alias to the LodelContext.__init__ method
322 325
     #@param site_id str : context name
@@ -398,7 +401,9 @@ initialize it anymore")
398 401
             #Add custom MetaPathFinder allowing implementing custom imports
399 402
             sys.meta_path = [LodelMetaPathFinder] + sys.meta_path
400 403
             #Create and set __loader__ context
401
-            cls.new(LOAD_CTX)
404
+            ctx = cls.new(LOAD_CTX)
405
+            #DIRTY enforcing
406
+            cls._current = ctx
402 407
             cls.set(LOAD_CTX)
403 408
         else:
404 409
             #Add a single context with no site_id

+ 0
- 2
lodel/plugins/multisite/loader.py View File

@@ -46,8 +46,6 @@ if not settings.started():
46 46
 LodelContext.expose_modules(globals(), {
47 47
     'lodel.settings': ['Settings']})
48 48
 
49
-print(Settings.lodelsites)
50
-
51 49
 LodelContext.expose_modules(globals(), {
52 50
     'lodel.plugin.hooks': ['LodelHook'],
53 51
 })

+ 171
- 0
lodel/plugins/multisite/loader_utils.py View File

@@ -0,0 +1,171 @@
1
+import os
2
+import os.path
3
+
4
+##@brief basename of multisite process conf folder
5
+#@todo find a better place to declare it
6
+SERVER_CONFD = 'server_conf.d' #Should be accessible elsewhere
7
+##@brief basename of lodelsites site conf folder
8
+#@todo find a better place to declare it
9
+LODELSITES_CONFD = 'lodelsites.conf.d' #Should be accessible elsewhere
10
+
11
+##@brief A cache allowing a fast application exposure
12
+#
13
+#This dict contains reference on interface module of each handled site in
14
+#order to quickly call the application (PEP 3333) function of concerned site
15
+FAST_APP_EXPOSAL_CACHE = dict()
16
+
17
+try:
18
+    from lodel.context import LodelContext
19
+except ImportError:
20
+    LODEL_BASE_DIR = os.path.dirname(
21
+        os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
22
+    from lodel.context import LodelContext, ContextError
23
+
24
+
25
+import lodel.buildconf
26
+
27
+##@brief Stores the main function of a multisite loader
28
+
29
+##@brief Function designed to bootstrap a multisite runner
30
+#
31
+#Handles lodelsites site loading, handled site list fecth & load
32
+#@note called at end of file
33
+#
34
+#@todo evaluate if it is safe to assume that lodelsites_datapath = os.getcwd()
35
+#@todo get rid of hardcoded stuff (like shortname fieldname)
36
+#@todo use the dyncode getter when it will be available (replaced by
37
+#the string SUPERDYNCODE_ACCESSOR.Lodelsite for the moment)
38
+def main():
39
+    #Set current context to reserved loader context
40
+    LodelContext.set(None)
41
+    LodelContext.expose_modules(globals(), {
42
+        'lodel.logger': 'logger',
43
+        'lodel.exceptions': ['LodelFatalError'],
44
+    })
45
+    
46
+    CONFDIR = os.path.join(os.getcwd(), SERVER_CONFD)
47
+    if not os.path.isdir(CONFDIR):
48
+        logger.critical('Multisite process bootstraping fails : unable to \
49
+find the %s folder' % SERVER_CONFD)
50
+    
51
+    #Settings bootstraping for mutlisite process
52
+    LodelContext.expose_modules(globals(), {
53
+        'lodel.settings.settings': [('Settings', 'settings')],
54
+        'lodel.plugins.multisite.confspecs': 'multisite_confspecs'})
55
+    settings(CONFDIR, multisite_confspecs.LODEL2_CONFSPECS)
56
+    #Loading settings
57
+    del(globals()['settings']) #useless but may be safer
58
+    #Exposing "real" settings object in loader context
59
+    LodelContext.expose_modules(globals(), {
60
+        'lodel.settings': ['Settings']})
61
+    #Fetching lodelsites informations
62
+    lodelsites_name = Settings.lodelsites.name
63
+    #Following path construction is kind of dirty ! We should be able
64
+    #to assume that the lodelsites_datapath == os.getcwd()....
65
+    lodelsites_datapath = os.path.join(
66
+        lodel.buildconf.LODEL2VARDIR, lodelsites_name)
67
+    #loading lodelsites site
68
+    print("DATAPATH : ", lodelsites_datapath)
69
+    site_load(lodelsites_datapath, LODELSITES_CONFD)
70
+
71
+    #Fetching handled sites list 
72
+    #WARNING ! Here we assert that context name == basename(lodelsites_datapath)
73
+    LodelContext.set(lodelsites_name)
74
+    #in lodelsites context
75
+    Lodelsite_leo = SUPERDYNCODE_ACCESSOR.Lodelsite #hardcoded leo name
76
+    LodelContext.expose_modules(globals(), {
77
+        'lodel.leapi.query': ['LeGetQuery'],
78
+    })
79
+    #the line bellow you will find another harcoded thing : the shortname
80
+    #fieldname for a lodelsite
81
+    handled_sites = LeGetQuery(lodelsite_leo, query_filters = [],
82
+        field_list = ['shortname'])
83
+    #Now that we have the handled sitenames list we can go back to
84
+    #loader context and clean it
85
+    LodelContext.set(None)
86
+    for mname in ['LeGetQuery', 'Settings']:
87
+        del(globals()[mname])
88
+    #Loading handled sites
89
+    for handled_sitename in [s['shortname'] for s in handled_sites]:
90
+        datapath = os.path.join(lodelsites_datapath, handled_sitename)
91
+        site_load(datapath) #using default conf.d configuration dirname
92
+    
93
+
94
+##@brief Load a site
95
+#
96
+#Apply a common (as MONOSITE) loading process to a site :
97
+#1. Conf preload
98
+#2. Plugins preload
99
+#3. Conf loading
100
+#4. starting plugins & hooks
101
+#@warning At this point we need a uniq identifier for the site (using it
102
+#as key for contexts & FAST_APP_EXPOSAL_CACHE). To achieve this we use
103
+#the data_path basename. It should works for handled sites and for the 
104
+#lodelsites instance
105
+#@param data_path str : path to the datas directory (containing the confdir)
106
+#@param confdir_basename str : the basename of the site confdir
107
+#
108
+#@todo For now the interface plugin name for sites is hardcoded (set to
109
+#webui). It HAS TO be loaded from settings. But it is a bit complicated, 
110
+#we have to get the plugin's module name abstracted from context :
111
+#lodel.something but if we ask directly to Plugin class the module name
112
+#it will return something like : lodelsites.sitename.something...
113
+#
114
+#@todo there is a quick & dirty workarround with comments saying that it
115
+#avoid context escape via hooks. We have to understand why and how and then
116
+#replace the workarround by a real solution !
117
+def site_load(data_path, confdir_basename = 'conf.d'):
118
+    #args check
119
+    if confdir_basename != os.path.basename(confdir_basename):
120
+        LodelFatalError('Bad argument given to site_load(). This really \
121
+sux !')
122
+    #Determining uniq sitename from data_path
123
+    data_path = data_path.rstrip('/') #else basename returns ''
124
+    ctx_name = os.path.basename(data_path)
125
+    #Immediately switching to the context
126
+    LodelContext.new(ctx_name)
127
+    LodelContext.set(ctx_name)
128
+    print(LodelContext.get())
129
+    os.chdir(data_path) #Now the confdir is ./$condir_basename
130
+    #Loading settings for current site
131
+    LodelContext.expose_modules(globals(), {
132
+        'lodel.settings.settings': [('Settings', 'settings_preloader')]})
133
+    print(settings_preloader)
134
+    if settings_preloader.started():
135
+        msg = 'Settings seems to be allready started for "%s". \
136
+This should not append !' % ctx_name
137
+        #switch back to loader context in order to log & raise
138
+        LodelContext.set(None)
139
+        logger.critical(msg)
140
+        raise LodelFatalError(msg)
141
+    settings_preloader(os.path.join('./', confdir_basename))
142
+    #
143
+    #Loading hooks & plugins
144
+    #
145
+    LodelContext.expose_modules(globals(), {
146
+        'lodel.plugin': ['Plugin', 'LodelHook'],
147
+        'lodel.logger': 'logger',
148
+        'lodel.plugin.core_hooks': 'core_hooks',
149
+        'lodel.plugin.core_scripts': 'core_scripts'
150
+    })
151
+    Plugin.load_all() #Then all plugins & hooks are loaded
152
+    #triggering dyncode datasource instanciations
153
+    LodelHook.call_hook('lodel2_plugins_loaded', '__main__', None)
154
+    #triggering boostrapped hook
155
+    LodelHook.call_hook('lodel2_bootstraped', '__main__', None)
156
+    #Populating FAST_APP_EXPOSAL_CACHE
157
+    #
158
+    #WARNING !!!! Hardcoded interface name ! Here we have to find the 
159
+    #interface plugin name in order to populate the cache properly
160
+    FAST_APP_EXPOSAL_CACHE[ctx_name] = LodelContext.module(
161
+        'lodel.plugins.webui.run')
162
+    #a dirty & quick attempt to fix context unwanted exite via
163
+    #hooks
164
+    for name in ( 'LodelHook', 'core_hooks', 'core_scripts',
165
+            'Settings', 'settings', 'logger', 'Plugin'):
166
+        del(globals()[name])
167
+    #site fully loaded, switching back to loader context
168
+    LodelContext.set(None)
169
+    #lodel2 multisite instances are loaded and ready to run
170
+
171
+

Loading…
Cancel
Save