mercurial/demandimport.py
author Matt Mackall <mpm@selenic.com>
Thu, 25 Jun 2015 17:53:16 -0500
changeset 25843 bf9ea348b487
parent 25674 5d0847cd1587
child 25933 1fc6c02782ab
permissions -rw-r--r--
merge: mark ancient debugging option
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
3877
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     1
# demandimport.py - global demand-loading of modules for Mercurial
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     2
#
4635
63b9d2deed48 Updated copyright notices and add "and others" to "hg version"
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4631
diff changeset
     3
# Copyright 2006, 2007 Matt Mackall <mpm@selenic.com>
3877
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     4
#
8225
46293a0c7e9f updated license to be explicit about GPL version 2
Martin Geisler <mg@lazybytes.net>
parents: 7861
diff changeset
     5
# This software may be used and distributed according to the terms of the
10263
25e572394f5c Update license to GPLv2+
Matt Mackall <mpm@selenic.com>
parents: 10242
diff changeset
     6
# GNU General Public License version 2 or any later version.
3877
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     7
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     8
'''
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     9
demandimport - automatic demandloading of modules
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    10
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    11
To enable this module, do:
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    12
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    13
  import demandimport; demandimport.enable()
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    14
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    15
Imports of the following forms will be demand-loaded:
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    16
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    17
  import a, b.c
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    18
  import a.b as c
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    19
  from a import b,c # a will be loaded immediately
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    20
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    21
These imports will not be delayed:
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    22
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    23
  from a import *
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    24
  b = __import__(a)
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    25
'''
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    26
25673
fa1f04529775 demandimport: alias __builtin__ as builtins
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25327
diff changeset
    27
import os, sys
25327
2e7804110b14 demandimport: define a `deactivated` context manager
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 23643
diff changeset
    28
from contextlib import contextmanager
25674
5d0847cd1587 demandimport: support importing builtins for Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25673
diff changeset
    29
5d0847cd1587 demandimport: support importing builtins for Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25673
diff changeset
    30
# __builtin__ in Python 2, builtins in Python 3.
5d0847cd1587 demandimport: support importing builtins for Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25673
diff changeset
    31
try:
5d0847cd1587 demandimport: support importing builtins for Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25673
diff changeset
    32
    import __builtin__ as builtins
5d0847cd1587 demandimport: support importing builtins for Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25673
diff changeset
    33
except ImportError:
5d0847cd1587 demandimport: support importing builtins for Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25673
diff changeset
    34
    import builtins
25327
2e7804110b14 demandimport: define a `deactivated` context manager
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 23643
diff changeset
    35
3877
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    36
_origimport = __import__
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    37
14977
1dbd42a02153 demandimport: use getattr instead of hasattr
Augie Fackler <durin42@gmail.com>
parents: 14976
diff changeset
    38
nothing = object()
1dbd42a02153 demandimport: use getattr instead of hasattr
Augie Fackler <durin42@gmail.com>
parents: 14976
diff changeset
    39
15096
868282fa29d8 demandimport: determine at load time if __import__ has level argument
Simon Heimberg <simohe@besonet.ch>
parents: 14977
diff changeset
    40
try:
21290
74be3fb1e3b8 demandimport: pass proper level to __import__ in Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 21025
diff changeset
    41
    # Python 3 doesn't have relative imports nor level -1.
74be3fb1e3b8 demandimport: pass proper level to __import__ in Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 21025
diff changeset
    42
    level = -1
74be3fb1e3b8 demandimport: pass proper level to __import__ in Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 21025
diff changeset
    43
    if sys.version_info[0] >= 3:
74be3fb1e3b8 demandimport: pass proper level to __import__ in Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 21025
diff changeset
    44
        level = 0
25673
fa1f04529775 demandimport: alias __builtin__ as builtins
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25327
diff changeset
    45
    _origimport(builtins.__name__, {}, {}, None, level)
15096
868282fa29d8 demandimport: determine at load time if __import__ has level argument
Simon Heimberg <simohe@besonet.ch>
parents: 14977
diff changeset
    46
