meson/meson-restore-python3.4.patch

406 lines
17 KiB
Diff

--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -32,7 +32,7 @@ from .. import compilers
from ..compilers import CompilerArgs, CCompiler
from ..linkers import ArLinker
from ..mesonlib import File, MesonException, OrderedSet
-from ..mesonlib import get_compiler_for_source, has_path_sep
+from ..mesonlib import get_compiler_for_source, has_path_sep, commonpath
from .backends import CleanTrees
from ..build import InvalidArguments
@@ -1011,8 +1011,8 @@ int dummy;
# Check if the vala file is in a subdir of --basedir
abs_srcbasedir = os.path.join(self.environment.get_source_dir(), target.get_subdir())
abs_vala_file = os.path.join(self.environment.get_build_dir(), vala_file)
- if PurePath(os.path.commonpath((abs_srcbasedir, abs_vala_file))) == PurePath(abs_srcbasedir):
- vala_c_subdir = PurePath(abs_vala_file).parent.relative_to(abs_srcbasedir)
+ if PurePath(commonpath((abs_srcbasedir, abs_vala_file))) == PurePath(abs_srcbasedir):
+ vala_c_subdir = str(PurePath(abs_vala_file).parent.relative_to(abs_srcbasedir))
vala_c_file = os.path.join(str(vala_c_subdir), vala_c_file)
else:
path_to_target = os.path.join(self.build_to_src, target.get_subdir())
--- a/mesonbuild/coredata.py
+++ b/mesonbuild/coredata.py
@@ -18,7 +18,7 @@ import sys
from pathlib import PurePath
from collections import OrderedDict
from .mesonlib import MesonException
-from .mesonlib import default_libdir, default_libexecdir, default_prefix
+from .mesonlib import default_libdir, default_libexecdir, default_prefix, commonpath
from .wrap import WrapMode
import ast
import argparse
@@ -302,7 +302,7 @@ class CoreData:
# commonpath will always return a path in the native format, so we
# must use pathlib.PurePath to do the same conversion before
# comparing.
- if os.path.commonpath([value, prefix]) != str(PurePath(prefix)):
+ if commonpath([value, prefix]) != str(PurePath(prefix)):
m = 'The value of the {!r} option is {!r} which must be a ' \
'subdir of the prefix {!r}.\nNote that if you pass a ' \
'relative path, it is assumed to be a subdir of prefix.'
--- a/mesonbuild/interpreterbase.py
+++ b/mesonbuild/interpreterbase.py
@@ -574,7 +574,9 @@ The result of this is undefined and will
if cur.operation == 'add':
if isinstance(l, dict) and isinstance(r, dict):
- return {**l, **r}
+ ret = l.copy()
+ ret.update(r)
+ return ret
try:
return l + r
except Exception as e:
@@ -661,7 +662,8 @@ The result of this is undefined and will
elif isinstance(old_variable, dict):
if not isinstance(addition, dict):
raise InvalidArguments('The += operator requires a dict on the right hand side if the variable on the left is a dict')
- new_value = {**old_variable, **addition}
+ new_value = old_variable.copy()
+ new_value.update(addition)
# Add other data types here.
else:
raise InvalidArguments('The += operator currently only works with arrays, dicts, strings or ints ')
--- a/mesonbuild/mesonlib.py
+++ b/mesonbuild/mesonlib.py
@@ -19,7 +19,8 @@ import sys
import stat
import time
import platform, subprocess, operator, os, shutil, re
-import collections
+import collections
+import collections.abc
from mesonbuild import mlog
have_fcntl = False
@@ -1062,6 +1062,30 @@ def substring_is_in_list(substr, strlist
return True
return False
+def commonpath(paths):
+ '''
+ For use on Python 3.4 where os.path.commonpath is not available.
+ '''
+ if sys.version_info >= (3, 5):
+ return os.path.commonpath(paths)
+
+ import pathlib
+ if not paths:
+ raise ValueError('commonpath() arg is an empty sequence')
+ common = pathlib.PurePath(paths[0])
+ for path in paths[1:]:
+ new = []
+ path = pathlib.PurePath(path)
+ for c, p in zip(common.parts, path.parts):
+ if c != p:
+ break
+ new.append(c)
+ if not new:
+ raise ValueError("Can't mix absolute and relative paths") from None
+ new = os.path.join(*new)
+ common = pathlib.PurePath(new)
+ return str(common)
+
class OrderedSet(collections.abc.MutableSet):
"""A set that preserves the order in which items are added, by first
insertion.
--- a/mesonbuild/mesonmain.py
+++ b/mesonbuild/mesonmain.py
@@ -269,8 +269,8 @@ def set_meson_command(mainfile):
mlog.log('meson_command is {!r}'.format(mesonlib.meson_command))
def run(original_args, mainfile):
- if sys.version_info < (3, 5):
- print('Meson works correctly only with python 3.5+.')
+ if sys.version_info < (3, 4):
+ print('Meson works correctly only with python 3.4+.')
print('You have python %s.' % sys.version)
print('Please update your environment')
return 1
--- a/mesonbuild/minstall.py
+++ b/mesonbuild/minstall.py
@@ -353,8 +353,8 @@ class Installer:
if shutil.which('pkexec') is not None and 'PKEXEC_UID' not in os.environ:
print('Installation failed due to insufficient permissions.')
print('Attempting to use polkit to gain elevated privileges...')
- os.execlp('pkexec', 'pkexec', sys.executable, main_file, *sys.argv[1:],
- '-C', os.getcwd())
+ os.execvp('pkexec', ['pkexec', sys.executable, main_file] + sys.argv[1:] +
+ ['-C', os.getcwd()])
else:
raise
--- a/mesonbuild/modules/python.py
+++ b/mesonbuild/modules/python.py
@@ -512,7 +512,7 @@ class PythonModule(ExtensionModule):
# Sanity check, we expect to have something that at least quacks in tune
try:
info = json.loads(run_command(python, INTROSPECT_COMMAND))
- except json.JSONDecodeError:
+ except ValueError:
info = None
if isinstance(info, dict) and 'version' in info and self._check_version(name_or_path, info['version']):
--- a/mesonbuild/mtest.py
+++ b/mesonbuild/mtest.py
@@ -115,7 +115,12 @@ def returncode_to_status(retcode):
if retcode < 0:
signum = -retcode
try:
- signame = signal.Signals(signum).name
+ if sys.version_info >= (3, 5):
+ signame = signal.Signals(signum).name
+ else:
+ try: signame = [next(n for n, i in signal.__dict__.items()
+ if i == signum)]
+ except StopIteration: raise ValueError
except ValueError:
signame = 'SIGinvalid'
return '(killed by signal %d %s)' % (signum, signame)
@@ -125,7 +130,12 @@ def returncode_to_status(retcode):
signum = retcode - 128
try:
- signame = signal.Signals(signum).name
+ if sys.version_info >= (3, 5):
+ signame = signal.Signals(signum).name
+ else:
+ try: signame = [next(n for n, i in signal.__dict__.items()
+ if i == signum)]
+ except StopIteration: raise ValueError
except ValueError:
signame = 'SIGinvalid'
return '(exit status %d or signal %d %s)' % (retcode, signum, signame)
--- a/mesonbuild/scripts/dist.py
+++ b/mesonbuild/scripts/dist.py
@@ -87,8 +87,8 @@ def run_dist_scripts(dist_root, dist_scr
silent=True)
if not ep.found():
sys.exit('Script %s could not be found in dist directory.' % d)
- pc = subprocess.run(ep.command, env=env)
- if pc.returncode != 0:
+ pc = subprocess.call(ep.command, env=env)
+ if pc != 0:
sys.exit('Dist script errored out.')
def create_dist_git(dist_name, src_root, bld_root, dist_sub, dist_scripts):
--- a/mesonbuild/scripts/gtkdochelper.py
+++ b/mesonbuild/scripts/gtkdochelper.py
@@ -17,7 +17,7 @@ import subprocess
import shlex
import shutil
import argparse
-from ..mesonlib import MesonException, Popen_safe, is_windows
+from ..mesonlib import MesonException, Popen_safe, is_windows, commonpath
from . import destdir_join
parser = argparse.ArgumentParser()
@@ -107,7 +107,7 @@ def build_gtkdoc(source_root, build_root
# FIXME: Use mesonlib.File objects so we don't need to do this
if not os.path.isabs(f):
f = os.path.join(doc_src, f)
- elif os.path.commonpath([f, build_root]) == build_root:
+ elif commonpath([f, build_root]) == build_root:
continue
shutil.copyfile(f, os.path.join(abs_out, os.path.basename(f)))
--- a/run_meson_command_tests.py
+++ b/run_meson_command_tests.py
@@ -18,6 +18,7 @@ import os
import tempfile
import unittest
import subprocess
+import sys
import zipapp
from pathlib import Path
@@ -73,13 +74,27 @@ class CommandTests(unittest.TestCase):
# If this call hangs CI will just abort. It is very hard to distinguish
# between CI issue and test bug in that case. Set timeout and fail loud
# instead.
- p = subprocess.run(command, stdout=subprocess.PIPE,
- stderr=subprocess.STDOUT, env=os.environ.copy(),
- universal_newlines=True, cwd=workdir, timeout=60 * 5)
- print(p.stdout)
- if p.returncode != 0:
- raise subprocess.CalledProcessError(p.returncode, command)
- return p.stdout
+ if sys.version_info >= (3, 5):
+ p = subprocess.run(command, stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT, env=os.environ.copy(),
+ universal_newlines=True,
+ cwd=workdir, timeout=60 * 5)
+ print(p.stdout)
+ if p.returncode != 0:
+ raise subprocess.CalledProcessError(p.returncode, command)
+ return p.stdout
+ else:
+ try:
+ po = subprocess.check_output(command, stderr=subprocess.STDOUT,
+ env=os.environ.copy(),
+ universal_newlines=True,
+ cwd=workdir, timeout=60 * 5)
+ except subprocess.CalledProcessError as e:
+ print(e.output)
+ raise subprocess.CalledProcessError(e.returncode, e.cmd)
+ else:
+ print(po)
+ return po
def assertMesonCommandIs(self, line, cmd):
self.assertTrue(line.startswith('meson_command '), msg=line)
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -21,6 +21,7 @@ import tempfile
import textwrap
import os
import shutil
+import sys
import unittest
import platform
from itertools import chain
@@ -892,6 +893,24 @@ class DataTests(unittest.TestCase):
defined = set([a.strip() for a in res.group().split('\\')][1:])
self.assertEqual(defined, set(chain(interp.funcs.keys(), interp.builtin.keys())))
+ def test_commonpath(self):
+ from os.path import sep
+ commonpath = mesonbuild.mesonlib.commonpath
+ self.assertRaises(ValueError, commonpath, [])
+ self.assertEqual(commonpath(['/usr', '/usr']), sep + 'usr')
+ self.assertEqual(commonpath(['/usr', '/usr/']), sep + 'usr')
+ self.assertEqual(commonpath(['/usr', '/usr/bin']), sep + 'usr')
+ self.assertEqual(commonpath(['/usr/', '/usr/bin']), sep + 'usr')
+ self.assertEqual(commonpath(['/usr/./', '/usr/bin']), sep + 'usr')
+ self.assertEqual(commonpath(['/usr/bin', '/usr/bin']), sep + 'usr' + sep + 'bin')
+ self.assertEqual(commonpath(['/usr//bin', '/usr/bin']), sep + 'usr' + sep + 'bin')
+ self.assertEqual(commonpath(['/usr/./bin', '/usr/bin']), sep + 'usr' + sep + 'bin')
+ self.assertEqual(commonpath(['/usr/local', '/usr/lib']), sep + 'usr')
+ self.assertEqual(commonpath(['/usr', '/bin']), sep)
+ prefix = '/some/path/to/prefix'
+ libdir = '/some/path/to/prefix/libdir'
+ self.assertEqual(commonpath([prefix, libdir]), str(PurePath(prefix)))
+
class BasePlatformTests(unittest.TestCase):
def setUp(self):
@@ -972,9 +991,16 @@ class BasePlatformTests(unittest.TestCas
# If this call hangs CI will just abort. It is very hard to distinguish
# between CI issue and test bug in that case. Set timeout and fail loud
# instead.
- p = subprocess.run(command, stdout=subprocess.PIPE,
- stderr=subprocess.STDOUT, env=os.environ.copy(),
- universal_newlines=True, cwd=workdir, timeout=60 * 5)
+ if sys.version_info >= (3, 5):
+ p = subprocess.run(command, stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT, env=os.environ.copy(),
+ universal_newlines=True, cwd=workdir,
+ timeout=60 * 5)
+ else:
+ p = subprocess.Popen(command, stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT, env=os.environ.copy(),
+ universal_newlines=True, cwd=workdir)
+ p.stdout = p.communicate(timeout=60 * 5)[0]
print(p.stdout)
if p.returncode != 0:
if 'MESON_SKIP_TEST' in p.stdout:
@@ -2698,17 +2724,23 @@ recommended as it is not supported on so
of = open(mfile, 'w')
of.write("project('foobar', 'c')\n")
of.close()
- pc = subprocess.run(self.setup_command,
- cwd=srcdir,
- stdout=subprocess.PIPE,
- stderr=subprocess.DEVNULL)
+ if sys.version_info >= (3, 5):
+ pc = subprocess.run(self.setup_command,
+ cwd=srcdir,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.DEVNULL)
+ else:
+ pc = subprocess.Popen(self.setup_command,
+ cwd=srcdir,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.DEVNULL)
+ pc.stdout = pc.communicate()[0]
self.assertIn(b'Must specify at least one directory name', pc.stdout)
with tempfile.TemporaryDirectory(dir=srcdir) as builddir:
- subprocess.run(self.setup_command,
- check=True,
- cwd=builddir,
- stdout=subprocess.DEVNULL,
- stderr=subprocess.DEVNULL)
+ subprocess.check_call(self.setup_command,
+ cwd=builddir,
+ stdout=subprocess.DEVNULL,
+ stderr=subprocess.DEVNULL)
def get_opts_as_dict(self):
result = {}
--- a/setup.py
+++ b/setup.py
@@ -18,9 +18,9 @@ import sys
from mesonbuild.coredata import version
-if sys.version_info < (3, 5, 0):
+if sys.version_info < (3, 4, 0):
print('Tried to install with an unsupported version of Python. '
- 'Meson requires Python 3.5.0 or greater')
+ 'Meson requires Python 3.4.0 or greater')
sys.exit(1)
from setuptools import setup
--- "a/test cases/common/188 find override/subdir/converter.py"
+++ "b/test cases/common/188 find override/subdir/converter.py"
@@ -10,6 +10,7 @@ ftempl = '''int %s() {
}
'''
-d = pathlib.Path(ifilename).read_text().split('\n')[0].strip()
-
-pathlib.Path(ofilename).write_text(ftempl % d)
+with pathlib.Path(ifilename).open('r') as f:
+ d = f.readline().strip()
+with pathlib.Path(ofilename).open('w') as f:
+ f.write(ftempl % d)
--- "a/test cases/common/188 find override/subdir/gencodegen.py.in"
+++ "b/test cases/common/188 find override/subdir/gencodegen.py.in"
@@ -10,6 +10,7 @@ ftempl = '''int %s() {
}
'''
-d = pathlib.Path(ifilename).read_text().split('\n')[0].strip()
-
-pathlib.Path(ofilename).write_text(ftempl % d)
+with pathlib.Path(ifilename).open('r') as f:
+ d = f.readline().strip()
+with pathlib.Path(ofilename).open('w') as f:
+ f.write(ftempl % d)
--- "a/test cases/unit/35 dist script/replacer.py"
+++ "b/test cases/unit/35 dist script/replacer.py"
@@ -7,6 +7,8 @@ source_root = pathlib.Path(os.environ['M
modfile = source_root / 'prog.c'
-contents = modfile.read_text()
+with modfile.open('r') as f:
+ contents = f.read()
contents = contents.replace('"incorrect"', '"correct"')
-modfile.write_text(contents)
+with modfile.open('w') as f:
+ f.write(contents)
--- "a/test cases/windows/13 test argument extra paths/test/test_run_exe.py"
+++ "b/test cases/windows/13 test argument extra paths/test/test_run_exe.py"
@@ -7,6 +7,6 @@ if __name__ == '__main__':
parser.add_argument('prog')
args = parser.parse_args()
- res = subprocess.run(args.prog)
+ ret = subprocess.call(args.prog)
- sys.exit(res.returncode - 42)
+ sys.exit(ret - 42)