summaryrefslogtreecommitdiff
path: root/django/utils
diff options
context:
space:
mode:
Diffstat (limited to 'django/utils')
-rw-r--r--django/utils/module_tools/__init__.py3
-rw-r--r--django/utils/module_tools/data_storage.py42
-rw-r--r--django/utils/module_tools/module_loader.py79
-rw-r--r--django/utils/module_tools/module_walker.py135
4 files changed, 259 insertions, 0 deletions
diff --git a/django/utils/module_tools/__init__.py b/django/utils/module_tools/__init__.py
new file mode 100644
index 0000000000..976d4b5e4f
--- /dev/null
+++ b/django/utils/module_tools/__init__.py
@@ -0,0 +1,3 @@
+from module_loader import *
+from module_walker import *
+
diff --git a/django/utils/module_tools/data_storage.py b/django/utils/module_tools/data_storage.py
new file mode 100644
index 0000000000..aed5980e6b
--- /dev/null
+++ b/django/utils/module_tools/data_storage.py
@@ -0,0 +1,42 @@
+"""
+Copyright 2009 55 Minutes (http://www.55minutes.com)
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+"""
+
+__all__ = ('Packages', 'Modules', 'Excluded', 'Errors')
+
+class SingletonType(type):
+ def __call__(cls, *args, **kwargs):
+ if getattr(cls, '__instance__', None) is None:
+ instance = cls.__new__(cls)
+ instance.__init__(*args, **kwargs)
+ cls.__instance__ = instance
+ return cls.__instance__
+
+class Packages(object):
+ __metaclass__ = SingletonType
+ packages = {}
+
+class Modules(object):
+ __metaclass__ = SingletonType
+ modules = {}
+
+class Excluded(object):
+ __metaclass__ = SingletonType
+ excluded = []
+
+class Errors(object):
+ __metaclass__ = SingletonType
+ errors = []
+
diff --git a/django/utils/module_tools/module_loader.py b/django/utils/module_tools/module_loader.py
new file mode 100644
index 0000000000..e6dd6ce4b8
--- /dev/null
+++ b/django/utils/module_tools/module_loader.py
@@ -0,0 +1,79 @@
+"""
+Copyright 2009 55 Minutes (http://www.55minutes.com)
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+"""
+
+import imp, sys, types
+
+__all__ = ('find_or_load_module',)
+
+def _brute_force_find_module(module_name, module_path, module_type):
+ for m in [m for n, m in sys.modules.iteritems() if type(m) == types.ModuleType]:
+ m_path = []
+ try:
+ if module_type in (imp.PY_COMPILED, imp.PY_SOURCE):
+ m_path = [m.__file__]
+ elif module_type==imp.PKG_DIRECTORY:
+ m_path = m.__path__
+ except AttributeError:
+ pass
+ for p in m_path:
+ if p.startswith(module_path):
+ return m
+ return None
+
+def _load_module(module_name, fo, fp, desc):
+ suffix, mode, mtype = desc
+ if module_name in sys.modules and \
+ sys.modules[module_name].__file__.startswith(fp):
+ module = sys.modules[module_name]
+ else:
+ module = _brute_force_find_module(module_name, fp, mtype)
+ if not module:
+ try:
+ module = imp.load_module(module_name, fo, fp, desc)
+ except:
+ raise ImportError
+ return module
+
+def _load_package(pkg_name, fp, desc):
+ suffix, mode, mtype = desc
+ if pkg_name in sys.modules:
+ if fp in sys.modules[pkg_name].__path__:
+ pkg = sys.modules[pkg_name]
+ else:
+ pkg = _brute_force_find_module(pkg_name, fp, mtype)
+ if not pkg:
+ pkg = imp.load_module(pkg_name, None, fp, desc)
+ return pkg
+
+def find_or_load_module(module_name, path=None):
+ """
+ Attempts to lookup ``module_name`` in ``sys.modules``, else uses the
+ facilities in the ``imp`` module to load the module.
+
+ If module_name specified is not of type ``imp.PY_SOURCE`` or
+ ``imp.PKG_DIRECTORY``, raise ``ImportError`` since we don't know
+ what to do with those.
+ """
+ fo, fp, desc = imp.find_module(module_name.split('.')[-1], path)
+ suffix, mode, mtype = desc
+ if mtype in (imp.PY_SOURCE, imp.PY_COMPILED):
+ module = _load_module(module_name, fo, fp, desc)
+ elif mtype==imp.PKG_DIRECTORY:
+ module = _load_package(module_name, fp, desc)
+ else:
+ raise ImportError("Don't know how to handle this module type.")
+ return module
+
diff --git a/django/utils/module_tools/module_walker.py b/django/utils/module_tools/module_walker.py
new file mode 100644
index 0000000000..442150e689
--- /dev/null
+++ b/django/utils/module_tools/module_walker.py
@@ -0,0 +1,135 @@
+"""
+Copyright 2009 55 Minutes (http://www.55minutes.com)
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+"""
+
+import os, re, sys
+from glob import glob
+
+from data_storage import *
+from module_loader import find_or_load_module
+
+try:
+ set
+except:
+ from sets import Set as set
+
+__all__ = ('get_all_modules',)
+
+def _build_pkg_path(pkg_name, pkg, path):
+ for rp in [x for x in pkg.__path__ if path.startswith(x)]:
+ p = path.replace(rp, '').replace(os.path.sep, '.')
+ return pkg_name + p
+
+def _build_module_path(pkg_name, pkg, path):
+ return _build_pkg_path(pkg_name, pkg, os.path.splitext(path)[0])
+
+def _prune_whitelist(whitelist, blacklist):
+ excluded = Excluded().excluded
+
+ for wp in whitelist[:]:
+ for bp in blacklist:
+ if re.search(bp, wp):
+ whitelist.remove(wp)
+ excluded.append(wp)
+ break
+ return whitelist
+
+def _parse_module_list(m_list):
+ packages = Packages().packages
+ modules = Modules().modules
+ excluded = Excluded().excluded
+ errors = Errors().errors
+
+ for m in m_list:
+ components = m.split('.')
+ m_name = ''
+ search_path = []
+ processed=False
+ for i, c in enumerate(components):
+ m_name = '.'.join([x for x in m_name.split('.') if x] + [c])
+ try:
+ module = find_or_load_module(m_name, search_path or None)
+ except ImportError:
+ processed=True
+ errors.append(m)
+ break
+ try:
+ search_path.extend(module.__path__)
+ except AttributeError:
+ processed = True
+ if i+1==len(components):
+ modules[m_name] = module
+ else:
+ errors.append(m)
+ break
+ if not processed:
+ packages[m_name] = module
+
+def prune_dirs(root, dirs, exclude_dirs):
+ _dirs = [os.path.join(root, d) for d in dirs]
+ for i, p in enumerate(_dirs):
+ for e in exclude_dirs:
+ if re.search(e, p):
+ del dirs[i]
+ break
+
+def _get_all_packages(pkg_name, pkg, blacklist, exclude_dirs):
+ packages = Packages().packages
+ errors = Errors().errors
+
+ for path in pkg.__path__:
+ for root, dirs, files in os.walk(path):
+ prune_dirs(root, dirs, exclude_dirs or [])
+ m_name = _build_pkg_path(pkg_name, pkg, root)
+ try:
+ if _prune_whitelist([m_name], blacklist):
+ m = find_or_load_module(m_name, [os.path.split(root)[0]])
+ packages[m_name] = m
+ else:
+ for d in dirs[:]:
+ dirs.remove(d)
+ except ImportError:
+ errors.append(m_name)
+ for d in dirs[:]:
+ dirs.remove(d)
+
+def _get_all_modules(pkg_name, pkg, blacklist):
+ modules = Modules().modules
+ errors = Errors().errors
+
+ for p in pkg.__path__:
+ for f in glob('%s/*.py' %p):
+ m_name = _build_module_path(pkg_name, pkg, f)
+ try:
+ if _prune_whitelist([m_name], blacklist):
+ m = find_or_load_module(m_name, [p])
+ modules[m_name] = m
+ except ImportError:
+ errors.append(m_name)
+
+def get_all_modules(whitelist, blacklist=None, exclude_dirs=None):
+ packages = Packages().packages
+ modules = Modules().modules
+ excluded = Excluded().excluded
+ errors = Errors().errors
+
+ whitelist = _prune_whitelist(whitelist, blacklist or [])
+ _parse_module_list(whitelist)
+ for pkg_name, pkg in packages.copy().iteritems():
+ _get_all_packages(pkg_name, pkg, blacklist, exclude_dirs)
+ for pkg_name, pkg in packages.copy().iteritems():
+ _get_all_modules(pkg_name, pkg, blacklist)
+ return packages, modules, list(set(excluded)), list(set(errors))
+