Commit d576fc38 authored by Krzysztof Gogolewski's avatar Krzysztof Gogolewski

Python 3 support, second attempt (Trac #9184)

Summary:
This is a fixup of https://phabricator.haskell.org/D233

The only difference is in findTFiles (first commit), which
previously broke Windows runner; now I translated literally
instead attempting to improve it, and checked it works.

Test Plan:
I used validate under 2,3 on Linux and under 2 on msys2.
On Windows I've seen a large number of failures, but they don't
seem to be connected with the patch.

Reviewers: hvr, simonmar, thomie, austin

Reviewed By: austin

Subscribers: thomie, carter, ezyang, simonmar

Differential Revision: https://phabricator.haskell.org/D310

GHC Trac Issues: #9184
parent abfbb0d6
...@@ -148,21 +148,17 @@ config.way_rts_flags = { ...@@ -148,21 +148,17 @@ config.way_rts_flags = {
# Useful classes of ways that can be used with only_ways() and # Useful classes of ways that can be used with only_ways() and
# expect_broken_for(). # expect_broken_for().
prof_ways = map (lambda x: x[0], \ prof_ways = [x[0] for x in config.way_flags('dummy_name').items()
filter(lambda x: '-prof' in x[1], \ if '-prof' in x[1]]
config.way_flags('dummy_name').items()))
threaded_ways = map (lambda x: x[0], \ threaded_ways = [x[0] for x in config.way_flags('dummy_name').items()
filter(lambda x: '-threaded' in x[1] or 'ghci' == x[0], \ if '-threaded' in x[1] or 'ghci' == x[0]]
config.way_flags('dummy_name').items()))
opt_ways = map (lambda x: x[0], \ opt_ways = [x[0] for x in config.way_flags('dummy_name').items()
filter(lambda x: '-O' in x[1], \ if '-O' in x[1]]
config.way_flags('dummy_name').items()))
llvm_ways = map (lambda x: x[0], \ llvm_ways = [x[0] for x in config.way_flags('dummy_name').items()
filter(lambda x: '-fllvm' in x[1], \ if '-fflvm' in x[1]]
config.way_flags('dummy_name').items()))
def get_compiler_info(): def get_compiler_info():
# This should really not go through the shell # This should really not go through the shell
...@@ -192,7 +188,7 @@ def get_compiler_info(): ...@@ -192,7 +188,7 @@ def get_compiler_info():
if re.match(".*_p(_.*|$)", rtsInfoDict["RTS way"]): if re.match(".*_p(_.*|$)", rtsInfoDict["RTS way"]):
config.compiler_profiled = True config.compiler_profiled = True
config.run_ways = filter(lambda x: x != 'ghci', config.run_ways) config.run_ways = [x for x in config.run_ways if x != 'ghci']
else: else:
config.compiler_profiled = False config.compiler_profiled = False
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
# (c) Simon Marlow 2002 # (c) Simon Marlow 2002
# #
from __future__ import print_function
import sys import sys
import os import os
import string import string
...@@ -21,6 +23,11 @@ try: ...@@ -21,6 +23,11 @@ try:
except: except:
pass pass
PYTHON3 = sys.version_info >= (3, 0)
if PYTHON3:
print("*** WARNING: running testsuite using Python 3.\n"
"*** Python 3 support is experimental. See Trac #9184.")
from testutil import * from testutil import *
from testglobals import * from testglobals import *
...@@ -52,12 +59,12 @@ opts, args = getopt.getopt(sys.argv[1:], "e:", long_options) ...@@ -52,12 +59,12 @@ opts, args = getopt.getopt(sys.argv[1:], "e:", long_options)
for opt,arg in opts: for opt,arg in opts:
if opt == '--config': if opt == '--config':
execfile(arg) exec(open(arg).read())
# -e is a string to execute from the command line. For example: # -e is a string to execute from the command line. For example:
# testframe -e 'config.compiler=ghc-5.04' # testframe -e 'config.compiler=ghc-5.04'
if opt == '-e': if opt == '-e':
exec arg exec(arg)
if opt == '--rootdir': if opt == '--rootdir':
config.rootdirs.append(arg) config.rootdirs.append(arg)
...@@ -83,9 +90,9 @@ for opt,arg in opts: ...@@ -83,9 +90,9 @@ for opt,arg in opts:
sys.stderr.write("ERROR: requested way \'" + sys.stderr.write("ERROR: requested way \'" +
arg + "\' does not exist\n") arg + "\' does not exist\n")
sys.exit(1) sys.exit(1)
config.other_ways = filter(neq(arg), config.other_ways) config.other_ways = [w for w in config.other_ways if w != arg]
config.run_ways = filter(neq(arg), config.run_ways) config.run_ways = [w for w in config.run_ways if w != arg]
config.compile_ways = filter(neq(arg), config.compile_ways) config.compile_ways = [w for w in config.compile_ways if w != arg]
if opt == '--threads': if opt == '--threads':
config.threads = int(arg) config.threads = int(arg)
...@@ -117,17 +124,17 @@ if config.use_threads == 1: ...@@ -117,17 +124,17 @@ if config.use_threads == 1:
maj = int(re.sub('[^0-9].*', '', str(maj))) maj = int(re.sub('[^0-9].*', '', str(maj)))
min = int(re.sub('[^0-9].*', '', str(min))) min = int(re.sub('[^0-9].*', '', str(min)))
pat = int(re.sub('[^0-9].*', '', str(pat))) pat = int(re.sub('[^0-9].*', '', str(pat)))
if (maj, min, pat) < (2, 5, 2): if (maj, min) < (2, 6):
print "Warning: Ignoring request to use threads as python version < 2.5.2" print("Python < 2.6 is not supported")
config.use_threads = 0 sys.exit(1)
# We also need to disable threads for python 2.7.2, because of # We also need to disable threads for python 2.7.2, because of
# this bug: http://bugs.python.org/issue13817 # this bug: http://bugs.python.org/issue13817
elif (maj, min, pat) == (2, 7, 2): elif (maj, min, pat) == (2, 7, 2):
print "Warning: Ignoring request to use threads as python version is 2.7.2" print("Warning: Ignoring request to use threads as python version is 2.7.2")
print "See http://bugs.python.org/issue13817 for details." print("See http://bugs.python.org/issue13817 for details.")
config.use_threads = 0 config.use_threads = 0
if windows: if windows:
print "Warning: Ignoring request to use threads as running on Windows" print("Warning: Ignoring request to use threads as running on Windows")
config.use_threads = 0 config.use_threads = 0
config.cygwin = False config.cygwin = False
...@@ -180,10 +187,10 @@ else: ...@@ -180,10 +187,10 @@ else:
h.close() h.close()
if v != '': if v != '':
os.environ['LC_ALL'] = v os.environ['LC_ALL'] = v
print "setting LC_ALL to", v print("setting LC_ALL to", v)
else: else:
print 'WARNING: No UTF8 locale found.' print('WARNING: No UTF8 locale found.')
print 'You may get some spurious test failures.' print('You may get some spurious test failures.')
# This has to come after arg parsing as the args can change the compiler # This has to come after arg parsing as the args can change the compiler
get_compiler_info() get_compiler_info()
...@@ -230,7 +237,7 @@ if config.use_threads: ...@@ -230,7 +237,7 @@ if config.use_threads:
if config.timeout == -1: if config.timeout == -1:
config.timeout = int(read_no_crs(config.top + '/timeout/calibrate.out')) config.timeout = int(read_no_crs(config.top + '/timeout/calibrate.out'))
print 'Timeout is ' + str(config.timeout) print('Timeout is ' + str(config.timeout))
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
# The main dude # The main dude
...@@ -240,40 +247,44 @@ if config.rootdirs == []: ...@@ -240,40 +247,44 @@ if config.rootdirs == []:
t_files = findTFiles(config.rootdirs) t_files = findTFiles(config.rootdirs)
print 'Found', len(t_files), '.T files...' print('Found', len(t_files), '.T files...')
t = getTestRun() t = getTestRun()
# Avoid cmd.exe built-in 'date' command on Windows # Avoid cmd.exe built-in 'date' command on Windows
t.start_time = time.localtime() t.start_time = time.localtime()
print 'Beginning test run at', time.strftime("%c %Z",t.start_time) print('Beginning test run at', time.strftime("%c %Z",t.start_time))
# set stdout to unbuffered (is this the best way to do it?)
sys.stdout.flush() sys.stdout.flush()
sys.stdout = os.fdopen(sys.__stdout__.fileno(), "w", 0) if PYTHON3:
# in Python 3, we output text, which cannot be unbuffered
sys.stdout = os.fdopen(sys.__stdout__.fileno(), "w")
else:
# set stdout to unbuffered (is this the best way to do it?)
sys.stdout = os.fdopen(sys.__stdout__.fileno(), "w", 0)
# First collect all the tests to be run # First collect all the tests to be run
for file in t_files: for file in t_files:
if_verbose(2, '====> Scanning %s' % file) if_verbose(2, '====> Scanning %s' % file)
newTestDir(os.path.dirname(file)) newTestDir(os.path.dirname(file))
try: try:
execfile(file) exec(open(file).read())
except: except Exception:
print '*** framework failure: found an error while executing ', file, ':' print('*** framework failure: found an error while executing ', file, ':')
t.n_framework_failures = t.n_framework_failures + 1 t.n_framework_failures = t.n_framework_failures + 1
traceback.print_exc() traceback.print_exc()
if config.list_broken: if config.list_broken:
global brokens global brokens
print '' print('')
print 'Broken tests:' print('Broken tests:')
print (' '.join(map (lambda (b, d, n) : '#' + str(b) + '(' + d + '/' + n + ')', brokens))) print(' '.join(map (lambda bdn: '#' + str(bdn[0]) + '(' + bdn[1] + '/' + bdn[2] + ')', brokens)))
print '' print('')
if t.n_framework_failures != 0: if t.n_framework_failures != 0:
print 'WARNING:', str(t.n_framework_failures), 'framework failures!' print('WARNING:', str(t.n_framework_failures), 'framework failures!')
print '' print('')
else: else:
# Now run all the tests # Now run all the tests
if config.use_threads: if config.use_threads:
......
This diff is collapsed.
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
# Utils # Utils
def id(a):
return a
def eq(x):
return lambda y,z=x: y == z
def neq(x):
return lambda y,z=x: y != z
def append(x,y):
return x + y
def concat(xs):
return reduce(append,xs,[])
def chop(s):
if s[len(s)-1:] == '\n':
return s[:len(s)-1]
else:
return s
def all(p,xs):
for x in xs:
if not p(x):
return False
return True
def elem(xs):
return lambda x: x in xs
def notElem(xs):
return lambda x: x not in xs
def version_to_ints(v): def version_to_ints(v):
return [ int(x) for x in v.split('.') ] return [ int(x) for x in v.split('.') ]
......
...@@ -50,10 +50,10 @@ test('ffi008', [exit_code(1), omit_ways(['ghci'])], compile_and_run, ['']) ...@@ -50,10 +50,10 @@ test('ffi008', [exit_code(1), omit_ways(['ghci'])], compile_and_run, [''])
maybe_skip = normal maybe_skip = normal
opts = '' opts = ''
if config.platform.startswith('i386-'): if config.platform.startswith('i386-'):
if config.compiler_type == 'ghc' and \ if config.compiler_type == 'ghc' and \
version_ge(config.compiler_version, '6.13'): version_ge(config.compiler_version, '6.13'):
opts = '-msse2' opts = '-msse2'
else: else:
maybe_skip = only_ways(['ghci']) maybe_skip = only_ways(['ghci'])
test('ffi009', [when(fast(), skip), test('ffi009', [when(fast(), skip),
...@@ -69,9 +69,9 @@ test('ffi011', normal, compile_and_run, ['']) ...@@ -69,9 +69,9 @@ test('ffi011', normal, compile_and_run, [''])
# it. # it.
if config.os == 'mingw32': if config.os == 'mingw32':
skip_if_not_windows = normal skip_if_not_windows = normal
else: else:
skip_if_not_windows = skip skip_if_not_windows = skip
test('ffi012', skip_if_not_windows, compile_and_run, ['']) test('ffi012', skip_if_not_windows, compile_and_run, [''])
test('ffi013', normal, compile_and_run, ['']) test('ffi013', normal, compile_and_run, [''])
......
...@@ -15,11 +15,11 @@ test('arith007', normal, compile_and_run, ['']) ...@@ -15,11 +15,11 @@ test('arith007', normal, compile_and_run, [''])
ways = normal ways = normal
opts = '' opts = ''
if config.platform.startswith('i386-'): if config.platform.startswith('i386-'):
if config.compiler_type == 'ghc' and \ if config.compiler_type == 'ghc' and \
version_ge(config.compiler_version, '6.13'): version_ge(config.compiler_version, '6.13'):
opts = '-msse2' opts = '-msse2'
else: else:
ways = expect_fail_for(['optasm','threaded2','hpc','dyn','profasm']) ways = expect_fail_for(['optasm','threaded2','hpc','dyn','profasm'])
test('arith008', ways, compile_and_run, [opts]) test('arith008', ways, compile_and_run, [opts])
......
def no_lint(name, opts): def no_lint(name, opts):
opts.compiler_always_flags = \ opts.compiler_always_flags = \
filter(lambda opt: opt != '-dcore-lint' and opt != '-dcmm-lint', opts.compiler_always_flags) [opt for opt in opts.compiler_always_flags if opt != '-dcore-lint' and opt != '-dcmm-lint']
setTestOpts(no_lint) setTestOpts(no_lint)
......
...@@ -4,9 +4,9 @@ ...@@ -4,9 +4,9 @@
test('T4255', unless(compiler_profiled(), skip), compile_fail, ['-v0']) test('T4255', unless(compiler_profiled(), skip), compile_fail, ['-v0'])
def f(name, opts): def f(name, opts):
opts.extra_hc_opts = '-XTemplateHaskell -package template-haskell' opts.extra_hc_opts = '-XTemplateHaskell -package template-haskell'
if (ghc_with_interpreter == 0): if (ghc_with_interpreter == 0):
opts.skip = 1 opts.skip = 1
setTestOpts(f) setTestOpts(f)
setTestOpts(only_compiler_types(['ghc'])) setTestOpts(only_compiler_types(['ghc']))
......
...@@ -19,8 +19,8 @@ test('TcCoercible', when(compiler_lt('ghc', '7.7'), skip), compile_and_run, [''] ...@@ -19,8 +19,8 @@ test('TcCoercible', when(compiler_lt('ghc', '7.7'), skip), compile_and_run, ['']
# Skip everything else if fast is on # Skip everything else if fast is on
def f(name, opts): def f(name, opts):
if config.fast: if config.fast:
opts.skip = 1 opts.skip = 1
setTestOpts(f) setTestOpts(f)
test('tcrun006', normal, compile_and_run, ['']) test('tcrun006', normal, compile_and_run, [''])
......
...@@ -10,7 +10,7 @@ except: ...@@ -10,7 +10,7 @@ except:
# We don't have resource, so this is a non-UNIX machine. # We don't have resource, so this is a non-UNIX machine.
# It's probably a reasonable modern x86/x86_64 machines, so we'd # It's probably a reasonable modern x86/x86_64 machines, so we'd
# probably calibrate to 300 anyway; thus just print 300. # probably calibrate to 300 anyway; thus just print 300.
print 300 print(300)
exit(0) exit(0)
compiler = argv[1] compiler = argv[1]
......
...@@ -21,7 +21,7 @@ try: ...@@ -21,7 +21,7 @@ try:
os.killpg(pid, signal.SIGKILL) os.killpg(pid, signal.SIGKILL)
else: else:
return return
except OSError, e: except OSError as e:
if e.errno == errno.ECHILD: if e.errno == errno.ECHILD:
return return
else: else:
......
#! /usr/bin/env python #! /usr/bin/env python
# Script to create and restore a git fingerprint of the ghc repositories. # Script to create and restore a git fingerprint of the ghc repositories.
from __future__ import print_function
from datetime import datetime from datetime import datetime
from optparse import OptionParser from optparse import OptionParser
import os import os
...@@ -23,7 +25,7 @@ def create_action(opts): ...@@ -23,7 +25,7 @@ def create_action(opts):
if len(fp) == 0: if len(fp) == 0:
error("Got empty fingerprint from source: "+str(opts.source)) error("Got empty fingerprint from source: "+str(opts.source))
if opts.output_file: if opts.output_file:
print "Writing fingerprint to: ", opts.output_file print("Writing fingerprint to: ", opts.output_file)
fp.write(opts.output) fp.write(opts.output)
def restore_action(opts): def restore_action(opts):
...@@ -89,7 +91,7 @@ def restore(fp, branch_name=None): ...@@ -89,7 +91,7 @@ def restore(fp, branch_name=None):
for (subdir, commit) in fp: for (subdir, commit) in fp:
if subdir != ".": if subdir != ".":
cmd = checkout + [commit] cmd = checkout + [commit]
print "==", subdir, " ".join(cmd) print("==", subdir, " ".join(cmd))
if os.path.exists(subdir): if os.path.exists(subdir):
rc = subprocess.call(cmd, cwd=subdir) rc = subprocess.call(cmd, cwd=subdir)
if rc != 0: if rc != 0:
...@@ -184,7 +186,7 @@ def validate(opts, args, parser): ...@@ -184,7 +186,7 @@ def validate(opts, args, parser):
def error(msg="fatal error", parser=None, exit=1): def error(msg="fatal error", parser=None, exit=1):
"""Function that prints error message and exits""" """Function that prints error message and exits"""
print "ERROR:", msg print("ERROR:", msg)
if parser: if parser:
parser.print_help() parser.print_help()
sys.exit(exit) sys.exit(exit)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment