Source code for anybox.recipe.openerp.runtime.patch_openerp_v5

"""Enable multiple addons paths in OpenERP 5.0.x

This is done as monkey patch, because the recipe must take care of not
modifying the source, so that release scripts don't refuse releasing the
buildout directory.

As of this writing, version 5.0 has been frozen for long already.
"""

import sys
import os


[docs]def do_patch(): import addons # reverting side effects of addons import, and storing our addons path if addons.ad is not None: addons.buildout_addons_paths = [ p.strip() for p in addons.tools.config['addons_path'].split(',')] sys.path.remove(addons.ad) if addons._ad != addons.ad: sys.path.remove(addons._ad) addons.ad = None def get_module_path(module, downloaded=False): """Return the path of the given module. """ logger, netsvc = addons.logger, addons.netsvc for path in addons.buildout_addons_paths: module_path = os.path.join(path, module) if (os.path.exists(module_path) or os.path.exists(module_path + '.zip')): logger.notifyChannel('init', netsvc.LOG_INFO, 'module %r: found at %s' % (module, module_path)) return module_path if downloaded: return os.path.join(addons._ad, module) logger.notifyChannel('init', netsvc.LOG_WARNING, 'module %r: module not found' % (module,)) 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 = os.path.join(dir, name) return os.path.isdir(name) or addons.zipfile.is_zipfile(name) return map(clean, filter(is_really_module, os.listdir(dir))) return list(set(m for path in addons.buildout_addons_paths for m in listdir(path))) import imp import zipimport def register_class(m): """ Register module named m, if not already registered Only modification from the original function is mentionned as comment. """ logger, netsvc = addons.logger, addons.netsvc 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) if m in addons.loaded: return logger.notifyChannel('init', netsvc.LOG_INFO, 'module %r: registering objects' % m) mod_path = get_module_path(m) try: zip_mod_path = mod_path + '.zip' if not os.path.isfile(zip_mod_path): # line below modified fm = imp.find_module(m, addons.buildout_addons_paths) try: imp.load_module(m, *fm) finally: if fm[0]: fm[0].close() else: zimp = zipimport.zipimporter(zip_mod_path) zimp.load_module(m) except Exception, e: log(e) raise else: addons.loaded.append(m) addons.get_module_path = get_module_path addons.get_modules = get_modules addons.register_class = register_class import tools.misc orig_file_open = tools.misc.file_open def file_open(name, mode="r", subdir='addons', pathinfo=False): """Modified version for calls after direct join of module names. For example, this can be seen in ``addons.load_module_graph()`` fp = tools.file_open(opj(m, filename)) Found it simpler (and necessary, given there were references to addons_path and root_path) to correct from here. The original one does try and replace subpaths by zip files if some are found. We simply call it back to avoid duplicating this (in the same way it's already doing after subdir related resolutions). """ if name.replace(os.path.sep, '/').startswith('addons/'): subdir = 'addons' name = name[7:] # First try to locate in addons_path if subdir: # remember that the default value is 'addons' subdir2 = subdir if subdir2.replace(os.path.sep, '/').startswith('addons/'): subdir2 = subdir2[7:] subdir2 = (subdir2 != 'addons' or None) and subdir2 if os.path.isabs(name): fn = name elif subdir2 is None: # first segment is necessary the module name fn = addons.get_module_resource(*name.split(os.path.sep, 1)) try: fn = os.path.normpath(fn) # subdir=None will skip this override's equivalent in # original code (leading to zip handling etc) fo = file_open(fn, mode=mode, subdir=None, pathinfo=pathinfo) if pathinfo: return fo, fn return fo except IOError: pass rtp = os.path.normcase(os.path.abspath(tools.config['root_path'])) if subdir: name = os.path.join(rtp, subdir, name) else: name = os.path.join(rtp, name) name = os.path.normpath(name) return orig_file_open(name, subdir=None, pathinfo=pathinfo) tools.misc.file_open = tools.file_open = file_open