--- a/setup.py Sat Oct 05 10:29:34 2019 -0400
+++ b/setup.py Sun Oct 06 09:45:02 2019 -0400
@@ -17,50 +17,63 @@
#
# TODO: when we actually work on Python 3, use this string as the
# actual supportedpy string.
- supportedpy = ','.join([
- '>=2.7',
- '!=3.0.*',
- '!=3.1.*',
- '!=3.2.*',
- '!=3.3.*',
- '!=3.4.*',
- '!=3.5.0',
- '!=3.5.1',
- '!=3.5.2',
- '!=3.6.0',
- '!=3.6.1',
- ])
+ supportedpy = ','.join(
+ [
+ '>=2.7',
+ '!=3.0.*',
+ '!=3.1.*',
+ '!=3.2.*',
+ '!=3.3.*',
+ '!=3.4.*',
+ '!=3.5.0',
+ '!=3.5.1',
+ '!=3.5.2',
+ '!=3.6.0',
+ '!=3.6.1',
+ ]
+ )
import sys, platform
import sysconfig
+
if sys.version_info[0] >= 3:
printf = eval('print')
libdir_escape = 'unicode_escape'
+
def sysstr(s):
return s.decode('latin-1')
+
+
else:
libdir_escape = 'string_escape'
+
def printf(*args, **kwargs):
f = kwargs.get('file', sys.stdout)
end = kwargs.get('end', '\n')
f.write(b' '.join(args) + end)
+
def sysstr(s):
return s
+
# Attempt to guide users to a modern pip - this means that 2.6 users
# should have a chance of getting a 4.2 release, and when we ratchet
# the version requirement forward again hopefully everyone will get
# something that works for them.
if sys.version_info < (2, 7, 0, 'final'):
- pip_message = ('This may be due to an out of date pip. '
- 'Make sure you have pip >= 9.0.1.')
+ pip_message = (
+ 'This may be due to an out of date pip. '
+ 'Make sure you have pip >= 9.0.1.'
+ )
try:
import pip
+
pip_version = tuple([int(x) for x in pip.__version__.split('.')[:3]])
- if pip_version < (9, 0, 1) :
+ if pip_version < (9, 0, 1):
pip_message = (
'Your pip version is out of date, please install '
- 'pip >= 9.0.1. pip {} detected.'.format(pip.__version__))
+ 'pip >= 9.0.1. pip {} detected.'.format(pip.__version__)
+ )
else:
# pip is new enough - it must be something else
pip_message = ''
@@ -70,7 +83,9 @@
Mercurial does not support Python older than 2.7.
Python {py} detected.
{pip}
-""".format(py=sys.version_info, pip=pip_message)
+""".format(
+ py=sys.version_info, pip=pip_message
+ )
printf(error, file=sys.stderr)
sys.exit(1)
@@ -100,7 +115,9 @@
See https://www.mercurial-scm.org/wiki/Python3 for more on Mercurial's
Python 3 support.
-""".format(py='.'.join('%d' % x for x in sys.version_info[0:2]))
+""".format(
+ py='.'.join('%d' % x for x in sys.version_info[0:2])
+ )
printf(error, file=sys.stderr)
sys.exit(1)
@@ -114,27 +131,33 @@
# Solaris Python packaging brain damage
try:
import hashlib
+
sha = hashlib.sha1()
except ImportError:
try:
import sha
- sha.sha # silence unused import warning
+
+ sha.sha # silence unused import warning
except ImportError:
raise SystemExit(
- "Couldn't import standard hashlib (incomplete Python install).")
+ "Couldn't import standard hashlib (incomplete Python install)."
+ )
try:
import zlib
- zlib.compressobj # silence unused import warning
+
+ zlib.compressobj # silence unused import warning
except ImportError:
raise SystemExit(
- "Couldn't import standard zlib (incomplete Python install).")
+ "Couldn't import standard zlib (incomplete Python install)."
+ )
# The base IronPython distribution (as of 2.7.1) doesn't support bz2
isironpython = False
try:
- isironpython = (platform.python_implementation()
- .lower().find("ironpython") != -1)
+ isironpython = (
+ platform.python_implementation().lower().find("ironpython") != -1
+ )
except AttributeError:
pass
@@ -143,10 +166,12 @@
else:
try:
import bz2
- bz2.BZ2Compressor # silence unused import warning
+
+ bz2.BZ2Compressor # silence unused import warning
except ImportError:
raise SystemExit(
- "Couldn't import standard bz2 (incomplete Python install).")
+ "Couldn't import standard bz2 (incomplete Python install)."
+ )
ispypy = "PyPy" in sys.version
@@ -163,10 +188,11 @@
import shutil
import tempfile
from distutils import log
+
# We have issues with setuptools on some platforms and builders. Until
# those are resolved, setuptools is opt-in except for platforms where
# we don't have issues.
-issetuptools = (os.name == 'nt' or 'FORCE_SETUPTOOLS' in os.environ)
+issetuptools = os.name == 'nt' or 'FORCE_SETUPTOOLS' in os.environ
if issetuptools:
from setuptools import setup
else:
@@ -194,6 +220,7 @@
# Explain to distutils.StrictVersion how our release candidates are versionned
StrictVersion.version_re = re.compile(r'^(\d+)\.(\d+)(\.(\d+))?-?(rc(\d+))?$')
+
def write_if_changed(path, content):
"""Write content to a file iff the content hasn't changed."""
if os.path.exists(path):
@@ -206,11 +233,13 @@
with open(path, 'wb') as fh:
fh.write(content)
+
scripts = ['hg']
if os.name == 'nt':
# We remove hg.bat if we are able to build hg.exe.
scripts.append('contrib/win32/hg.bat')
+
def cancompile(cc, code):
tmpdir = tempfile.mkdtemp(prefix='hg-install-')
devnull = oldstderr = None
@@ -238,32 +267,39 @@
devnull.close()
shutil.rmtree(tmpdir)
+
# simplified version of distutils.ccompiler.CCompiler.has_function
# that actually removes its temporary files.
def hasfunction(cc, funcname):
code = 'int main(void) { %s(); }\n' % funcname
return cancompile(cc, code)
+
def hasheader(cc, headername):
code = '#include <%s>\nint main(void) { return 0; }\n' % headername
return cancompile(cc, code)
+
# py2exe needs to be installed to work
try:
import py2exe
- py2exe.Distribution # silence unused import warning
+
+ py2exe.Distribution # silence unused import warning
py2exeloaded = True
# import py2exe's patched Distribution class
from distutils.core import Distribution
except ImportError:
py2exeloaded = False
+
def runcmd(cmd, env, cwd=None):
- p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
- stderr=subprocess.PIPE, env=env, cwd=cwd)
+ p = subprocess.Popen(
+ cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env, cwd=cwd
+ )
out, err = p.communicate()
return p.returncode, out, err
+
class hgcommand(object):
def __init__(self, cmd, env):
self.cmd = cmd
@@ -279,22 +315,31 @@
return ''
return out
+
def filterhgerr(err):
# If root is executing setup.py, but the repository is owned by
# another user (as in "sudo python setup.py install") we will get
# trust warnings since the .hg/hgrc file is untrusted. That is
# fine, we don't want to load it anyway. Python may warn about
# a missing __init__.py in mercurial/locale, we also ignore that.
- err = [e for e in err.splitlines()
- if (not e.startswith(b'not trusting file')
- and not e.startswith(b'warning: Not importing')
- and not e.startswith(b'obsolete feature not enabled')
- and not e.startswith(b'*** failed to import extension')
- and not e.startswith(b'devel-warn:')
- and not (e.startswith(b'(third party extension')
- and e.endswith(b'or newer of Mercurial; disabling)')))]
+ err = [
+ e
+ for e in err.splitlines()
+ if (
+ not e.startswith(b'not trusting file')
+ and not e.startswith(b'warning: Not importing')
+ and not e.startswith(b'obsolete feature not enabled')
+ and not e.startswith(b'*** failed to import extension')
+ and not e.startswith(b'devel-warn:')
+ and not (
+ e.startswith(b'(third party extension')
+ and e.endswith(b'or newer of Mercurial; disabling)')
+ )
+ )
+ ]
return b'\n'.join(b' ' + e for e in err)
+
def findhg():
"""Try to figure out how we should invoke hg for examining the local
repository contents.
@@ -334,18 +379,23 @@
if retcode == 0 and not filterhgerr(err):
return hgcommand(hgcmd, hgenv)
- raise SystemExit('Unable to find a working hg binary to extract the '
- 'version from the repository tags')
+ raise SystemExit(
+ 'Unable to find a working hg binary to extract the '
+ 'version from the repository tags'
+ )
+
def localhgenv():
"""Get an environment dictionary to use for invoking or importing
mercurial from the local repository."""
# Execute hg out of this directory with a custom environment which takes
# care to not use any hgrc files and do no localization.
- env = {'HGMODULEPOLICY': 'py',
- 'HGRCPATH': '',
- 'LANGUAGE': 'C',
- 'PATH': ''} # make pypi modules that use os.environ['PATH'] happy
+ env = {
+ 'HGMODULEPOLICY': 'py',
+ 'HGRCPATH': '',
+ 'LANGUAGE': 'C',
+ 'PATH': '',
+ } # make pypi modules that use os.environ['PATH'] happy
if 'LD_LIBRARY_PATH' in os.environ:
env['LD_LIBRARY_PATH'] = os.environ['LD_LIBRARY_PATH']
if 'SystemRoot' in os.environ:
@@ -354,6 +404,7 @@
env['SystemRoot'] = os.environ['SystemRoot']
return env
+
version = ''
if os.path.isdir('.hg'):
@@ -367,11 +418,11 @@
# Continuing with an invalid version number will break extensions
# that define minimumhgversion.
raise SystemExit('Unable to determine hg version from local repository')
- if numerictags: # tag(s) found
+ if numerictags: # tag(s) found
version = numerictags[-1]
- if hgid.endswith('+'): # propagate the dirty status to the tag
+ if hgid.endswith('+'): # propagate the dirty status to the tag
version += '+'
- else: # no tag found
+ else: # no tag found
ltagcmd = ['parents', '--template', '{latesttag}']
ltag = sysstr(hg.run(ltagcmd))
changessincecmd = ['log', '-T', 'x\n', '-r', "only(.,'%s')" % ltag]
@@ -380,8 +431,9 @@
if version.endswith('+'):
version += time.strftime('%Y%m%d')
elif os.path.exists('.hg_archival.txt'):
- kw = dict([[t.strip() for t in l.split(':', 1)]
- for l in open('.hg_archival.txt')])
+ kw = dict(
+ [[t.strip() for t in l.split(':', 1)] for l in open('.hg_archival.txt')]
+ )
if 'tag' in kw:
version = kw['tag']
elif 'latesttag' in kw:
@@ -397,15 +449,21 @@
if not isinstance(versionb, bytes):
versionb = versionb.encode('ascii')
- write_if_changed('mercurial/__version__.py', b''.join([
- b'# this file is autogenerated by setup.py\n'
- b'version = b"%s"\n' % versionb,
- ]))
+ write_if_changed(
+ 'mercurial/__version__.py',
+ b''.join(
+ [
+ b'# this file is autogenerated by setup.py\n'
+ b'version = b"%s"\n' % versionb,
+ ]
+ ),
+ )
try:
oldpolicy = os.environ.get('HGMODULEPOLICY', None)
os.environ['HGMODULEPOLICY'] = 'py'
from mercurial import __version__
+
version = __version__.version
except ImportError:
version = b'unknown'
@@ -415,19 +473,23 @@
else:
os.environ['HGMODULEPOLICY'] = oldpolicy
+
class hgbuild(build):
# Insert hgbuildmo first so that files in mercurial/locale/ are found
# when build_py is run next.
sub_commands = [('build_mo', None)] + build.sub_commands
+
class hgbuildmo(build):
description = "build translations (.mo files)"
def run(self):
if not find_executable('msgfmt'):
- self.warn("could not find msgfmt executable, no translations "
- "will be built")
+ self.warn(
+ "could not find msgfmt executable, no translations "
+ "will be built"
+ )
return
podir = 'i18n'
@@ -466,18 +528,23 @@
# too late for some cases
return not self.pure and Distribution.has_ext_modules(self)
+
# This is ugly as a one-liner. So use a variable.
buildextnegops = dict(getattr(build_ext, 'negative_options', {}))
buildextnegops['no-zstd'] = 'zstd'
buildextnegops['no-rust'] = 'rust'
+
class hgbuildext(build_ext):
user_options = build_ext.user_options + [
('zstd', None, 'compile zstd bindings [default]'),
('no-zstd', None, 'do not compile zstd bindings'),
- ('rust', None,
- 'compile Rust extensions if they are in use '
- '(requires Cargo) [default]'),
+ (
+ 'rust',
+ None,
+ 'compile Rust extensions if they are in use '
+ '(requires Cargo) [default]',
+ ),
('no-rust', None, 'do not compile Rust extensions'),
]
@@ -499,14 +566,17 @@
return build_ext.finalize_options(self)
def build_extensions(self):
- ruststandalones = [e for e in self.extensions
- if isinstance(e, RustStandaloneExtension)]
- self.extensions = [e for e in self.extensions
- if e not in ruststandalones]
+ ruststandalones = [
+ e for e in self.extensions if isinstance(e, RustStandaloneExtension)
+ ]
+ self.extensions = [
+ e for e in self.extensions if e not in ruststandalones
+ ]
# Filter out zstd if disabled via argument.
if not self.zstd:
- self.extensions = [e for e in self.extensions
- if e.name != 'mercurial.zstd']
+ self.extensions = [
+ e for e in self.extensions if e.name != 'mercurial.zstd'
+ ]
# Build Rust standalon extensions if it'll be used
# and its build is not explictely disabled (for external build
@@ -518,16 +588,21 @@
return build_ext.build_extensions(self)
def build_extension(self, ext):
- if (self.distribution.rust and self.rust
- and isinstance(ext, RustExtension)):
- ext.rustbuild()
+ if (
+ self.distribution.rust
+ and self.rust
+ and isinstance(ext, RustExtension)
+ ):
+ ext.rustbuild()
try:
build_ext.build_extension(self, ext)
except CCompilerError:
if not getattr(ext, 'optional', False):
raise
- log.warn("Failed to build optional extension '%s' (skipping)",
- ext.name)
+ log.warn(
+ "Failed to build optional extension '%s' (skipping)", ext.name
+ )
+
class hgbuildscripts(build_scripts):
def run(self):
@@ -554,6 +629,7 @@
return build_scripts.run(self)
+
class hgbuildpy(build_py):
def finalize_options(self):
build_py.finalize_options(self)
@@ -565,18 +641,24 @@
bdiffbuild,
mpatchbuild,
)
- exts = [mpatchbuild.ffi.distutils_extension(),
- bdiffbuild.ffi.distutils_extension()]
+
+ exts = [
+ mpatchbuild.ffi.distutils_extension(),
+ bdiffbuild.ffi.distutils_extension(),
+ ]
# cffi modules go here
if sys.platform == 'darwin':
from mercurial.cffi import osutilbuild
+
exts.append(osutilbuild.ffi.distutils_extension())
self.distribution.ext_modules = exts
else:
h = os.path.join(get_python_inc(), 'Python.h')
if not os.path.exists(h):
- raise SystemExit('Python headers are required to build '
- 'Mercurial but weren\'t found in %s' % h)
+ raise SystemExit(
+ 'Python headers are required to build '
+ 'Mercurial but weren\'t found in %s' % h
+ )
def run(self):
basepath = os.path.join(self.build_lib, 'mercurial')
@@ -591,15 +673,17 @@
else:
modulepolicy = 'rust+c' if rust else 'c'
- content = b''.join([
- b'# this file is autogenerated by setup.py\n',
- b'modulepolicy = b"%s"\n' % modulepolicy.encode('ascii'),
- ])
- write_if_changed(os.path.join(basepath, '__modulepolicy__.py'),
- content)
+ content = b''.join(
+ [
+ b'# this file is autogenerated by setup.py\n',
+ b'modulepolicy = b"%s"\n' % modulepolicy.encode('ascii'),
+ ]
+ )
+ write_if_changed(os.path.join(basepath, '__modulepolicy__.py'), content)
build_py.run(self)
+
class buildhgextindex(Command):
description = 'generate prebuilt index of hgext (for frozen package)'
user_options = []
@@ -617,10 +701,13 @@
f.write('# empty\n')
# here no extension enabled, disabled() lists up everything
- code = ('import pprint; from mercurial import extensions; '
- 'pprint.pprint(extensions.disabled())')
- returncode, out, err = runcmd([sys.executable, '-c', code],
- localhgenv())
+ code = (
+ 'import pprint; from mercurial import extensions; '
+ 'pprint.pprint(extensions.disabled())'
+ )
+ returncode, out, err = runcmd(
+ [sys.executable, '-c', code], localhgenv()
+ )
if err or returncode != 0:
raise DistutilsExecError(err)
@@ -629,12 +716,17 @@
f.write(b'docs = ')
f.write(out)
+
class buildhgexe(build_ext):
description = 'compile hg.exe from mercurial/exewrapper.c'
user_options = build_ext.user_options + [
- ('long-paths-support', None, 'enable support for long paths on '
- 'Windows (off by default and '
- 'experimental)'),
+ (
+ 'long-paths-support',
+ None,
+ 'enable support for long paths on '
+ 'Windows (off by default and '
+ 'experimental)',
+ ),
]
LONG_PATHS_MANIFEST = """
@@ -656,34 +748,39 @@
if os.name != 'nt':
return
if isinstance(self.compiler, HackedMingw32CCompiler):
- self.compiler.compiler_so = self.compiler.compiler # no -mdll
- self.compiler.dll_libraries = [] # no -lmsrvc90
+ self.compiler.compiler_so = self.compiler.compiler # no -mdll
+ self.compiler.dll_libraries = [] # no -lmsrvc90
# Different Python installs can have different Python library
# names. e.g. the official CPython distribution uses pythonXY.dll
# and MinGW uses libpythonX.Y.dll.
_kernel32 = ctypes.windll.kernel32
- _kernel32.GetModuleFileNameA.argtypes = [ctypes.c_void_p,
- ctypes.c_void_p,
- ctypes.c_ulong]
+ _kernel32.GetModuleFileNameA.argtypes = [
+ ctypes.c_void_p,
+ ctypes.c_void_p,
+ ctypes.c_ulong,
+ ]
_kernel32.GetModuleFileNameA.restype = ctypes.c_ulong
size = 1000
buf = ctypes.create_string_buffer(size + 1)
- filelen = _kernel32.GetModuleFileNameA(sys.dllhandle, ctypes.byref(buf),
- size)
+ filelen = _kernel32.GetModuleFileNameA(
+ sys.dllhandle, ctypes.byref(buf), size
+ )
if filelen > 0 and filelen != size:
dllbasename = os.path.basename(buf.value)
if not dllbasename.lower().endswith(b'.dll'):
- raise SystemExit('Python DLL does not end with .dll: %s' %
- dllbasename)
+ raise SystemExit(
+ 'Python DLL does not end with .dll: %s' % dllbasename
+ )
pythonlib = dllbasename[:-4]
else:
- log.warn('could not determine Python DLL filename; '
- 'assuming pythonXY')
+ log.warn(
+ 'could not determine Python DLL filename; ' 'assuming pythonXY'
+ )
hv = sys.hexversion
- pythonlib = 'python%d%d' % (hv >> 24, (hv >> 16) & 0xff)
+ pythonlib = 'python%d%d' % (hv >> 24, (hv >> 16) & 0xFF)
log.info('using %s as Python library name' % pythonlib)
with open('mercurial/hgpythonlib.h', 'wb') as f:
@@ -694,14 +791,16 @@
if sys.version_info[0] >= 3:
macros = [('_UNICODE', None), ('UNICODE', None)]
- objects = self.compiler.compile(['mercurial/exewrapper.c'],
- output_dir=self.build_temp,
- macros=macros)
+ objects = self.compiler.compile(
+ ['mercurial/exewrapper.c'],
+ output_dir=self.build_temp,
+ macros=macros,
+ )
dir = os.path.dirname(self.get_ext_fullpath('dummy'))
self.hgtarget = os.path.join(dir, 'hg')
- self.compiler.link_executable(objects, self.hgtarget,
- libraries=[],
- output_dir=self.build_temp)
+ self.compiler.link_executable(
+ objects, self.hgtarget, libraries=[], output_dir=self.build_temp
+ )
if self.long_paths_support:
self.addlongpathsmanifest()
@@ -733,8 +832,16 @@
log.info("running mt.exe to update hg.exe's manifest in-place")
# supplying both -manifest and -inputresource to mt.exe makes
# it merge the embedded and supplied manifests in the -outputresource
- self.spawn(['mt.exe', '-nologo', '-manifest', manfname,
- inputresource, outputresource])
+ self.spawn(
+ [
+ 'mt.exe',
+ '-nologo',
+ '-manifest',
+ manfname,
+ inputresource,
+ outputresource,
+ ]
+ )
log.info("done updating hg.exe's manifest")
os.remove(manfname)
@@ -743,6 +850,7 @@
dir = os.path.dirname(self.get_ext_fullpath('dummy'))
return os.path.join(self.build_temp, dir, 'hg.exe')
+
class hgbuilddoc(Command):
description = 'build documentation'
user_options = [
@@ -782,12 +890,12 @@
txt = 'doc/%s.txt' % root
log.info('generating %s' % txt)
res, out, err = runcmd(
- [sys.executable, 'gendoc.py', root],
- os.environ,
- cwd='doc')
+ [sys.executable, 'gendoc.py', root], os.environ, cwd='doc'
+ )
if res:
- raise SystemExit('error running gendoc.py: %s' %
- '\n'.join([out, err]))
+ raise SystemExit(
+ 'error running gendoc.py: %s' % '\n'.join([out, err])
+ )
with open(txt, 'wb') as fh:
fh.write(out)
@@ -799,10 +907,12 @@
res, out, err = runcmd(
[sys.executable, 'gendoc.py', '%s.gendoc' % root],
os.environ,
- cwd='doc')
+ cwd='doc',
+ )
if res:
- raise SystemExit('error running gendoc: %s' %
- '\n'.join([out, err]))
+ raise SystemExit(
+ 'error running gendoc: %s' % '\n'.join([out, err])
+ )
with open(gendoc, 'wb') as fh:
fh.write(out)
@@ -810,34 +920,58 @@
def genman(root):
log.info('generating doc/%s' % root)
res, out, err = runcmd(
- [sys.executable, 'runrst', 'hgmanpage', '--halt', 'warning',
- '--strip-elements-with-class', 'htmlonly',
- '%s.txt' % root, root],
+ [
+ sys.executable,
+ 'runrst',
+ 'hgmanpage',
+ '--halt',
+ 'warning',
+ '--strip-elements-with-class',
+ 'htmlonly',
+ '%s.txt' % root,
+ root,
+ ],
os.environ,
- cwd='doc')
+ cwd='doc',
+ )
if res:
- raise SystemExit('error running runrst: %s' %
- '\n'.join([out, err]))
+ raise SystemExit(
+ 'error running runrst: %s' % '\n'.join([out, err])
+ )
normalizecrlf('doc/%s' % root)
def genhtml(root):
log.info('generating doc/%s.html' % root)
res, out, err = runcmd(
- [sys.executable, 'runrst', 'html', '--halt', 'warning',
- '--link-stylesheet', '--stylesheet-path', 'style.css',
- '%s.txt' % root, '%s.html' % root],
+ [
+ sys.executable,
+ 'runrst',
+ 'html',
+ '--halt',
+ 'warning',
+ '--link-stylesheet',
+ '--stylesheet-path',
+ 'style.css',
+ '%s.txt' % root,
+ '%s.html' % root,
+ ],
os.environ,
- cwd='doc')
+ cwd='doc',
+ )
if res:
- raise SystemExit('error running runrst: %s' %
- '\n'.join([out, err]))
+ raise SystemExit(
+ 'error running runrst: %s' % '\n'.join([out, err])
+ )
normalizecrlf('doc/%s.html' % root)
# This logic is duplicated in doc/Makefile.
- sources = set(f for f in os.listdir('mercurial/help')
- if re.search(r'[0-9]\.txt$', f))
+ sources = set(
+ f
+ for f in os.listdir('mercurial/help')
+ if re.search(r'[0-9]\.txt$', f)
+ )
# common.txt is a one-off.
gentxt('common')
@@ -854,13 +988,20 @@
if self.html:
genhtml(root)
+
class hginstall(install):
user_options = install.user_options + [
- ('old-and-unmanageable', None,
- 'noop, present for eggless setuptools compat'),
- ('single-version-externally-managed', None,
- 'noop, present for eggless setuptools compat'),
+ (
+ 'old-and-unmanageable',
+ None,
+ 'noop, present for eggless setuptools compat',
+ ),
+ (
+ 'single-version-externally-managed',
+ None,
+ 'noop, present for eggless setuptools compat',
+ ),
]
# Also helps setuptools not be sad while we refuse to create eggs.
@@ -873,6 +1014,7 @@
excl = set(['bdist_egg'])
return filter(lambda x: x not in excl, install.get_sub_commands(self))
+
class hginstalllib(install_lib):
'''
This is a specialization of install_lib that replaces the copy_file used
@@ -887,6 +1029,7 @@
def run(self):
realcopyfile = file_util.copy_file
+
def copyfileandsetmode(*args, **kwargs):
src, dst = args[0], args[1]
dst, copied = realcopyfile(*args, **kwargs)
@@ -901,12 +1044,14 @@
m = stat.S_IMODE(st[stat.ST_MODE])
m = (m & ~int('0777', 8)) | setmode
os.chmod(dst, m)
+
file_util.copy_file = copyfileandsetmode
try:
install_lib.run(self)
finally:
file_util.copy_file = realcopyfile
+
class hginstallscripts(install_scripts):
'''
This is a specialization of install_scripts that replaces the @LIBDIR@ with
@@ -921,8 +1066,7 @@
def finalize_options(self):
install_scripts.finalize_options(self)
- self.set_undefined_options('install',
- ('install_lib', 'install_lib'))
+ self.set_undefined_options('install', ('install_lib', 'install_lib'))
def run(self):
install_scripts.run(self)
@@ -946,17 +1090,19 @@
# we can't reliably set the libdir in wheels: the default behavior
# of looking in sys.path must do.
- if (os.path.splitdrive(self.install_dir)[0] !=
- os.path.splitdrive(self.install_lib)[0]):
+ if (
+ os.path.splitdrive(self.install_dir)[0]
+ != os.path.splitdrive(self.install_lib)[0]
+ ):
# can't make relative paths from one drive to another, so use an
# absolute path instead
libdir = self.install_lib
else:
common = os.path.commonprefix((self.install_dir, self.install_lib))
- rest = self.install_dir[len(common):]
+ rest = self.install_dir[len(common) :]
uplevel = len([n for n in os.path.split(rest) if n])
- libdir = uplevel * ('..' + os.sep) + self.install_lib[len(common):]
+ libdir = uplevel * ('..' + os.sep) + self.install_lib[len(common) :]
for outfile in self.outfiles:
with open(outfile, 'rb') as fp:
@@ -970,14 +1116,17 @@
# install path. During wheel packaging, the shebang has a special
# value.
if data.startswith(b'#!python'):
- log.info('not rewriting @LIBDIR@ in %s because install path '
- 'not known' % outfile)
+ log.info(
+ 'not rewriting @LIBDIR@ in %s because install path '
+ 'not known' % outfile
+ )
continue
data = data.replace(b'@LIBDIR@', libdir.encode(libdir_escape))
with open(outfile, 'wb') as fp:
fp.write(data)
+
# virtualenv installs custom distutils/__init__.py and
# distutils/distutils.cfg files which essentially proxy back to the
# "real" distutils in the main Python install. The presence of this
@@ -1020,8 +1169,10 @@
res.modules = modules
import opcode
- distutilsreal = os.path.join(os.path.dirname(opcode.__file__),
- 'distutils')
+
+ distutilsreal = os.path.join(
+ os.path.dirname(opcode.__file__), 'distutils'
+ )
for root, dirs, files in os.walk(distutilsreal):
for f in sorted(files):
@@ -1042,60 +1193,74 @@
continue
if modname.endswith('.__init__'):
- modname = modname[:-len('.__init__')]
+ modname = modname[: -len('.__init__')]
path = os.path.dirname(full)
else:
path = None
- res.modules[modname] = py2exemodule(modname, full,
- path=path)
+ res.modules[modname] = py2exemodule(
+ modname, full, path=path
+ )
if 'distutils' not in res.modules:
raise SystemExit('could not find distutils modules')
return res
-cmdclass = {'build': hgbuild,
- 'build_doc': hgbuilddoc,
- 'build_mo': hgbuildmo,
- 'build_ext': hgbuildext,
- 'build_py': hgbuildpy,
- 'build_scripts': hgbuildscripts,
- 'build_hgextindex': buildhgextindex,
- 'install': hginstall,
- 'install_lib': hginstalllib,
- 'install_scripts': hginstallscripts,
- 'build_hgexe': buildhgexe,
- }
+
+cmdclass = {
+ 'build': hgbuild,
+ 'build_doc': hgbuilddoc,
+ 'build_mo': hgbuildmo,
+ 'build_ext': hgbuildext,
+ 'build_py': hgbuildpy,
+ 'build_scripts': hgbuildscripts,
+ 'build_hgextindex': buildhgextindex,
+ 'install': hginstall,
+ 'install_lib': hginstalllib,
+ 'install_scripts': hginstallscripts,
+ 'build_hgexe': buildhgexe,
+}
if py2exehacked:
cmdclass['py2exe'] = hgbuildpy2exe
-packages = ['mercurial',
- 'mercurial.cext',
- 'mercurial.cffi',
- 'mercurial.hgweb',
- 'mercurial.interfaces',
- 'mercurial.pure',
- 'mercurial.thirdparty',
- 'mercurial.thirdparty.attr',
- 'mercurial.thirdparty.zope',
- 'mercurial.thirdparty.zope.interface',
- 'mercurial.utils',
- 'mercurial.revlogutils',
- 'mercurial.testing',
- 'hgext', 'hgext.convert', 'hgext.fsmonitor',
- 'hgext.fastannotate',
- 'hgext.fsmonitor.pywatchman',
- 'hgext.highlight',
- 'hgext.infinitepush',
- 'hgext.largefiles', 'hgext.lfs', 'hgext.narrow',
- 'hgext.remotefilelog',
- 'hgext.zeroconf', 'hgext3rd',
- 'hgdemandimport']
+packages = [
+ 'mercurial',
+ 'mercurial.cext',
+ 'mercurial.cffi',
+ 'mercurial.hgweb',
+ 'mercurial.interfaces',
+ 'mercurial.pure',
+ 'mercurial.thirdparty',
+ 'mercurial.thirdparty.attr',
+ 'mercurial.thirdparty.zope',
+ 'mercurial.thirdparty.zope.interface',
+ 'mercurial.utils',
+ 'mercurial.revlogutils',
+ 'mercurial.testing',
+ 'hgext',
+ 'hgext.convert',
+ 'hgext.fsmonitor',
+ 'hgext.fastannotate',
+ 'hgext.fsmonitor.pywatchman',
+ 'hgext.highlight',
+ 'hgext.infinitepush',
+ 'hgext.largefiles',
+ 'hgext.lfs',
+ 'hgext.narrow',
+ 'hgext.remotefilelog',
+ 'hgext.zeroconf',
+ 'hgext3rd',
+ 'hgdemandimport',
+]
if sys.version_info[0] == 2:
- packages.extend(['mercurial.thirdparty.concurrent',
- 'mercurial.thirdparty.concurrent.futures'])
+ packages.extend(
+ [
+ 'mercurial.thirdparty.concurrent',
+ 'mercurial.thirdparty.concurrent.futures',
+ ]
+ )
if 'HG_PY2EXE_EXTRA_INSTALL_PACKAGES' in os.environ:
# py2exe can't cope with namespace packages very well, so we have to
@@ -1103,9 +1268,11 @@
# image here. This is gross, but you gotta do what you gotta do.
packages.extend(os.environ['HG_PY2EXE_EXTRA_INSTALL_PACKAGES'].split(' '))
-common_depends = ['mercurial/bitmanipulation.h',
- 'mercurial/compat.h',
- 'mercurial/cext/util.h']
+common_depends = [
+ 'mercurial/bitmanipulation.h',
+ 'mercurial/compat.h',
+ 'mercurial/cext/util.h',
+]
common_include_dirs = ['mercurial']
osutil_cflags = []
@@ -1117,16 +1284,24 @@
osutil_cflags.append('-DHAVE_%s' % func.upper())
for plat, macro, code in [
- ('bsd|darwin', 'BSD_STATFS', '''
+ (
+ 'bsd|darwin',
+ 'BSD_STATFS',
+ '''
#include <sys/param.h>
#include <sys/mount.h>
int main() { struct statfs s; return sizeof(s.f_fstypename); }
- '''),
- ('linux', 'LINUX_STATFS', '''
+ ''',
+ ),
+ (
+ 'linux',
+ 'LINUX_STATFS',
+ '''
#include <linux/magic.h>
#include <sys/vfs.h>
int main() { struct statfs s; return sizeof(s.f_type); }
- '''),
+ ''',
+ ),
]:
if re.search(plat, sys.platform) and cancompile(new_compiler(), code):
osutil_cflags.append('-DHAVE_%s' % macro)
@@ -1150,17 +1325,20 @@
'mercurial/thirdparty/xdiff/xutils.h',
]
+
class RustCompilationError(CCompilerError):
"""Exception class for Rust compilation errors."""
+
class RustExtension(Extension):
"""Base classes for concrete Rust Extension classes.
"""
rusttargetdir = os.path.join('rust', 'target', 'release')
- def __init__(self, mpath, sources, rustlibname, subcrate,
- py3_features=None, **kw):
+ def __init__(
+ self, mpath, sources, rustlibname, subcrate, py3_features=None, **kw
+ ):
Extension.__init__(self, mpath, sources, **kw)
srcdir = self.rustsrcdir = os.path.join('rust', subcrate)
self.py3_features = py3_features
@@ -1172,9 +1350,11 @@
if os.path.exists(cargo_lock):
self.depends.append(cargo_lock)
for dirpath, subdir, fnames in os.walk(os.path.join(srcdir, 'src')):
- self.depends.extend(os.path.join(dirpath, fname)
- for fname in fnames
- if os.path.splitext(fname)[1] == '.rs')
+ self.depends.extend(
+ os.path.join(dirpath, fname)
+ for fname in fnames
+ if os.path.splitext(fname)[1] == '.rs'
+ )
@staticmethod
def rustdylibsuffix():
@@ -1202,16 +1382,19 @@
# Unix only fix (os.path.expanduser not really reliable if
# HOME is shadowed like this)
import pwd
+
env['HOME'] = pwd.getpwuid(os.getuid()).pw_dir
cargocmd = ['cargo', 'rustc', '-vv', '--release']
if sys.version_info[0] == 3 and self.py3_features is not None:
- cargocmd.extend(('--features', self.py3_features,
- '--no-default-features'))
+ cargocmd.extend(
+ ('--features', self.py3_features, '--no-default-features')
+ )
cargocmd.append('--')
if sys.platform == 'darwin':
- cargocmd.extend(("-C", "link-arg=-undefined",
- "-C", "link-arg=dynamic_lookup"))
+ cargocmd.extend(
+ ("-C", "link-arg=-undefined", "-C", "link-arg=dynamic_lookup")
+ )
try:
subprocess.check_call(cargocmd, env=env, cwd=self.rustsrcdir)
except OSError as exc:
@@ -1219,14 +1402,17 @@
raise RustCompilationError("Cargo not found")
elif exc.errno == errno.EACCES:
raise RustCompilationError(
- "Cargo found, but permisssion to execute it is denied")
+ "Cargo found, but permisssion to execute it is denied"
+ )
else:
raise
except subprocess.CalledProcessError:
raise RustCompilationError(
"Cargo failed. Working directory: %r, "
"command: %r, environment: %r"
- % (self.rustsrcdir, cargocmd, env))
+ % (self.rustsrcdir, cargocmd, env)
+ )
+
class RustEnhancedExtension(RustExtension):
"""A C Extension, conditionally enhanced with Rust code.
@@ -1237,8 +1423,9 @@
"""
def __init__(self, mpath, sources, rustlibname, subcrate, **kw):
- RustExtension.__init__(self, mpath, sources, rustlibname, subcrate,
- **kw)
+ RustExtension.__init__(
+ self, mpath, sources, rustlibname, subcrate, **kw
+ )
if hgrustext != 'direct-ffi':
return
self.extra_compile_args.append('-DWITH_RUST')
@@ -1249,11 +1436,12 @@
if hgrustext == 'direct-ffi':
RustExtension.rustbuild(self)
+
class RustStandaloneExtension(RustExtension):
-
def __init__(self, pydottedname, rustcrate, dylibname, **kw):
- RustExtension.__init__(self, pydottedname, [], dylibname, rustcrate,
- **kw)
+ RustExtension.__init__(
+ self, pydottedname, [], dylibname, rustcrate, **kw
+ )
self.dylibname = dylibname
def build(self, target_dir):
@@ -1261,58 +1449,85 @@
target = [target_dir]
target.extend(self.name.split('.'))
target[-1] += DYLIB_SUFFIX
- shutil.copy2(os.path.join(self.rusttargetdir,
- self.dylibname + self.rustdylibsuffix()),
- os.path.join(*target))
+ shutil.copy2(
+ os.path.join(
+ self.rusttargetdir, self.dylibname + self.rustdylibsuffix()
+ ),
+ os.path.join(*target),
+ )
extmodules = [
- Extension('mercurial.cext.base85', ['mercurial/cext/base85.c'],
- include_dirs=common_include_dirs,
- depends=common_depends),
- Extension('mercurial.cext.bdiff', ['mercurial/bdiff.c',
- 'mercurial/cext/bdiff.c'] + xdiff_srcs,
- include_dirs=common_include_dirs,
- depends=common_depends + ['mercurial/bdiff.h'] + xdiff_headers),
- Extension('mercurial.cext.mpatch', ['mercurial/mpatch.c',
- 'mercurial/cext/mpatch.c'],
- include_dirs=common_include_dirs,
- depends=common_depends),
+ Extension(
+ 'mercurial.cext.base85',
+ ['mercurial/cext/base85.c'],
+ include_dirs=common_include_dirs,
+ depends=common_depends,
+ ),
+ Extension(
+ 'mercurial.cext.bdiff',
+ ['mercurial/bdiff.c', 'mercurial/cext/bdiff.c'] + xdiff_srcs,
+ include_dirs=common_include_dirs,
+ depends=common_depends + ['mercurial/bdiff.h'] + xdiff_headers,
+ ),
+ Extension(
+ 'mercurial.cext.mpatch',
+ ['mercurial/mpatch.c', 'mercurial/cext/mpatch.c'],
+ include_dirs=common_include_dirs,
+ depends=common_depends,
+ ),
RustEnhancedExtension(
- 'mercurial.cext.parsers', ['mercurial/cext/charencode.c',
- 'mercurial/cext/dirs.c',
- 'mercurial/cext/manifest.c',
- 'mercurial/cext/parsers.c',
- 'mercurial/cext/pathencode.c',
- 'mercurial/cext/revlog.c'],
+ 'mercurial.cext.parsers',
+ [
+ 'mercurial/cext/charencode.c',
+ 'mercurial/cext/dirs.c',
+ 'mercurial/cext/manifest.c',
+ 'mercurial/cext/parsers.c',
+ 'mercurial/cext/pathencode.c',
+ 'mercurial/cext/revlog.c',
+ ],
'hgdirectffi',
'hg-direct-ffi',
include_dirs=common_include_dirs,
- depends=common_depends + ['mercurial/cext/charencode.h',
- 'mercurial/cext/revlog.h',
- 'rust/hg-core/src/ancestors.rs',
- 'rust/hg-core/src/lib.rs']),
- Extension('mercurial.cext.osutil', ['mercurial/cext/osutil.c'],
- include_dirs=common_include_dirs,
- extra_compile_args=osutil_cflags,
- extra_link_args=osutil_ldflags,
- depends=common_depends),
+ depends=common_depends
+ + [
+ 'mercurial/cext/charencode.h',
+ 'mercurial/cext/revlog.h',
+ 'rust/hg-core/src/ancestors.rs',
+ 'rust/hg-core/src/lib.rs',
+ ],
+ ),
Extension(
- 'mercurial.thirdparty.zope.interface._zope_interface_coptimizations', [
- 'mercurial/thirdparty/zope/interface/_zope_interface_coptimizations.c',
- ]),
- Extension('hgext.fsmonitor.pywatchman.bser',
- ['hgext/fsmonitor/pywatchman/bser.c']),
- RustStandaloneExtension('mercurial.rustext', 'hg-cpython', 'librusthg',
- py3_features='python3'),
- ]
+ 'mercurial.cext.osutil',
+ ['mercurial/cext/osutil.c'],
+ include_dirs=common_include_dirs,
+ extra_compile_args=osutil_cflags,
+ extra_link_args=osutil_ldflags,
+ depends=common_depends,
+ ),
+ Extension(
+ 'mercurial.thirdparty.zope.interface._zope_interface_coptimizations',
+ [
+ 'mercurial/thirdparty/zope/interface/_zope_interface_coptimizations.c',
+ ],
+ ),
+ Extension(
+ 'hgext.fsmonitor.pywatchman.bser', ['hgext/fsmonitor/pywatchman/bser.c']
+ ),
+ RustStandaloneExtension(
+ 'mercurial.rustext', 'hg-cpython', 'librusthg', py3_features='python3'
+ ),
+]
sys.path.insert(0, 'contrib/python-zstandard')
import setup_zstd
-extmodules.append(setup_zstd.get_c_extension(
- name='mercurial.zstd',
- root=os.path.abspath(os.path.dirname(__file__))))
+
+extmodules.append(
+ setup_zstd.get_c_extension(
+ name='mercurial.zstd', root=os.path.abspath(os.path.dirname(__file__))
+ )
+)
try:
from distutils import cygwinccompiler
@@ -1337,6 +1552,7 @@
class HackedMingw32CCompiler(object):
pass
+
if os.name == 'nt':
# Allow compiler/linker flags to be added to Visual Studio builds. Passing
# extra_link_args to distutils.extensions.Extension() doesn't have any
@@ -1354,15 +1570,21 @@
msvccompiler.MSVCCompiler = HackedMSVCCompiler
-packagedata = {'mercurial': ['locale/*/LC_MESSAGES/hg.mo',
- 'help/*.txt',
- 'help/internals/*.txt',
- 'default.d/*.rc',
- 'dummycert.pem']}
+packagedata = {
+ 'mercurial': [
+ 'locale/*/LC_MESSAGES/hg.mo',
+ 'help/*.txt',
+ 'help/internals/*.txt',
+ 'default.d/*.rc',
+ 'dummycert.pem',
+ ]
+}
+
def ordinarypath(p):
return p and p[0] != '.' and p[-1] != '~'
+
for root in ('templates',):
for curdir, dirs, files in os.walk(os.path.join('mercurial', root)):
curdir = curdir.split(os.sep, 1)[1]
@@ -1402,9 +1624,12 @@
if py2exeloaded:
extra['console'] = [
- {'script':'hg',
- 'copyright':'Copyright (C) 2005-2019 Matt Mackall and others',
- 'product_version':version}]
+ {
+ 'script': 'hg',
+ 'copyright': 'Copyright (C) 2005-2019 Matt Mackall and others',
+ 'product_version': version,
+ }
+ ]
# Sub command of 'build' because 'py2exe' does not handle sub_commands.
# Need to override hgbuild because it has a private copy of
# build.sub_commands.
@@ -1438,8 +1663,9 @@
version = version[0]
if sys.version_info[0] == 3:
version = version.decode('utf-8')
- xcode4 = (version.startswith('Xcode') and
- StrictVersion(version.split()[1]) >= StrictVersion('4.0'))
+ xcode4 = version.startswith('Xcode') and StrictVersion(
+ version.split()[1]
+ ) >= StrictVersion('4.0')
xcode51 = re.match(r'^Xcode\s+5\.1', version) is not None
else:
# xcodebuild returns empty on OS X Lion with XCode 4.3 not
@@ -1463,59 +1689,66 @@
cflags = get_config_var('CFLAGS')
if cflags and re.search(r'-mno-fused-madd\b', cflags) is not None:
os.environ['CFLAGS'] = (
- os.environ.get('CFLAGS', '') + ' -Qunused-arguments')
+ os.environ.get('CFLAGS', '') + ' -Qunused-arguments'
+ )
-setup(name='mercurial',
- version=setupversion,
- author='Matt Mackall and many others',
- author_email='mercurial@mercurial-scm.org',
- url='https://mercurial-scm.org/',
- download_url='https://mercurial-scm.org/release/',
- description=('Fast scalable distributed SCM (revision control, version '
- 'control) system'),
- long_description=('Mercurial is a distributed SCM tool written in Python.'
- ' It is used by a number of large projects that require'
- ' fast, reliable distributed revision control, such as '
- 'Mozilla.'),
- license='GNU GPLv2 or any later version',
- classifiers=[
- 'Development Status :: 6 - Mature',
- 'Environment :: Console',
- 'Intended Audience :: Developers',
- 'Intended Audience :: System Administrators',
- 'License :: OSI Approved :: GNU General Public License (GPL)',
- 'Natural Language :: Danish',
- 'Natural Language :: English',
- 'Natural Language :: German',
- 'Natural Language :: Italian',
- 'Natural Language :: Japanese',
- 'Natural Language :: Portuguese (Brazilian)',
- 'Operating System :: Microsoft :: Windows',
- 'Operating System :: OS Independent',
- 'Operating System :: POSIX',
- 'Programming Language :: C',
- 'Programming Language :: Python',
- 'Topic :: Software Development :: Version Control',
- ],
- scripts=scripts,
- packages=packages,
- ext_modules=extmodules,
- data_files=datafiles,
- package_data=packagedata,
- cmdclass=cmdclass,
- distclass=hgdist,
- options={
- 'py2exe': {
- 'bundle_files': 3,
- 'dll_excludes': py2exedllexcludes,
- 'excludes': py2exeexcludes,
- 'packages': py2exepackages,
- },
- 'bdist_mpkg': {
- 'zipdist': False,
- 'license': 'COPYING',
- 'readme': 'contrib/packaging/macosx/Readme.html',
- 'welcome': 'contrib/packaging/macosx/Welcome.html',
- },
- },
- **extra)
+setup(
+ name='mercurial',
+ version=setupversion,
+ author='Matt Mackall and many others',
+ author_email='mercurial@mercurial-scm.org',
+ url='https://mercurial-scm.org/',
+ download_url='https://mercurial-scm.org/release/',
+ description=(
+ 'Fast scalable distributed SCM (revision control, version '
+ 'control) system'
+ ),
+ long_description=(
+ 'Mercurial is a distributed SCM tool written in Python.'
+ ' It is used by a number of large projects that require'
+ ' fast, reliable distributed revision control, such as '
+ 'Mozilla.'
+ ),
+ license='GNU GPLv2 or any later version',
+ classifiers=[
+ 'Development Status :: 6 - Mature',
+ 'Environment :: Console',
+ 'Intended Audience :: Developers',
+ 'Intended Audience :: System Administrators',
+ 'License :: OSI Approved :: GNU General Public License (GPL)',
+ 'Natural Language :: Danish',
+ 'Natural Language :: English',
+ 'Natural Language :: German',
+ 'Natural Language :: Italian',
+ 'Natural Language :: Japanese',
+ 'Natural Language :: Portuguese (Brazilian)',
+ 'Operating System :: Microsoft :: Windows',
+ 'Operating System :: OS Independent',
+ 'Operating System :: POSIX',
+ 'Programming Language :: C',
+ 'Programming Language :: Python',
+ 'Topic :: Software Development :: Version Control',
+ ],
+ scripts=scripts,
+ packages=packages,
+ ext_modules=extmodules,
+ data_files=datafiles,
+ package_data=packagedata,
+ cmdclass=cmdclass,
+ distclass=hgdist,
+ options={
+ 'py2exe': {
+ 'bundle_files': 3,
+ 'dll_excludes': py2exedllexcludes,
+ 'excludes': py2exeexcludes,
+ 'packages': py2exepackages,
+ },
+ 'bdist_mpkg': {
+ 'zipdist': False,
+ 'license': 'COPYING',
+ 'readme': 'contrib/packaging/macosx/Readme.html',
+ 'welcome': 'contrib/packaging/macosx/Welcome.html',
+ },
+ },
+ **extra
+)