hgdemandimport/demandimportpy2.py
author Pierre-Yves David <pierre-yves.david@octobus.net>
Tue, 27 Jun 2017 01:31:18 +0200
changeset 33144 d0e5bf12f314
parent 32448 91a2ec8e7fa0
child 33529 ded3ebae8779
permissions -rw-r--r--
obsutil: move 'allprecursors' to the new modules We have a new 'obsutil' module now. We move the high level utility there to bring 'obsolete.py' back to a more reasonable size.
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
25943
3beed01daff9 demandimport: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25937
diff changeset
    27
from __future__ import absolute_import
3beed01daff9 demandimport: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25937
diff changeset
    28
3beed01daff9 demandimport: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25937
diff changeset
    29
import contextlib
3beed01daff9 demandimport: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25937
diff changeset
    30
import os
3beed01daff9 demandimport: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25937
diff changeset
    31
import sys
25674
5d0847cd1587 demandimport: support importing builtins for Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25673
diff changeset
    32
5d0847cd1587 demandimport: support importing builtins for Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25673
diff changeset
    33
# __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
    34
try:
5d0847cd1587 demandimport: support importing builtins for Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25673
diff changeset
    35
    import __builtin__ as builtins
5d0847cd1587 demandimport: support importing builtins for Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25673
diff changeset
    36
except ImportError:
5d0847cd1587 demandimport: support importing builtins for Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25673
diff changeset
    37
    import builtins
25327
2e7804110b14 demandimport: define a `deactivated` context manager
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 23643
diff changeset
    38
25943
3beed01daff9 demandimport: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25937
diff changeset
    39
contextmanager = contextlib.contextmanager
3beed01daff9 demandimport: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25937
diff changeset
    40
3877
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    41
_origimport = __import__
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    42
14977
1dbd42a02153 demandimport: use getattr instead of hasattr
Augie Fackler <durin42@gmail.com>
parents: 14976
diff changeset
    43
nothing = object()
1dbd42a02153 demandimport: use getattr instead of hasattr
Augie Fackler <durin42@gmail.com>
parents: 14976
diff changeset
    44
25933
1fc6c02782ab demandimport: remove support for Python < 2.5
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25674
diff changeset
    45
# Python 3 doesn't have relative imports nor level -1.
1fc6c02782ab demandimport: remove support for Python < 2.5
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25674
diff changeset
    46
level = -1
1fc6c02782ab demandimport: remove support for Python < 2.5
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25674
diff changeset
    47
if sys.version_info[0] >= 3:
1fc6c02782ab demandimport: remove support for Python < 2.5
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25674
diff changeset
    48
    level = 0
1fc6c02782ab demandimport: remove support for Python < 2.5
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25674
diff changeset
    49
_import = _origimport
15096
868282fa29d8 demandimport: determine at load time if __import__ has level argument
Simon Heimberg <simohe@besonet.ch>
parents: 14977
diff changeset
    50
25936
f90bb2002bcf demandimport: support keyword arguments on _hgextimport
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25935
diff changeset
    51
def _hgextimport(importfunc, name, globals, *args, **kwargs):
19933
621a26eb3a99 demandimport: allow extensions to import own modules by absolute name
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 19932
diff changeset
    52
    try:
25936
f90bb2002bcf demandimport: support keyword arguments on _hgextimport
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25935
diff changeset
    53
        return importfunc(name, globals, *args, **kwargs)
19933
621a26eb3a99 demandimport: allow extensions to import own modules by absolute name
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 19932
diff changeset
    54
    except ImportError:
621a26eb3a99 demandimport: allow extensions to import own modules by absolute name
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 19932
diff changeset
    55
        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
    56
            raise
621a26eb3a99 demandimport: allow extensions to import own modules by absolute name
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 19932
diff changeset
    57
        # 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
    58
        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
    59
        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
    60
        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
    61
        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
    62
            raise
621a26eb3a99 demandimport: allow extensions to import own modules by absolute name
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 19932
diff changeset
    63
        # retry to import with "hgext_" prefix
25936
f90bb2002bcf demandimport: support keyword arguments on _hgextimport
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25935
diff changeset
    64
        return importfunc(hgextname, globals, *args, **kwargs)
19933
621a26eb3a99 demandimport: allow extensions to import own modules by absolute name
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 19932
diff changeset
    65
