Merge branch 'master' of https://github.com/odoo/odoo
[odoo/odoo.git] / openerp / modules / module.py
index 66119ce..e6f6eed 100644 (file)
@@ -39,11 +39,12 @@ import openerp.release as release
 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
@@ -89,6 +90,10 @@ def initialize_sys_path():
     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:
@@ -150,7 +155,7 @@ def get_module_filetree(module, dir='.'):
 
     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
@@ -159,7 +164,6 @@ def get_module_resource(module, *args):
     :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)
@@ -171,6 +175,33 @@ def get_module_resource(module, *args):
             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):
@@ -227,7 +258,6 @@ def load_information_from_description_file(module, mod_path=None):
                 'icon': get_module_icon(module),
                 'installable': True,
                 'license': 'AGPL-3',
-                'name': False,
                 'post_load': None,
                 'version': '1.0',
                 'web': False,
@@ -245,6 +275,13 @@ def load_information_from_description_file(module, mod_path=None):
             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']
@@ -278,7 +315,7 @@ def init_module_models(cr, module_name, obj_list):
     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()
@@ -425,11 +462,12 @@ def run_unit_tests(module_name, dbname, position=runs_at_install):
         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))