Mercurial > hg
view mercurial/policy.py @ 37947:3ea3c96ada54
encoding: introduce tagging type for non-lossy non-ASCII string
This fixes the weird behavior of toutf8b(), which would convert a local
string back to UTF-8 *only if* it was lossy in the system encoding.
Before b7b26e54e37a "encoding: avoid localstr when a string can be encoded
losslessly (issue2763)", all local strings were wrapped by the localstr
class. I think this would justify the round-trip behavior of toutf8b().
ASCII strings are special-cased, so the cost of wrapping with safelocalstr
is negligible.
(with mercurial repo)
$ export HGRCPATH=/dev/null HGPLAIN= HGENCODING=latin-1
$ hg log --time --config experimental.evolution=all > /dev/null
(original)
time: real 11.340 secs (user 11.290+0.000 sys 0.060+0.000)
time: real 11.390 secs (user 11.300+0.000 sys 0.080+0.000)
time: real 11.430 secs (user 11.360+0.000 sys 0.070+0.000)
(this patch)
time: real 11.200 secs (user 11.100+0.000 sys 0.100+0.000)
time: real 11.370 secs (user 11.300+0.000 sys 0.070+0.000)
time: real 11.190 secs (user 11.130+0.000 sys 0.060+0.000)
author | Yuya Nishihara <yuya@tcha.org> |
---|---|
date | Sun, 23 Apr 2017 13:15:30 +0900 |
parents | 2025bf60adb2 |
children | 0304f22497fa |
line wrap: on
line source
# 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 # Rules for how modules can be loaded. Values are: # # c - require C extensions # allow - allow pure Python implementation when C loading fails # cffi - required cffi versions (implemented within pure module) # cffi-allow - allow pure Python implementation if cffi version is missing # py - only load pure Python modules # # 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' _packageprefs = { # policy: (versioned package, pure package) b'c': (r'cext', None), b'allow': (r'cext', r'pure'), b'cffi': (r'cffi', None), b'cffi-allow': (r'cffi', r'pure'), b'py': (None, r'pure'), } try: from . import __modulepolicy__ 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. if r'__pypy__' in sys.builtin_module_names: policy = b'cffi' # Environment variable can always force settings. if sys.version_info[0] >= 3: if r'HGMODULEPOLICY' in os.environ: policy = os.environ[r'HGMODULEPOLICY'].encode(r'utf-8') else: policy = os.environ.get(r'HGMODULEPOLICY', policy) 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: raise ImportError(r'cannot import name %s' % modname) # force import; fakelocals[modname] may be replaced with the real module getattr(mod, r'__doc__', None) return fakelocals[modname] # keep in sync with "version" in C modules _cextversions = { (r'cext', r'base85'): 1, (r'cext', r'bdiff'): 3, (r'cext', r'mpatch'): 1, (r'cext', r'osutil'): 4, (r'cext', r'parsers'): 4, } # map import request to other package or module _modredirects = { (r'cext', r'charencode'): (r'cext', r'parsers'), (r'cffi', r'base85'): (r'pure', r'base85'), (r'cffi', r'charencode'): (r'pure', r'charencode'), (r'cffi', r'parsers'): (r'pure', r'parsers'), } def _checkmod(pkgname, modname, mod): expected = _cextversions.get((pkgname, modname)) actual = getattr(mod, r'version', None) if actual != expected: raise ImportError(r'cannot import module %s.%s ' r'(expected version: %d, actual: %r)' % (pkgname, modname, expected, actual)) def importmod(modname): """Import module according to policy and check API version""" try: verpkg, purepkg = _packageprefs[policy] except KeyError: raise ImportError(r'invalid HGMODULEPOLICY %r' % policy) assert verpkg or purepkg if verpkg: pn, mn = _modredirects.get((verpkg, modname), (verpkg, modname)) try: mod = _importfrom(pn, mn) if pn == verpkg: _checkmod(pn, mn, mod) return mod except ImportError: if not purepkg: raise pn, mn = _modredirects.get((purepkg, modname), (purepkg, modname)) return _importfrom(pn, mn)