3877
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    66
class _demandmod(object):
29737
ae9a4d6a8d51 demandimport: omit default value of "level" at construction of _demandmod
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29736
diff changeset
    67
    """module demand-loader and proxy
ae9a4d6a8d51 demandimport: omit default value of "level" at construction of _demandmod
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29736
diff changeset
    68
ae9a4d6a8d51 demandimport: omit default value of "level" at construction of _demandmod
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29736
diff changeset
    69
    Specify 1 as 'level' argument at construction, to import module
ae9a4d6a8d51 demandimport: omit default value of "level" at construction of _demandmod
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29736
diff changeset
    70
    relatively.
ae9a4d6a8d51 demandimport: omit default value of "level" at construction of _demandmod
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29736
diff changeset
    71
    """
32446
63365e9621d6 demandimport: insert empty line per method
Yuya Nishihara <yuya@tcha.org>
parents: 32445
diff changeset
    72
29737
ae9a4d6a8d51 demandimport: omit default value of "level" at construction of _demandmod
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29736
diff changeset
    73
    def __init__(self, name, globals, locals, level):
3877
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    74
        if '.' in name:
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    75
            head, rest = name.split('.', 1)
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    76
            after = [rest]
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    77
        else:
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    78
            head = name
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    79
            after = []
31644
f80d9ddc40f3 py3: abuse r'' to preserve str-ness of literals passed to __setattr__()
Yuya Nishihara <yuya@tcha.org>
parents: 30647
diff changeset
    80
        object.__setattr__(self, r"_data",
26457
7e81305092a0 demandimport: replace more references to _demandmod instances
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26456
diff changeset
    81
                           (head, globals, locals, after, level, set()))
31644
f80d9ddc40f3 py3: abuse r'' to preserve str-ness of literals passed to __setattr__()
Yuya Nishihara <yuya@tcha.org>
parents: 30647
diff changeset
    82
        object.__setattr__(self, r"_module", None)
32446
63365e9621d6 demandimport: insert empty line per method
Yuya Nishihara <yuya@tcha.org>
parents: 32445
diff changeset
    83
3877
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    84
    def _extend(self, name):
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    85
        """add to the list of submodules to load"""
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    86
        self._data[3].append(name)
26457
7e81305092a0 demandimport: replace more references to _demandmod instances
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26456
diff changeset
    87
7e81305092a0 demandimport: replace more references to _demandmod instances
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26456
diff changeset
    88
    def _addref(self, name):
7e81305092a0 demandimport: replace more references to _demandmod instances
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26456
diff changeset
    89
        """Record that the named module ``name`` imports this module.
7e81305092a0 demandimport: replace more references to _demandmod instances
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26456
diff changeset
    90
7e81305092a0 demandimport: replace more references to _demandmod instances
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26456
diff changeset
    91
        References to this proxy class having the name of this module will be
7e81305092a0 demandimport: replace more references to _demandmod instances
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26456
diff changeset
    92
        replaced at module load time. We assume the symbol inside the importing
7e81305092a0 demandimport: replace more references to _demandmod instances
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26456
diff changeset
    93
        module is identical to the "head" name of this module. We don't
7e81305092a0 demandimport: replace more references to _demandmod instances
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26456
diff changeset
    94
        actually know if "as X" syntax is being used to change the symbol name
7e81305092a0 demandimport: replace more references to _demandmod instances
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26456
diff changeset
    95
        because this information isn't exposed to __import__.
7e81305092a0 demandimport: replace more references to _demandmod instances
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26456
diff changeset
    96
        """
7e81305092a0 demandimport: replace more references to _demandmod instances
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26456
diff changeset
    97
        self._data[5].add(name)
7e81305092a0 demandimport: replace more references to _demandmod instances
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26456
diff changeset
    98
3877
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    99
    def _load(self):
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   100
        if not self._module:
26457
7e81305092a0 demandimport: replace more references to _demandmod instances
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26456
diff changeset
   101
            head, globals, locals, after, level, modrefs = 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
   102
            mod = _hgextimport(_import, head, globals, locals, None, level)
29642
8960fcb76ca4 demandimport: avoid infinite recursion at actual module importing (issue5304)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29375
diff changeset
   103
            if mod is self:
8960fcb76ca4 demandimport: avoid infinite recursion at actual module importing (issue5304)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29375
diff changeset
   104
                # In this case, _hgextimport() above should imply
8960fcb76ca4 demandimport: avoid infinite recursion at actual module importing (issue5304)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29375
diff changeset
   105
                # _demandimport(). Otherwise, _hgextimport() never
8960fcb76ca4 demandimport: avoid infinite recursion at actual module importing (issue5304)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29375
diff changeset
   106
                # returns _demandmod. This isn't intentional behavior,
8960fcb76ca4 demandimport: avoid infinite recursion at actual module importing (issue5304)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29375
diff changeset
   107
                # in fact. (see also issue5304 for detail)
