Remove python2 support from tests/utils scripts
diff --git a/mingw-ldd.py b/mingw-ldd.py
index 1d659ef..abc3d78 100755
--- a/mingw-ldd.py
+++ b/mingw-ldd.py
@@ -1,10 +1,9 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 
 # Copied from https://github.com/xantares/mingw-ldd/blob/master/mingw-ldd.py
 # Modified to point to right prefix location on Fedora.
 
 # WTFPL - Do What the Fuck You Want to Public License
-from __future__ import print_function
 import pefile
 import os
 import sys
diff --git a/src/gen-arabic-table.py b/src/gen-arabic-table.py
index 7fe26b0..5e4206b 100755
--- a/src/gen-arabic-table.py
+++ b/src/gen-arabic-table.py
@@ -1,6 +1,4 @@
-#!/usr/bin/env python
-
-from __future__ import print_function, division, absolute_import
+#!/usr/bin/env python3
 
 import io, os.path, sys
 
diff --git a/src/gen-def.py b/src/gen-def.py
index 9111c69..fd3c7b0 100755
--- a/src/gen-def.py
+++ b/src/gen-def.py
@@ -1,6 +1,4 @@
-#!/usr/bin/env python
-
-from __future__ import print_function, division, absolute_import
+#!/usr/bin/env python3
 
 import io, os, re, sys
 
diff --git a/src/gen-emoji-table.py b/src/gen-emoji-table.py
index 0dc0dcc..c02febc 100755
--- a/src/gen-emoji-table.py
+++ b/src/gen-emoji-table.py
@@ -1,6 +1,5 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 
-from __future__ import print_function, division, absolute_import
 import sys
 import os.path
 from collections import OrderedDict
diff --git a/src/gen-indic-table.py b/src/gen-indic-table.py
index 8f9f678..e9d152a 100755
--- a/src/gen-indic-table.py
+++ b/src/gen-indic-table.py
@@ -1,6 +1,4 @@
-#!/usr/bin/env python
-
-from __future__ import print_function, division, absolute_import
+#!/usr/bin/env python3
 
 import io, sys
 
diff --git a/src/gen-os2-unicode-ranges.py b/src/gen-os2-unicode-ranges.py
index 515f4ca..49239d6 100755
--- a/src/gen-os2-unicode-ranges.py
+++ b/src/gen-os2-unicode-ranges.py
@@ -1,13 +1,9 @@
-#!/usr/bin/python
-
-# -*- coding: utf-8 -*-
+#!/usr/bin/env python3
 
 # Generates the code for a sorted unicode range array as used in hb-ot-os2-unicode-ranges.hh
 # Input is a tab seperated list of unicode ranges from the otspec
 # (https://docs.microsoft.com/en-us/typography/opentype/spec/os2#ur).
 
-from __future__ import print_function, division, absolute_import
-
 import io
 import re
 import sys
diff --git a/src/gen-tag-table.py b/src/gen-tag-table.py
index d63aae5..80d7a0a 100755
--- a/src/gen-tag-table.py
+++ b/src/gen-tag-table.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 
 """Generator of the mapping from OpenType tags to BCP 47 tags and vice
 versa.
@@ -22,8 +22,6 @@
 - https://www.iana.org/assignments/language-subtag-registry/language-subtag-registry
 """
 
-from __future__ import absolute_import, division, print_function, unicode_literals
-
 import collections
 try:
 	from HTMLParser import HTMLParser
@@ -758,7 +756,7 @@
 ot.add_language ('und-Syrj', 'SYRJ')
 ot.add_language ('und-Syrn', 'SYRN')
 
-bcp_47.names['xst'] = u"Silt'e"
+bcp_47.names['xst'] = "Silt'e"
 bcp_47.scopes['xst'] = ' (retired code)'
 bcp_47.macrolanguages['xst'] = {'stv', 'wle'}
 
@@ -865,7 +863,7 @@
 	Returns:
 		A snippet of C++ representing ``tag``.
 	"""
-	return u"HB_TAG('%s','%s','%s','%s')" % tuple (('%-4s' % tag)[:4])
+	return "HB_TAG('%s','%s','%s','%s')" % tuple (('%-4s' % tag)[:4])
 
 def get_variant_set (name):
 	"""Return a set of variant language names from a name.
