author | Matt Harbison <matt_harbison@yahoo.com> |
Tue, 20 Aug 2019 18:05:07 -0400 | |
changeset 42815 | 197e7326b8b8 |
parent 39256 | 574e1d3bc667 |
child 43076 | 2372284d9457 |
permissions | -rw-r--r-- |
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 | 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 |
|
33530
05e3fa254b6b
demandimport: drop Py3 workarounds from Py2 implementation
Yuya Nishihara <yuya@tcha.org>
parents:
33529
diff
changeset
|
29 |
import __builtin__ as builtins |
25943
3beed01daff9
demandimport: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25937
diff
changeset
|
30 |
import contextlib |
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 |
|
39256
574e1d3bc667
demandimport: instrument python 2 code with trace events
Augie Fackler <augie@google.com>
parents:
37843
diff
changeset
|
33 |
from . import tracing |
574e1d3bc667
demandimport: instrument python 2 code with trace events
Augie Fackler <augie@google.com>
parents:
37843
diff
changeset
|
34 |
|
25943
3beed01daff9
demandimport: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25937
diff
changeset
|
35 |
contextmanager = contextlib.contextmanager |
3beed01daff9
demandimport: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25937
diff
changeset
|
36 |
|
3877
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
37 |
_origimport = __import__ |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
38 |
|
14977
1dbd42a02153
demandimport: use getattr instead of hasattr
Augie Fackler <durin42@gmail.com>
parents:
14976
diff
changeset
|
39 |
nothing = object() |
1dbd42a02153
demandimport: use getattr instead of hasattr
Augie Fackler <durin42@gmail.com>
parents:
14976
diff
changeset
|
40 |
|
25936
f90bb2002bcf
demandimport: support keyword arguments on _hgextimport
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25935
diff
changeset
|
41 |
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
|
42 |
try: |
25936
f90bb2002bcf
demandimport: support keyword arguments on _hgextimport
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25935
diff
changeset
|
43 |
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
|
44 |
except ImportError: |
621a26eb3a99
demandimport: allow extensions to import own modules by absolute name
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
19932
diff
changeset
|
45 |
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
|
46 |
raise |
621a26eb3a99
demandimport: allow extensions to import own modules by absolute name
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
19932
diff
changeset
|
47 |
# 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
|
48 |
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
|
49 |
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
|
50 |
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
|
51 |
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
|
52 |
raise |
621a26eb3a99
demandimport: allow extensions to import own modules by absolute name
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
19932
diff
changeset
|
53 |
# retry to import with "hgext_" prefix |
25936
f90bb2002bcf
demandimport: support keyword arguments on _hgextimport
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25935
diff
changeset
|
54 |
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
|
55 |
|
3877
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
56 |
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
|
57 |
"""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
|
58 |
|
ae9a4d6a8d51
demandimport: omit default value of "level" at construction of _demandmod
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
29736
diff
changeset
|
59 |
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
|
60 |
relatively. |
ae9a4d6a8d51
demandimport: omit default value of "level" at construction of _demandmod
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
29736
diff
changeset
|
61 |
""" |
32446
63365e9621d6
demandimport: insert empty line per method
Yuya Nishihara <yuya@tcha.org>
parents:
32445
diff
changeset
|
62 |
|
29737
ae9a4d6a8d51
demandimport: omit default value of "level" at construction of _demandmod
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
29736
diff
changeset
|
63 |
def __init__(self, name, globals, locals, level): |
3877
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
64 |
if '.' in name: |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
65 |
head, rest = name.split('.', 1) |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
66 |
after = [rest] |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
67 |
else: |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
68 |
head = name |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
69 |
after = [] |
31644
f80d9ddc40f3
py3: abuse r'' to preserve str-ness of literals passed to __setattr__()
Yuya Nishihara <yuya@tcha.org>
parents:
30647
diff
changeset
|
70 |
object.__setattr__(self, r"_data", |
26457
7e81305092a0
demandimport: replace more references to _demandmod instances
Gregory Szorc <gregory.szorc@gmail.com>
parents:
26456
diff
changeset
|
71 |
(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
|
72 |
object.__setattr__(self, r"_module", None) |
32446
63365e9621d6
demandimport: insert empty line per method
Yuya Nishihara <yuya@tcha.org>
parents:
32445
diff
changeset
|
73 |
|
3877
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
74 |
def _extend(self, name): |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
75 |
"""add to the list of submodules to load""" |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
76 |
self._data[3].append(name) |
26457
7e81305092a0
demandimport: replace more references to _demandmod instances
Gregory Szorc <gregory.szorc@gmail.com>
parents:
26456
diff
changeset
|
77 |
|
7e81305092a0
demandimport: replace more references to _demandmod instances
Gregory Szorc <gregory.szorc@gmail.com>
parents:
26456
diff
changeset
|
78 |
def _addref(self, name): |
7e81305092a0
demandimport: replace more references to _demandmod instances
Gregory Szorc <gregory.szorc@gmail.com>
parents:
26456
diff
changeset
|
79 |
"""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
|
80 |
|
7e81305092a0
demandimport: replace more references to _demandmod instances
Gregory Szorc <gregory.szorc@gmail.com>
parents:
26456
diff
changeset
|
81 |
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
|
82 |
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
|
83 |
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
|
84 |
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
|
85 |
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
|
86 |
""" |
7e81305092a0
demandimport: replace more references to _demandmod instances
Gregory Szorc <gregory.szorc@gmail.com>
parents:
26456
diff
changeset
|
87 |
self._data[5].add(name) |
7e81305092a0
demandimport: replace more references to _demandmod instances
Gregory Szorc <gregory.szorc@gmail.com>
parents:
26456
diff
changeset
|
88 |
|
3877
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
89 |
def _load(self): |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
90 |
if not self._module: |
39256
574e1d3bc667
demandimport: instrument python 2 code with trace events
Augie Fackler <augie@google.com>
parents:
37843
diff
changeset
|
91 |
with tracing.log('demandimport %s', self._data[0]): |
574e1d3bc667
demandimport: instrument python 2 code with trace events
Augie Fackler <augie@google.com>
parents:
37843
diff
changeset
|
92 |
head, globals, locals, after, level, modrefs = self._data |
574e1d3bc667
demandimport: instrument python 2 code with trace events
Augie Fackler <augie@google.com>
parents:
37843
diff
changeset
|
93 |
mod = _hgextimport( |
574e1d3bc667
demandimport: instrument python 2 code with trace events
Augie Fackler <augie@google.com>
parents:
37843
diff
changeset
|
94 |
_origimport, head, globals, locals, None, level) |
574e1d3bc667
demandimport: instrument python 2 code with trace events
Augie Fackler <augie@google.com>
parents:
37843
diff
changeset
|
95 |
if mod is self: |
574e1d3bc667
demandimport: instrument python 2 code with trace events
Augie Fackler <augie@google.com>
parents:
37843
diff
changeset
|
96 |
# In this case, _hgextimport() above should imply |
574e1d3bc667
demandimport: instrument python 2 code with trace events
Augie Fackler <augie@google.com>
parents:
37843
diff
changeset
|
97 |
# _demandimport(). Otherwise, _hgextimport() never |
574e1d3bc667
demandimport: instrument python 2 code with trace events
Augie Fackler <augie@google.com>
parents:
37843
diff
changeset
|
98 |
# returns _demandmod. This isn't intentional behavior, |
574e1d3bc667
demandimport: instrument python 2 code with trace events
Augie Fackler <augie@google.com>
parents:
37843
diff
changeset
|
99 |
# in fact. (see also issue5304 for detail) |
574e1d3bc667
demandimport: instrument python 2 code with trace events
Augie Fackler <augie@google.com>
parents:
37843
diff
changeset
|
100 |
# |
574e1d3bc667
demandimport: instrument python 2 code with trace events
Augie Fackler <augie@google.com>
parents:
37843
diff
changeset
|
101 |
# If self._module is already bound at this point, self |
574e1d3bc667
demandimport: instrument python 2 code with trace events
Augie Fackler <augie@google.com>
parents:
37843
diff
changeset
|
102 |
# should be already _load()-ed while _hgextimport(). |
574e1d3bc667
demandimport: instrument python 2 code with trace events
Augie Fackler <augie@google.com>
parents:
37843
diff
changeset
|
103 |
# Otherwise, there is no way to import actual module |
574e1d3bc667
demandimport: instrument python 2 code with trace events
Augie Fackler <augie@google.com>
parents:
37843
diff
changeset
|
104 |
# as expected, because (re-)invoking _hgextimport() |
574e1d3bc667
demandimport: instrument python 2 code with trace events
Augie Fackler <augie@google.com>
parents:
37843
diff
changeset
|
105 |
# should cause same result. |
574e1d3bc667
demandimport: instrument python 2 code with trace events
Augie Fackler <augie@google.com>
parents:
37843
diff
changeset
|
106 |
# This is reason why _load() returns without any more |
574e1d3bc667
demandimport: instrument python 2 code with trace events
Augie Fackler <augie@google.com>
parents:
37843
diff
changeset
|
107 |
# setup but assumes self to be already bound. |
574e1d3bc667
demandimport: instrument python 2 code with trace events
Augie Fackler <augie@google.com>
parents:
37843
diff
changeset
|
108 |
mod = self._module |
574e1d3bc667
demandimport: instrument python 2 code with trace events
Augie Fackler <augie@google.com>
parents:
37843
diff
changeset
|
109 |
assert mod and mod is not self, "%s, %s" % (self, mod) |
574e1d3bc667
demandimport: instrument python 2 code with trace events
Augie Fackler <augie@google.com>
parents:
37843
diff
changeset
|
110 |
return |
29642
8960fcb76ca4
demandimport: avoid infinite recursion at actual module importing (issue5304)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
29375
diff
changeset
|
111 |
|
39256
574e1d3bc667
demandimport: instrument python 2 code with trace events
Augie Fackler <augie@google.com>
parents:
37843
diff
changeset
|
112 |
# load submodules |
574e1d3bc667
demandimport: instrument python 2 code with trace events
Augie Fackler <augie@google.com>
parents:
37843
diff
changeset
|
113 |
def subload(mod, p): |
574e1d3bc667
demandimport: instrument python 2 code with trace events
Augie Fackler <augie@google.com>
parents:
37843
diff
changeset
|
114 |
h, t = p, None |
574e1d3bc667
demandimport: instrument python 2 code with trace events
Augie Fackler <augie@google.com>
parents:
37843
diff
changeset
|
115 |
if '.' in p: |
574e1d3bc667
demandimport: instrument python 2 code with trace events
Augie Fackler <augie@google.com>
parents:
37843
diff
changeset
|
116 |
h, t = p.split('.', 1) |
574e1d3bc667
demandimport: instrument python 2 code with trace events
Augie Fackler <augie@google.com>
parents:
37843
diff
changeset
|
117 |
if getattr(mod, h, nothing) is nothing: |
574e1d3bc667
demandimport: instrument python 2 code with trace events
Augie Fackler <augie@google.com>
parents:
37843
diff
changeset
|
118 |
setattr(mod, h, _demandmod( |
574e1d3bc667
demandimport: instrument python 2 code with trace events
Augie Fackler <augie@google.com>
parents:
37843
diff
changeset
|
119 |
p, mod.__dict__, mod.__dict__, level=1)) |
574e1d3bc667
demandimport: instrument python 2 code with trace events
Augie Fackler <augie@google.com>
parents:
37843
diff
changeset
|
120 |
elif t: |
574e1d3bc667
demandimport: instrument python 2 code with trace events
Augie Fackler <augie@google.com>
parents:
37843
diff
changeset
|
121 |
subload(getattr(mod, h), 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
|
122 |
|
39256
574e1d3bc667
demandimport: instrument python 2 code with trace events
Augie Fackler <augie@google.com>
parents:
37843
diff
changeset
|
123 |
for x in after: |
574e1d3bc667
demandimport: instrument python 2 code with trace events
Augie Fackler <augie@google.com>
parents:
37843
diff
changeset
|
124 |
subload(mod, x) |
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
|
125 |
|
39256
574e1d3bc667
demandimport: instrument python 2 code with trace events
Augie Fackler <augie@google.com>
parents:
37843
diff
changeset
|
126 |
# Replace references to this proxy instance with the |
574e1d3bc667
demandimport: instrument python 2 code with trace events
Augie Fackler <augie@google.com>
parents:
37843
diff
changeset
|
127 |
# actual module. |
574e1d3bc667
demandimport: instrument python 2 code with trace events
Augie Fackler <augie@google.com>
parents:
37843
diff
changeset
|
128 |
if locals: |
574e1d3bc667
demandimport: instrument python 2 code with trace events
Augie Fackler <augie@google.com>
parents:
37843
diff
changeset
|
129 |
if locals.get(head) is self: |
574e1d3bc667
demandimport: instrument python 2 code with trace events
Augie Fackler <augie@google.com>
parents:
37843
diff
changeset
|
130 |
locals[head] = mod |
574e1d3bc667
demandimport: instrument python 2 code with trace events
Augie Fackler <augie@google.com>
parents:
37843
diff
changeset
|
131 |
elif locals.get(head + r'mod') is self: |
574e1d3bc667
demandimport: instrument python 2 code with trace events
Augie Fackler <augie@google.com>
parents:
37843
diff
changeset
|
132 |
locals[head + r'mod'] = mod |
26457
7e81305092a0
demandimport: replace more references to _demandmod instances
Gregory Szorc <gregory.szorc@gmail.com>
parents:
26456
diff
changeset
|
133 |
|
39256
574e1d3bc667
demandimport: instrument python 2 code with trace events
Augie Fackler <augie@google.com>
parents:
37843
diff
changeset
|
134 |
for modname in modrefs: |
574e1d3bc667
demandimport: instrument python 2 code with trace events
Augie Fackler <augie@google.com>
parents:
37843
diff
changeset
|
135 |
modref = sys.modules.get(modname, None) |
574e1d3bc667
demandimport: instrument python 2 code with trace events
Augie Fackler <augie@google.com>
parents:
37843
diff
changeset
|
136 |
if modref and getattr(modref, head, None) is self: |
574e1d3bc667
demandimport: instrument python 2 code with trace events
Augie Fackler <augie@google.com>
parents:
37843
diff
changeset
|
137 |
setattr(modref, head, mod) |
26457
7e81305092a0
demandimport: replace more references to _demandmod instances
Gregory Szorc <gregory.szorc@gmail.com>
parents:
26456
diff
changeset
|
138 |
|
39256
574e1d3bc667
demandimport: instrument python 2 code with trace events
Augie Fackler <augie@google.com>
parents:
37843
diff
changeset
|
139 |
object.__setattr__(self, r"_module", mod) |
4631
e3afa670e484
demandimport: fix issue579 and add a test
Matt Mackall <mpm@selenic.com>
parents:
4626
diff
changeset
|
140 |
|
3877
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
141 |
def __repr__(self): |
4631
e3afa670e484
demandimport: fix issue579 and add a test
Matt Mackall <mpm@selenic.com>
parents:
4626
diff
changeset
|
142 |
if self._module: |
e3afa670e484
demandimport: fix issue579 and add a test
Matt Mackall <mpm@selenic.com>
parents:
4626
diff
changeset
|
143 |
return "<proxied module '%s'>" % self._data[0] |
3877
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
144 |
return "<unloaded module '%s'>" % self._data[0] |
32446
63365e9621d6
demandimport: insert empty line per method
Yuya Nishihara <yuya@tcha.org>
parents:
32445
diff
changeset
|
145 |
|
3877
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
146 |
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
|
147 |
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
|
148 |
|
32448
91a2ec8e7fa0
demandimport: stop overriding __getattribute__()
Yuya Nishihara <yuya@tcha.org>
parents:
32447
diff
changeset
|
149 |
def __getattr__(self, attr): |
3877
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
150 |
self._load() |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
151 |
return getattr(self._module, attr) |
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 __setattr__(self, attr, val): |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
154 |
self._load() |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
155 |
setattr(self._module, attr, val) |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
156 |
|
32448
91a2ec8e7fa0
demandimport: stop overriding __getattribute__()
Yuya Nishihara <yuya@tcha.org>
parents:
32447
diff
changeset
|
157 |
@property |
91a2ec8e7fa0
demandimport: stop overriding __getattribute__()
Yuya Nishihara <yuya@tcha.org>
parents:
32447
diff
changeset
|
158 |
def __dict__(self): |
91a2ec8e7fa0
demandimport: stop overriding __getattribute__()
Yuya Nishihara <yuya@tcha.org>
parents:
32447
diff
changeset
|
159 |
self._load() |
91a2ec8e7fa0
demandimport: stop overriding __getattribute__()
Yuya Nishihara <yuya@tcha.org>
parents:
32447
diff
changeset
|
160 |
return self._module.__dict__ |
91a2ec8e7fa0
demandimport: stop overriding __getattribute__()
Yuya Nishihara <yuya@tcha.org>
parents:
32447
diff
changeset
|
161 |
|
91a2ec8e7fa0
demandimport: stop overriding __getattribute__()
Yuya Nishihara <yuya@tcha.org>
parents:
32447
diff
changeset
|
162 |
@property |
91a2ec8e7fa0
demandimport: stop overriding __getattribute__()
Yuya Nishihara <yuya@tcha.org>
parents:
32447
diff
changeset
|
163 |
def __doc__(self): |
91a2ec8e7fa0
demandimport: stop overriding __getattribute__()
Yuya Nishihara <yuya@tcha.org>
parents:
32447
diff
changeset
|
164 |
self._load() |
91a2ec8e7fa0
demandimport: stop overriding __getattribute__()
Yuya Nishihara <yuya@tcha.org>
parents:
32447
diff
changeset
|
165 |
return self._module.__doc__ |
91a2ec8e7fa0
demandimport: stop overriding __getattribute__()
Yuya Nishihara <yuya@tcha.org>
parents:
32447
diff
changeset
|
166 |
|
27536
f7d890bc5e01
demandimport: add support for PyPy
Bryan O'Sullivan <bos@serpentine.com>
parents:
27069
diff
changeset
|
167 |
_pypy = '__pypy__' in sys.builtin_module_names |
f7d890bc5e01
demandimport: add support for PyPy
Bryan O'Sullivan <bos@serpentine.com>
parents:
27069
diff
changeset
|
168 |
|
33530
05e3fa254b6b
demandimport: drop Py3 workarounds from Py2 implementation
Yuya Nishihara <yuya@tcha.org>
parents:
33529
diff
changeset
|
169 |
def _demandimport(name, globals=None, locals=None, fromlist=None, level=-1): |
37843
670eb4fa1b86
demandimport: make module ignores a set (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33859
diff
changeset
|
170 |
if locals is None or name in ignores or fromlist == ('*',): |
3877
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
171 |
# these cases we can't really delay |
33529
ded3ebae8779
demandimport: drop hack for old Pythons which had no level argument
Yuya Nishihara <yuya@tcha.org>
parents:
32448
diff
changeset
|
172 |
return _hgextimport(_origimport, name, globals, locals, fromlist, level) |
3877
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
173 |
elif not fromlist: |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
174 |
# import a [as b] |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
175 |
if '.' in name: # a.b |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
176 |
base, rest = name.split('.', 1) |
3903
f9136599700f
Make demandimport pass all tests on python2.5.
Brendan Cully <brendan@kublai.com>
parents:
3898
diff
changeset
|
177 |
# email.__init__ loading email.mime |
f9136599700f
Make demandimport pass all tests on python2.5.
Brendan Cully <brendan@kublai.com>
parents:
3898
diff
changeset
|
178 |
if globals and globals.get('__name__', None) == base: |
33529
ded3ebae8779
demandimport: drop hack for old Pythons which had no level argument
Yuya Nishihara <yuya@tcha.org>
parents:
32448
diff
changeset
|
179 |
return _origimport(name, globals, locals, fromlist, level) |
3877
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
180 |
# 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
|
181 |
if base in locals: |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
182 |
if isinstance(locals[base], _demandmod): |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
183 |
locals[base]._extend(rest) |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
184 |
return locals[base] |
19932
e3a5922e18c3
demandimport: support "absolute_import" for external libraries (issue4029)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
15096
diff
changeset
|
185 |
return _demandmod(name, globals, locals, level) |
3877
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
186 |
else: |
25935
49dd4fd3f283
demandimport: refactor logic and add documentation
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25934
diff
changeset
|
187 |
# There is a fromlist. |
49dd4fd3f283
demandimport: refactor logic and add documentation
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25934
diff
changeset
|
188 |
# from a import b,c,d |
49dd4fd3f283
demandimport: refactor logic and add documentation
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25934
diff
changeset
|
189 |
# from . import b,c,d |
49dd4fd3f283
demandimport: refactor logic and add documentation
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25934
diff
changeset
|
190 |
# from .a import b,c,d |
49dd4fd3f283
demandimport: refactor logic and add documentation
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25934
diff
changeset
|
191 |
|
49dd4fd3f283
demandimport: refactor logic and add documentation
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25934
diff
changeset
|
192 |
# 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
|
193 |
# 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
|
194 |
# 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
|
195 |
# 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
|
196 |
|
26457
7e81305092a0
demandimport: replace more references to _demandmod instances
Gregory Szorc <gregory.szorc@gmail.com>
parents:
26456
diff
changeset
|
197 |
# 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
|
198 |
globalname = globals.get('__name__') |
7e81305092a0
demandimport: replace more references to _demandmod instances
Gregory Szorc <gregory.szorc@gmail.com>
parents:
26456
diff
changeset
|
199 |
|
26873
78d05778907b
demandimport: fix level passed to loader of sub-modules
Yuya Nishihara <yuya@tcha.org>
parents:
26830
diff
changeset
|
200 |
def processfromitem(mod, attr): |
26455
f2bf76d3d567
demandimport: consolidate code for processing items in fromlist
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25943
diff
changeset
|
201 |
"""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
|
202 |
|
30022
26a4e46af2bc
demandimport: error out early on missing attribute of non package (issue5373)
Yuya Nishihara <yuya@tcha.org>
parents:
30021
diff
changeset
|
203 |
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
|
204 |
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
|
205 |
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
|
206 |
""" |
26456
86fc4a2863ff
demandimport: refactor processfromitem
Gregory Szorc <gregory.szorc@gmail.com>
parents:
26455
diff
changeset
|
207 |
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
|
208 |
nonpkg = getattr(mod, '__path__', nothing) is nothing |
26456
86fc4a2863ff
demandimport: refactor processfromitem
Gregory Szorc <gregory.szorc@gmail.com>
parents:
26455
diff
changeset
|
209 |
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
|
210 |
if nonpkg: |
30647
1914db1b7d9e
demandimport: do not raise ImportError for unknown item in fromlist
Yuya Nishihara <yuya@tcha.org>
parents:
30156
diff
changeset
|
211 |
# 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
|
212 |
# 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
|
213 |
# 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
|
214 |
# 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
|
215 |
return |
28175
c25e3fd38ff1
demandimport: enforce ignore list while processing modules in fromlist
Yuya Nishihara <yuya@tcha.org>
parents:
27537
diff
changeset
|
216 |
mn = '%s.%s' % (mod.__name__, attr) |
37843
670eb4fa1b86
demandimport: make module ignores a set (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33859
diff
changeset
|
217 |
if mn in ignores: |
28175
c25e3fd38ff1
demandimport: enforce ignore list while processing modules in fromlist
Yuya Nishihara <yuya@tcha.org>
parents:
27537
diff
changeset
|
218 |
importfunc = _origimport |
c25e3fd38ff1
demandimport: enforce ignore list while processing modules in fromlist
Yuya Nishihara <yuya@tcha.org>
parents:
27537
diff
changeset
|
219 |
else: |
c25e3fd38ff1
demandimport: enforce ignore list while processing modules in fromlist
Yuya Nishihara <yuya@tcha.org>
parents:
27537
diff
changeset
|
220 |
importfunc = _demandmod |
c25e3fd38ff1
demandimport: enforce ignore list while processing modules in fromlist
Yuya Nishihara <yuya@tcha.org>
parents:
27537
diff
changeset
|
221 |
symbol = importfunc(attr, mod.__dict__, locals, level=1) |
26456
86fc4a2863ff
demandimport: refactor processfromitem
Gregory Szorc <gregory.szorc@gmail.com>
parents:
26455
diff
changeset
|
222 |
setattr(mod, attr, symbol) |
26455
f2bf76d3d567
demandimport: consolidate code for processing items in fromlist
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25943
diff
changeset
|
223 |
|
26457
7e81305092a0
demandimport: replace more references to _demandmod instances
Gregory Szorc <gregory.szorc@gmail.com>
parents:
26456
diff
changeset
|
224 |
# 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
|
225 |
# 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
|
226 |
# time. |
7e81305092a0
demandimport: replace more references to _demandmod instances
Gregory Szorc <gregory.szorc@gmail.com>
parents:
26456
diff
changeset
|
227 |
if globalname and isinstance(symbol, _demandmod): |
7e81305092a0
demandimport: replace more references to _demandmod instances
Gregory Szorc <gregory.szorc@gmail.com>
parents:
26456
diff
changeset
|
228 |
symbol._addref(globalname) |
7e81305092a0
demandimport: replace more references to _demandmod instances
Gregory Szorc <gregory.szorc@gmail.com>
parents:
26456
diff
changeset
|
229 |
|
29375
fcaf20175b1b
demandimport: delay loading for "from a import b" with absolute_import
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
28286
diff
changeset
|
230 |
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
|
231 |
# 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
|
232 |
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
|
233 |
for comp in modname.split('.')[1:]: |
33531
9cbbf9118c6c
demandimport: prefer loaded module over package attribute (issue5617)
Yuya Nishihara <yuya@tcha.org>
parents:
33530
diff
changeset
|
234 |
obj = getattr(mod, comp, nothing) |
9cbbf9118c6c
demandimport: prefer loaded module over package attribute (issue5617)
Yuya Nishihara <yuya@tcha.org>
parents:
33530
diff
changeset
|
235 |
if obj is nothing: |
9cbbf9118c6c
demandimport: prefer loaded module over package attribute (issue5617)
Yuya Nishihara <yuya@tcha.org>
parents:
33530
diff
changeset
|
236 |
obj = _demandmod(comp, mod.__dict__, mod.__dict__, level=1) |
9cbbf9118c6c
demandimport: prefer loaded module over package attribute (issue5617)
Yuya Nishihara <yuya@tcha.org>
parents:
33530
diff
changeset
|
237 |
setattr(mod, comp, obj) |
9cbbf9118c6c
demandimport: prefer loaded module over package attribute (issue5617)
Yuya Nishihara <yuya@tcha.org>
parents:
33530
diff
changeset
|
238 |
elif mod.__name__ + '.' + comp in sys.modules: |
9cbbf9118c6c
demandimport: prefer loaded module over package attribute (issue5617)
Yuya Nishihara <yuya@tcha.org>
parents:
33530
diff
changeset
|
239 |
# prefer loaded module over attribute (issue5617) |
9cbbf9118c6c
demandimport: prefer loaded module over package attribute (issue5617)
Yuya Nishihara <yuya@tcha.org>
parents:
33530
diff
changeset
|
240 |
obj = sys.modules[mod.__name__ + '.' + comp] |
9cbbf9118c6c
demandimport: prefer loaded module over package attribute (issue5617)
Yuya Nishihara <yuya@tcha.org>
parents:
33530
diff
changeset
|
241 |
mod = obj |
29375
fcaf20175b1b
demandimport: delay loading for "from a import b" with absolute_import
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
28286
diff
changeset
|
242 |
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
|
243 |
|
25935
49dd4fd3f283
demandimport: refactor logic and add documentation
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25934
diff
changeset
|
244 |
if level >= 0: |
25937
4f1144c3c72b
demandimport: support lazy loading for absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25936
diff
changeset
|
245 |
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
|
246 |
# "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
|
247 |
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
|
248 |
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
|
249 |
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
|
250 |
elif _pypy: |
27536
f7d890bc5e01
demandimport: add support for PyPy
Bryan O'Sullivan <bos@serpentine.com>
parents:
27069
diff
changeset
|
251 |
# PyPy's __import__ throws an exception if invoked |
f7d890bc5e01
demandimport: add support for PyPy
Bryan O'Sullivan <bos@serpentine.com>
parents:
27069
diff
changeset
|
252 |
# 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
|
253 |
# desired behaviour by hand. |
f7d890bc5e01
demandimport: add support for PyPy
Bryan O'Sullivan <bos@serpentine.com>
parents:
27069
diff
changeset
|
254 |
mn = globalname |
f7d890bc5e01
demandimport: add support for PyPy
Bryan O'Sullivan <bos@serpentine.com>
parents:
27069
diff
changeset
|
255 |
mod = sys.modules[mn] |
f7d890bc5e01
demandimport: add support for PyPy
Bryan O'Sullivan <bos@serpentine.com>
parents:
27069
diff
changeset
|
256 |
if getattr(mod, '__path__', nothing) is nothing: |
f7d890bc5e01
demandimport: add support for PyPy
Bryan O'Sullivan <bos@serpentine.com>
parents:
27069
diff
changeset
|
257 |
mn = mn.rsplit('.', 1)[0] |
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 level > 1: |
f7d890bc5e01
demandimport: add support for PyPy
Bryan O'Sullivan <bos@serpentine.com>
parents:
27069
diff
changeset
|
260 |
mn = mn.rsplit('.', level - 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 |
else: |
f7d890bc5e01
demandimport: add support for PyPy
Bryan O'Sullivan <bos@serpentine.com>
parents:
27069
diff
changeset
|
263 |
mod = _hgextimport(_origimport, name, globals, locals, |
f7d890bc5e01
demandimport: add support for PyPy
Bryan O'Sullivan <bos@serpentine.com>
parents:
27069
diff
changeset
|
264 |
level=level) |
26455
f2bf76d3d567
demandimport: consolidate code for processing items in fromlist
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25943
diff
changeset
|
265 |
|
25937
4f1144c3c72b
demandimport: support lazy loading for absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25936
diff
changeset
|
266 |
for x in fromlist: |
26873
78d05778907b
demandimport: fix level passed to loader of sub-modules
Yuya Nishihara <yuya@tcha.org>
parents:
26830
diff
changeset
|
267 |
processfromitem(mod, x) |
25937
4f1144c3c72b
demandimport: support lazy loading for absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25936
diff
changeset
|
268 |
|
4f1144c3c72b
demandimport: support lazy loading for absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25936
diff
changeset
|
269 |
return mod |
25935
49dd4fd3f283
demandimport: refactor logic and add documentation
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25934
diff
changeset
|
270 |
|
49dd4fd3f283
demandimport: refactor logic and add documentation
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25934
diff
changeset
|
271 |
# 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
|
272 |
# 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
|
273 |
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
|
274 |
mod = chainmodules(mod, name) |
26455
f2bf76d3d567
demandimport: consolidate code for processing items in fromlist
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25943
diff
changeset
|
275 |
|
3877
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
276 |
for x in fromlist: |
26455
f2bf76d3d567
demandimport: consolidate code for processing items in fromlist
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25943
diff
changeset
|
277 |
processfromitem(mod, x) |
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 |
return mod |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
280 |
|
37843
670eb4fa1b86
demandimport: make module ignores a set (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33859
diff
changeset
|
281 |
ignores = set() |
3877
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
282 |
|
37843
670eb4fa1b86
demandimport: make module ignores a set (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33859
diff
changeset
|
283 |
def init(ignoreset): |
670eb4fa1b86
demandimport: make module ignores a set (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33859
diff
changeset
|
284 |
global ignores |
670eb4fa1b86
demandimport: make module ignores a set (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33859
diff
changeset
|
285 |
ignores = ignoreset |
30020
bf94fe556f16
demandimport: add '_ctypes.pointer' to ignore list on PyPy
Yuya Nishihara <yuya@tcha.org>
parents:
29980
diff
changeset
|
286 |
|
20422
aac87f70f38e
hooks: only disable/re-enable demandimport when it's already enabled
Brodie Rao <brodie@sf.io>
parents:
19933
diff
changeset
|
287 |
def isenabled(): |
25673
fa1f04529775
demandimport: alias __builtin__ as builtins
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25327
diff
changeset
|
288 |
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
|
289 |
|
3877
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
290 |
def enable(): |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
291 |
"enable global demand-loading of modules" |
33859
8fb5212652ec
demandimport: move HGDEMANDIMPORT test to __init__.py
Jun Wu <quark@fb.com>
parents:
33531
diff
changeset
|
292 |
builtins.__import__ = _demandimport |
3877
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
293 |
|
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
294 |
def disable(): |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
295 |
"disable global demand-loading of modules" |
25673
fa1f04529775
demandimport: alias __builtin__ as builtins
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25327
diff
changeset
|
296 |
builtins.__import__ = _origimport |
25327
2e7804110b14
demandimport: define a `deactivated` context manager
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
23643
diff
changeset
|
297 |
|
2e7804110b14
demandimport: define a `deactivated` context manager
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
23643
diff
changeset
|
298 |
@contextmanager |
2e7804110b14
demandimport: define a `deactivated` context manager
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
23643
diff
changeset
|
299 |
def deactivated(): |
2e7804110b14
demandimport: define a `deactivated` context manager
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
23643
diff
changeset
|
300 |
"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
|
301 |
demandenabled = isenabled() |
2e7804110b14
demandimport: define a `deactivated` context manager
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
23643
diff
changeset
|
302 |
if demandenabled: |
2e7804110b14
demandimport: define a `deactivated` context manager
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
23643
diff
changeset
|
303 |
disable() |
2e7804110b14
demandimport: define a `deactivated` context manager
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
23643
diff
changeset
|
304 |
|
2e7804110b14
demandimport: define a `deactivated` context manager
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
23643
diff
changeset
|
305 |
try: |
2e7804110b14
demandimport: define a `deactivated` context manager
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
23643
diff
changeset
|
306 |
yield |
2e7804110b14
demandimport: define a `deactivated` context manager
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
23643
diff
changeset
|
307 |
finally: |
2e7804110b14
demandimport: define a `deactivated` context manager
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
23643
diff
changeset
|
308 |
if demandenabled: |
2e7804110b14
demandimport: define a `deactivated` context manager
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
23643
diff
changeset
|
309 |
enable() |