cubicweb/cwconfig.py
changeset 11899 bf6106b91633
parent 11870 3a84a79c4ed5
child 11900 8496135b6dc1
--- a/cubicweb/cwconfig.py	Wed Jan 18 17:16:00 2017 +0100
+++ b/cubicweb/cwconfig.py	Thu Jan 19 15:27:39 2017 +0100
@@ -185,7 +185,7 @@
 import logging.config
 import os
 from os.path import (exists, join, expanduser, abspath, normpath,
-                     basename, isdir, dirname, splitext)
+                     basename, isdir, dirname, splitext, realpath)
 import pkgutil
 import pkg_resources
 import re
@@ -275,6 +275,40 @@
     return cube
 
 
+def _expand_modname(modname):
+    """expand modules names `modname` if exists by walking non package submodules
+    and yield (submodname, filepath) including `modname` itself
+
+    If the file ends with .pyc or .pyo (python bytecode) also check that the
+    corresponding source .py file exists before yielding.
+    """
+    try:
+        loader = pkgutil.find_loader(modname)
+    except ImportError:
+        return
+    if not loader:
+        return
+
+    def check_source_file(filepath):
+        if filepath[-4:] in ('.pyc', '.pyo'):
+            if not exists(filepath[:-1]):
+                return False
+        return True
+
+    filepath = loader.get_filename()
+    if not check_source_file(filepath):
+        return
+    yield modname, filepath
+    if loader.is_package(modname):
+        path = dirname(filepath)
+        for subloader, subname, ispkg in pkgutil.walk_packages([path]):
+            # ignore subpackages (historical behavior)
+            if not ispkg:
+                filepath = subloader.find_module(subname).get_filename()
+                if check_source_file(filepath):
+                    yield modname + '.' + subname, filepath
+
+
 # persistent options definition
 PERSISTENT_OPTIONS = (
     ('encoding',
@@ -775,6 +809,20 @@
         # configure simpleTal logger
         logging.getLogger('simpleTAL').setLevel(logging.ERROR)
 
+    def schema_modnames(self):
+        modnames = []
+        for name in ('bootstrap', 'base', 'workflow', 'Bookmark'):
+            modnames.append(('cubicweb', 'cubicweb.schemas.' + name))
+        for cube in reversed(self.cubes()):
+            for modname, filepath in _expand_modname('cubes.{0}.schema'.format(cube)):
+                modnames.append((cube, modname))
+        if self.apphome:
+            apphome = realpath(self.apphome)
+            for modname, filepath in _expand_modname('schema'):
+                if realpath(filepath).startswith(apphome):
+                    modnames.append(('data', modname))
+        return modnames
+
     def appobjects_path(self):
         """return a list of files or directories where the registry will look
         for application objects. By default return nothing in NoApp config.