##// END OF EJS Templates
tests: test symbolic revision (de)reference in all hgweb styles...
tests: test symbolic revision (de)reference in all hgweb styles Right now the way revisions get specified in hgweb urls is ignored, i.e. after revision is resolved, only its node hash (or sometimes local revision number) is used for all links in the templates. So, basically, every page for "tip" revision (or any other symbolic rev id) will dereference it: lose the nice symbolic name by putting node hash/local rev number in its place. The only exception so far is archive links on some pages: /archive/tip.{bz2,gz,zip}. The fact that this dereferencing is neither convenient nor intuitive is reflected in issue2296, issue2826 and issue3594. issue3634 also mentions this. But to fix this it's first needed to demonstrate and test the way templates currently form links. The new test file is separate from other hgweb tests, since it seems big and distinct enough. And it's so big because links are formed in each template independently, so it's necessary to test them all to avoid any inconsistent behavior.

File last commit:

r25327:2e780411 default
r25586:e7455316 default
Show More
demandimport.py
196 lines | 6.4 KiB | text/x-python | PythonLexer
Matt Mackall
Replace demandload with new demandimport
r3877 # demandimport.py - global demand-loading of modules for Mercurial
#
Thomas Arendsen Hein
Updated copyright notices and add "and others" to "hg version"
r4635 # Copyright 2006, 2007 Matt Mackall <mpm@selenic.com>
Matt Mackall
Replace demandload with new demandimport
r3877 #
Martin Geisler
updated license to be explicit about GPL version 2
r8225 # This software may be used and distributed according to the terms of the
Matt Mackall
Update license to GPLv2+
r10263 # GNU General Public License version 2 or any later version.
Matt Mackall
Replace demandload with new demandimport
r3877
'''
demandimport - automatic demandloading of modules
To enable this module, do:
import demandimport; demandimport.enable()
Imports of the following forms will be demand-loaded:
import a, b.c
import a.b as c
from a import b,c # a will be loaded immediately
These imports will not be delayed:
from a import *
b = __import__(a)
'''
Gregory Szorc
demandimport: pass proper level to __import__ in Python 3...
r21290 import __builtin__, os, sys
Jordi Gutiérrez Hermoso
demandimport: define a `deactivated` context manager...
r25327 from contextlib import contextmanager
Matt Mackall
Replace demandload with new demandimport
r3877 _origimport = __import__
Augie Fackler
demandimport: use getattr instead of hasattr...
r14977 nothing = object()
Simon Heimberg
demandimport: determine at load time if __import__ has level argument
r15096 try:
Gregory Szorc
demandimport: pass proper level to __import__ in Python 3...
r21290 # Python 3 doesn't have relative imports nor level -1.
level = -1
if sys.version_info[0] >= 3:
level = 0
_origimport(__builtin__.__name__, {}, {}, None, level)
Simon Heimberg
demandimport: determine at load time if __import__ has level argument
r15096 except TypeError: # no level argument
def _import(name, globals, locals, fromlist, level):
"call _origimport with no level argument"
return _origimport(name, globals, locals, fromlist)
else:
_import = _origimport
FUJIWARA Katsunori
demandimport: allow extensions to import own modules by absolute name...
r19933 def _hgextimport(importfunc, name, globals, *args):
try:
return importfunc(name, globals, *args)
except ImportError:
if not globals:
raise
# extensions are loaded with "hgext_" prefix
hgextname = 'hgext_%s' % name
nameroot = hgextname.split('.', 1)[0]
contextroot = globals.get('__name__', '').split('.', 1)[0]
if nameroot != contextroot:
raise
# retry to import with "hgext_" prefix
return importfunc(hgextname, globals, *args)
Matt Mackall
Replace demandload with new demandimport
r3877 class _demandmod(object):
"""module demand-loader and proxy"""
Gregory Szorc
demandimport: pass proper level to __import__ in Python 3...
r21290 def __init__(self, name, globals, locals, level=level):
Matt Mackall
Replace demandload with new demandimport
r3877 if '.' in name:
head, rest = name.split('.', 1)
after = [rest]
else:
head = name
after = []
FUJIWARA Katsunori
demandimport: support "absolute_import" for external libraries (issue4029)...
r19932 object.__setattr__(self, "_data",
(head, globals, locals, after, level))
Benoit Boissinot
use parent.__setattr__ instead of __dict__
r3896 object.__setattr__(self, "_module", None)
Matt Mackall
Replace demandload with new demandimport
r3877 def _extend(self, name):
"""add to the list of submodules to load"""
self._data[3].append(name)
def _load(self):
if not self._module:
FUJIWARA Katsunori
demandimport: support "absolute_import" for external libraries (issue4029)...
r19932 head, globals, locals, after, level = self._data
FUJIWARA Katsunori
demandimport: allow extensions to import own modules by absolute name...
r19933 mod = _hgextimport(_import, head, globals, locals, None, level)
Matt Mackall
Replace demandload with new demandimport
r3877 # load submodules
Matt Mackall
demandimport: fix import x.y.z as a when x.y is already imported.
r3921 def subload(mod, p):
h, t = p, None
if '.' in p:
h, t = p.split('.', 1)
Augie Fackler
demandimport: use getattr instead of hasattr...
r14977 if getattr(mod, h, nothing) is nothing:
Matt Mackall
demandimport: back out 50a4e55aa278 (issue2467)
r12894 setattr(mod, h, _demandmod(p, mod.__dict__, mod.__dict__))
Brendan Cully
demandimport: handle already-loaded nested modules in subload
r3926 elif t:
Matt Mackall
demandimport: fix import x.y.z as a when x.y is already imported.
r3921 subload(getattr(mod, h), t)
Matt Mackall
Replace demandload with new demandimport
r3877 for x in after:
Matt Mackall
demandimport: fix import x.y.z as a when x.y is already imported.
r3921 subload(mod, x)
Matt Mackall
Replace demandload with new demandimport
r3877 # are we in the locals dictionary still?
if locals and locals.get(head) == self:
locals[head] = mod
Benoit Boissinot
use parent.__setattr__ instead of __dict__
r3896 object.__setattr__(self, "_module", mod)
Matt Mackall
demandimport: fix issue579 and add a test...
r4631
Matt Mackall
Replace demandload with new demandimport
r3877 def __repr__(self):
Matt Mackall
demandimport: fix issue579 and add a test...
r4631 if self._module:
return "<proxied module '%s'>" % self._data[0]
Matt Mackall
Replace demandload with new demandimport
r3877 return "<unloaded module '%s'>" % self._data[0]
def __call__(self, *args, **kwargs):
Matt Mackall
demandload: give better diagnostic for call of an unloaded module
r5639 raise TypeError("%s object is not callable" % repr(self))
Brendan Cully
Make demandimport pass all tests on python2.5.
r3903 def __getattribute__(self, attr):
if attr in ('_data', '_extend', '_load', '_module'):
return object.__getattribute__(self, attr)
Matt Mackall
Replace demandload with new demandimport
r3877 self._load()
return getattr(self._module, attr)
def __setattr__(self, attr, val):
self._load()
setattr(self._module, attr, val)
Gregory Szorc
demandimport: pass proper level to __import__ in Python 3...
r21290 def _demandimport(name, globals=None, locals=None, fromlist=None, level=level):
Matt Mackall
Replace demandload with new demandimport
r3877 if not locals or name in ignore or fromlist == ('*',):
# these cases we can't really delay
FUJIWARA Katsunori
demandimport: allow extensions to import own modules by absolute name...
r19933 return _hgextimport(_import, name, globals, locals, fromlist, level)
Matt Mackall
Replace demandload with new demandimport
r3877 elif not fromlist:
# import a [as b]
if '.' in name: # a.b
base, rest = name.split('.', 1)
Brendan Cully
Make demandimport pass all tests on python2.5.
r3903 # email.__init__ loading email.mime
if globals and globals.get('__name__', None) == base:
Simon Heimberg
demandimport: determine at load time if __import__ has level argument
r15096 return _import(name, globals, locals, fromlist, level)
Matt Mackall
Replace demandload with new demandimport
r3877 # if a is already demand-loaded, add b to its submodule list
if base in locals:
if isinstance(locals[base], _demandmod):
locals[base]._extend(rest)
return locals[base]
FUJIWARA Katsunori
demandimport: support "absolute_import" for external libraries (issue4029)...
r19932 return _demandmod(name, globals, locals, level)
Matt Mackall
Replace demandload with new demandimport
r3877 else:
Dan Villiom Podlaski Christiansen
demandimport: change default for level from None to -1...
r13082 if level != -1:
Matt Mackall
demandimport: back out 50a4e55aa278 (issue2467)
r12894 # from . import b,c,d or from .a import b,c,d
return _origimport(name, globals, locals, fromlist, level)
# from a import b,c,d
FUJIWARA Katsunori
demandimport: allow extensions to import own modules by absolute name...
r19933 mod = _hgextimport(_origimport, name, globals, locals)
Matt Mackall
Replace demandload with new demandimport
r3877 # recurse down the module chain
for comp in name.split('.')[1:]:
Augie Fackler
demandimport: use getattr instead of hasattr...
r14977 if getattr(mod, comp, nothing) is nothing:
Matt Mackall
demandimport: back out 50a4e55aa278 (issue2467)
r12894 setattr(mod, comp, _demandmod(comp, mod.__dict__, mod.__dict__))
Matt Mackall
Replace demandload with new demandimport
r3877 mod = getattr(mod, comp)
for x in fromlist:
# set requested submodules for demand load
Augie Fackler
demandimport: use getattr instead of hasattr...
r14977 if getattr(mod, x, nothing) is nothing:
Matt Mackall
demandimport: back out 50a4e55aa278 (issue2467)
r12894 setattr(mod, x, _demandmod(x, mod.__dict__, locals))
Matt Mackall
Replace demandload with new demandimport
r3877 return mod
Patrick Mezard
demandimport: ignore resource module, not available under Windows.
r5098 ignore = [
'_hashlib',
'_xmlplus',
'fcntl',
'win32com.gen_py',
Dirkjan Ochtman
demandimport: ignore _winreg (used in python-2.7 mimetypes)
r10242 '_winreg', # 2.7 mimetypes needs immediate ImportError
Steve Borho
demandimport: blacklist pythoncom...
r7861 'pythoncom',
Patrick Mezard
demandimport: ignore resource module, not available under Windows.
r5098 # imported by tarfile, not available under Windows
'pwd',
'grp',
# imported by profile, itself imported by hotshot.stats,
# not available under Windows
'resource',
Steve Borho
demandimport: blacklist gtk...
r9458 # this trips up many extension authors
'gtk',
Greg Ward
demandimport: add __main__ to the blacklist (because of setuptools)
r10598 # setuptools' pkg_resources.py expects "from __main__ import x" to
# raise ImportError if x not defined
'__main__',
Dirkjan Ochtman
demandimport: blacklist _ssl (issue1964)
r10612 '_ssl', # conditional imports in the stdlib, issue1964
Augie Fackler
demandimport: blacklist rfc822 and mimetools to prevent spurious warnings
r14976 'rfc822',
'mimetools',
Augie Fackler
demandimport: blacklist distutils.msvc9compiler (issue4475)...
r23643 # setuptools 8 expects this module to explode early when not on windows
'distutils.msvc9compiler'
Patrick Mezard
demandimport: ignore resource module, not available under Windows.
r5098 ]
Matt Mackall
Replace demandload with new demandimport
r3877
Brodie Rao
hooks: only disable/re-enable demandimport when it's already enabled...
r20422 def isenabled():
return __builtin__.__import__ == _demandimport
Matt Mackall
Replace demandload with new demandimport
r3877 def enable():
"enable global demand-loading of modules"
Mads Kiilerich
demandimport: make it possible to disable by setting HGDEMANDIMPORT=disable...
r21025 if os.environ.get('HGDEMANDIMPORT') != 'disable':
__builtin__.__import__ = _demandimport
Matt Mackall
Replace demandload with new demandimport
r3877
def disable():
"disable global demand-loading of modules"
Dirkjan Ochtman
demandimport: patch __builtin__ instead of __builtins__...
r7727 __builtin__.__import__ = _origimport
Jordi Gutiérrez Hermoso
demandimport: define a `deactivated` context manager...
r25327
@contextmanager
def deactivated():
"context manager for disabling demandimport in 'with' blocks"
demandenabled = isenabled()
if demandenabled:
disable()
try:
yield
finally:
if demandenabled:
enable()