8960fcb76ca4 demandimport: avoid infinite recursion at actual module importing (issue5304)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29375
diff changeset
   108
                #
8960fcb76ca4 demandimport: avoid infinite recursion at actual module importing (issue5304)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29375
diff changeset
   109
                # If self._module is already bound at this point, self
8960fcb76ca4 demandimport: avoid infinite recursion at actual module importing (issue5304)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29375
diff changeset
   110
                # should be already _load()-ed while _hgextimport().
8960fcb76ca4 demandimport: avoid infinite recursion at actual module importing (issue5304)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29375
diff changeset
   111
                # Otherwise, there is no way to import actual module
8960fcb76ca4 demandimport: avoid infinite recursion at actual module importing (issue5304)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29375
diff changeset
   112
                # as expected, because (re-)invoking _hgextimport()
8960fcb76ca4 demandimport: avoid infinite recursion at actual module importing (issue5304)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29375
diff changeset
   113
                # should cause same result.
8960fcb76ca4 demandimport: avoid infinite recursion at actual module importing (issue5304)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29375
diff changeset
   114
                # This is reason why _load() returns without any more
8960fcb76ca4 demandimport: avoid infinite recursion at actual module importing (issue5304)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29375
diff changeset
   115
                # setup but assumes self to be already bound.
8960fcb76ca4 demandimport: avoid infinite recursion at actual module importing (issue5304)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29375
diff changeset
   116
                mod = self._module
8960fcb76ca4 demandimport: avoid infinite recursion at actual module importing (issue5304)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29375
diff changeset
   117
                assert mod and mod is not self, "%s, %s" % (self, mod)
8960fcb76ca4 demandimport: avoid infinite recursion at actual module importing (issue5304)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29375
diff changeset
   118
                return
8960fcb76ca4 demandimport: avoid infinite recursion at actual module importing (issue5304)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29375
diff changeset
   119
3877
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   120
            # 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
   121
            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
   122
                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
   123
                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
   124
                    h, t = p.split('.', 1)
14977
1dbd42a02153 demandimport: use getattr instead of hasattr
Augie Fackler <durin42@gmail.com>
parents: 14976
diff changeset
   125
                if getattr(mod, h, nothing) is nothing:
29736
14f077f7519a demandimport: import sub-module relatively as expected (issue5208)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29642
diff changeset
   126
                    setattr(mod, h, _demandmod(p, mod.__dict__, mod.__dict__,
14f077f7519a demandimport: import sub-module relatively as expected (issue5208)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29642
diff changeset
   127
                                               level=1))
3926
de6ae8f016af demandimport: handle already-loaded nested modules in subload
Brendan Cully <brendan@kublai.com>
parents: 3921
diff changeset
   128
                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
   129
                    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
   130
3877
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   131
            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
   132
                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
   133
26457
7e81305092a0 demandimport: replace more references to _demandmod instances
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26456
diff changeset
   134
            # Replace references to this proxy instance with the actual module.
32447
252d2260c74e demandimport: look for 'mod' suffix as alternative name for module reference
Yuya Nishihara <yuya@tcha.org>
parents: 32446
diff changeset
   135
            if locals:
252d2260c74e demandimport: look for 'mod' suffix as alternative name for module reference
Yuya Nishihara <yuya@tcha.org>
parents: 32446
diff changeset
   136
                if locals.get(head) is self:
252d2260c74e demandimport: look for 'mod' suffix as alternative name for module reference
Yuya Nishihara <yuya@tcha.org>
parents: 32446
diff changeset
   137
                    locals[head] = mod
252d2260c74e demandimport: look for 'mod' suffix as alternative name for module reference
Yuya Nishihara <yuya@tcha.org>
parents: 32446
diff changeset
   138
                elif locals.get(head + r'mod') is self:
252d2260c74e demandimport: look for 'mod' suffix as alternative name for module reference
Yuya Nishihara <yuya@tcha.org>
parents: 32446
diff changeset
   139
                    locals[head + r'mod'] = mod
26457
7e81305092a0 demandimport: replace more references to _demandmod instances
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26456
diff changeset
   140
7e81305092a0 demandimport: replace more references to _demandmod instances
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26456
diff changeset
   141
            for modname in modrefs:
7e81305092a0 demandimport: replace more references to _demandmod instances
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26456
diff changeset
   142
                modref = sys.modules.get(modname, None)
32445
847233374434 demandimport: strictly compare identity of proxy object
Yuya Nishihara <yuya@tcha.org>
parents: 32422
diff changeset
   143
                if modref and getattr(modref, head, None) is self:
