~ubuntu-branches/ubuntu/trusty/python3.4/trusty-proposed

« back to all changes in this revision

Viewing changes to Lib/importlib/util.py

  • Committer: Package Import Robot
  • Author(s): Matthias Klose
  • Date: 2013-11-25 09:44:27 UTC
  • Revision ID: package-import@ubuntu.com-20131125094427-lzxj8ap5w01lmo7f
Tags: upstream-3.4~b1
ImportĀ upstreamĀ versionĀ 3.4~b1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
"""Utility code for constructing importers, etc."""
 
2
 
 
3
from ._bootstrap import MAGIC_NUMBER
 
4
from ._bootstrap import cache_from_source
 
5
from ._bootstrap import decode_source
 
6
from ._bootstrap import source_from_cache
 
7
from ._bootstrap import spec_from_loader
 
8
from ._bootstrap import spec_from_file_location
 
9
from ._bootstrap import _resolve_name
 
10
 
 
11
from contextlib import contextmanager
 
12
import functools
 
13
import sys
 
14
import warnings
 
15
 
 
16
 
 
17
def resolve_name(name, package):
 
18
    """Resolve a relative module name to an absolute one."""
 
19
    if not name.startswith('.'):
 
20
        return name
 
21
    elif not package:
 
22
        raise ValueError('{!r} is not a relative name '
 
23
                         '(no leading dot)'.format(name))
 
24
    level = 0
 
25
    for character in name:
 
26
        if character != '.':
 
27
            break
 
28
        level += 1
 
29
    return _resolve_name(name[level:], package, level)
 
30
 
 
31
 
 
32
@contextmanager
 
33
def _module_to_load(name):
 
34
    is_reload = name in sys.modules
 
35
 
 
36
    module = sys.modules.get(name)
 
37
    if not is_reload:
 
38
        # This must be done before open() is called as the 'io' module
 
39
        # implicitly imports 'locale' and would otherwise trigger an
 
40
        # infinite loop.
 
41
        module = type(sys)(name)
 
42
        # This must be done before putting the module in sys.modules
 
43
        # (otherwise an optimization shortcut in import.c becomes wrong)
 
44
        module.__initializing__ = True
 
45
        sys.modules[name] = module
 
46
    try:
 
47
        yield module
 
48
    except Exception:
 
49
        if not is_reload:
 
50
            try:
 
51
                del sys.modules[name]
 
52
            except KeyError:
 
53
                pass
 
54
    finally:
 
55
        module.__initializing__ = False
 
56
 
 
57
 
 
58
# XXX deprecate
 
59
def set_package(fxn):
 
60
    """Set __package__ on the returned module."""
 
61
    @functools.wraps(fxn)
 
62
    def set_package_wrapper(*args, **kwargs):
 
63
        module = fxn(*args, **kwargs)
 
64
        if getattr(module, '__package__', None) is None:
 
65
            module.__package__ = module.__name__
 
66
            if not hasattr(module, '__path__'):
 
67
                module.__package__ = module.__package__.rpartition('.')[0]
 
68
        return module
 
69
    return set_package_wrapper
 
70
 
 
71
 
 
72
# XXX deprecate
 
73
def set_loader(fxn):
 
74
    """Set __loader__ on the returned module."""
 
75
    @functools.wraps(fxn)
 
76
    def set_loader_wrapper(self, *args, **kwargs):
 
77
        module = fxn(self, *args, **kwargs)
 
78
        if getattr(module, '__loader__', None) is None:
 
79
            module.__loader__ = self
 
80
        return module
 
81
    return set_loader_wrapper
 
82
 
 
83
 
 
84
def module_for_loader(fxn):
 
85
    """Decorator to handle selecting the proper module for loaders.
 
86
 
 
87
    The decorated function is passed the module to use instead of the module
 
88
    name. The module passed in to the function is either from sys.modules if
 
89
    it already exists or is a new module. If the module is new, then __name__
 
90
    is set the first argument to the method, __loader__ is set to self, and
 
91
    __package__ is set accordingly (if self.is_package() is defined) will be set
 
92
    before it is passed to the decorated function (if self.is_package() does
 
93
    not work for the module it will be set post-load).
 
94
 
 
95
    If an exception is raised and the decorator created the module it is
 
96
    subsequently removed from sys.modules.
 
97
 
 
98
    The decorator assumes that the decorated function takes the module name as
 
99
    the second argument.
 
100
 
 
101
    """
 
102
    warnings.warn('The import system now takes care of this automatically.',
 
103
                  PendingDeprecationWarning, stacklevel=2)
 
104
    @functools.wraps(fxn)
 
105
    def module_for_loader_wrapper(self, fullname, *args, **kwargs):
 
106
        with _module_to_load(fullname) as module:
 
107
            module.__loader__ = self
 
108
            try:
 
109
                is_package = self.is_package(fullname)
 
110
            except (ImportError, AttributeError):
 
111
                pass
 
112
            else:
 
113
                if is_package:
 
114
                    module.__package__ = fullname
 
115
                else:
 
116
                    module.__package__ = fullname.rpartition('.')[0]
 
117
            # If __package__ was not set above, __import__() will do it later.
 
118
            return fxn(self, module, *args, **kwargs)
 
119
 
 
120
    return module_for_loader_wrapper