@@ -877,7 +875,7 @@
 	Returns:
 		A set of normalized language names.
 	"""
-	return set (unicodedata.normalize ('NFD', n.replace ('\u2019', u"'"))
+	return set (unicodedata.normalize ('NFD', n.replace ('\u2019', "'"))
 			.encode ('ASCII', 'ignore')
 			.strip ()
 			for n in re.split ('[\n(),]', name) if n)
diff --git a/src/gen-ucd-table.py b/src/gen-ucd-table.py
index 1a01288..2178836 100755
--- a/src/gen-ucd-table.py
+++ b/src/gen-ucd-table.py
@@ -1,6 +1,4 @@
-#!/usr/bin/env python
-
-from __future__ import print_function, division, absolute_import
+#!/usr/bin/env python3
 
 import io, os.path, sys, re
 import logging
diff --git a/src/gen-use-table.py b/src/gen-use-table.py
index bce99a4..e6e6113 100755
--- a/src/gen-use-table.py
+++ b/src/gen-use-table.py
@@ -1,8 +1,6 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 # flake8: noqa
 
-from __future__ import print_function, division, absolute_import
-
 import io
 import sys
 
diff --git a/src/gen-vowel-constraints.py b/src/gen-vowel-constraints.py
index 3d5d6a6..0718641 100755
--- a/src/gen-vowel-constraints.py
+++ b/src/gen-vowel-constraints.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 
 """Generator of the function to prohibit certain vowel sequences.
 