26457
7e81305092a0 demandimport: replace more references to _demandmod instances
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26456
diff changeset
   144
                    setattr(modref, head, mod)
7e81305092a0 demandimport: replace more references to _demandmod instances
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26456
diff changeset
   145
31644
f80d9ddc40f3 py3: abuse r'' to preserve str-ness of literals passed to __setattr__()
Yuya Nishihara <yuya@tcha.org>
parents: 30647
diff changeset
   146
            object.__setattr__(self, r"_module", mod)
4631
e3afa670e484 demandimport: fix issue579 and add a test
Matt Mackall <mpm@selenic.com>
parents: 4626
diff changeset
   147
3877
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   148
    def __repr__(self):
4631
e3afa670e484 demandimport: fix issue579 and add a test
Matt Mackall <mpm@selenic.com>
parents: 4626
diff changeset
   149
        if self._module:
e3afa670e484 demandimport: fix issue579 and add a test
Matt Mackall <mpm@selenic.com>
parents: 4626
diff changeset
   150
            return "<proxied module '%s'>" % self._data[0]
3877
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   151
        return "<unloaded module '%s'>" % self._data[0]
32446
63365e9621d6 demandimport: insert empty line per method
Yuya Nishihara <yuya@tcha.org>
parents: 32445
diff changeset
   152
3877
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   153
    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
   154
        raise TypeError("%s object is not callable" % repr(self))
32446
63365e9621d6 demandimport: insert empty line per method
Yuya Nishihara <yuya@tcha.org>
parents: 32445
diff changeset
   155
32448
91a2ec8e7fa0 demandimport: stop overriding __getattribute__()
Yuya Nishihara <yuya@tcha.org>
parents: 32447
diff changeset
   156
    def __getattr__(self, attr):
3877
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   157
        self._load()
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   158
        return getattr(self._module, attr)
32446
63365e9621d6 demandimport: insert empty line per method
Yuya Nishihara <yuya@tcha.org>
parents: 32445
diff changeset
   159
3877
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   160
    def __setattr__(self, attr, val):
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   161
        self._load()
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   162
        setattr(self._module, attr, val)
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   163
32448
91a2ec8e7fa0 demandimport: stop overriding __getattribute__()
Yuya Nishihara <yuya@tcha.org>
parents: 32447
diff changeset
   164
    @property
91a2ec8e7fa0 demandimport: stop overriding __getattribute__()
Yuya Nishihara <yuya@tcha.org>
parents: 32447
diff changeset
   165
    def __dict__(self):
91a2ec8e7fa0 demandimport: stop overriding __getattribute__()
Yuya Nishihara <yuya@tcha.org>
parents: 32447
diff changeset
   166
        self._load()
91a2ec8e7fa0 demandimport: stop overriding __getattribute__()
Yuya Nishihara <yuya@tcha.org>
parents: 32447
diff changeset
   167
        return self._module.__dict__
91a2ec8e7fa0 demandimport: stop overriding __getattribute__()
Yuya Nishihara <yuya@tcha.org>
parents: 32447
diff changeset
   168
91a2ec8e7fa0 demandimport: stop overriding __getattribute__()
Yuya Nishihara <yuya@tcha.org>
parents: 32447
diff changeset
   169
    @property
91a2ec8e7fa0 demandimport: stop overriding __getattribute__()
Yuya Nishihara <yuya@tcha.org>
parents: 32447
diff changeset
   170
    def __doc__(self):
91a2ec8e7fa0 demandimport: stop overriding __getattribute__()
Yuya Nishihara <yuya@tcha.org>
parents: 32447
diff changeset
   171
        self._load()
91a2ec8e7fa0 demandimport: stop overriding __getattribute__()
Yuya Nishihara <yuya@tcha.org>
parents: 32447
diff changeset
   172
        return self._module.__doc__
91a2ec8e7fa0 demandimport: stop overriding __getattribute__()
Yuya Nishihara <yuya@tcha.org>
parents: 32447
diff changeset
   173
27536
f7d890bc5e01 demandimport: add support for PyPy
Bryan O'Sullivan <bos@serpentine.com>
parents: 27069
diff changeset
   174
_pypy = '__pypy__' in sys.builtin_module_names
f7d890bc5e01 demandimport: add support for PyPy
Bryan O'Sullivan <bos@serpentine.com>
parents: 27069
diff changeset
   175
21290
74be3fb1e3b8 demandimport: pass proper level to __import__ in Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 21025
diff changeset
   176
def _demandimport(name, globals=None, locals=None, fromlist=None, level=level):
32365
b2b5605285ec demandimport: strictly check missing locals argument
Yuya Nishihara <yuya@tcha.org>
parents: 32173
diff changeset
   177
    if locals is None or name in ignore or fromlist == ('*',):
