from openerp.tools.safe_eval import safe_eval as eval
MANIFEST = '__openerp__.py'
+README = ['README.rst', 'README.md', 'README.txt']
_logger = logging.getLogger(__name__)
# addons path as a list
-ad_paths = [tools.config.addons_data_dir]
+ad_paths = []
hooked = False
# Modules already loaded
global ad_paths
global hooked
+ dd = tools.config.addons_data_dir
+ if dd not in ad_paths:
+ ad_paths.append(dd)
+
for ad in tools.config['addons_path'].split(','):
ad = os.path.abspath(tools.ustr(ad.strip()))
if ad not in ad_paths:
return tree
-def get_module_resource(module, *args):
+def get_resource_path(module, *args):
"""Return the full path of a resource of the given module.
:param module: module name
:rtype: str
:return: absolute path to the resource
- TODO name it get_resource_path
TODO make it available inside on osv object (self.get_resource_path)
"""
mod_path = get_module_path(module)
return resource_path
return False
+# backwards compatibility
+get_module_resource = get_resource_path
+
+def get_resource_from_path(path):
+ """Tries to extract the module name and the resource's relative path
+ out of an absolute resource path.
+
+ If operation is successfull, returns a tuple containing the module name, the relative path
+ to the resource using '/' as filesystem seperator[1] and the same relative path using
+ os.path.sep seperators.
+
+ [1] same convention as the resource path declaration in manifests
+
+ :param path: absolute resource path
+
+ :rtype: tuple
+ :return: tuple(module_name, relative_path, os_relative_path) if possible, else None
+ """
+ resource = [path.replace(adpath, '') for adpath in ad_paths if path.startswith(adpath)]
+ if resource:
+ relative = resource[0].split(os.path.sep)
+ if not relative[0]:
+ relative.pop(0)
+ module = relative.pop(0)
+ return (module, '/'.join(relative), os.path.sep.join(relative))
+ return None
+
def get_module_icon(module):
iconpath = ['static', 'description', 'icon.png']
if get_module_resource(module, *iconpath):
'icon': get_module_icon(module),
'installable': True,
'license': 'AGPL-3',
- 'name': False,
'post_load': None,
'version': '1.0',
'web': False,
finally:
f.close()
+ if not info.get('description'):
+ readme_path = [opj(mod_path, x) for x in README
+ if os.path.isfile(opj(mod_path, x))]
+ if readme_path:
+ readme_text = tools.file_open(readme_path[0]).read()
+ info['description'] = readme_text
+
if 'active' in info:
# 'active' has been renamed 'auto_install'
info['auto_install'] = info['active']
for obj in obj_list:
obj._auto_end(cr, {'module': module_name})
cr.commit()
- todo.sort()
+ todo.sort(key=lambda x: x[0])
for t in todo:
t[1](cr, *t[2])
cr.commit()
suite = unittest2.TestSuite(itertools.ifilter(position, tests))
if suite.countTestCases():
- tm0 = time.time()
+ t0 = time.time()
+ t0_sql = openerp.sql_db.sql_counter
_logger.info('%s running tests.', m.__name__)
result = unittest2.TextTestRunner(verbosity=2, stream=TestStream(m.__name__)).run(suite)
- if time.time() - tm0 > 5:
- _logger.log(25, "%s tested in %.2fs", m.__name__, time.time() - tm0)
+ if time.time() - t0 > 5:
+ _logger.log(25, "%s tested in %.2fs, %s queries", m.__name__, time.time() - t0, openerp.sql_db.sql_counter - t0_sql)
if not result.wasSuccessful():
r = False
_logger.error("Module %s: %d failures, %d errors", module_name, len(result.failures), len(result.errors))