##// END OF EJS Templates
hgdemandimport: apply lazy module loading to sys.meta_path finders...
hgdemandimport: apply lazy module loading to sys.meta_path finders Python's `sys.meta_path` finders are the primary objects whose job it is to find a module at import time. When `import` is called, Python iterates objects in this list and calls `o.find_spec(...)` to find a `ModuleSpec` (or None if the module couldn't be found by that finder). If no meta path finder can find a module, import fails. One of the default meta path finders is `PathFinder`. Its job is to import modules from the filesystem and is probably the most important importer. This finder looks at `sys.path` and `sys.path_hooks` to do its job. The `ModuleSpec` returned by `MetaPathImporter.find_spec()` has a `loader` attribute, which defines the concrete module loader to use. `sys.path_hooks` is a hook point for teaching `PathFinder` to instantiate custom loader types. Previously, we injected a custom `sys.path_hook` that told `PathFinder` to wrap the default loaders with a loader that creates a module object that is lazy. This approach worked. But its main limitation was that it only applied to the `PathFinder` meta path importer. There are other meta path importers that are registered. And in the case of PyOxidizer loading modules from memory, `PathFinder` doesn't come into play since PyOxidizer's own meta path importer was handling all imports. This commit changes our approach to lazy module loading by proxying all meta path importers. Specifically, we overload the `find_spec()` method to swap in a wrapped loader on the `ModuleSpec` before it is returned. The end result of this is all meta path importers should be lazy. As much as I would have loved to utilize .__class__ manipulation to achieve this, some meta path importers are implemented in C/Rust in such a way that they cannot be monkeypatched. This is why we use __getattribute__ to define a proxy. Also, this change could theoretically open us up to regressions in meta path importers whose loader is creating module objects which can't be monkeypatched. But I'm not aware of any of these in the wild. So I think we'll be safe. According to hyperfine, this change yields a decent startup time win of 5-6ms: ``` Benchmark #1: ~/.pyenv/versions/3.6.10/bin/python ./hg version Time (mean ± σ): 86.8 ms ± 0.5 ms [User: 78.0 ms, System: 8.7 ms] Range (min … max): 86.0 ms … 89.1 ms 50 runs Time (mean ± σ): 81.1 ms ± 2.7 ms [User: 74.5 ms, System: 6.5 ms] Range (min … max): 77.8 ms … 90.5 ms 50 runs Benchmark #2: ~/.pyenv/versions/3.7.6/bin/python ./hg version Time (mean ± σ): 78.9 ms ± 0.6 ms [User: 70.2 ms, System: 8.7 ms] Range (min … max): 78.1 ms … 81.2 ms 50 runs Time (mean ± σ): 73.4 ms ± 0.6 ms [User: 65.3 ms, System: 8.0 ms] Range (min … max): 72.4 ms … 75.7 ms 50 runs Benchmark #3: ~/.pyenv/versions/3.8.1/bin/python ./hg version Time (mean ± σ): 78.1 ms ± 0.6 ms [User: 70.2 ms, System: 7.9 ms] Range (min … max): 77.4 ms … 80.9 ms 50 runs Time (mean ± σ): 72.1 ms ± 0.4 ms [User: 64.4 ms, System: 7.6 ms] Range (min … max): 71.4 ms … 74.1 ms 50 runs ``` Differential Revision: https://phab.mercurial-scm.org/D7954

File last commit:

r44271:e8a3bbff default
r44577:f81c17ec default
Show More
hghave.py
1025 lines | 25.8 KiB | text/x-python | PythonLexer
formatting: introduce a `test-check-format-black.t` that enforce formatting...
r43365 from __future__ import absolute_import, print_function
Gregory Szorc
tests: use absolute_import in hghave.py
r27298
Augie Fackler
hghave: verify we have a black that is new enough for our format...
r43669 import distutils.version
Augie Fackler
hghave: use subprocess instead of os.popen...
r26137 import os
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 import re
Yuya Nishihara
cmdserver: add service that listens on unix domain socket and forks process...
r22994 import socket
Augie Fackler
hghave: use subprocess instead of os.popen...
r26137 import stat
import subprocess
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 import sys
import tempfile
tempprefix = 'hg-hghave-'
Matt Mackall
tests: use a decorator for hghave checks
r22093 checks = {
"true": (lambda: True, "yak shaving"),
"false": (lambda: False, "nail clipper"),
}
Matt Harbison
py3: use bytes stdout in hghave.py...
r41039 try:
import msvcrt
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Harbison
py3: use bytes stdout in hghave.py...
r41039 msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
msvcrt.setmode(sys.stderr.fileno(), os.O_BINARY)
except ImportError:
pass
stdout = getattr(sys.stdout, 'buffer', sys.stdout)
stderr = getattr(sys.stderr, 'buffer', sys.stderr)
Matt Harbison
py3: fix a type error in hghave.has_hardlink...
r39795 if sys.version_info[0] >= 3:
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Harbison
py3: fix a type error in hghave.has_hardlink...
r39795 def _bytespath(p):
if p is None:
return p
return p.encode('utf-8')
def _strpath(p):
if p is None:
return p
return p.decode('utf-8')
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Harbison
py3: fix a type error in hghave.has_hardlink...
r39795 else:
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Harbison
py3: fix a type error in hghave.has_hardlink...
r39795 def _bytespath(p):
return p
_strpath = _bytespath
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Mackall
tests: use a decorator for hghave checks
r22093 def check(name, desc):
timeless
hghave: add docstring for check
r28757 """Registers a check function for a feature."""
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Mackall
tests: use a decorator for hghave checks
r22093 def decorator(func):
checks[name] = (func, desc)
return func
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Mackall
tests: use a decorator for hghave checks
r22093 return decorator
Augie Fackler
formatting: blacken the codebase...
r43346
timeless
hghave: add checkvers function
r28758 def checkvers(name, desc, vers):
"""Registers a check function for each of a series of versions.
Kyle Lippincott
hghave: document format for version feature checks as <name><vers>, no dots...
r43383 vers can be a list or an iterator.
Produces a series of feature checks that have the form <name><vers> without
any punctuation (even if there's punctuation in 'vers'; i.e. this produces
'py38', not 'py3.8' or 'py-38')."""
Augie Fackler
formatting: blacken the codebase...
r43346
timeless
hghave: add checkvers function
r28758 def decorator(func):
def funcv(v):
def f():
return func(v)
Augie Fackler
formatting: blacken the codebase...
r43346
timeless
hghave: add checkvers function
r28758 return f
Augie Fackler
formatting: blacken the codebase...
r43346
timeless
hghave: add checkvers function
r28758 for v in vers:
v = str(v)
f = funcv(v)
checks['%s%s' % (name, v.replace('.', ''))] = (f, desc % v)
return func
Augie Fackler
formatting: blacken the codebase...
r43346
timeless
hghave: add checkvers function
r28758 return decorator
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
hghave: move feature checking into hghave.py...
r26067 def checkfeatures(features):
result = {
'error': [],
'missing': [],
'skipped': [],
}
for feature in features:
negate = feature.startswith('no-')
if negate:
feature = feature[3:]
if feature not in checks:
result['missing'].append(feature)
continue
check, desc = checks[feature]
try:
available = check()
except Exception:
result['error'].append('hghave check failed: %s' % feature)
continue
if not negate and not available:
result['skipped'].append('missing feature: %s' % desc)
elif negate and available:
result['skipped'].append('system supports %s' % desc)
return result
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
hghave: remove quiet option...
r26068 def require(features):
Gregory Szorc
hghave: move feature checking into hghave.py...
r26067 """Require that features are available, exiting if not."""
result = checkfeatures(features)
Gregory Szorc
hghave: remove quiet option...
r26068 for missing in result['missing']:
Augie Fackler
formatting: blacken the codebase...
r43346 stderr.write(
('skipped: unknown feature: %s\n' % missing).encode('utf-8')
)
Gregory Szorc
hghave: remove quiet option...
r26068 for msg in result['skipped']:
Matt Harbison
py3: use bytes stdout in hghave.py...
r41039 stderr.write(('skipped: %s\n' % msg).encode('utf-8'))
Gregory Szorc
hghave: remove quiet option...
r26068 for msg in result['error']:
Matt Harbison
py3: use bytes stdout in hghave.py...
r41039 stderr.write(('%s\n' % msg).encode('utf-8'))
Gregory Szorc
hghave: move feature checking into hghave.py...
r26067
if result['missing']:
sys.exit(2)
if result['skipped'] or result['error']:
sys.exit(1)
Augie Fackler
formatting: blacken the codebase...
r43346
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 def matchoutput(cmd, regexp, ignorestatus=False):
timeless
hghave.py: fix matchoutput documentation
r27114 """Return the match object if cmd executes successfully and its output
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 is matched by the supplied regular expression.
"""
r = re.compile(regexp)
Martin von Zweigbergk
hghave: let OSError with ENOENT through like any other...
r41402 p = subprocess.Popen(
Augie Fackler
formatting: blacken the codebase...
r43346 cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT
)
Matt Harbison
hghave: avoid a deadlock reading the child process's output...
r38205 s = p.communicate()[0]
ret = p.returncode
Augie Fackler
hghave: use subprocess instead of os.popen...
r26137 return (ignorestatus or not ret) and r.search(s)
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("baz", "GNU Arch baz client")
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 def has_baz():
timeless
hghave: matchoutput needs to use bytes for regexp...
r29140 return matchoutput('baz --version 2>&1', br'baz Bazaar version')
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("bzr", "Canonical's Bazaar client")
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 def has_bzr():
try:
import bzrlib
timeless
hghave: make bzr checks stricter...
r29866 import bzrlib.bzrdir
import bzrlib.errors
import bzrlib.revision
Yuya Nishihara
hghave: fix has_bzr() to not try to import RevisionSpec as module...
r29903 import bzrlib.revisionspec
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
hghave: fix has_bzr() to not try to import RevisionSpec as module...
r29903 bzrlib.revisionspec.RevisionSpec
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 return bzrlib.__doc__ is not None
Yuya Nishihara
hghave: fix has_bzr() to not try to import RevisionSpec as module...
r29903 except (AttributeError, ImportError):
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 return False
Augie Fackler
formatting: blacken the codebase...
r43346
timeless
hghave: use checkvers for bzr114
r28760 @checkvers("bzr", "Canonical's Bazaar client >= %s", (1.14,))
def has_bzr_range(v):
hghave: deal with "rc" release...
r42401 major, minor = v.split('rc')[0].split('.')[0:2]
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 try:
import bzrlib
Augie Fackler
formatting: blacken the codebase...
r43346
return bzrlib.__doc__ is not None and bzrlib.version_info[:2] >= (
int(major),
int(minor),
)
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 except ImportError:
return False
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
hghave: add "chg" flag to skip tests that can't be compatible with chg...
r28880 @check("chg", "running with chg")
def has_chg():
return 'CHGHG' in os.environ
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("cvs", "cvs client/server")
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 def has_cvs():
timeless
hghave: matchoutput needs to use bytes for regexp...
r29140 re = br'Concurrent Versions System.*?server'
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 return matchoutput('cvs --version 2>&1', re) and not has_msys()
Augie Fackler
formatting: blacken the codebase...
r43346
timeless
hghave: update cvs112 description...
r28756 @check("cvs112", "cvs client/server 1.12.* (not cvsnt)")
Bryan O'Sullivan
hghave: introduce a test (unused) for cvs >= 1.12
r18285 def has_cvs112():
timeless
hghave: matchoutput needs to use bytes for regexp...
r29140 re = br'Concurrent Versions System \(CVS\) 1.12.*?server'
Bryan O'Sullivan
hghave: introduce a test (unused) for cvs >= 1.12
r18285 return matchoutput('cvs --version 2>&1', re) and not has_msys()
Augie Fackler
formatting: blacken the codebase...
r43346
timeless
hghave: add cvsnt...
r28796 @check("cvsnt", "cvsnt client/server")
def has_cvsnt():
timeless
hghave: matchoutput needs to use bytes for regexp...
r29140 re = br'Concurrent Versions System \(CVSNT\) (\d+).(\d+).*\(client/server\)'
timeless
hghave: add cvsnt...
r28796 return matchoutput('cvsnt --version 2>&1', re)
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("darcs", "darcs client")
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 def has_darcs():
Yuya Nishihara
hghave: check darcs version more strictly...
r30297 return matchoutput('darcs --version', br'\b2\.([2-9]|\d{2})', True)
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("mtn", "monotone client (>= 1.0)")
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 def has_mtn():
timeless
hghave: matchoutput needs to use bytes for regexp...
r29140 return matchoutput('mtn --version', br'monotone', True) and not matchoutput(
Augie Fackler
formatting: blacken the codebase...
r43346 'mtn --version', br'monotone 0\.', True
)
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("eol-in-paths", "end-of-lines in paths")
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 def has_eol_in_paths():
try:
Mads Kiilerich
tests/hghave: consistently use dir='.', prefix=tempprefix for tempfiles...
r16968 fd, path = tempfile.mkstemp(dir='.', prefix=tempprefix, suffix='\n\r')
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 os.close(fd)
os.remove(path)
return True
except (IOError, OSError):
return False
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("execbit", "executable bit")
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 def has_executablebit():
try:
EXECFLAGS = stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH
Mads Kiilerich
tests/hghave: consistently use dir='.', prefix=tempprefix for tempfiles...
r16968 fh, fn = tempfile.mkstemp(dir='.', prefix=tempprefix)
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 try:
os.close(fh)
Gregory Szorc
global: mass rewrite to use modern octal syntax...
r25658 m = os.stat(fn).st_mode & 0o777
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 new_file_has_exec = m & EXECFLAGS
os.chmod(fn, m ^ EXECFLAGS)
Augie Fackler
formatting: blacken the codebase...
r43346 exec_flags_cannot_flip = (os.stat(fn).st_mode & 0o777) == m
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 finally:
os.unlink(fn)
except (IOError, OSError):
# we don't care, the user probably won't be able to commit anyway
return False
return not (new_file_has_exec or exec_flags_cannot_flip)
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("icasefs", "case insensitive file system")
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 def has_icasefs():
# Stolen from mercurial.util
Mads Kiilerich
tests/hghave: consistently use dir='.', prefix=tempprefix for tempfiles...
r16968 fd, path = tempfile.mkstemp(dir='.', prefix=tempprefix)
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 os.close(fd)
try:
s1 = os.stat(path)
d, b = os.path.split(path)
p2 = os.path.join(d, b.upper())
if path == p2:
p2 = os.path.join(d, b.lower())
try:
s2 = os.stat(p2)
return s2 == s1
except OSError:
return False
finally:
os.remove(path)
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("fifo", "named pipes")
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 def has_fifo():
Mads Kiilerich
tests/hghave: test that a fifo actually can be created on the filesystem...
r16969 if getattr(os, "mkfifo", None) is None:
return False
name = tempfile.mktemp(dir='.', prefix=tempprefix)
try:
os.mkfifo(name)
os.unlink(name)
return True
except OSError:
return False
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("killdaemons", 'killdaemons.py support')
Patrick Mezard
test-http-branchmap: enable on Windows...
r17467 def has_killdaemons():
return True
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("cacheable", "cacheable filesystem")
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 def has_cacheable_fs():
from mercurial import util
Mads Kiilerich
tests/hghave: consistently use dir='.', prefix=tempprefix for tempfiles...
r16968 fd, path = tempfile.mkstemp(dir='.', prefix=tempprefix)
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 os.close(fd)
try:
return util.cachestat(path).cacheable()
finally:
os.remove(path)
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("lsprof", "python lsprof module")
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 def has_lsprof():
try:
import _lsprof
Augie Fackler
formatting: blacken the codebase...
r43346
_lsprof.Profiler # silence unused import warning
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 return True
except ImportError:
return False
Augie Fackler
formatting: blacken the codebase...
r43346
timeless
hghave: add hg06..hg39...
r28761 def gethgversion():
timeless
hghave: matchoutput needs to use bytes for regexp...
r29140 m = matchoutput('hg --version --quiet 2>&1', br'(\d+)\.(\d+)')
timeless
hghave: add hg06..hg39...
r28761 if not m:
return (0, 0)
return (int(m.group(1)), int(m.group(2)))
Augie Fackler
formatting: blacken the codebase...
r43346
@checkvers(
"hg", "Mercurial >= %s", list([(1.0 * x) / 10 for x in range(9, 99)])
)
timeless
hghave: add hg06..hg39...
r28761 def has_hg_range(v):
major, minor = v.split('.')[0:2]
return gethgversion() >= (int(major), int(minor))
Augie Fackler
formatting: blacken the codebase...
r43346
timeless
hghave: add hg06..hg39...
r28761 @check("hg08", "Mercurial >= 0.8")
def has_hg08():
if checks["hg09"][0]():
return True
return matchoutput('hg help annotate 2>&1', '--date')
Augie Fackler
formatting: blacken the codebase...
r43346
timeless
hghave: add hg06..hg39...
r28761 @check("hg07", "Mercurial >= 0.7")
def has_hg07():
if checks["hg08"][0]():
return True
return matchoutput('hg --version --quiet 2>&1', 'Mercurial Distributed SCM')
Augie Fackler
formatting: blacken the codebase...
r43346
timeless
hghave: add hg06..hg39...
r28761 @check("hg06", "Mercurial >= 0.6")
def has_hg06():
if checks["hg07"][0]():
return True
return matchoutput('hg --version --quiet 2>&1', 'Mercurial version')
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("gettext", "GNU Gettext (msgfmt)")
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 def has_gettext():
timeless
hghave: matchoutput needs to use bytes for regexp...
r29140 return matchoutput('msgfmt --version', br'GNU gettext-tools')
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("git", "git command line client")
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 def has_git():
timeless
hghave: matchoutput needs to use bytes for regexp...
r29140 return matchoutput('git --version 2>&1', br'^git version')
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966
Augie Fackler
formatting: blacken the codebase...
r43346
Sean Farley
hghave: add has_git_range for testing if git understands ext::sh...
r32901 def getgitversion():
m = matchoutput('git --version 2>&1', br'git version (\d+)\.(\d+)')
if not m:
return (0, 0)
return (int(m.group(1)), int(m.group(2)))
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Harbison
hghave: add a check for lfs-test-server...
r35137 # https://github.com/git-lfs/lfs-test-server
@check("lfs-test-server", "git-lfs test server")
def has_lfsserver():
exe = 'lfs-test-server'
if has_windows():
exe = 'lfs-test-server.exe'
return any(
os.access(os.path.join(path, exe), os.X_OK)
for path in os.environ["PATH"].split(os.pathsep)
)
Augie Fackler
formatting: blacken the codebase...
r43346
Sean Farley
hghave: add has_git_range for testing if git understands ext::sh...
r32901 @checkvers("git", "git client (with ext::sh support) version >= %s", (1.9,))
def has_git_range(v):
major, minor = v.split('.')[0:2]
return getgitversion() >= (int(major), int(minor))
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("docutils", "Docutils text processing library")
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 def has_docutils():
try:
Yuya Nishihara
hghave: replace relative import of docutils.core
r28779 import docutils.core
Augie Fackler
formatting: blacken the codebase...
r43346
docutils.core.publish_cmdline # silence unused import
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 return True
except ImportError:
return False
Augie Fackler
formatting: blacken the codebase...
r43346
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 def getsvnversion():
timeless
hghave: matchoutput needs to use bytes for regexp...
r29140 m = matchoutput('svn --version --quiet 2>&1', br'^(\d+)\.(\d+)')
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 if not m:
return (0, 0)
return (int(m.group(1)), int(m.group(2)))
Augie Fackler
formatting: blacken the codebase...
r43346
timeless
hghave: replace has_svn13/has_svn15 with checkvers...
r28759 @checkvers("svn", "subversion client and admin tools >= %s", (1.3, 1.5))
def has_svn_range(v):
major, minor = v.split('.')[0:2]
return getsvnversion() >= (int(major), int(minor))
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("svn", "subversion client and admin tools")
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 def has_svn():
Augie Fackler
formatting: blacken the codebase...
r43346 return matchoutput('svn --version 2>&1', br'^svn, version') and matchoutput(
'svnadmin --version 2>&1', br'^svnadmin, version'
)
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("svn-bindings", "subversion python bindings")
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 def has_svn_bindings():
try:
import svn.core
Augie Fackler
formatting: blacken the codebase...
r43346
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 version = svn.core.SVN_VER_MAJOR, svn.core.SVN_VER_MINOR
if version < (1, 4):
return False
return True
except ImportError:
return False
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("p4", "Perforce server and client")
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 def has_p4():
Augie Fackler
formatting: blacken the codebase...
r43346 return matchoutput('p4 -V', br'Rev\. P4/') and matchoutput(
'p4d -V', br'Rev\. P4D/'
)
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("symlink", "symbolic links")
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 def has_symlink():
Matt Harbison
hghave: disallow symlinks on Windows...
r43760 # mercurial.windows.checklink() is a hard 'no' at the moment
if os.name == 'nt' or getattr(os, "symlink", None) is None:
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 return False
Mads Kiilerich
tests/hghave: consistently use dir='.', prefix=tempprefix for tempfiles...
r16968 name = tempfile.mktemp(dir='.', prefix=tempprefix)
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 try:
os.symlink(".", name)
os.unlink(name)
return True
except (OSError, AttributeError):
return False
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("hardlink", "hardlinks")
Mads Kiilerich
tests: introduce hghave hardlinks...
r16971 def has_hardlink():
from mercurial import util
Augie Fackler
formatting: blacken the codebase...
r43346
Mads Kiilerich
tests: introduce hghave hardlinks...
r16971 fh, fn = tempfile.mkstemp(dir='.', prefix=tempprefix)
os.close(fh)
name = tempfile.mktemp(dir='.', prefix=tempprefix)
try:
Matt Harbison
py3: fix a type error in hghave.has_hardlink...
r39795 util.oslink(_bytespath(fn), _bytespath(name))
Matt Mackall
hghave: use try/except/finally
r25090 os.unlink(name)
return True
except OSError:
return False
Mads Kiilerich
tests: introduce hghave hardlinks...
r16971 finally:
os.unlink(fn)
Augie Fackler
formatting: blacken the codebase...
r43346
Jun Wu
hghave: add a check about whitelisted filesystem that supports hardlink...
r31576 @check("hardlink-whitelisted", "hardlinks on whitelisted filesystems")
def has_hardlink_whitelisted():
Yuya Nishihara
hghave: use util.getfstype
r31674 from mercurial import util
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
statfs: make getfstype() raise OSError...
r31678 try:
Augie Fackler
hghave: fix hardlink-whitelisted check on Python 3...
r36960 fstype = util.getfstype(b'.')
Yuya Nishihara
statfs: make getfstype() raise OSError...
r31678 except OSError:
return False
Jun Wu
hghave: add a check about whitelisted filesystem that supports hardlink...
r31576 return fstype in util._hardlinkfswhitelist
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
tests: run "cwd was removed" test only if cwd can actually be removed...
r30230 @check("rmcwd", "can remove current working directory")
def has_rmcwd():
ocwd = os.getcwd()
temp = tempfile.mkdtemp(dir='.', prefix=tempprefix)
try:
os.chdir(temp)
# On Linux, 'rmdir .' isn't allowed, but the other names are okay.
# On Solaris and Windows, the cwd can't be removed by any names.
os.rmdir(os.getcwd())
return True
except OSError:
return False
finally:
os.chdir(ocwd)
Yuya Nishihara
hghave: fix 'rmcwd' to ensure temporary directory is removed...
r30242 # clean up temp dir on platforms where cwd can't be removed
try:
os.rmdir(temp)
except OSError:
pass
Yuya Nishihara
tests: run "cwd was removed" test only if cwd can actually be removed...
r30230
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("tla", "GNU Arch tla client")
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 def has_tla():
timeless
hghave: matchoutput needs to use bytes for regexp...
r29140 return matchoutput('tla --version 2>&1', br'The GNU Arch Revision')
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("gpg", "gpg client")
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 def has_gpg():
timeless
hghave: matchoutput needs to use bytes for regexp...
r29140 return matchoutput('gpg --version 2>&1', br'GnuPG')
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
test-gpg: start gpg-agent under control of the test runner...
r29790 @check("gpg2", "gpg client v2")
def has_gpg2():
return matchoutput('gpg --version 2>&1', br'GnuPG[^0-9]+2\.')
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
test-gpg: start gpg-agent by gpg-connect-agent only if GnuPG v2.1+ detected...
r29873 @check("gpg21", "gpg client v2.1+")
def has_gpg21():
return matchoutput('gpg --version 2>&1', br'GnuPG[^0-9]+2\.(?!0)')
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("unix-permissions", "unix-style permissions")
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 def has_unix_permissions():
Mads Kiilerich
tests/hghave: consistently use dir='.', prefix=tempprefix for tempfiles...
r16968 d = tempfile.mkdtemp(dir='.', prefix=tempprefix)
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 try:
fname = os.path.join(d, 'foo')
Gregory Szorc
global: mass rewrite to use modern octal syntax...
r25658 for umask in (0o77, 0o07, 0o22):
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 os.umask(umask)
f = open(fname, 'w')
f.close()
mode = os.stat(fname).st_mode
os.unlink(fname)
Gregory Szorc
global: mass rewrite to use modern octal syntax...
r25658 if mode & 0o777 != ~umask & 0o666:
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 return False
return True
finally:
os.rmdir(d)
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
cmdserver: add service that listens on unix domain socket and forks process...
r22994 @check("unix-socket", "AF_UNIX socket family")
def has_unix_socket():
return getattr(socket, 'AF_UNIX', None) is not None
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("root", "root permissions")
Matt Mackall
tests: skip tests that require not having root (issue4089)...
r20008 def has_root():
Simon Heimberg
tests: fix `hghave root` on windows...
r20114 return getattr(os, 'geteuid', None) and os.geteuid() == 0
Matt Mackall
tests: skip tests that require not having root (issue4089)...
r20008
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("pyflakes", "Pyflakes python linter")
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 def has_pyflakes():
Augie Fackler
formatting: blacken the codebase...
r43346 return matchoutput(
"sh -c \"echo 'import re' 2>&1 | pyflakes\"",
br"<stdin>:1: 're' imported but unused",
True,
)
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966
Pierre-Yves David
test: add a basic 'test-check-pylint.t'...
r31413 @check("pylint", "Pylint python linter")
def has_pylint():
Augie Fackler
formatting: blacken the codebase...
r43346 return matchoutput("pylint --help", br"Usage: pylint", True)
Pierre-Yves David
test: add a basic 'test-check-pylint.t'...
r31413
Augie Fackler
hghave: add a check for clang-format...
r34697 @check("clang-format", "clang-format C code formatter")
def has_clang_format():
Yuya Nishihara
hghave: require clang-format >= 6 due to output change
r38725 m = matchoutput('clang-format --version', br'clang-format version (\d)')
# style changed somewhere between 4.x and 6.x
return m and int(m.group(1)) >= 6
Augie Fackler
hghave: add a check for clang-format...
r34697
Augie Fackler
formatting: blacken the codebase...
r43346
av6
tests: use jshint when available to check .js files
r35034 @check("jshint", "JSHint static code analysis tool")
def has_jshint():
return matchoutput("jshint --version 2>&1", br"jshint v")
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("pygments", "Pygments source highlighting library")
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 def has_pygments():
try:
import pygments
Augie Fackler
formatting: blacken the codebase...
r43346
pygments.highlight # silence unused import warning
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 return True
except ImportError:
return False
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("outer-repo", "outer repo")
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 def has_outer_repo():
Mads Kiilerich
tests: hghave outer-repo should be true even if a bad repo is found...
r17016 # failing for other reasons than 'no repo' imply that there is a repo
Augie Fackler
formatting: blacken the codebase...
r43346 return not matchoutput('hg root 2>&1', br'abort: no repository found', True)
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966
Gregory Szorc
hghave: change ssl check to just check ssl module...
r28591 @check("ssl", "ssl module available")
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 def has_ssl():
try:
import ssl
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
hghave: change ssl check to just check ssl module...
r28591 ssl.CERT_NONE
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 return True
except ImportError:
return False
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
test-https: test basic functions of client certificate authentication...
r25413 @check("sslcontext", "python >= 2.7.9 ssl")
def has_sslcontext():
try:
import ssl
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
test-https: test basic functions of client certificate authentication...
r25413 ssl.SSLContext
return True
except (ImportError, AttributeError):
return False
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
test-https: enable dummycert test only if Apple python is used (issue4500)...
r24289 @check("defaultcacerts", "can verify SSL certs by system's CA certs store")
def has_defaultcacerts():
Gregory Szorc
sslutil: pass ui to _defaultcacerts...
r29483 from mercurial import sslutil, ui as uimod
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
ui: factor out ui.load() to create a ui without loading configs (API)...
r30559 ui = uimod.ui.load()
Gregory Szorc
sslutil: pass ui to _defaultcacerts...
r29483 return sslutil._defaultcacerts(ui) or sslutil._canloaddefaultcerts
Yuya Nishihara
test-https: enable dummycert test only if Apple python is used (issue4500)...
r24289
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
tests: better testing of loaded certificates...
r29481 @check("defaultcacertsloaded", "detected presence of loaded system CA certs")
def has_defaultcacertsloaded():
import ssl
Gregory Szorc
sslutil: pass ui to _defaultcacerts...
r29483 from mercurial import sslutil, ui as uimod
Gregory Szorc
tests: better testing of loaded certificates...
r29481
if not has_defaultcacerts():
return False
if not has_sslcontext():
return False
Yuya Nishihara
ui: factor out ui.load() to create a ui without loading configs (API)...
r30559 ui = uimod.ui.load()
Gregory Szorc
sslutil: pass ui to _defaultcacerts...
r29483 cafile = sslutil._defaultcacerts(ui)
Gregory Szorc
tests: better testing of loaded certificates...
r29481 ctx = ssl.create_default_context()
if cafile:
ctx.load_verify_locations(cafile=cafile)
else:
ctx.load_default_certs()
return len(ctx.get_ca_certs()) > 0
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
sslutil: more robustly detect protocol support...
r29601 @check("tls1.2", "TLS 1.2 protocol support")
def has_tls1_2():
from mercurial import sslutil
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
tests: add b'' when testing for tls1.2...
r41426 return b'tls1.2' in sslutil.supportedprotocols
Gregory Szorc
sslutil: more robustly detect protocol support...
r29601
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("windows", "Windows")
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 def has_windows():
return os.name == 'nt'
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("system-sh", "system() uses sh")
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 def has_system_sh():
return os.name != 'nt'
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("serve", "platform and python can manage 'hg serve -d'")
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 def has_serve():
Matt Harbison
hghave: enable 'serve' on Windows...
r32856 return True
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("test-repo", "running tests from repository")
Matt Mackall
tests: add repository check for pyflakes test...
r21208 def has_test_repo():
t = os.environ["TESTDIR"]
return os.path.isdir(os.path.join(t, "..", ".hg"))
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("tic", "terminfo compiler and curses module")
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 def has_tic():
Mads Kiilerich
tests: 'hghave tic' also requires curses support in Python...
r20304 try:
import curses
Augie Fackler
formatting: blacken the codebase...
r43346
Mads Kiilerich
tests: 'hghave tic' also requires curses support in Python...
r20304 curses.COLOR_BLUE
timeless
hghave: matchoutput needs to use bytes for regexp...
r29140 return matchoutput('test -x "`which tic`"', br'')
Mads Kiilerich
tests: 'hghave tic' also requires curses support in Python...
r20304 except ImportError:
return False
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Harbison
hghave: add a check for the `xz` compression utility...
r44098 @check("xz", "xz compression utility")
def has_xz():
# When Windows invokes a subprocess in shell mode, it uses `cmd.exe`, which
# only knows `where`, not `which`. So invoke MSYS shell explicitly.
return matchoutput("sh -c 'test -x \"`which xz`\"'", b'')
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("msys", "Windows with MSYS")
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 def has_msys():
return os.getenv('MSYSTEM')
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("aix", "AIX")
Jim Hague
tests: AIX can't handle negative date in test-dirstate.t...
r19092 def has_aix():
return sys.platform.startswith("aix")
Augie Fackler
formatting: blacken the codebase...
r43346
Mads Kiilerich
ssl: on OS X, use a dummy cert to trick Python/OpenSSL to use system CA certs...
r22575 @check("osx", "OS X")
def has_osx():
return sys.platform == 'darwin'
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
hghave: add check for OS X packaging tools
r29026 @check("osxpackaging", "OS X packaging tools")
def has_osxpackaging():
try:
Augie Fackler
formatting: blacken the codebase...
r43346 return (
matchoutput('pkgbuild', br'Usage: pkgbuild ', ignorestatus=1)
and matchoutput(
'productbuild', br'Usage: productbuild ', ignorestatus=1
)
and matchoutput('lsbom', br'Usage: lsbom', ignorestatus=1)
and matchoutput('xar --help', br'Usage: xar', ignorestatus=1)
)
Augie Fackler
hghave: add check for OS X packaging tools
r29026 except ImportError:
return False
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
fsmonitor: warn when fsmonitor could be used...
r34886 @check('linuxormacos', 'Linux or MacOS')
def has_linuxormacos():
# This isn't a perfect test for MacOS. But it is sufficient for our needs.
return sys.platform.startswith(('linux', 'darwin'))
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
hghave: add a check for docker support...
r26111 @check("docker", "docker support")
def has_docker():
timeless
hghave: matchoutput needs to use bytes for regexp...
r29140 pat = br'A self-sufficient runtime for'
Augie Fackler
hghave: add a check for docker support...
r26111 if matchoutput('docker --help', pat):
if 'linux' not in sys.platform:
# TODO: in theory we should be able to test docker-based
# package creation on non-linux using boot2docker, but in
# practice that requires extra coordination to make sure
# $TESTTEMP is going to be visible at the same path to the
# boot2docker VM. If we figure out how to verify that, we
# can use the following instead of just saying False:
# return 'DOCKER_HOST' in os.environ
return False
return True
return False
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
hghave: add a check for debian packaging tools
r26110 @check("debhelper", "debian packaging tools")
def has_debhelper():
Kyle Lippincott
hghave: fix dpkg --version check to work on recent dpkg versions...
r34395 # Some versions of dpkg say `dpkg', some say 'dpkg' (` vs ' on the first
# quote), so just accept anything in that spot.
Augie Fackler
formatting: blacken the codebase...
r43346 dpkg = matchoutput(
'dpkg --version', br"Debian .dpkg' package management program"
)
dh = matchoutput(
'dh --help', br'dh is a part of debhelper.', ignorestatus=True
)
dh_py2 = matchoutput(
'dh_python2 --help', br'other supported Python versions'
)
Kyle Lippincott
hghave: check for debuild being installed as well...
r34400 # debuild comes from the 'devscripts' package, though you might want
# the 'build-debs' package instead, which has a dependency on devscripts.
Augie Fackler
formatting: blacken the codebase...
r43346 debuild = matchoutput(
'debuild --help', br'to run debian/rules with given parameter'
)
Kyle Lippincott
hghave: check for debuild being installed as well...
r34400 return dpkg and dh and dh_py2 and debuild
Augie Fackler
hghave: add a check for debian packaging tools
r26110
Augie Fackler
formatting: blacken the codebase...
r43346
@check(
"debdeps", "debian build dependencies (run dpkg-checkbuilddeps in contrib/)"
)
Kyle Lippincott
tests: add "have" check for dpkg builddeps...
r34402 def has_debdeps():
# just check exit status (ignoring output)
Gregory Szorc
packaging: move contrib/debian to contrib/packaging/...
r38029 path = '%s/../contrib/packaging/debian/control' % os.environ['TESTDIR']
Kyle Lippincott
tests: add "have" check for dpkg builddeps...
r34402 return matchoutput('dpkg-checkbuilddeps %s' % path, br'')
Augie Fackler
formatting: blacken the codebase...
r43346
timeless
hghave: add demandimport checking
r29867 @check("demandimport", "demandimport enabled")
def has_demandimport():
Saurabh Singh
hghave: disable demandimport when chg is running...
r34841 # chg disables demandimport intentionally for performance wins.
Augie Fackler
formatting: blacken the codebase...
r43346 return (not has_chg()) and os.environ.get('HGDEMANDIMPORT') != 'disable'
timeless
hghave: add demandimport checking
r29867
Kyle Lippincott
hghave: document format for version feature checks as <name><vers>, no dots...
r43383 # Add "py27", "py35", ... as possible feature checks. Note that there's no
# punctuation here.
Gregory Szorc
hghave: add pyXY features for Python version numbers...
r41488 @checkvers("py", "Python >= %s", (2.7, 3.5, 3.6, 3.7, 3.8, 3.9))
def has_python_range(v):
major, minor = v.split('.')[0:2]
py_major, py_minor = sys.version_info.major, sys.version_info.minor
return (py_major, py_minor) >= (int(major), int(minor))
Augie Fackler
formatting: blacken the codebase...
r43346
Martijn Pieters
py3: use py3 as the test tag, dropping the k...
r40299 @check("py3", "running with Python 3.x")
def has_py3():
FUJIWARA Katsunori
hghave: add "py3k" feature to check whether test runs with Python 3.x...
r19931 return 3 == sys.version_info[0]
Yuya Nishihara
tests: disable test of buffer overflow in parsers.c if --pure...
r25859
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
run-tests: add --with-python3 to define a Python 3 interpreter...
r28582 @check("py3exe", "a Python 3.x interpreter is available")
def has_python3exe():
Augie Fackler
hghave: move from requiring the PYTHON3 env var to looking for `python3`...
r39387 return matchoutput('python3 -V', br'^Python 3.(5|6|7|8|9)')
Gregory Szorc
run-tests: add --with-python3 to define a Python 3 interpreter...
r28582
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
tests: disable test of buffer overflow in parsers.c if --pure...
r25859 @check("pure", "running with pure Python code")
def has_pure():
Augie Fackler
formatting: blacken the codebase...
r43346 return any(
[
os.environ.get("HGMODULEPOLICY") == "py",
os.environ.get("HGTEST_RUN_TESTS_PURE") == "--pure",
]
)
Augie Fackler
run-tests: add support for marking tests as very slow...
r26109
Kyle Lippincott
tests: hint how to run slow tests when rejecting
r32473 @check("slow", "allow slow tests (use --allow-slow-tests)")
Augie Fackler
run-tests: add support for marking tests as very slow...
r26109 def has_slow():
return os.environ.get('HGTEST_SLOW') == 'slow'
David R. MacIver
testing: add hypothesis fuzz testing...
r26842
Augie Fackler
formatting: blacken the codebase...
r43346
timeless
hghave: improve description of Hypothesis
r28383 @check("hypothesis", "Hypothesis automated test generation")
David R. MacIver
testing: add hypothesis fuzz testing...
r26842 def has_hypothesis():
try:
import hypothesis
Augie Fackler
formatting: blacken the codebase...
r43346
David R. MacIver
testing: add hypothesis fuzz testing...
r26842 hypothesis.given
return True
except ImportError:
return False
Augie Fackler
hghave: add a check for unzip(1) that understands symlinks...
r29843
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
hghave: add a check for unzip(1) that understands symlinks...
r29843 @check("unziplinks", "unzip(1) understands and extracts symlinks")
def unzip_understands_symlinks():
return matchoutput('unzip --help', br'Info-ZIP')
Gregory Szorc
hghave: add check for zstd support...
r30441
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
hghave: add check for zstd support...
r30441 @check("zstd", "zstd Python module available")
def has_zstd():
try:
import mercurial.zstd
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
hghave: add check for zstd support...
r30441 mercurial.zstd.__version__
return True
except ImportError:
return False
Bryan O'Sullivan
stdio: add Linux-specific tests for error checking
r31964
Augie Fackler
formatting: blacken the codebase...
r43346
Bryan O'Sullivan
stdio: add Linux-specific tests for error checking
r31964 @check("devfull", "/dev/full special file")
def has_dev_full():
return os.path.exists('/dev/full')
Augie Fackler
hghave: add check for virtualenv
r32726
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
tests: look for ensurepip before using venv...
r43730 @check("ensurepip", "ensurepip module")
def has_ensurepip():
try:
import ensurepip
ensurepip.bootstrap
return True
except ImportError:
return False
Augie Fackler
hghave: add check for virtualenv
r32726 @check("virtualenv", "Python virtualenv support")
def has_virtualenv():
try:
import virtualenv
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
hghave: add check for virtualenv
r32726 virtualenv.ACTIVATE_SH
return True
except ImportError:
return False
Siddharth Agarwal
hghave: add test for whether fsmonitor is enabled...
r32770
Augie Fackler
formatting: blacken the codebase...
r43346
Siddharth Agarwal
hghave: add test for whether fsmonitor is enabled...
r32770 @check("fsmonitor", "running tests with fsmonitor")
def has_fsmonitor():
return 'HGFSMONITOR_TESTS' in os.environ
Rishabh Madan
releasenotes: add import check for fuzzywuzzy...
r33660
Augie Fackler
formatting: blacken the codebase...
r43346
Rishabh Madan
releasenotes: add import check for fuzzywuzzy...
r33660 @check("fuzzywuzzy", "Fuzzy string matching library")
def has_fuzzywuzzy():
try:
import fuzzywuzzy
Augie Fackler
formatting: blacken the codebase...
r43346
Rishabh Madan
releasenotes: add import check for fuzzywuzzy...
r33660 fuzzywuzzy.__version__
return True
except ImportError:
return False
Augie Fackler
hghave: add test for clang 6 and later...
r35686
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
hghave: add test for clang 6 and later...
r35686 @check("clang-libfuzzer", "clang new enough to include libfuzzer")
def has_clang_libfuzzer():
Gregory Szorc
tests: use raw strings for regular expressions with escapes...
r41684 mat = matchoutput('clang --version', br'clang version (\d)')
Augie Fackler
hghave: add test for clang 6 and later...
r35686 if mat:
# libfuzzer is new in clang 6
return int(mat.group(1)) > 5
return False
Jun Wu
tests: add tests about diff quality...
r36696
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
test-fuzz-targets: look for clang-6.0 binary as well...
r38238 @check("clang-6.0", "clang 6.0 with version suffix (libfuzzer included)")
def has_clang60():
Gregory Szorc
tests: use raw strings for regular expressions with escapes...
r41684 return matchoutput('clang-6.0 --version', br'clang version 6\.')
Yuya Nishihara
test-fuzz-targets: look for clang-6.0 binary as well...
r38238
Augie Fackler
formatting: blacken the codebase...
r43346
Jun Wu
tests: add tests about diff quality...
r36696 @check("xdiff", "xdiff algorithm")
def has_xdiff():
try:
from mercurial import policy
Augie Fackler
formatting: blacken the codebase...
r43346
Jun Wu
tests: add tests about diff quality...
r36696 bdiff = policy.importmod('bdiff')
Augie Fackler
hghave: fix xdiff check on Python 3...
r36959 return bdiff.xdiffblocks(b'', b'') == [(0, 0, 0, 0)]
Augie Fackler
hghave: remove unused "as ex" in exception block...
r36712 except (ImportError, AttributeError):
Jun Wu
tests: add tests about diff quality...
r36696 return False
Gregory Szorc
tests: conditionalize tests based on presence of revlogs for files...
r37356
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
tests: conditionalize tests based on presence of custom extensions...
r37360 @check('extraextensions', 'whether tests are running with extra extensions')
def has_extraextensions():
return 'HGTESTEXTRAEXTENSIONS' in os.environ
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
tests: conditionalize tests based on presence of revlogs for files...
r37356 def getrepofeatures():
"""Obtain set of repository features in use.
HGREPOFEATURES can be used to define or remove features. It contains
a space-delimited list of feature strings. Strings beginning with ``-``
mean to remove.
"""
# Default list provided by core.
features = {
Gregory Szorc
tests: disallow using simple store repo with bundlerepo...
r37364 'bundlerepo',
Gregory Szorc
tests: conditionalize tests based on presence of revlogs for files...
r37356 'revlogstore',
Gregory Szorc
simplestore: use a custom store for the simple store repo...
r37433 'fncache',
Gregory Szorc
tests: conditionalize tests based on presence of revlogs for files...
r37356 }
# Features that imply other features.
implies = {
Gregory Szorc
simplestore: use a custom store for the simple store repo...
r37433 'simplestore': ['-revlogstore', '-bundlerepo', '-fncache'],
Gregory Szorc
tests: conditionalize tests based on presence of revlogs for files...
r37356 }
for override in os.environ.get('HGREPOFEATURES', '').split(' '):
if not override:
continue
if override.startswith('-'):
if override[1:] in features:
features.remove(override[1:])
else:
features.add(override)
for imply in implies.get(override, []):
if imply.startswith('-'):
if imply[1:] in features:
features.remove(imply[1:])
else:
features.add(imply)
return features
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
tests: conditionalize tests based on presence of revlogs for files...
r37356 @check('reporevlogstore', 'repository using the default revlog store')
def has_reporevlogstore():
return 'revlogstore' in getrepofeatures()
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
tests: conditionalize tests based on presence of revlogs for files...
r37356 @check('reposimplestore', 'repository using simple storage extension')
def has_reposimplestore():
return 'simplestore' in getrepofeatures()
Gregory Szorc
tests: disallow using simple store repo with bundlerepo...
r37364
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
tests: disallow using simple store repo with bundlerepo...
r37364 @check('repobundlerepo', 'whether we can open bundle files as repos')
def has_repobundlerepo():
return 'bundlerepo' in getrepofeatures()
Gregory Szorc
simplestore: use a custom store for the simple store repo...
r37433
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
simplestore: use a custom store for the simple store repo...
r37433 @check('repofncache', 'repository has an fncache')
def has_repofncache():
return 'fncache' in getrepofeatures()
Augie Fackler
hghave: add a checker for the vcr HTTP record/replay library...
r39684
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
sqlitestore: file storage backend using SQLite...
r40362 @check('sqlite', 'sqlite3 module is available')
def has_sqlite():
try:
import sqlite3
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
tests: require SQLite 3.8.3+ as sqlitestore relies on "WITH" clause...
r40492 version = sqlite3.sqlite_version_info
Gregory Szorc
sqlitestore: file storage backend using SQLite...
r40362 except ImportError:
return False
Yuya Nishihara
tests: require SQLite 3.8.3+ as sqlitestore relies on "WITH" clause...
r40492 if version < (3, 8, 3):
# WITH clause not supported
return False
Gregory Szorc
tests: use raw strings for regular expressions with escapes...
r41684 return matchoutput('sqlite3 -version', br'^3\.\d+')
Gregory Szorc
sqlitestore: file storage backend using SQLite...
r40362
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
hghave: add a checker for the vcr HTTP record/replay library...
r39684 @check('vcr', 'vcr http mocking library')
def has_vcr():
try:
import vcr
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
hghave: add a checker for the vcr HTTP record/replay library...
r39684 vcr.VCR
return True
except (ImportError, AttributeError):
pass
return False
Augie Fackler
hghave: add check for GNU emacs...
r41953
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
hghave: add check for GNU emacs...
r41953 @check('emacs', 'GNU Emacs')
def has_emacs():
Augie Fackler
hghave: skip emacs tests on 24.3 and earlier...
r42008 # Our emacs lisp uses `with-eval-after-load` which is new in emacs
# 24.4, so we allow emacs 24.4, 24.5, and 25+ (24.5 was the last
# 24 release)
return matchoutput('emacs --version', b'GNU Emacs 2(4.4|4.5|5|6|7|8|9)')
formatting: introduce a `test-check-format-black.t` that enforce formatting...
r43365
formatting: using black to check for formatting
r43664 @check('black', 'the black formatter for python')
formatting: introduce a `test-check-format-black.t` that enforce formatting...
r43365 def has_black():
formatting: using black to check for formatting
r43664 blackcmd = 'black --version'
Augie Fackler
hghave: verify we have a black that is new enough for our format...
r43669 version_regex = b'black, version ([0-9a-b.]+)'
version = matchoutput(blackcmd, version_regex)
sv = distutils.version.StrictVersion
Augie Fackler
hghave: fix bytes/string issue on Python 3
r43724 return version and sv(_strpath(version.group(1))) >= sv('19.10b0')
Augie Fackler
hghave: add a check for pytype, Google's Python type checker...
r43771
@check('pytype', 'the pytype type checker')
def has_pytype():
pytypecmd = 'pytype --version'
version = matchoutput(pytypecmd, b'[0-9a-b.]+')
sv = distutils.version.StrictVersion
return version and sv(_strpath(version.group(0))) >= sv('2019.10.17')
Gregory Szorc
tests: add test for Rust formatting...
r44271
@check("rustfmt", "rustfmt tool")
def has_rustfmt():
# We use Nightly's rustfmt due to current unstable config options.
return matchoutput(
'`rustup which --toolchain nightly rustfmt` --version', b'rustfmt'
)