3877
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   178
        # 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
   179
        return _hgextimport(_import, name, globals, locals, fromlist, level)
3877
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   180
    elif not fromlist:
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   181
        # import a [as b]
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   182
        if '.' in name: # a.b
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   183
            base, rest = name.split('.', 1)
3903
f9136599700f Make demandimport pass all tests on python2.5.
Brendan Cully <brendan@kublai.com>
parents: 3898
diff changeset
   184
            # email.__init__ loading email.mime
f9136599700f Make demandimport pass all tests on python2.5.
Brendan Cully <brendan@kublai.com>
parents: 3898
diff changeset
   185
            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
   186
                return _import(name, globals, locals, fromlist, level)
3877
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   187
            # 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
   188
            if base in locals:
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   189
                if isinstance(locals[base], _demandmod):
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   190
                    locals[base]._extend(rest)
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   191
                return locals[base]
19932
e3a5922e18c3 demandimport: support "absolute_import" for external libraries (issue4029)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15096
diff changeset
   192
        return _demandmod(name, globals, locals, level)
3877
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   193
    else:
25935
49dd4fd3f283 demandimport: refactor logic and add documentation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25934
diff changeset
   194
        # There is a fromlist.
49dd4fd3f283 demandimport: refactor logic and add documentation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25934
diff changeset
   195
        # from a import b,c,d
49dd4fd3f283 demandimport: refactor logic and add documentation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25934
diff changeset
   196
        # from . import b,c,d
49dd4fd3f283 demandimport: refactor logic and add documentation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25934
diff changeset
   197
        # from .a import b,c,d
49dd4fd3f283 demandimport: refactor logic and add documentation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25934
diff changeset
   198
49dd4fd3f283 demandimport: refactor logic and add documentation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25934
diff changeset
   199
        # level == -1: relative and absolute attempted (Python 2 only).
49dd4fd3f283 demandimport: refactor logic and add documentation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25934
diff changeset
   200
        # level >= 0: absolute only (Python 2 w/ absolute_import and Python 3).
49dd4fd3f283 demandimport: refactor logic and add documentation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25934
diff changeset
   201
        # The modern Mercurial convention is to use absolute_import everywhere,
49dd4fd3f283 demandimport: refactor logic and add documentation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25934
diff changeset
   202
        # so modern Mercurial code will have level >= 0.
49dd4fd3f283 demandimport: refactor logic and add documentation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25934
diff changeset
   203
26457
7e81305092a0 demandimport: replace more references to _demandmod instances
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26456
diff changeset
   204
        # The name of the module the import statement is located in.
7e81305092a0 demandimport: replace more references to _demandmod instances
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26456
diff changeset
   205
        globalname = globals.get('__name__')
7e81305092a0 demandimport: replace more references to _demandmod instances
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26456
diff changeset
   206
26873
78d05778907b demandimport: fix level passed to loader of sub-modules
Yuya Nishihara <yuya@tcha.org>
parents: 26830
diff changeset
   207
        def processfromitem(mod, attr):
26455
f2bf76d3d567 demandimport: consolidate code for processing items in fromlist
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25943
diff changeset
   208
            """Process an imported symbol in the import statement.
f2bf76d3d567 demandimport: consolidate code for processing items in fromlist
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25943
diff changeset
   209
30022
26a4e46af2bc demandimport: error out early on missing attribute of non package (issue5373)
Yuya Nishihara <yuya@tcha.org>
parents: 30021
diff changeset
   210
            If the symbol doesn't exist in the parent module, and if the
26a4e46af2bc demandimport: error out early on missing attribute of non package (issue5373)
Yuya Nishihara <yuya@tcha.org>
parents: 30021
diff changeset
   211
            parent module is a package, it must be a module. We set missing
26a4e46af2bc demandimport: error out early on missing attribute of non package (issue5373)
Yuya Nishihara <yuya@tcha.org>
parents: 30021
diff changeset
   212
            modules up as _demandmod instances.
26455
f2bf76d3d567 demandimport: consolidate code for processing items in fromlist
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25943
diff changeset
   213
            """
26456
86fc4a2863ff demandimport: refactor processfromitem
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26455
diff changeset
   214
            symbol = getattr(mod, attr, nothing)
30022
26a4e46af2bc demandimport: error out early on missing attribute of non package (issue5373)
Yuya Nishihara <yuya@tcha.org>
parents: 30021
diff changeset
   215
            nonpkg = getattr(mod, '__path__', nothing) is nothing
26456
86fc4a2863ff demandimport: refactor processfromitem
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26455
diff changeset
   216
            if symbol is nothing:
30022
26a4e46af2bc demandimport: error out early on missing attribute of non package (issue5373)
Yuya Nishihara <yuya@tcha.org>
parents: 30021
diff changeset
   217
                if nonpkg:
30647
1914db1b7d9e demandimport: do not raise ImportError for unknown item in fromlist
Yuya Nishihara <yuya@tcha.org>
parents: 30156
diff changeset
   218
                    # do not try relative import, which would raise ValueError,
1914db1b7d9e demandimport: do not raise ImportError for unknown item in fromlist
Yuya Nishihara <yuya@tcha.org>
parents: 30156
diff changeset
   219
                    # and leave unknown attribute as the default __import__()
1914db1b7d9e demandimport: do not raise ImportError for unknown item in fromlist
Yuya Nishihara <yuya@tcha.org>
parents: 30156
diff changeset
   220
                    # would do. the missing attribute will be detected later
1914db1b7d9e demandimport: do not raise ImportError for unknown item in fromlist
Yuya Nishihara <yuya@tcha.org>
parents: 30156
diff changeset
   221
                    # while processing the import statement.
1914db1b7d9e demandimport: do not raise ImportError for unknown item in fromlist
Yuya Nishihara <yuya@tcha.org>
parents: 30156
diff changeset
   222
                    return
28175
c25e3fd38ff1 demandimport: enforce ignore list while processing modules in fromlist
Yuya Nishihara <yuya@tcha.org>
parents: 27537
diff changeset
   223
                mn = '%s.%s' % (mod.__name__, attr)
c25e3fd38ff1 demandimport: enforce ignore list while processing modules in fromlist
Yuya Nishihara <yuya@tcha.org>
parents: 27537
diff changeset
   224
                if mn in ignore:
c25e3fd38ff1 demandimport: enforce ignore list while processing modules in fromlist
Yuya Nishihara <yuya@tcha.org>
parents: 27537
diff changeset
   225
                    importfunc = _origimport
c25e3fd38ff1 demandimport: enforce ignore list while processing modules in fromlist
Yuya Nishihara <yuya@tcha.org>
parents: 27537
diff changeset
   226
                else:
c25e3fd38ff1 demandimport: enforce ignore list while processing modules in fromlist
Yuya Nishihara <yuya@tcha.org>
parents: 27537
diff changeset
   227
                    importfunc = _demandmod
c25e3fd38ff1 demandimport: enforce ignore list while processing modules in fromlist
Yuya Nishihara <yuya@tcha.org>
parents: 27537
diff changeset
   228
                symbol = importfunc(attr, mod.__dict__, locals, level=1)
26456
86fc4a2863ff demandimport: refactor processfromitem
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26455
diff changeset
   229
                setattr(mod, attr, symbol)
26455
f2bf76d3d567 demandimport: consolidate code for processing items in fromlist
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25943
diff changeset
   230
26457
7e81305092a0 demandimport: replace more references to _demandmod instances
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26456
diff changeset
   231
            # Record the importing module references this symbol so we can
7e81305092a0 demandimport: replace more references to _demandmod instances
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26456
diff changeset
   232
            # replace the symbol with the actual module instance at load
7e81305092a0 demandimport: replace more references to _demandmod instances
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26456
diff changeset
   233
            # time.
7e81305092a0 demandimport: replace more references to _demandmod instances
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26456
diff changeset
   234
            if globalname and isinstance(symbol, _demandmod):
7e81305092a0 demandimport: replace more references to _demandmod instances
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26456
diff changeset
   235
                symbol._addref(globalname)
7e81305092a0 demandimport: replace more references to _demandmod instances
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26456
diff changeset
   236
29375
fcaf20175b1b demandimport: delay loading for "from a import b" with absolute_import
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28286
diff changeset
   237
        def chainmodules(rootmod, modname):
fcaf20175b1b demandimport: delay loading for "from a import b" with absolute_import
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28286
diff changeset
   238
            # recurse down the module chain, and return the leaf module
fcaf20175b1b demandimport: delay loading for "from a import b" with absolute_import
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28286
diff changeset
   239
            mod = rootmod
fcaf20175b1b demandimport: delay loading for "from a import b" with absolute_import
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28286
diff changeset
   240
            for comp in modname.split('.')[1:]:
fcaf20175b1b demandimport: delay loading for "from a import b" with absolute_import
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28286
diff changeset
   241
                if getattr(mod, comp, nothing) is nothing:
29736
14f077f7519a demandimport: import sub-module relatively as expected (issue5208)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29642
diff changeset
   242
                    setattr(mod, comp, _demandmod(comp, mod.__dict__,
14f077f7519a demandimport: import sub-module relatively as expected (issue5208)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29642
diff changeset
   243
                                                  mod.__dict__, level=1))
29375
fcaf20175b1b demandimport: delay loading for "from a import b" with absolute_import
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28286
diff changeset
   244
                mod = getattr(mod, comp)
fcaf20175b1b demandimport: delay loading for "from a import b" with absolute_import
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28286
diff changeset
   245
            return mod
fcaf20175b1b demandimport: delay loading for "from a import b" with absolute_import
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28286
diff changeset
   246
25935
49dd4fd3f283 demandimport: refactor logic and add documentation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25934
diff changeset
   247
        if level >= 0:
25937
4f1144c3c72b demandimport: support lazy loading for absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25936
diff changeset
   248
            if name:
29375
fcaf20175b1b demandimport: delay loading for "from a import b" with absolute_import
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28286
diff changeset
   249
                # "from a import b" or "from .a import b" style
fcaf20175b1b demandimport: delay loading for "from a import b" with absolute_import
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28286
diff changeset
   250
                rootmod = _hgextimport(_origimport, name, globals, locals,
fcaf20175b1b demandimport: delay loading for "from a import b" with absolute_import
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28286
diff changeset
   251
                                       level=level)
fcaf20175b1b demandimport: delay loading for "from a import b" with absolute_import
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28286
diff changeset
   252
                mod = chainmodules(rootmod, name)
fcaf20175b1b demandimport: delay loading for "from a import b" with absolute_import
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28286
diff changeset
   253
            elif _pypy:
27536
f7d890bc5e01 demandimport: add support for PyPy
Bryan O'Sullivan <bos@serpentine.com>
parents: 27069
diff changeset
   254
                # PyPy's __import__ throws an exception if invoked
f7d890bc5e01 demandimport: add support for PyPy
Bryan O'Sullivan <bos@serpentine.com>
parents: 27069
diff changeset
   255
                # with an empty name and no fromlist.  Recreate the
f7d890bc5e01 demandimport: add support for PyPy
Bryan O'Sullivan <bos@serpentine.com>
parents: 27069
diff changeset
   256
                # desired behaviour by hand.
f7d890bc5e01 demandimport: add support for PyPy
Bryan O'Sullivan <bos@serpentine.com>
parents: 27069
diff changeset
   257
                mn = globalname
f7d890bc5e01 demandimport: add support for PyPy
Bryan O'Sullivan <bos@serpentine.com>
parents: 27069
diff changeset
   258
                mod = sys.modules[mn]
f7d890bc5e01 demandimport: add support for PyPy
Bryan O'Sullivan <bos@serpentine.com>
parents: 27069
diff changeset
   259
                if getattr(mod, '__path__', nothing) is nothing:
f7d890bc5e01 demandimport: add support for PyPy
Bryan O'Sullivan <bos@serpentine.com>
parents: 27069
diff changeset
   260
                    mn = mn.rsplit('.', 1)[0]
f7d890bc5e01 demandimport: add support for PyPy
Bryan O'Sullivan <bos@serpentine.com>
parents: 27069
diff changeset
   261
                    mod = sys.modules[mn]
f7d890bc5e01 demandimport: add support for PyPy
Bryan O'Sullivan <bos@serpentine.com>
parents: 27069
diff changeset
   262
                if level > 1:
f7d890bc5e01 demandimport: add support for PyPy
Bryan O'Sullivan <bos@serpentine.com>
parents: 27069
diff changeset
   263
                    mn = mn.rsplit('.', level - 1)[0]
f7d890bc5e01 demandimport: add support for PyPy
Bryan O'Sullivan <bos@serpentine.com>
parents: 27069
diff changeset
   264
                    mod = sys.modules[mn]
f7d890bc5e01 demandimport: add support for PyPy
Bryan O'Sullivan <bos@serpentine.com>
parents: 27069
diff changeset
   265
            else:
f7d890bc5e01 demandimport: add support for PyPy
Bryan O'Sullivan <bos@serpentine.com>
parents: 27069
diff changeset
   266
                mod = _hgextimport(_origimport, name, globals, locals,
f7d890bc5e01 demandimport: add support for PyPy
Bryan O'Sullivan <bos@serpentine.com>
parents: 27069
diff changeset
   267
                                   level=level)
26455
f2bf76d3d567 demandimport: consolidate code for processing items in fromlist
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25943
diff changeset
   268
25937
4f1144c3c72b demandimport: support lazy loading for absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25936
diff changeset
   269
            for x in fromlist:
26873
78d05778907b demandimport: fix level passed to loader of sub-modules
Yuya Nishihara <yuya@tcha.org>
parents: 26830
diff changeset
   270
                processfromitem(mod, x)
25937
4f1144c3c72b demandimport: support lazy loading for absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25936
diff changeset
   271
4f1144c3c72b demandimport: support lazy loading for absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25936
diff changeset
   272
            return mod
25935
49dd4fd3f283 demandimport: refactor logic and add documentation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25934
diff changeset
   273
49dd4fd3f283 demandimport: refactor logic and add documentation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25934
diff changeset
   274
        # But, we still need to support lazy loading of standard library and 3rd
49dd4fd3f283 demandimport: refactor logic and add documentation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25934
diff changeset
   275
        # party modules. So handle level == -1.
19933
621a26eb3a99 demandimport: allow extensions to import own modules by absolute name
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 19932
diff changeset
   276
        mod = _hgextimport(_origimport, name, globals, locals)
29375
fcaf20175b1b demandimport: delay loading for "from a import b" with absolute_import
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28286
diff changeset
   277
        mod = chainmodules(mod, name)
26455
f2bf76d3d567 demandimport: consolidate code for processing items in fromlist
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25943
diff changeset
   278
3877
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   279
        for x in fromlist:
26455
f2bf76d3d567 demandimport: consolidate code for processing items in fromlist
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25943
diff changeset
   280
            processfromitem(mod, x)
f2bf76d3d567 demandimport: consolidate code for processing items in fromlist
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25943
diff changeset
   281
3877
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   282
        return mod
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   283
32422
f37f9499fea8 demandimport: move ignore list to __init__.py
Siddharth Agarwal <sid0@fb.com>
parents: 32420
diff changeset
   284
ignore = []
3877
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   285
32422
f37f9499fea8 demandimport: move ignore list to __init__.py
Siddharth Agarwal <sid0@fb.com>
parents: 32420
diff changeset
   286
def init(ignorelist):
f37f9499fea8 demandimport: move ignore list to __init__.py
Siddharth Agarwal <sid0@fb.com>
parents: 32420
diff changeset
   287
    global ignore
f37f9499fea8 demandimport: move ignore list to __init__.py
Siddharth Agarwal <sid0@fb.com>
parents: 32420
diff changeset
   288
    ignore = ignorelist
30020
bf94fe556f16 demandimport: add '_ctypes.pointer' to ignore list on PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 29980
diff changeset
   289
20422
aac87f70f38e hooks: only disable/re-enable demandimport when it's already enabled
Brodie Rao <brodie@sf.io>
parents: 19933
diff changeset
   290
def isenabled():
25673
fa1f04529775 demandimport: alias __builtin__ as builtins
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25327
diff changeset
   291
    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
   292
3877
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   293
def enable():
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   294
    "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
   295
    if os.environ.get('HGDEMANDIMPORT') != 'disable':
25673
fa1f04529775 demandimport: alias __builtin__ as builtins
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25327
diff changeset
   296
        builtins.__import__ = _demandimport
3877
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   297
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   298
def disable():
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   299
    "disable global demand-loading of modules"
25673
fa1f04529775 demandimport: alias __builtin__ as builtins
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25327
diff changeset
   300
    builtins.__import__ = _origimport
25327
2e7804110b14 demandimport: define a `deactivated` context manager
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 23643
diff changeset
   301
2e7804110b14 demandimport: define a `deactivated` context manager
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 23643
diff changeset
   302
@contextmanager
2e7804110b14 demandimport: define a `deactivated` context manager
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 23643
diff changeset
   303
def deactivated():
2e7804110b14 demandimport: define a `deactivated` context manager
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 23643
diff changeset
   304
    "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
   305
    demandenabled = isenabled()
2e7804110b14 demandimport: define a `deactivated` context manager
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 23643
diff changeset
   306
    if demandenabled:
2e7804110b14 demandimport: define a `deactivated` context manager
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 23643
diff changeset
   307
        disable()
2e7804110b14 demandimport: define a `deactivated` context manager
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 23643
diff changeset
   308
2e7804110b14 demandimport: define a `deactivated` context manager
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 23643
diff changeset
   309
    try:
2e7804110b14 demandimport: define a `deactivated` context manager
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 23643
diff changeset
   310
        yield
2e7804110b14 demandimport: define a `deactivated` context manager
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 23643
diff changeset
   311
    finally:
2e7804110b14 demandimport: define a `deactivated` context manager
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 23643
diff changeset
   312
        if demandenabled:
2e7804110b14 demandimport: define a `deactivated` context manager
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 23643
diff changeset
   313
            enable()