diff options
| author | Vo Minh Thu <vmt@openerp.com> | 2011-05-11 19:24:48 +0200 |
|---|---|---|
| committer | Vo Minh Thu <vmt@openerp.com> | 2011-05-11 19:24:48 +0200 |
| commit | 1fe579d8ec2a246dbfc2e4fa8cbd7df5497929bf (patch) | |
| tree | 874a52239197eaad2742ee27384f5ee11f284b6c /openerp/modules/__init__.py | |
| parent | fb476648e0dce64cfbef0d10bee29e0ea6127a16 (diff) | |
[REF] module code goes into openerp.modules.module.
bzr revid: vmt@openerp.com-20110511172448-p12p1rizvf3lqv97
Diffstat (limited to 'openerp/modules/__init__.py')
| -rw-r--r-- | openerp/modules/__init__.py | 328 |
1 files changed, 7 insertions, 321 deletions
diff --git a/openerp/modules/__init__.py b/openerp/modules/__init__.py index cf8d022842e..c37016628a9 100644 --- a/openerp/modules/__init__.py +++ b/openerp/modules/__init__.py @@ -54,31 +54,15 @@ import openerp.modules.db import openerp.modules.graph import openerp.modules.migration -logger = netsvc.Logger() - -_ad = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'addons') # default addons path (base) -ad_paths = [] - -# Modules already loaded -loaded = [] - -def initialize_sys_path(): - global ad_paths - - if ad_paths: - return +from openerp.modules.module import \ + get_modules, get_modules_with_version, \ + load_information_from_description_file, \ + get_module_resource, zip_directory, \ + get_module_path, initialize_sys_path, \ + register_module_classes, init_module_models - ad_paths = map(lambda m: os.path.abspath(tools.ustr(m.strip())), tools.config['addons_path'].split(',')) - - sys.path.insert(1, _ad) - - ad_cnt=1 - for adp in ad_paths: - if adp != _ad: - sys.path.insert(ad_cnt, adp) - ad_cnt+=1 +logger = netsvc.Logger() - ad_paths.append(_ad) # for get_module_path def open_openerp_namespace(): # See comment for open_openerp_namespace. @@ -88,304 +72,6 @@ def open_openerp_namespace(): sys.modules[k[8:]] = v -def get_module_path(module, downloaded=False): - """Return the path of the given module. - - Search the addons paths and return the first path where the given - module is found. If downloaded is True, return the default addons - path if nothing else is found. - - """ - initialize_sys_path() - for adp in ad_paths: - if os.path.exists(opj(adp, module)) or os.path.exists(opj(adp, '%s.zip' % module)): - return opj(adp, module) - - if downloaded: - return opj(_ad, module) - logger.notifyChannel('init', netsvc.LOG_WARNING, 'module %s: module not found' % (module,)) - return False - - -def get_module_filetree(module, dir='.'): - path = get_module_path(module) - if not path: - return False - - dir = os.path.normpath(dir) - if dir == '.': - dir = '' - if dir.startswith('..') or (dir and dir[0] == '/'): - raise Exception('Cannot access file outside the module') - - if not os.path.isdir(path): - # zipmodule - zip = zipfile.ZipFile(path + ".zip") - files = ['/'.join(f.split('/')[1:]) for f in zip.namelist()] - else: - files = osutil.listdir(path, True) - - tree = {} - for f in files: - if not f.startswith(dir): - continue - - if dir: - f = f[len(dir)+int(not dir.endswith('/')):] - lst = f.split(os.sep) - current = tree - while len(lst) != 1: - current = current.setdefault(lst.pop(0), {}) - current[lst.pop(0)] = None - - return tree - -def zip_directory(directory, b64enc=True, src=True): - """Compress a directory - - @param directory: The directory to compress - @param base64enc: if True the function will encode the zip file with base64 - @param src: Integrate the source files - - @return: a string containing the zip file - """ - - RE_exclude = re.compile('(?:^\..+\.swp$)|(?:\.py[oc]$)|(?:\.bak$)|(?:\.~.~$)', re.I) - - def _zippy(archive, path, src=True): - path = os.path.abspath(path) - base = os.path.basename(path) - for f in osutil.listdir(path, True): - bf = os.path.basename(f) - if not RE_exclude.search(bf) and (src or bf in ('__openerp__.py', '__terp__.py') or not bf.endswith('.py')): - archive.write(os.path.join(path, f), os.path.join(base, f)) - - archname = StringIO() - archive = PyZipFile(archname, "w", ZIP_DEFLATED) - - # for Python 2.5, ZipFile.write() still expects 8-bit strings (2.6 converts to utf-8) - directory = tools.ustr(directory).encode('utf-8') - - archive.writepy(directory) - _zippy(archive, directory, src=src) - archive.close() - archive_data = archname.getvalue() - archname.close() - - if b64enc: - return base64.encodestring(archive_data) - - return archive_data - -def get_module_as_zip(modulename, b64enc=True, src=True): - """Generate a module as zip file with the source or not and can do a base64 encoding - - @param modulename: The module name - @param b64enc: if True the function will encode the zip file with base64 - @param src: Integrate the source files - - @return: a stream to store in a file-like object - """ - - ap = get_module_path(str(modulename)) - if not ap: - raise Exception('Unable to find path for module %s' % modulename) - - ap = ap.encode('utf8') - if os.path.isfile(ap + '.zip'): - val = file(ap + '.zip', 'rb').read() - if b64enc: - val = base64.encodestring(val) - else: - val = zip_directory(ap, b64enc, src) - - return val - - -def get_module_resource(module, *args): - """Return the full path of a resource of the given module. - - @param module: the module - @param args: the resource path components - - @return: absolute path to the resource - - TODO name it get_resource_path - TODO make it available inside on osv object (self.get_resource_path) - """ - a = get_module_path(module) - if not a: return False - resource_path = opj(a, *args) - if zipfile.is_zipfile( a +'.zip') : - zip = zipfile.ZipFile( a + ".zip") - files = ['/'.join(f.split('/')[1:]) for f in zip.namelist()] - resource_path = '/'.join(args) - if resource_path in files: - return opj(a, resource_path) - elif os.path.exists(resource_path): - return resource_path - return False - -def get_modules(): - """Returns the list of module names - """ - def listdir(dir): - def clean(name): - name = os.path.basename(name) - if name[-4:] == '.zip': - name = name[:-4] - return name - - def is_really_module(name): - name = opj(dir, name) - return os.path.isdir(name) or zipfile.is_zipfile(name) - return map(clean, filter(is_really_module, os.listdir(dir))) - - plist = [] - initialize_sys_path() - for ad in ad_paths: - plist.extend(listdir(ad)) - return list(set(plist)) - -def load_information_from_description_file(module): - """ - :param module: The name of the module (sale, purchase, ...) - """ - - terp_file = get_module_resource(module, '__openerp__.py') - if not terp_file: - terp_file = get_module_resource(module, '__terp__.py') - mod_path = get_module_path(module) - if terp_file: - info = {} - if os.path.isfile(terp_file) or zipfile.is_zipfile(mod_path+'.zip'): - terp_f = tools.file_open(terp_file) - try: - info = eval(terp_f.read()) - except Exception: - logger.notifyChannel('modules', netsvc.LOG_ERROR, - 'module %s: exception while evaluating file %s' % - (module, terp_file)) - raise - finally: - terp_f.close() - # TODO the version should probably be mandatory - info.setdefault('version', '0') - info.setdefault('category', 'Uncategorized') - info.setdefault('depends', []) - info.setdefault('author', '') - info.setdefault('website', '') - info.setdefault('name', False) - info.setdefault('description', '') - info['certificate'] = info.get('certificate') or None - info['web'] = info.get('web') or False - info['license'] = info.get('license') or 'AGPL-3' - info.setdefault('installable', True) - info.setdefault('active', False) - for kind in ['data', 'demo', 'test', - 'init_xml', 'update_xml', 'demo_xml']: - info.setdefault(kind, []) - return info - - #TODO: refactor the logger in this file to follow the logging guidelines - # for 6.0 - logging.getLogger('modules').debug('module %s: no descriptor file' - ' found: __openerp__.py or __terp__.py (deprecated)', module) - return {} - - -def get_modules_with_version(): - modules = get_modules() - res = {} - for module in modules: - try: - info = load_information_from_description_file(module) - res[module] = "%s.%s" % (release.major_version, info['version']) - except Exception, e: - continue - return res - - -def init_module_models(cr, module_name, obj_list): - """ Initialize a list of models. - - Call _auto_init and init on each model to create or update the - database tables supporting the models. - - TODO better explanation of _auto_init and init. - - """ - - logger.notifyChannel('init', netsvc.LOG_INFO, - 'module %s: creating or updating database tables' % module_name) - # TODO _auto_init doesn't seem to return anything - # so this todo list would be useless. - todo = [] - for obj in obj_list: - try: - # TODO the module in the context doesn't seem usefull: - # it is available (at least) in the class' _module attribute. - # (So module_name would be useless too.) - result = obj._auto_init(cr, {'module': module_name}) - except Exception, e: - raise - if result: - todo += result - if hasattr(obj, 'init'): - obj.init(cr) - cr.commit() - todo.sort() - for t in todo: - t[1](cr, *t[2]) - cr.commit() - - -def load_module(module_name): - """ Load a Python module found on the addons paths.""" - fm = imp.find_module(module_name, ad_paths) - try: - imp.load_module(module_name, *fm) - finally: - if fm[0]: - fm[0].close() - - -def register_module_classes(m): - """ Register module named m, if not already registered. - - This will load the module and register all of its models. (Actually, the - explicit constructor call of each of the models inside the module will - register them.) - - """ - - def log(e): - mt = isinstance(e, zipimport.ZipImportError) and 'zip ' or '' - msg = "Couldn't load %smodule %s" % (mt, m) - logger.notifyChannel('init', netsvc.LOG_CRITICAL, msg) - logger.notifyChannel('init', netsvc.LOG_CRITICAL, e) - - global loaded - if m in loaded: - return - logger.notifyChannel('init', netsvc.LOG_INFO, 'module %s: registering objects' % m) - mod_path = get_module_path(m) - - initialize_sys_path() - try: - zip_mod_path = mod_path + '.zip' - if not os.path.isfile(zip_mod_path): - load_module(m) - else: - zimp = zipimport.zipimporter(zip_mod_path) - zimp.load_module(m) - except Exception, e: - log(e) - raise - else: - loaded.append(m) - - def load_module_graph(cr, graph, status=None, perform_checks=True, skip_modules=None, report=None): """Migrates+Updates or Installs all module nodes from ``graph`` :param graph: graph of module nodes to load |