except TypeError: # no level argument
868282fa29d8 demandimport: determine at load time if __import__ has level argument
Simon Heimberg <simohe@besonet.ch>
parents: 14977
diff changeset
    47
    def _import(name, globals, locals, fromlist, level):
868282fa29d8 demandimport: determine at load time if __import__ has level argument
Simon Heimberg <simohe@besonet.ch>
parents: 14977
diff changeset
    48
        "call _origimport with no level argument"
868282fa29d8 demandimport: determine at load time if __import__ has level argument
Simon Heimberg <simohe@besonet.ch>
parents: 14977
diff changeset
    49
        return _origimport(name, globals, locals, fromlist)
868282fa29d8 demandimport: determine at load time if __import__ has level argument
Simon Heimberg <simohe@besonet.ch>
parents: 14977
diff changeset
    50
else:
868282fa29d8 demandimport: determine at load time if __import__ has level argument
Simon Heimberg <simohe@besonet.ch>
parents: 14977
diff changeset
    51
    _import = _origimport
868282fa29d8 demandimport: determine at load time if __import__ has level argument
Simon Heimberg <simohe@besonet.ch>
parents: 14977
diff changeset
    52
19933
621a26eb3a99 demandimport: allow extensions to import own modules by absolute name
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 19932
diff changeset
    53
def _hgextimport(importfunc, name, globals, *args):
621a26eb3a99 demandimport: allow extensions to import own modules by absolute name
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 19932
diff changeset
    54
    try:
621a26eb3a99 demandimport: allow extensions to import own modules by absolute name
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 19932
diff changeset
    55
        return importfunc(name, globals, *args)
621a26eb3a99 demandimport: allow extensions to import own modules by absolute name
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 19932
diff changeset
    56
    except ImportError:
621a26eb3a99 demandimport: allow extensions to import own modules by absolute name
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 19932
diff changeset
    57
        if not globals:
621a26eb3a99 demandimport: allow extensions to import own modules by absolute name
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 19932
diff changeset
    58
            raise
621a26eb3a99 demandimport: allow extensions to import own modules by absolute name
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 19932
diff changeset
    59
        # extensions are loaded with "hgext_" prefix
621a26eb3a99 demandimport: allow extensions to import own modules by absolute name
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 19932
diff changeset
    60
        hgextname = 'hgext_%s' % name
621a26eb3a99 demandimport: allow extensions to import own modules by absolute name
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 19932
diff changeset
    61
        nameroot = hgextname.split('.', 1)[0]
621a26eb3a99 demandimport: allow extensions to import own modules by absolute name
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 19932
diff changeset
    62
        contextroot = globals.get('__name__', '').split('.', 1)[0]
621a26eb3a99 demandimport: allow extensions to import own modules by absolute name
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 19932
diff changeset
    63
        if nameroot != contextroot:
621a26eb3a99 demandimport: allow extensions to import own modules by absolute name
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 19932
diff changeset
    64
            raise
621a26eb3a99 demandimport: allow extensions to import own modules by absolute name
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 19932
diff changeset
    65
        # retry to import with "hgext_" prefix
621a26eb3a99 demandimport: allow extensions to import own modules by absolute name
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 19932
diff changeset
    66
        return importfunc(hgextname, globals, *args)
621a26eb3a99 demandimport: allow extensions to import own modules by absolute name
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 19932
diff changeset
    67
3877
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    68
class _demandmod(object):
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    69
    """module demand-loader and proxy"""
21290
74be3fb1e3b8 demandimport: pass proper level to __import__ in Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 21025
diff changeset
    70
    def __init__(self, name, globals, locals, level=level):
3877
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    71
        if '.' in name:
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    72
            head, rest = name.split('.', 1)
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    73
            after = [rest]
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    74
        else:
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    75
            head = name
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    76
            after = []
19932
e3a5922e18c3 demandimport: support "absolute_import" for external libraries (issue4029)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15096
diff changeset
    77
        object.__setattr__(self, "_data",
e3a5922e18c3 demandimport: support "absolute_import" for external libraries (issue4029)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15096
diff changeset
    78
                           (head, globals, locals, after, level))
3896
3b628b5da9e9 use parent.__setattr__ instead of __dict__
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3877
diff changeset
    79
        object.__setattr__(self, "_module", None)
3877
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    80
    def _extend(self, name):
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    81
        """add to the list of submodules to load"""
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    82
        self._data[3].append(name)
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    83
    def _load(self):
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    84
        if not self._module:
19932
e3a5922e18c3 demandimport: support "absolute_import" for external libraries (issue4029)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15096
diff changeset
    85
            head, globals, locals, after, level = self._data
19933
621a26eb3a99 demandimport: allow extensions to import own modules by absolute name
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 19932
diff changeset
    86
            mod = _hgextimport(_import, head, globals, locals, None, level)
3877
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    87
            # load submodules
3921
6d0d025e125a demandimport: fix import x.y.z as a when x.y is already imported.
Matt Mackall <mpm@selenic.com>
parents: 3903
diff changeset
    88
            def subload(mod, p):
6d0d025e125a demandimport: fix import x.y.z as a when x.y is already imported.
Matt Mackall <mpm@selenic.com>
parents: 3903
diff changeset
    89
                h, t = p, None
6d0d025e125a demandimport: fix import x.y.z as a when x.y is already imported.
Matt Mackall <mpm@selenic.com>
parents: 3903
diff changeset
    90
                if '.' in p:
6d0d025e125a demandimport: fix import x.y.z as a when x.y is already imported.
Matt Mackall <mpm@selenic.com>
parents: 3903
diff changeset
    91
                    h, t = p.split('.', 1)
14977
1dbd42a02153 demandimport: use getattr instead of hasattr
Augie Fackler <durin42@gmail.com>
parents: 14976
diff changeset
    92
                if getattr(mod, h, nothing) is nothing:
12894
bc91a79fa3d0 demandimport: back out 50a4e55aa278 (issue2467)
Matt Mackall <mpm@selenic.com>
parents: 12801
diff changeset
    93
                    setattr(mod, h, _demandmod(p, mod.__dict__, mod.__dict__))
3926
de6ae8f016af demandimport: handle already-loaded nested modules in subload
Brendan Cully <brendan@kublai.com>
parents: 3921
diff changeset
    94
                elif t:
3921
6d0d025e125a demandimport: fix import x.y.z as a when x.y is already imported.
Matt Mackall <mpm@selenic.com>
parents: 3903
diff changeset
    95
                    subload(getattr(mod, h), t)
6d0d025e125a demandimport: fix import x.y.z as a when x.y is already imported.
Matt Mackall <mpm@selenic.com>
parents: 3903
diff changeset
    96
3877
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    97
            for x in after:
3921
6d0d025e125a demandimport: fix import x.y.z as a when x.y is already imported.
Matt Mackall <mpm@selenic.com>
parents: 3903
diff changeset
    98
                subload(mod, x)
6d0d025e125a demandimport: fix import x.y.z as a when x.y is already imported.
Matt Mackall <mpm@selenic.com>
parents: 3903
diff changeset
    99
3877
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   100
            # are we in the locals dictionary still?
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   101
            if locals and locals.get(head) == self:
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   102
                locals[head] = mod
3896
3b628b5da9e9 use parent.__setattr__ instead of __dict__
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3877
diff changeset
   103
            object.__setattr__(self, "_module", mod)
4631
e3afa670e484 demandimport: fix issue579 and add a test
Matt Mackall <mpm@selenic.com>
parents: 4626
diff changeset
   104
3877
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   105
    def __repr__(self):
4631
e3afa670e484 demandimport: fix issue579 and add a test
Matt Mackall <mpm@selenic.com>
parents: 4626
diff changeset
   106
        if self._module:
e3afa670e484 demandimport: fix issue579 and add a test
Matt Mackall <mpm@selenic.com>
parents: 4626
diff changeset
   107
            return "<proxied module '%s'>" % self._data[0]
3877
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   108
        return "<unloaded module '%s'>" % self._data[0]
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   109
    def __call__(self, *args, **kwargs):
5639
7dd5cf9d1e09 demandload: give better diagnostic for call of an unloaded module
Matt Mackall <mpm@selenic.com>
parents: 5098
diff changeset
   110
        raise TypeError("%s object is not callable" % repr(self))
