##// END OF EJS Templates
commit: refactor salvage calculation to a different function...
commit: refactor salvage calculation to a different function Differential Revision: https://phab.mercurial-scm.org/D9191

File last commit:

r45691:61e74644 default
r46297:61454026 default
Show More
policy.py
157 lines | 4.7 KiB | text/x-python | PythonLexer
timeless
debuginstall: expose modulepolicy...
r29266 # policy.py - module policy logic for Mercurial.
#
# Copyright 2015 Gregory Szorc <gregory.szorc@gmail.com>
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
from __future__ import absolute_import
import os
import sys
Gregory Szorc
py3: manually import getattr where it is needed...
r43359 from .pycompat import getattr
timeless
debuginstall: expose modulepolicy...
r29266 # Rules for how modules can be loaded. Values are:
#
# c - require C extensions
Georges Racinet
rust: module policy with importrust...
r42651 # rust+c - require Rust and C extensions
# rust+c-allow - allow Rust and C extensions with fallback to pure Python
# for each
timeless
debuginstall: expose modulepolicy...
r29266 # allow - allow pure Python implementation when C loading fails
Maciej Fijalkowski
policy: add cffi policy for PyPy...
r29490 # cffi - required cffi versions (implemented within pure module)
# cffi-allow - allow pure Python implementation if cffi version is missing
timeless
debuginstall: expose modulepolicy...
r29266 # py - only load pure Python modules
#
Yuya Nishihara
policy: relax the default for in-place build...
r32251 # By default, fall back to the pure modules so the in-place build can
# run without recompiling the C extensions. This will be overridden by
# __modulepolicy__ generated by setup.py.
policy = b'allow'
Yuya Nishihara
policy: add helper to import cext/pure module...
r32366 _packageprefs = {
# policy: (versioned package, pure package)
Augie Fackler
cleanup: remove pointless r-prefixes on single-quoted strings...
r43906 b'c': ('cext', None),
b'allow': ('cext', 'pure'),
b'cffi': ('cffi', None),
b'cffi-allow': ('cffi', 'pure'),
b'py': (None, 'pure'),
Georges Racinet
rust: module policy with importrust...
r42651 # For now, rust policies impact importrust only
Augie Fackler
cleanup: remove pointless r-prefixes on single-quoted strings...
r43906 b'rust+c': ('cext', None),
b'rust+c-allow': ('cext', 'pure'),
Yuya Nishihara
policy: add helper to import cext/pure module...
r32366 }
Maciej Fijalkowski
policy: add cffi policy for PyPy...
r29490
timeless
debuginstall: expose modulepolicy...
r29266 try:
from . import __modulepolicy__
Augie Fackler
style: run a patched black on a subset of mercurial...
r43345
timeless
debuginstall: expose modulepolicy...
r29266 policy = __modulepolicy__.modulepolicy
except ImportError:
pass
# PyPy doesn't load C extensions.
#
# The canonical way to do this is to test platform.python_implementation().
# But we don't import platform and don't bloat for it here.
Augie Fackler
cleanup: remove pointless r-prefixes on single-quoted strings...
r43906 if '__pypy__' in sys.builtin_module_names:
Yuya Nishihara
policy: mark all string literals as sysstr or bytes...
r32205 policy = b'cffi'
timeless
debuginstall: expose modulepolicy...
r29266
# Environment variable can always force settings.
FUJIWARA Katsunori
py3: add "b" prefix to string literals related to module policy...
r31361 if sys.version_info[0] >= 3:
Augie Fackler
cleanup: remove pointless r-prefixes on single-quoted strings...
r43906 if 'HGMODULEPOLICY' in os.environ:
policy = os.environ['HGMODULEPOLICY'].encode('utf-8')
FUJIWARA Katsunori
py3: add "b" prefix to string literals related to module policy...
r31361 else:
Augie Fackler
cleanup: remove pointless r-prefixes on single-quoted strings...
r43906 policy = os.environ.get('HGMODULEPOLICY', policy)
Yuya Nishihara
policy: add helper to import cext/pure module...
r32366
Augie Fackler
style: run a patched black on a subset of mercurial...
r43345
Yuya Nishihara
policy: add helper to import cext/pure module...
r32366 def _importfrom(pkgname, modname):
# from .<pkgname> import <modname> (where . is looked through this module)
fakelocals = {}
pkg = __import__(pkgname, globals(), fakelocals, [modname], level=1)
try:
fakelocals[modname] = mod = getattr(pkg, modname)
except AttributeError:
Augie Fackler
cleanup: remove pointless r-prefixes on single-quoted strings...
r43906 raise ImportError('cannot import name %s' % modname)
Yuya Nishihara
policy: add helper to import cext/pure module...
r32366 # force import; fakelocals[modname] may be replaced with the real module
Gregory Szorc
py3: stop normalizing 2nd argument of *attr() to unicode...
r43373 getattr(mod, '__doc__', None)
Yuya Nishihara
policy: add helper to import cext/pure module...
r32366 return fakelocals[modname]
Augie Fackler
style: run a patched black on a subset of mercurial...
r43345
Jun Wu
policy: define C module versions individually...
r32428 # keep in sync with "version" in C modules
_cextversions = {
Augie Fackler
cleanup: remove pointless r-prefixes on single-quoted strings...
r43906 ('cext', 'base85'): 1,
('cext', 'bdiff'): 3,
('cext', 'mpatch'): 1,
('cext', 'osutil'): 4,
Joerg Sonnenberger
phases: sparsify phaseroots and phasesets...
r45691 ('cext', 'parsers'): 17,
Jun Wu
policy: define C module versions individually...
r32428 }
Yuya Nishihara
policy: reroute proxy modules internally...
r33755 # map import request to other package or module
_modredirects = {
Augie Fackler
cleanup: remove pointless r-prefixes on single-quoted strings...
r43906 ('cext', 'charencode'): ('cext', 'parsers'),
('cffi', 'base85'): ('pure', 'base85'),
('cffi', 'charencode'): ('pure', 'charencode'),
('cffi', 'parsers'): ('pure', 'parsers'),
Yuya Nishihara
policy: reroute proxy modules internally...
r33755 }
Augie Fackler
style: run a patched black on a subset of mercurial...
r43345
Yuya Nishihara
policy: add helper to import cext/pure module...
r32366 def _checkmod(pkgname, modname, mod):
Yuya Nishihara
policy: extend API version checks for cffi...
r32511 expected = _cextversions.get((pkgname, modname))
Gregory Szorc
py3: stop normalizing 2nd argument of *attr() to unicode...
r43373 actual = getattr(mod, 'version', None)
Yuya Nishihara
policy: add helper to import cext/pure module...
r32366 if actual != expected:
Augie Fackler
style: run a patched black on a subset of mercurial...
r43345 raise ImportError(
Augie Fackler
cleanup: remove pointless r-prefixes on single-quoted strings...
r43906 'cannot import module %s.%s '
'(expected version: %d, actual: %r)'
Augie Fackler
style: run a patched black on a subset of mercurial...
r43345 % (pkgname, modname, expected, actual)
)
Yuya Nishihara
policy: add helper to import cext/pure module...
r32366
def importmod(modname):
"""Import module according to policy and check API version"""
try:
verpkg, purepkg = _packageprefs[policy]
except KeyError:
Augie Fackler
cleanup: remove pointless r-prefixes on single-quoted strings...
r43906 raise ImportError('invalid HGMODULEPOLICY %r' % policy)
Yuya Nishihara
policy: add helper to import cext/pure module...
r32366 assert verpkg or purepkg
if verpkg:
Yuya Nishihara
policy: reroute proxy modules internally...
r33755 pn, mn = _modredirects.get((verpkg, modname), (verpkg, modname))
Yuya Nishihara
policy: add helper to import cext/pure module...
r32366 try:
Yuya Nishihara
policy: reroute proxy modules internally...
r33755 mod = _importfrom(pn, mn)
if pn == verpkg:
_checkmod(pn, mn, mod)
Yuya Nishihara
policy: add helper to import cext/pure module...
r32366 return mod
except ImportError:
if not purepkg:
raise
Yuya Nishihara
policy: reroute proxy modules internally...
r33755 pn, mn = _modredirects.get((purepkg, modname), (purepkg, modname))
return _importfrom(pn, mn)
Georges Racinet
rust: module policy with importrust...
r42651
Augie Fackler
style: run a patched black on a subset of mercurial...
r43345
Georges Racinet
rust: module policy with importrust...
r42651 def _isrustpermissive():
"""Assuming the policy is a Rust one, tell if it's permissive."""
return policy.endswith(b'-allow')
Augie Fackler
style: run a patched black on a subset of mercurial...
r43345
Georges Racinet
rust: module policy with importrust...
r42651 def importrust(modname, member=None, default=None):
"""Import Rust module according to policy and availability.
If policy isn't a Rust one, this returns `default`.
If either the module or its member is not available, this returns `default`
if policy is permissive and raises `ImportError` if not.
"""
if not policy.startswith(b'rust'):
return default
try:
Augie Fackler
cleanup: remove pointless r-prefixes on single-quoted strings...
r43906 mod = _importfrom('rustext', modname)
Georges Racinet
rust: module policy with importrust...
r42651 except ImportError:
if _isrustpermissive():
return default
raise
if member is None:
return mod
try:
return getattr(mod, member)
except AttributeError:
if _isrustpermissive():
return default
Augie Fackler
cleanup: remove pointless r-prefixes on double-quoted strings...
r43809 raise ImportError("Cannot import name %s" % member)