...
[limo.git] / modules / __init__.py
blob6a15e0d761b85c7261076ab641745df6d697181d
1 import os, sys
2 from limoutil import *
3 from db import FastQuery, safe, Model
4 from settings import Settings
5 import modules.core
6 from theme import Theme
7 import datetime
8 from model import LimoModel
10 __all__ = ["core", "blocks", "init", "clear"]
11 blocks = {}
12 _mtimes = {}
14 def init(skipModels=False, olderThan=None):
15 global blocks
16 if Settings.logModuleLoading:
17 log("Importing all modules:")
19 LimoModel() # instantiate once to make sure db has been put in place
21 # first grab all the system block from modules.core
22 for block in dir(modules.core):
23 type = eval("modules.core."+block)
24 if classInheritsFrom(type, "LimoBlock"):
25 blocks[block] = type
26 for module_dir in os.listdir(os.path.sep.join(__file__.split(os.path.sep)[:-1])):
27 # for everything in /modules/module_dir
28 if os.path.isdir(os.path.sep.join(["modules",module_dir])):
29 if Settings.logModuleLoading:
30 log("\t%s" % module_dir)
31 for d in os.listdir(os.path.sep.join(["modules",module_dir])):
32 # save a copy of d (which right now is just the filename)
33 n = d
34 # make d into the fully qualified path
35 d = os.path.sep.join(["modules",module_dir,d])
36 # if d is a directory
37 if os.path.isdir(d):
38 # then this should be a module
39 FastQuery("insert ignore into modules (name) values ('%s')" % safe(n))
40 for row in FastQuery("select active, weight from modules where name = '%s'" % safe(n)):
41 (active, weight) = row
42 break
43 # only if active (disabled by default)
44 if int(active) == 0:
45 if Settings.logModuleLoading:
46 log("\t\t%s (ignored)" % n)
47 else:
48 profile("module_%s" % n)
49 # search all subtrees of the module, and register all the files
50 # the theme module will use these and the weights to find the 'right' file later on
51 len_d = len(d.split(os.path.sep))
52 for mf in os.walk(d):
53 loc = mf[0]
54 # mf[0] has the full path, remove the base from the front of it
55 loc_offset = loc.replace(d, '')
56 # mf[2] is a list of the files in this dir
57 for f in mf[2]:
58 if f[0] not in ("_",".") and f.split(".")[-1] not in ("pyc",): # skip some files
59 # .py files are imported, and any Block's or Model's are harvested out of them
60 if f.endswith(".py"):
61 ff = os.path.sep.join((mf[0],f)) # ff is a full physical path to the .py file
62 mt = os.path.getmtime(ff)
63 if _mtimes.get(ff, 0.0) >= mt:
64 # log('skipping')
65 continue # skip files the we've already loaded that havent changed
66 log('(re-)loading %s' % ff)
67 _mtimes[ff] = mt
68 # get the name of the module we are about to import
69 m = f.replace(".py","")
70 # import the module
71 i = n+"_"+m # it will be imported and assigned to this name
72 exec "%(i)s = __import__('modules.%(module_dir)s.%(n)s.%(m)s').%(module_dir)s.%(n)s.%(m)s" % locals()
73 exec "reload(%(i)s)" % locals()
74 for b in dir(eval(i)):
75 # for every member defined in the module
76 member_type = eval("%s.%s" % (i,b))
77 # log("Found member type: %s" % str(member_type))
78 # if that member is a Block
79 if classInheritsFrom(member_type, 'LimoBlock'):
80 # log("Loading Block member")
81 # make sure that we have a record of the blocks existence
82 bid = Model.int_uid(b)
83 FastQuery("insert ignore into blocks (bid, name, module) values (%d, '%s', '%s')" % (bid, b, m))
84 # and that the block is active
85 for row in FastQuery("select active from blocks where bid = %d" % (bid,) ):
86 (active,) = row
87 if int(active) == 0:
88 if Settings.logModuleLoading:
89 log("Skipping disabled block %s." % (b,))
90 else:
91 # then bind the block globally so its available for rendering
92 log("blocks['%s'] = modules.%s.%s.%s.%s" % (b,module_dir,n,m,b))
93 exec "blocks['%s'] = modules.%s.%s.%s.%s" % (b,module_dir,n,m,b)
94 elif not skipModels and classInheritsFrom(member_type, 'Model'):
95 # log("Loading Model object: %s" % str(member_type))
96 # or if the member is a Model
97 member_type() # instantiate it once to init the model in the database
98 elif Settings.developmentMode and classInheritsFrom(member_type, 'LimoTest'):
99 # log("Loading Test...%s" % str(member_type))
100 member_type() # instantiate it once to put it in the global list of tests: LimoTest.all()
101 # on a production system, they never take up memory, and are thus never able to be run from the test console
102 else:
103 # all other files are registered with the theme, making them overridable later on
104 Theme().provideFile( os.path.sep.join([loc_offset, f]), os.path.sep.join([loc, f]), weight)
105 elapsed = profile("module_%s" % n)
106 if Settings.logModuleLoading:
107 log("\t\t%s (in %sms)" % (n, elapsed))
109 def clear():
110 global blocks
111 del blocks
112 blocks = {}