3903
f9136599700f Make demandimport pass all tests on python2.5.
Brendan Cully <brendan@kublai.com>
parents: 3898
diff changeset
   111
    def __getattribute__(self, attr):
f9136599700f Make demandimport pass all tests on python2.5.
Brendan Cully <brendan@kublai.com>
parents: 3898
diff changeset
   112
        if attr in ('_data', '_extend', '_load', '_module'):
f9136599700f Make demandimport pass all tests on python2.5.
Brendan Cully <brendan@kublai.com>
parents: 3898
diff changeset
   113
            return object.__getattribute__(self, attr)
3877
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   114
        self._load()
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   115
        return getattr(self._module, attr)
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   116
    def __setattr__(self, attr, val):
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   117
        self._load()
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   118
        setattr(self._module, attr, val)
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   119
21290
74be3fb1e3b8 demandimport: pass proper level to __import__ in Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 21025
diff changeset
   120
def _demandimport(name, globals=None, locals=None, fromlist=None, level=level):
3877
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   121
    if not locals or name in ignore or fromlist == ('*',):
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   122
        # these cases we can't really delay
19933
621a26eb3a99 demandimport: allow extensions to import own modules by absolute name
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 19932
diff changeset
   123
        return _hgextimport(_import, name, globals, locals, fromlist, level)
3877
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   124
    elif not fromlist:
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   125
        # import a [as b]
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   126
        if '.' in name: # a.b
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   127
            base, rest = name.split('.', 1)
3903
f9136599700f Make demandimport pass all tests on python2.5.
Brendan Cully <brendan@kublai.com>
parents: 3898
diff changeset
   128
            # email.__init__ loading email.mime
f9136599700f Make demandimport pass all tests on python2.5.
Brendan Cully <brendan@kublai.com>
parents: 3898
diff changeset
   129
            if globals and globals.get('__name__', None) == base:
15096
868282fa29d8 demandimport: determine at load time if __import__ has level argument
Simon Heimberg <simohe@besonet.ch>
parents: 14977
diff changeset
   130
                return _import(name, globals, locals, fromlist, level)
3877
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   131
            # if a is already demand-loaded, add b to its submodule list
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   132
            if base in locals:
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   133
                if isinstance(locals[base], _demandmod):
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   134
                    locals[base]._extend(rest)
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   135
                return locals[base]
19932
e3a5922e18c3 demandimport: support "absolute_import" for external libraries (issue4029)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15096
diff changeset
   136
        return _demandmod(name, globals, locals, level)
3877
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   137
    else:
13082
4db5bfea1b07 demandimport: change default for level from None to -1
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 12964
diff changeset
   138
        if level != -1:
12894
bc91a79fa3d0 demandimport: back out 50a4e55aa278 (issue2467)
Matt Mackall <mpm@selenic.com>
parents: 12801
diff changeset
   139
            # from . import b,c,d or from .a import b,c,d
bc91a79fa3d0 demandimport: back out 50a4e55aa278 (issue2467)
Matt Mackall <mpm@selenic.com>
parents: 12801
diff changeset
   140
            return _origimport(name, globals, locals, fromlist, level)
bc91a79fa3d0 demandimport: back out 50a4e55aa278 (issue2467)
Matt Mackall <mpm@selenic.com>
parents: 12801
diff changeset
   141
        # from a import b,c,d
19933
621a26eb3a99 demandimport: allow extensions to import own modules by absolute name
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 19932
diff changeset
   142
        mod = _hgextimport(_origimport, name, globals, locals)
3877
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   143
        # recurse down the module chain
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   144
        for comp in name.split('.')[1:]:
14977
1dbd42a02153 demandimport: use getattr instead of hasattr
Augie Fackler <durin42@gmail.com>
parents: 14976
diff changeset
   145
            if getattr(mod, comp, nothing) is nothing:
12894
bc91a79fa3d0 demandimport: back out 50a4e55aa278 (issue2467)
Matt Mackall <mpm@selenic.com>
parents: 12801
diff changeset
   146
                setattr(mod, comp, _demandmod(comp, mod.__dict__, mod.__dict__))
