[REF] module code goes into openerp.modules.module.
bzr revid: vmt@openerp.com-20110511172448-p12p1rizvf3lqv97
This commit is contained in:
parent
fb476648e0
commit
1fe579d8ec
|
@ -54,31 +54,15 @@ import openerp.modules.db
|
|||
import openerp.modules.graph
|
||||
import openerp.modules.migration
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
|
|
@ -48,8 +48,6 @@ from cStringIO import StringIO
|
|||
|
||||
import logging
|
||||
|
||||
import openerp.modules.db
|
||||
|
||||
logger = netsvc.Logger()
|
||||
|
||||
|
||||
|
@ -102,7 +100,7 @@ class Graph(dict):
|
|||
# This will raise an exception if no/unreadable descriptor file.
|
||||
# NOTE The call to load_information_from_description_file is already
|
||||
# done by db.initialize, so it is possible to not do it again here.
|
||||
info = openerp.modules.load_information_from_description_file(module)
|
||||
info = openerp.modules.module.load_information_from_description_file(module)
|
||||
if info['installable']:
|
||||
packages.append((module, info)) # TODO directly a dict, like in get_modules_with_version
|
||||
else:
|
||||
|
|
|
@ -98,7 +98,7 @@ class MigrationManager(object):
|
|||
if not (hasattr(pkg, 'update') or pkg.state == 'to upgrade'):
|
||||
continue
|
||||
|
||||
get_module_filetree = openerp.modules.get_module_filetree
|
||||
get_module_filetree = openerp.modules.module.get_module_filetree
|
||||
self.migrations[pkg.name]['module'] = get_module_filetree(pkg.name, 'migrations') or {}
|
||||
self.migrations[pkg.name]['maintenance'] = get_module_filetree('base', 'maintenance/migrations/' + pkg.name) or {}
|
||||
|
||||
|
|
|
@ -0,0 +1,379 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
|
||||
# Copyright (C) 2010-2011 OpenERP s.a. (<http://openerp.com>).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import os, sys, imp
|
||||
from os.path import join as opj
|
||||
import itertools
|
||||
import zipimport
|
||||
|
||||
import openerp
|
||||
|
||||
import openerp.osv as osv
|
||||
import openerp.tools as tools
|
||||
import openerp.tools.osutil as osutil
|
||||
from openerp.tools.safe_eval import safe_eval as eval
|
||||
import openerp.pooler as pooler
|
||||
from openerp.tools.translate import _
|
||||
|
||||
import openerp.netsvc as netsvc
|
||||
|
||||
import zipfile
|
||||
import openerp.release as release
|
||||
|
||||
import re
|
||||
import base64
|
||||
from zipfile import PyZipFile, ZIP_DEFLATED
|
||||
from cStringIO import StringIO
|
||||
|
||||
import logging
|
||||
|
||||
import openerp.modules.db
|
||||
import openerp.modules.graph
|
||||
|
||||
_ad = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'addons') # default addons path (base)
|
||||
ad_paths = []
|
||||
|
||||
# Modules already loaded
|
||||
loaded = []
|
||||
|
||||
logger = netsvc.Logger()
|
||||
|
||||
def initialize_sys_path():
|
||||
global ad_paths
|
||||
|
||||
if ad_paths:
|
||||
return
|
||||
|
||||
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
|
||||
|
||||
ad_paths.append(_ad) # for get_module_path
|
||||
|
||||
|
||||
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 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 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 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 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
|
||||
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
|
@ -135,7 +135,7 @@ def file_open(name, mode="r", subdir='addons', pathinfo=False):
|
|||
@return: fileobject if pathinfo is False else (fileobject, filepath)
|
||||
"""
|
||||
import openerp.modules as addons
|
||||
adps = addons.ad_paths
|
||||
adps = addons.module.ad_paths
|
||||
rtp = os.path.normcase(os.path.abspath(config['root_path']))
|
||||
|
||||
if name.replace(os.path.sep, '/').startswith('addons/'):
|
||||
|
|
Loading…
Reference in New Issue