@@ -9,8 +9,6 @@
 
 """
 
-from __future__ import absolute_import, division, print_function, unicode_literals
-
 import collections
 try:
 	from HTMLParser import HTMLParser
diff --git a/src/sample.py b/src/sample.py
index 5d65aa0..889efec 100755
--- a/src/sample.py
+++ b/src/sample.py
@@ -1,27 +1,12 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-from __future__ import print_function, division, absolute_import
+#!/usr/bin/env python3
 
 import sys
 import array
 from gi.repository import HarfBuzz as hb
 from gi.repository import GLib
 
-# Python 2/3 compatibility
-try:
-	unicode
-except NameError:
-	unicode = str
-
-def tounicode(s, encoding='utf-8'):
-	if not isinstance(s, unicode):
-		return s.decode(encoding)
-	else:
-		return s
-
 fontdata = open (sys.argv[1], 'rb').read ()
-text = tounicode(sys.argv[2])
+text = sys.argv[2]
 # Need to create GLib.Bytes explicitly until this bug is fixed:
 # https://bugzilla.gnome.org/show_bug.cgi?id=729541
 blob = hb.glib_blob_create (GLib.Bytes.new (fontdata))
diff --git a/test/fuzzing/run-shape-fuzzer-tests.py b/test/fuzzing/run-shape-fuzzer-tests.py
index 94fc877..a44065f 100755
--- a/test/fuzzing/run-shape-fuzzer-tests.py
+++ b/test/fuzzing/run-shape-fuzzer-tests.py
@@ -1,6 +1,4 @@
-#!/usr/bin/env python
-
-from __future__ import print_function, division, absolute_import
+#!/usr/bin/env python3
 
 import sys, os, subprocess, tempfile, threading
 
diff --git a/test/fuzzing/run-subset-fuzzer-tests.py b/test/fuzzing/run-subset-fuzzer-tests.py
index 9e3bb84..071c644 100755
--- a/test/fuzzing/run-subset-fuzzer-tests.py
+++ b/test/fuzzing/run-subset-fuzzer-tests.py
@@ -1,6 +1,4 @@
-#!/usr/bin/env python
-
-from __future__ import print_function, division, absolute_import
+#!/usr/bin/env python3
 
 import sys, os, subprocess, tempfile, threading
 
diff --git a/test/shaping/data/text-rendering-tests/extract-tests.py b/test/shaping/data/text-rendering-tests/extract-tests.py
index f1722b5..7f26329 100755
--- a/test/shaping/data/text-rendering-tests/extract-tests.py
+++ b/test/shaping/data/text-rendering-tests/extract-tests.py
@@ -1,6 +1,4 @@
-#!/usr/bin/env python
-
-from __future__ import print_function, division, absolute_import
+#!/usr/bin/env python3
 
 import sys
 import xml.etree.ElementTree as ET
diff --git a/test/shaping/hb-diff b/test/shaping/hb-diff
index 3705de7..3a79737 100755
--- a/test/shaping/hb-diff
+++ b/test/shaping/hb-diff
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 
 from hb_test_tools import *
 import sys, os
diff --git a/test/shaping/hb-diff-colorize b/test/shaping/hb-diff-colorize
index 1fdae8a..7c481f5 100755
--- a/test/shaping/hb-diff-colorize
+++ b/test/shaping/hb-diff-colorize
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 
 from hb_test_tools import *
 
diff --git a/test/shaping/hb-diff-filter-failures b/test/shaping/hb-diff-filter-failures
index 34b76de..fc868d9 100755
--- a/test/shaping/hb-diff-filter-failures
+++ b/test/shaping/hb-diff-filter-failures
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 
 from hb_test_tools import *
 
diff --git a/test/shaping/hb-diff-stat b/test/shaping/hb-diff-stat
index 12ee8f0..f847116 100755
--- a/test/shaping/hb-diff-stat
+++ b/test/shaping/hb-diff-stat
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 
 from hb_test_tools import *
 
diff --git a/test/shaping/hb-unicode-decode b/test/shaping/hb-unicode-decode
index 9ac5ed6..1dc7052 100755
--- a/test/shaping/hb-unicode-decode
+++ b/test/shaping/hb-unicode-decode
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 
 from hb_test_tools import *
 
diff --git a/test/shaping/hb-unicode-encode b/test/shaping/hb-unicode-encode
index 5889807..99a99b3 100755
--- a/test/shaping/hb-unicode-encode
+++ b/test/shaping/hb-unicode-encode
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 
 from hb_test_tools import *
 
diff --git a/test/shaping/hb-unicode-prettyname b/test/shaping/hb-unicode-prettyname
index 1d004c0..41289b5 100755
--- a/test/shaping/hb-unicode-prettyname
+++ b/test/shaping/hb-unicode-prettyname
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 
 from hb_test_tools import *
 
diff --git a/test/shaping/hb_test_tools.py b/test/shaping/hb_test_tools.py
index feff70a..2a3cc91 100644
--- a/test/shaping/hb_test_tools.py
+++ b/test/shaping/hb_test_tools.py
@@ -1,6 +1,4 @@
-#!/usr/bin/env python
-
-from __future__ import print_function, division, absolute_import
+#!/usr/bin/env python3
 
 import sys, os, re, difflib, unicodedata, errno, cgi
 from itertools import *
@@ -15,78 +13,6 @@
 def codepoints(s):
 	return (ord (u) for u in s)
 
-try:
-	unichr = unichr
-
-	if sys.maxunicode < 0x10FFFF:
-		# workarounds for Python 2 "narrow" builds with UCS2-only support.
-
-		_narrow_unichr = unichr
-
-		def unichr(i):
-			"""
-			Return the unicode character whose Unicode code is the integer 'i'.
-			The valid range is 0 to 0x10FFFF inclusive.
-
-			>>> _narrow_unichr(0xFFFF + 1)
-			Traceback (most recent call last):
-			  File "<stdin>", line 1, in ?
-			ValueError: unichr() arg not in range(0x10000) (narrow Python build)
-			>>> unichr(0xFFFF + 1) == u'\U00010000'
-			True
-			>>> unichr(1114111) == u'\U0010FFFF'
-			True
-			>>> unichr(0x10FFFF + 1)
-			Traceback (most recent call last):
-			  File "<stdin>", line 1, in ?
-			ValueError: unichr() arg not in range(0x110000)
-			"""
-			try:
-				return _narrow_unichr(i)
-			except ValueError:
-				try:
-					padded_hex_str = hex(i)[2:].zfill(8)
-					escape_str = "\\U" + padded_hex_str
-					return escape_str.decode("unicode-escape")
-				except UnicodeDecodeError:
-					raise ValueError('unichr() arg not in range(0x110000)')
-
-		def codepoints(s):
-			high_surrogate = None
-			for u in s:
-				cp = ord (u)
-				if 0xDC00 <= cp <= 0xDFFF:
-					if high_surrogate:
-						yield 0x10000 + (high_surrogate - 0xD800) * 0x400 + (cp - 0xDC00)
-						high_surrogate = None
-					else:
-						yield 0xFFFD
-				else:
-					if high_surrogate:
-						yield 0xFFFD
-						high_surrogate = None
-					if 0xD800 <= cp <= 0xDBFF:
-						high_surrogate = cp
-					else:
-						yield cp
-						high_surrogate = None
-			if high_surrogate:
-				yield 0xFFFD
-
-except NameError:
-	unichr = chr
-
-try:
-	unicode = unicode
-except NameError:
-	unicode = str
-
-def tounicode(s, encoding='ascii', errors='strict'):
-	if not isinstance(s, unicode):
-		return s.decode(encoding, errors)
-	else:
-		return s
-
 class ColorFormatter:
 
 	class Null:
@@ -460,7 +386,7 @@
 
 	@staticmethod
 	def decode (s):
-		return u','.join ("U+%04X" % cp for cp in codepoints (tounicode (s, 'utf-8')))
+		return ','.join ("U+%04X" % cp for cp in codepoints (s))
 
 	@staticmethod
 	def parse (s):
@@ -470,9 +396,7 @@
 
 	@staticmethod
 	def encode (s):
-		s = u''.join (unichr (x) for x in Unicode.parse (s))
-		if sys.version_info[0] == 2: s = s.encode ('utf-8')
-		return s
+		return ''.join (chr (x) for x in Unicode.parse (s))
 
 	shorthands = {
 		"ZERO WIDTH NON-JOINER": "ZWNJ",
@@ -508,8 +432,8 @@
 	def pretty_names (s):
 		s = re.sub (r"[<+>\\uU]", " ", s)
 		s = re.sub (r"0[xX]", " ", s)
-		s = [unichr (int (x, 16)) for x in re.split ('[, \n]', s) if len (x)]
-		return u' + '.join (Unicode.pretty_name (x) for x in s).encode ('utf-8')
+		s = [chr (int (x, 16)) for x in re.split ('[, \n]', s) if len (x)]
+		return ' + '.join (Unicode.pretty_name (x) for x in s).encode ('utf-8')
 
 
 class FileHelpers:
diff --git a/test/shaping/record-test.sh b/test/shaping/record-test.sh
index 7f24354..62a4795 100755
--- a/test/shaping/record-test.sh
+++ b/test/shaping/record-test.sh
@@ -115,7 +115,7 @@
 exec 4<"$glyphs_file"
 relative_subset="$subset"
 if test "$out" != "/dev/stdout"; then
-	relative_subset="$(/usr/bin/python -c 'import os, sys; print (os.path.relpath (sys.argv[1], sys.argv[2]))' "$subset" "$(dirname "$out")")"
+	relative_subset="$(/usr/bin/env python3 -c 'import os, sys; print (os.path.relpath (sys.argv[1], sys.argv[2]))' "$subset" "$(dirname "$out")")"
 fi
 while read uline <&3 && read gline <&4; do
 	echo "$relative_subset:$options:$uline:$gline" >> "$out"
diff --git a/test/shaping/run-tests.py b/test/shaping/run-tests.py
index 26853e4..188badf 100755
--- a/test/shaping/run-tests.py
+++ b/test/shaping/run-tests.py
@@ -1,6 +1,4 @@
-#!/usr/bin/env python
-
-from __future__ import print_function, division, absolute_import
+#!/usr/bin/env python3
 
 import sys, os, subprocess, hashlib, tempfile, shutil
 
diff --git a/test/subset/generate-expected-outputs.py b/test/subset/generate-expected-outputs.py
index e2c75c5..286de8d 100755
--- a/test/subset/generate-expected-outputs.py
+++ b/test/subset/generate-expected-outputs.py
@@ -1,10 +1,8 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 
 # Pre-generates the expected output subset files (via fonttools) for
 # specified subset test suite(s).
 
-from __future__ import print_function, division, absolute_import
-
 import io
 import os
 import sys
diff --git a/test/subset/run-tests.py b/test/subset/run-tests.py
index 5a90c9b..7d18350 100755
--- a/test/subset/run-tests.py
+++ b/test/subset/run-tests.py
@@ -1,10 +1,8 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 
 # Runs a subsetting test suite. Compares the results of subsetting via harfbuzz
 # to subsetting via fonttools.
 
-from __future__ import print_function, division, absolute_import
-
 import io
 from difflib import unified_diff
 import os
diff --git a/test/subset/subset_test_suite.py b/test/subset/subset_test_suite.py
index 47664d0..a990fa0 100644
--- a/test/subset/subset_test_suite.py
+++ b/test/subset/subset_test_suite.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 
 import io
 import os