3877
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   147
            mod = getattr(mod, comp)
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   148
        for x in fromlist:
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   149
            # set requested submodules for demand load
14977
1dbd42a02153 demandimport: use getattr instead of hasattr
Augie Fackler <durin42@gmail.com>
parents: 14976
diff changeset
   150
            if getattr(mod, x, nothing) is nothing:
12894
bc91a79fa3d0 demandimport: back out 50a4e55aa278 (issue2467)
Matt Mackall <mpm@selenic.com>
parents: 12801
diff changeset
   151
                setattr(mod, x, _demandmod(x, mod.__dict__, locals))
3877
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   152
        return mod
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   153
5098
0bbd86b847dd demandimport: ignore resource module, not available under Windows.
Patrick Mezard <pmezard@gmail.com>
parents: 5097
diff changeset
   154
ignore = [
0bbd86b847dd demandimport: ignore resource module, not available under Windows.
Patrick Mezard <pmezard@gmail.com>
parents: 5097
diff changeset
   155
    '_hashlib',
0bbd86b847dd demandimport: ignore resource module, not available under Windows.
Patrick Mezard <pmezard@gmail.com>
parents: 5097
diff changeset
   156
    '_xmlplus',
0bbd86b847dd demandimport: ignore resource module, not available under Windows.
Patrick Mezard <pmezard@gmail.com>
parents: 5097
diff changeset
   157
    'fcntl',
0bbd86b847dd demandimport: ignore resource module, not available under Windows.
Patrick Mezard <pmezard@gmail.com>
parents: 5097
diff changeset
   158
    'win32com.gen_py',
10242
ecd0a5c8bbe5 demandimport: ignore _winreg (used in python-2.7 mimetypes)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 9458
diff changeset
   159
    '_winreg', # 2.7 mimetypes needs immediate ImportError
7861
2bc14da14992 demandimport: blacklist pythoncom
Steve Borho <steve@borho.org>
parents: 7727
diff changeset
   160
    'pythoncom',
5098
0bbd86b847dd demandimport: ignore resource module, not available under Windows.
Patrick Mezard <pmezard@gmail.com>
parents: 5097
diff changeset
   161
    # imported by tarfile, not available under Windows
0bbd86b847dd demandimport: ignore resource module, not available under Windows.
Patrick Mezard <pmezard@gmail.com>
parents: 5097
diff changeset
   162
    'pwd',
0bbd86b847dd demandimport: ignore resource module, not available under Windows.
Patrick Mezard <pmezard@gmail.com>
parents: 5097
diff changeset
   163
    'grp',
0bbd86b847dd demandimport: ignore resource module, not available under Windows.
Patrick Mezard <pmezard@gmail.com>
parents: 5097
diff changeset
   164
    # imported by profile, itself imported by hotshot.stats,
0bbd86b847dd demandimport: ignore resource module, not available under Windows.
Patrick Mezard <pmezard@gmail.com>
parents: 5097
diff changeset
   165
    # not available under Windows
0bbd86b847dd demandimport: ignore resource module, not available under Windows.
Patrick Mezard <pmezard@gmail.com>
parents: 5097
diff changeset
   166
    'resource',
9458
ffeaf5ba25d8 demandimport: blacklist gtk
Steve Borho <steve@borho.org>
parents: 9315
diff changeset
   167
    # this trips up many extension authors
ffeaf5ba25d8 demandimport: blacklist gtk
Steve Borho <steve@borho.org>
parents: 9315
diff changeset
   168
    'gtk',
10598
1037bd445768 demandimport: add __main__ to the blacklist (because of setuptools)
Greg Ward <greg-hg@gerg.ca>
parents: 10263
diff changeset
   169
    # setuptools' pkg_resources.py expects "from __main__ import x" to
1037bd445768 demandimport: add __main__ to the blacklist (because of setuptools)
Greg Ward <greg-hg@gerg.ca>
parents: 10263
diff changeset
   170
    # raise ImportError if x not defined
1037bd445768 demandimport: add __main__ to the blacklist (because of setuptools)
Greg Ward <greg-hg@gerg.ca>
parents: 10263
diff changeset
   171
    '__main__',
10612
30553ac3e355 demandimport: blacklist _ssl (issue1964)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 10598
diff changeset
   172
    '_ssl', # conditional imports in the stdlib, issue1964
14976
04a950b1c2ad demandimport: blacklist rfc822 and mimetools to prevent spurious warnings
Augie Fackler <durin42@gmail.com>
parents: 13082
diff changeset
   173
    'rfc822',
04a950b1c2ad demandimport: blacklist rfc822 and mimetools to prevent spurious warnings
Augie Fackler <durin42@gmail.com>
parents: 13082
diff changeset
   174
    'mimetools',
23643
2205d00b6d2b demandimport: blacklist distutils.msvc9compiler (issue4475)
Augie Fackler <raf@durin42.com>
parents: 21290
diff changeset
   175
    # setuptools 8 expects this module to explode early when not on windows
2205d00b6d2b demandimport: blacklist distutils.msvc9compiler (issue4475)
Augie Fackler <raf@durin42.com>
parents: 21290
diff changeset
   176
    'distutils.msvc9compiler'
5098
0bbd86b847dd demandimport: ignore resource module, not available under Windows.
Patrick Mezard <pmezard@gmail.com>
parents: 5097
diff changeset
   177
    ]
