Coverage for /home/martinb/.local/share/virtualenvs/camcops/lib/python3.6/site-packages/celery/utils/imports.py : 22%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1# -*- coding: utf-8 -*-
2"""Utilities related to importing modules and symbols by name."""
3from __future__ import absolute_import, unicode_literals
5import importlib
6import os
7import sys
8import warnings
9from contextlib import contextmanager
11from kombu.utils.imports import symbol_by_name
13from celery.five import reload
15#: Billiard sets this when execv is enabled.
16#: We use it to find out the name of the original ``__main__``
17#: module, so that we can properly rewrite the name of the
18#: task to be that of ``App.main``.
19MP_MAIN_FILE = os.environ.get('MP_MAIN_FILE')
21__all__ = (
22 'NotAPackage', 'qualname', 'instantiate', 'symbol_by_name',
23 'cwd_in_path', 'find_module', 'import_from_cwd',
24 'reload_from_cwd', 'module_file', 'gen_task_name',
25)
28class NotAPackage(Exception):
29 """Raised when importing a package, but it's not a package."""
32if sys.version_info > (3, 3): # pragma: no cover
33 def qualname(obj):
34 """Return object name."""
35 if not hasattr(obj, '__name__') and hasattr(obj, '__class__'):
36 obj = obj.__class__
37 q = getattr(obj, '__qualname__', None)
38 if '.' not in q:
39 q = '.'.join((obj.__module__, q))
40 return q
41else:
42 def qualname(obj): # noqa
43 """Return object name."""
44 if not hasattr(obj, '__name__') and hasattr(obj, '__class__'):
45 obj = obj.__class__
46 return '.'.join((obj.__module__, obj.__name__))
49def instantiate(name, *args, **kwargs):
50 """Instantiate class by name.
52 See Also:
53 :func:`symbol_by_name`.
54 """
55 return symbol_by_name(name)(*args, **kwargs)
58@contextmanager
59def cwd_in_path():
60 """Context adding the current working directory to sys.path."""
61 cwd = os.getcwd()
62 if cwd in sys.path:
63 yield
64 else:
65 sys.path.insert(0, cwd)
66 try:
67 yield cwd
68 finally:
69 try:
70 sys.path.remove(cwd)
71 except ValueError: # pragma: no cover
72 pass
75def find_module(module, path=None, imp=None):
76 """Version of :func:`imp.find_module` supporting dots."""
77 if imp is None:
78 imp = importlib.import_module
79 with cwd_in_path():
80 try:
81 return imp(module)
82 except ImportError:
83 # Raise a more specific error if the problem is that one of the
84 # dot-separated segments of the module name is not a package.
85 if '.' in module:
86 parts = module.split('.')
87 for i, part in enumerate(parts[:-1]):
88 package = '.'.join(parts[:i + 1])
89 try:
90 mpart = imp(package)
91 except ImportError:
92 # Break out and re-raise the original ImportError
93 # instead.
94 break
95 try:
96 mpart.__path__
97 except AttributeError:
98 raise NotAPackage(package)
99 raise
102def import_from_cwd(module, imp=None, package=None):
103 """Import module, temporarily including modules in the current directory.
105 Modules located in the current directory has
106 precedence over modules located in `sys.path`.
107 """
108 if imp is None:
109 imp = importlib.import_module
110 with cwd_in_path():
111 return imp(module, package=package)
114def reload_from_cwd(module, reloader=None):
115 """Reload module (ensuring that CWD is in sys.path)."""
116 if reloader is None:
117 reloader = reload
118 with cwd_in_path():
119 return reloader(module)
122def module_file(module):
123 """Return the correct original file name of a module."""
124 name = module.__file__
125 return name[:-1] if name.endswith('.pyc') else name
128def gen_task_name(app, name, module_name):
129 """Generate task name from name/module pair."""
130 module_name = module_name or '__main__'
131 try:
132 module = sys.modules[module_name]
133 except KeyError:
134 # Fix for manage.py shell_plus (Issue #366)
135 module = None
137 if module is not None:
138 module_name = module.__name__
139 # - If the task module is used as the __main__ script
140 # - we need to rewrite the module part of the task name
141 # - to match App.main.
142 if MP_MAIN_FILE and module.__file__ == MP_MAIN_FILE:
143 # - see comment about :envvar:`MP_MAIN_FILE` above.
144 module_name = '__main__'
145 if module_name == '__main__' and app.main:
146 return '.'.join([app.main, name])
147 return '.'.join(p for p in (module_name, name) if p)
150def load_extension_class_names(namespace):
151 try:
152 from pkg_resources import iter_entry_points
153 except ImportError: # pragma: no cover
154 return
156 for ep in iter_entry_points(namespace):
157 yield ep.name, ':'.join([ep.module_name, ep.attrs[0]])
160def load_extension_classes(namespace):
161 for name, class_name in load_extension_class_names(namespace):
162 try:
163 cls = symbol_by_name(class_name)
164 except (ImportError, SyntaxError) as exc:
165 warnings.warn(
166 'Cannot load {0} extension {1!r}: {2!r}'.format(
167 namespace, class_name, exc))
168 else:
169 yield name, cls