3877
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   178
20422
aac87f70f38e hooks: only disable/re-enable demandimport when it's already enabled
Brodie Rao <brodie@sf.io>
parents: 19933
diff changeset
   179
def isenabled():
25673
fa1f04529775 demandimport: alias __builtin__ as builtins
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25327
diff changeset
   180
    return builtins.__import__ == _demandimport
20422
aac87f70f38e hooks: only disable/re-enable demandimport when it's already enabled
Brodie Rao <brodie@sf.io>
parents: 19933
diff changeset
   181
3877
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   182
def enable():
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   183
    "enable global demand-loading of modules"
21025
54af51c18c4c demandimport: make it possible to disable by setting HGDEMANDIMPORT=disable
Mads Kiilerich <madski@unity3d.com>
parents: 20422
diff changeset
   184
    if os.environ.get('HGDEMANDIMPORT') != 'disable':
25673
fa1f04529775 demandimport: alias __builtin__ as builtins
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25327
diff changeset
   185
        builtins.__import__ = _demandimport
3877
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   186
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   187
def disable():
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   188
    "disable global demand-loading of modules"
25673
fa1f04529775 demandimport: alias __builtin__ as builtins
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25327
diff changeset
   189
    builtins.__import__ = _origimport
25327
2e7804110b14 demandimport: define a `deactivated` context manager
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 23643
diff changeset
   190
2e7804110b14 demandimport: define a `deactivated` context manager
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 23643
diff changeset
   191
@contextmanager
2e7804110b14 demandimport: define a `deactivated` context manager
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 23643
diff changeset
   192
def deactivated():
2e7804110b14 demandimport: define a `deactivated` context manager
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 23643
diff changeset
   193
    "context manager for disabling demandimport in 'with' blocks"
2e7804110b14 demandimport: define a `deactivated` context manager
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 23643
diff changeset
   194
    demandenabled = isenabled()
2e7804110b14 demandimport: define a `deactivated` context manager
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 23643
diff changeset
   195
    if demandenabled:
2e7804110b14 demandimport: define a `deactivated` context manager
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 23643
diff changeset
   196
        disable()
2e7804110b14 demandimport: define a `deactivated` context manager
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 23643
diff changeset
   197
2e7804110b14 demandimport: define a `deactivated` context manager
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 23643
diff changeset
   198
    try:
2e7804110b14 demandimport: define a `deactivated` context manager
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 23643
diff changeset
   199
        yield
2e7804110b14 demandimport: define a `deactivated` context manager
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 23643
diff changeset
   200
    finally:
2e7804110b14 demandimport: define a `deactivated` context manager
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 23643
diff changeset
   201
        if demandenabled:
2e7804110b14 demandimport: define a `deactivated` context manager
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 23643
diff changeset
   202
            enable()