Remove most uses of module string
diff --git a/Lib/fontTools/afmLib.py b/Lib/fontTools/afmLib.py
index b5aa79b..3c0b4bc 100644
--- a/Lib/fontTools/afmLib.py
+++ b/Lib/fontTools/afmLib.py
@@ -5,7 +5,6 @@
 # File Format Specification). Still, it should read most "common" AFM files.
 
 import re
-import string
 
 __version__ = "$Id: afmLib.py,v 1.6 2003-05-24 12:50:47 jvr Exp $"
 
@@ -111,7 +110,7 @@
 	def read(self, path):
 		lines = readlines(path)
 		for line in lines:
-			if not string.strip(line):
+			if not line.strip():
 				continue
 			m = identifierRE.match(line)
 			if m is None:
@@ -119,7 +118,7 @@
 			
 			pos = m.regs[1][1]
 			word = line[:pos]
-			rest = string.strip(line[pos:])
+			rest = line[pos:].strip()
 			if word in self._keywords:
 				continue
 			if word == "C":
@@ -140,7 +139,7 @@
 			things.append(rest[fr:to])
 		charname = things[2]
 		del things[2]
-		charnum, width, l, b, r, t = [string.atoi(thing) for thing in things]
+		charnum, width, l, b, r, t = (int(thing) for thing in things)
 		self._chars[charname] = charnum, width, (l, b, r, t)
 	
 	def parsekernpair(self, rest):
@@ -151,18 +150,18 @@
 		for fr, to in m.regs[1:]:
 			things.append(rest[fr:to])
 		leftchar, rightchar, value = things
-		value = string.atoi(value)
+		value = int(value)
 		self._kerning[(leftchar, rightchar)] = value
 	
 	def parseattr(self, word, rest):
 		if word == "FontBBox":
-			l, b, r, t = [string.atoi(thing) for thing in string.split(rest)]
+			l, b, r, t = [int(thing) for thing in rest.split()]
 			self._attrs[word] = l, b, r, t
 		elif word == "Comment":
 			self._comments.append(rest)
 		else:
 			try:
-				value = string.atoi(rest)
+				value = int(rest)
 			except (ValueError, OverflowError):
 				self._attrs[word] = rest
 			else:
@@ -194,7 +193,7 @@
 		import time
 		lines = [	"StartFontMetrics 2.0",
 				"Comment Generated by afmLib, version %s; at %s" % 
-						(string.split(__version__)[2],
+						(__version__.split()[2],
 						time.strftime("%m/%d/%Y %H:%M:%S", 
 						time.localtime(time.time())))]
 		
@@ -351,7 +350,7 @@
 		sep = sep + '\r'	# mac or dos
 	if '\n' in data:
 		sep = sep + '\n'	# unix or dos
-	return string.split(data, sep)
+	return data.split(sep)
 
 def writelines(path, lines, sep='\r'):
 	f = open(path, 'wb')
diff --git a/Lib/fontTools/cffLib.py b/Lib/fontTools/cffLib.py
index d0c35f2..2bccee6 100644
--- a/Lib/fontTools/cffLib.py
+++ b/Lib/fontTools/cffLib.py
@@ -6,7 +6,6 @@
 
 import struct
 from fontTools.misc import sstruct
-import string
 from fontTools.misc import psCharStrings
 from fontTools.misc.textTools import safeEval
 
@@ -896,7 +895,7 @@
 	if isCID:
 		for i in range(numGlyphs - 1):
 			CID = readCard16(file)
-			charset.append("cid" + string.zfill(str(CID), 5) )
+			charset.append("cid" + str(CID).zfill(5))
 	else:
 		for i in range(numGlyphs - 1):
 			SID = readCard16(file)
@@ -915,7 +914,7 @@
 		nLeft = nLeftFunc(file)
 		if isCID:
 			for CID in range(first, first+nLeft+1):
-				charset.append("cid" + string.zfill(str(CID), 5) )
+				charset.append("cid" + str(CID).zfill(5))
 		else:
 			for SID in range(first, first+nLeft+1):
 				charset.append(strings[SID])
diff --git a/Lib/fontTools/fondLib.py b/Lib/fontTools/fondLib.py
index 6af0d34..d3b6c2f 100644
--- a/Lib/fontTools/fondLib.py
+++ b/Lib/fontTools/fondLib.py
@@ -1,7 +1,6 @@
 import os
 import struct
 from fontTools.misc import sstruct
-import string
 try:
 	from Carbon import Res
 except ImportError:
@@ -289,7 +288,7 @@
 			for firstchar, secondchar, kerndistance in table:
 				data.append(struct.pack(">cch", chr(firstchar), chr(secondchar), kerndistance))
 		
-		data = string.join(data, '')
+		data = ''.join(data)
 		
 		if DEBUG:
 			print("kerning table is the same?", self._rawkerningtables == data and 'yes.' or 'no.')
diff --git a/Lib/fontTools/misc/eexec.py b/Lib/fontTools/misc/eexec.py
index 84e3b31..25321f4 100644
--- a/Lib/fontTools/misc/eexec.py
+++ b/Lib/fontTools/misc/eexec.py
@@ -6,8 +6,6 @@
 # all four public functions get overridden by the *much* faster 
 # C extension module eexecOp, if available.
 
-import string
-
 error = "eexec.error"
 
 
@@ -31,7 +29,7 @@
 	for cipher in cipherstring:
 		plain, R = _decryptChar(cipher, R)
 		plainList.append(plain)
-	plainstring = string.join(plainList, '')
+	plainstring = ''.join(plainList)
 	return plainstring, int(R)
 
 def encrypt(plainstring, R):
@@ -39,7 +37,7 @@
 	for plain in plainstring:
 		cipher, R = _encryptChar(plain, R)
 		cipherList.append(cipher)
-	cipherstring = string.join(cipherList, '')
+	cipherstring = ''.join(cipherList)
 	return cipherstring, int(R)
 
 
diff --git a/Lib/fontTools/misc/psCharStrings.py b/Lib/fontTools/misc/psCharStrings.py
index 6894e92..d4d411b 100644
--- a/Lib/fontTools/misc/psCharStrings.py
+++ b/Lib/fontTools/misc/psCharStrings.py
@@ -3,7 +3,6 @@
 """
 
 import struct
-import string
 
 
 DEBUG = 0
@@ -374,10 +373,10 @@
 						bits = []
 						for byte in hintMask:
 							bits.append(num2binary(ord(byte), 8))
-						hintMask = string.join(bits, "")
-						line = string.join(args + [token, hintMask], " ")
+						hintMask = ''.join(bits)
+						line = ' '.join(args + [token, hintMask])
 					else:
-						line = string.join(args + [token], " ")
+						line = ' '.join(args + [token])
 					xmlWriter.write(line)
 					xmlWriter.newline()
 					args = []
diff --git a/Lib/fontTools/misc/textTools.py b/Lib/fontTools/misc/textTools.py
index 5ea20cd..5632ec5 100644
--- a/Lib/fontTools/misc/textTools.py
+++ b/Lib/fontTools/misc/textTools.py
@@ -15,13 +15,12 @@
 
 def deHexStr(hexdata):
 	"""Convert a hex string to binary data."""
-	parts = string.split(hexdata)
-	hexdata = string.join(parts, "")
+	hexdata = ''.join(hexdata.split())
 	if len(hexdata) % 2:
 		hexdata = hexdata + "0"
 	data = []
 	for i in range(0, len(hexdata), 2):
-		data.append(chr(string.atoi(hexdata[i:i+2], 16)))
+		data.append(chr(int(hexdata[i:i+2], 16)))
 	return "".join(data)
 
 
@@ -51,11 +50,11 @@
 		all.append(bin)
 	all.reverse()
 	assert l in (0, -1), "number doesn't fit in number of bits"
-	return string.join(all, " ")
+	return ' '.join(all)
 
 
 def binary2num(bin):
-	bin = string.join(string.split(bin), "")
+	bin = ''.join(bin.split())
 	l = 0
 	for digit in bin:
 		l = l << 1
diff --git a/Lib/fontTools/misc/xmlWriter.py b/Lib/fontTools/misc/xmlWriter.py
index 6a323c4..48372ea 100644
--- a/Lib/fontTools/misc/xmlWriter.py
+++ b/Lib/fontTools/misc/xmlWriter.py
@@ -58,7 +58,7 @@
 	
 	def comment(self, data):
 		data = escape(data)
-		lines = string.split(data, "\n")
+		lines = data.split("\n")
 		self.writeraw("<!-- " + lines[0])
 		for line in lines[1:]:
 			self.newline()
@@ -121,14 +121,14 @@
 	
 
 def escape(data):
-	data = string.replace(data, "&", "&amp;")
-	data = string.replace(data, "<", "&lt;")
+	data = data.replace("&", "&amp;")
+	data = data.replace("<", "&lt;")
 	return data
 
 def escapeattr(data):
-	data = string.replace(data, "&", "&amp;")
-	data = string.replace(data, "<", "&lt;")
-	data = string.replace(data, '"', "&quot;")
+	data = data.replace("&", "&amp;")
+	data = data.replace("<", "&lt;")
+	data = data.replace('"', "&quot;")
 	return data
 
 def escape8bit(data):
diff --git a/Lib/fontTools/nfntLib.py b/Lib/fontTools/nfntLib.py
index 2c340e5..3e5212e 100644
--- a/Lib/fontTools/nfntLib.py
+++ b/Lib/fontTools/nfntLib.py
@@ -1,6 +1,5 @@
 import struct
 from fontTools.misc import sstruct
-import string
 
 
 # FontRec header
@@ -71,8 +70,8 @@
 		for i in range(nEntries):
 			owTable[i] = chr(self.offsetTable[i]) + chr(self.widthTable[i])
 			locTable[i] = struct.pack("h", self.locTable[i])
-		owTable = string.join(owTable, "")
-		locTable = string.join(locTable, "")
+		owTable = ''.join(owTable)
+		locTable = ''.join(locTable)
 		assert len(locTable) == len(owTable) == 2 * (self.lastChar - self.firstChar + 3)
 		return header + self.bits + locTable + owTable
 	
@@ -158,7 +157,7 @@
 				for x in range(8):
 					byte = byte | ((bitImage[8 * xByte + x, y] & 0x01) << (7 - x))
 				bits.append(chr(byte))
-		bits = string.join(bits, "")
+		bits = ''.join(bits)
 		
 		# assign values
 		self.fontType = 0x9000
diff --git a/Lib/fontTools/t1Lib.py b/Lib/fontTools/t1Lib.py
index cea58c2..6255a8c 100644
--- a/Lib/fontTools/t1Lib.py
+++ b/Lib/fontTools/t1Lib.py
@@ -22,7 +22,6 @@
 
 from fontTools.misc import eexec
 from fontTools.misc.macCreatorType import getMacCreatorAndType
-import string
 import re
 import os
 
@@ -102,7 +101,7 @@
 
 def read(path, onlyHeader=0):
 	"""reads any Type 1 font file, returns raw data"""
-	normpath = string.lower(path)
+	normpath = path.lower()
 	creator, type = getMacCreatorAndType(path)
 	if type == 'LWFN':
 		return readLWFN(path, onlyHeader), 'LWFN'
@@ -113,7 +112,7 @@
 
 def write(path, data, kind='OTHER', dohex=0):
 	assertType1(data)
-	kind = string.upper(kind)
+	kind = kind.upper()
 	try:
 		os.remove(path)
 	except os.error:
@@ -169,7 +168,7 @@
 				raise T1Error('bad chunk code: ' + repr(code))
 	finally:
 		Res.CloseResFile(resRef)
-	data = string.join(data, '')
+	data = ''.join(data)
 	assertType1(data)
 	return data
 
@@ -193,7 +192,7 @@
 		if onlyHeader:
 			break
 	f.close()
-	data = string.join(data, '')
+	data = ''.join(data)
 	assertType1(data)
 	return data
 
@@ -211,7 +210,7 @@
 			data.append(deHexString(chunk))
 		else:
 			data.append(chunk)
-	return string.join(data, '')
+	return ''.join(data)
 
 # file writing tools
 
@@ -307,23 +306,23 @@
 				data.append(chunk[:-len(EEXECBEGIN)-1])
 			else:
 				data.append(chunk)
-	return string.join(data, '')
+	return ''.join(data)
 
 def findEncryptedChunks(data):
 	chunks = []
 	while True:
-		eBegin = string.find(data, EEXECBEGIN)
+		eBegin = data.find(EEXECBEGIN)
 		if eBegin < 0:
 			break
 		eBegin = eBegin + len(EEXECBEGIN) + 1
-		eEnd = string.find(data, EEXECEND, eBegin)
+		eEnd = data.find(EEXECEND, eBegin)
 		if eEnd < 0:
 			raise T1Error("can't find end of eexec part")
 		cypherText = data[eBegin:eEnd + 2]
 		if isHex(cypherText[:4]):
 			cypherText = deHexString(cypherText)
 		plainText, R = eexec.decrypt(cypherText, 55665)
-		eEndLocal = string.find(plainText, EEXECINTERNALEND)
+		eEndLocal = plainText.find(EEXECINTERNALEND)
 		if eEndLocal < 0:
 			raise T1Error("can't find end of eexec part")
 		chunks.append((0, data[:eBegin]))
@@ -333,7 +332,7 @@
 	return chunks
 
 def deHexString(hexstring):
-	return eexec.deHexString(string.join(string.split(hexstring), ""))
+	return eexec.deHexString(''.join(hexstring.split()))
 
 
 # Type 1 assertion
@@ -348,7 +347,7 @@
 		raise T1Error("not a PostScript font")
 	if not _fontType1RE.search(data):
 		raise T1Error("not a Type 1 font")
-	if string.find(data, "currentfile eexec") < 0:
+	if data.find("currentfile eexec") < 0:
 		raise T1Error("not an encrypted Type 1 font")
 	# XXX what else?
 	return data
diff --git a/Lib/fontTools/ttLib/__init__.py b/Lib/fontTools/ttLib/__init__.py
index feee006..2e208b4 100644
--- a/Lib/fontTools/ttLib/__init__.py
+++ b/Lib/fontTools/ttLib/__init__.py
@@ -47,7 +47,6 @@
 
 import sys
 import os
-import string
 
 haveMacSupport = 0
 if sys.platform == "mac":
@@ -500,8 +499,7 @@
 						glyphName = agl.UV2AGL[unicode]
 					else:
 						# create uni<CODE> name
-						glyphName = "uni" + string.upper(string.zfill(
-								hex(unicode)[2:], 4))
+						glyphName = "uni%04X" % unicode
 					tempName = glyphName
 					n = 1
 					while tempName in allNames:
@@ -881,7 +879,7 @@
 	elif tag == "GlyphOrder":
 		return tag
 	if re.match("[A-Za-z_][A-Za-z_0-9]* *$", tag):
-		return string.strip(tag)
+		return tag.strip()
 	else:
 		return tagToIdentifier(tag)
 
diff --git a/Lib/fontTools/ttLib/tables/C_B_D_T_.py b/Lib/fontTools/ttLib/tables/C_B_D_T_.py
index cb01021..2b72011 100644
--- a/Lib/fontTools/ttLib/tables/C_B_D_T_.py
+++ b/Lib/fontTools/ttLib/tables/C_B_D_T_.py
@@ -4,7 +4,6 @@
 
 
 from . import E_B_D_T_
-import string
 import struct
 from fontTools.misc import sstruct
 from .BitmapGlyphMetrics import BigGlyphMetrics, bigGlyphMetricsFormat, SmallGlyphMetrics, smallGlyphMetricsFormat
@@ -51,7 +50,7 @@
 		dataList.append(sstruct.pack(smallGlyphMetricsFormat, self.metrics))
 		dataList.append(struct.pack(">L", len(self.imageData)))
 		dataList.append(self.imageData)
-		return string.join(dataList, "")
+		return ''.join(dataList)
 
 class cbdt_bitmap_format_18(BitmapPlusBigMetricsMixin, ColorBitmapGlyph):
 
@@ -70,7 +69,7 @@
 		dataList.append(sstruct.pack(bigGlyphMetricsFormat, self.metrics))
 		dataList.append(struct.pack(">L", len(self.imageData)))
 		dataList.append(self.imageData)
-		return string.join(dataList, "")
+		return ''.join(dataList)
 
 class cbdt_bitmap_format_19(ColorBitmapGlyph):
 
diff --git a/Lib/fontTools/ttLib/tables/DefaultTable.py b/Lib/fontTools/ttLib/tables/DefaultTable.py
index 704546e..5202f6a 100644
--- a/Lib/fontTools/ttLib/tables/DefaultTable.py
+++ b/Lib/fontTools/ttLib/tables/DefaultTable.py
@@ -1,4 +1,3 @@
-import string
 import sys
 
 class DefaultTable:
diff --git a/Lib/fontTools/ttLib/tables/E_B_D_T_.py b/Lib/fontTools/ttLib/tables/E_B_D_T_.py
index 7a1dbb6..3e1e45c 100644
--- a/Lib/fontTools/ttLib/tables/E_B_D_T_.py
+++ b/Lib/fontTools/ttLib/tables/E_B_D_T_.py
@@ -1,7 +1,6 @@
 
 from . import DefaultTable
 import os
-import string
 import struct
 from fontTools.misc import sstruct
 import itertools
@@ -113,7 +112,7 @@
 				# of any of the problems in the convertion that may arise.
 				curIndexSubTable.locations = dataLocations
 
-		return string.join(dataList, "")
+		return ''.join(dataList)
 
 	def toXML(self, writer, ttFont):
 		# When exporting to XML if one of the data export formats
@@ -212,7 +211,7 @@
 				binaryList.append('0')
 			value = value >> 1
 		numBits -= numBitsCut
-	return string.join(binaryList, "")
+	return ''.join(binaryList)
 
 def _binary2data(binary):
 	byteList = []
@@ -224,7 +223,7 @@
 			if curBit == '1':
 				curByte |= 1
 		byteList.append(chr(curByte))
-	return string.join(byteList, "")
+	return ''.join(byteList)
 
 def _memoize(f):
 	class memodict(dict):
@@ -332,7 +331,7 @@
 		name, attr, content = element
 		if name == 'row':
 			mapParams = zip(attr['value'], itertools.repeat('1'))
-			rowData = string.join(itertools.starmap(binaryConv.get, mapParams), "")
+			rowData = ''.join(itertools.starmap(binaryConv.get, mapParams))
 			dataRows.append(_binary2data(rowData))
 
 	bitmapObject.setRows(dataRows, bitDepth=bitDepth, metrics=metrics, reverseBytes=True)
@@ -532,7 +531,7 @@
 			dataList.append(chr(newByte))
 
 		# The way the data is kept is opposite the algorithm used.
-		data = string.join(dataList, "")
+		data = ''.join(dataList)
 		if not reverseBytes:
 			data = _reverseBytes(data)
 		return data
@@ -711,7 +710,7 @@
 		for curComponent in self.componentArray:
 			curComponent.glyphCode = ttFont.getGlyphID(curComponent.name)
 			dataList.append(sstruct.pack(ebdtComponentFormat, curComponent))
-		return string.join(dataList, "")
+		return ''.join(dataList)
 
 
 class ebdt_bitmap_format_9(BitmapPlusBigMetricsMixin, ComponentBitmapGlyph):
@@ -735,7 +734,7 @@
 		for curComponent in self.componentArray:
 			curComponent.glyphCode = ttFont.getGlyphID(curComponent.name)
 			dataList.append(sstruct.pack(ebdtComponentFormat, curComponent))
-		return string.join(dataList, "")
+		return ''.join(dataList)
 
 
 # Dictionary of bitmap formats to the class representing that format
diff --git a/Lib/fontTools/ttLib/tables/E_B_L_C_.py b/Lib/fontTools/ttLib/tables/E_B_L_C_.py
index 8bff48a..b5a3e6f 100644
--- a/Lib/fontTools/ttLib/tables/E_B_L_C_.py
+++ b/Lib/fontTools/ttLib/tables/E_B_L_C_.py
@@ -1,6 +1,5 @@
 
 from . import DefaultTable
-import string
 import struct
 from fontTools.misc import sstruct
 import itertools
@@ -197,7 +196,7 @@
 			dataList.append(data)
 		dataList.extend(indexSubTablePairDataList)
 
-		return string.join(dataList, "")
+		return ''.join(dataList)
 
 	def toXML(self, writer, ttFont):
 		writer.simpletag('header', [('version', self.version)])
@@ -477,7 +476,7 @@
 			# Take care of any padding issues. Only occurs in format 3.
 			if offsetDataSize * len(dataList) % 4 != 0:
 				dataList.append(struct.pack(dataFormat, 0))
-			return string.join(dataList, "")
+			return ''.join(dataList)
 
 	return OffsetArrayIndexSubTableMixin
 
@@ -534,7 +533,7 @@
 		dataList = [EblcIndexSubTable.compile(self, ttFont)]
 		dataList.append(struct.pack(">L", self.imageSize))
 		dataList.append(sstruct.pack(bigGlyphMetricsFormat, self.metrics))
-		return string.join(dataList, "")
+		return ''.join(dataList)
 
 class eblc_index_sub_table_3(_createOffsetArrayIndexSubTableMixin('H'), EblcIndexSubTable):
 	pass
@@ -576,7 +575,7 @@
 		dataList.append(struct.pack(">L", len(glyphIds)))
 		tmp = [struct.pack(codeOffsetPairFormat, *cop) for cop in zip(idsPlusPad, offsets)]
 		dataList += tmp
-		data = string.join(dataList, "")
+		data = ''.join(dataList)
 		return data
 
 class eblc_index_sub_table_5(FixedSizeIndexSubTableMixin, EblcIndexSubTable):
@@ -604,7 +603,7 @@
 		dataList += [struct.pack(">H", curId) for curId in glyphIds]
 		if len(glyphIds) % 2 == 1:
 			dataList.append(struct.pack(">H", 0))
-		return string.join(dataList, "")
+		return ''.join(dataList)
 
 # Dictionary of indexFormat to the class representing that format.
 eblc_sub_table_classes = {
diff --git a/Lib/fontTools/ttLib/tables/M_E_T_A_.py b/Lib/fontTools/ttLib/tables/M_E_T_A_.py
index 9137a76..9289350 100644
--- a/Lib/fontTools/ttLib/tables/M_E_T_A_.py
+++ b/Lib/fontTools/ttLib/tables/M_E_T_A_.py
@@ -2,7 +2,6 @@
 import struct
 from fontTools.misc import sstruct
 from fontTools.misc.textTools import safeEval
-import string
 import sys
 
 
diff --git a/Lib/fontTools/ttLib/tables/S_I_N_G_.py b/Lib/fontTools/ttLib/tables/S_I_N_G_.py
index 68ca8b8..0813700 100644
--- a/Lib/fontTools/ttLib/tables/S_I_N_G_.py
+++ b/Lib/fontTools/ttLib/tables/S_I_N_G_.py
@@ -2,7 +2,6 @@
 from fontTools.misc import sstruct
 import struct
 import time
-import string
 from fontTools.misc.textTools import safeEval, num2binary, binary2num
 
 SINGFormat = """
diff --git a/Lib/fontTools/ttLib/tables/S_V_G_.py b/Lib/fontTools/ttLib/tables/S_V_G_.py
index f92d4e7..d33dcf3 100644
--- a/Lib/fontTools/ttLib/tables/S_V_G_.py
+++ b/Lib/fontTools/ttLib/tables/S_V_G_.py
@@ -50,7 +50,6 @@
     import xml.etree.cElementTree as ET
 except ImportError:
     import xml.etree.ElementTree as ET
-import string
 import re
 
 XML = ET.XML
diff --git a/Lib/fontTools/ttLib/tables/T_S_I__1.py b/Lib/fontTools/ttLib/tables/T_S_I__1.py
index d2a9465..7f23593 100644
--- a/Lib/fontTools/ttLib/tables/T_S_I__1.py
+++ b/Lib/fontTools/ttLib/tables/T_S_I__1.py
@@ -1,5 +1,4 @@
 from . import DefaultTable
-import string
 
 class table_T_S_I__1(DefaultTable.DefaultTable):
 	
@@ -85,7 +84,7 @@
 				continue
 			writer.begintag("glyphProgram", name=name)
 			writer.newline()
-			writer.write_noindent(string.replace(text, "\r", "\n"))
+			writer.write_noindent(text.replace("\r", "\n"))
 			writer.newline()
 			writer.endtag("glyphProgram")
 			writer.newline()
@@ -98,7 +97,7 @@
 				continue
 			writer.begintag("extraProgram", name=name)
 			writer.newline()
-			writer.write_noindent(string.replace(text, "\r", "\n"))
+			writer.write_noindent(text.replace("\r", "\n"))
 			writer.newline()
 			writer.endtag("extraProgram")
 			writer.newline()
@@ -108,8 +107,8 @@
 		if not hasattr(self, "glyphPrograms"):
 			self.glyphPrograms = {}
 			self.extraPrograms = {}
-		lines = string.split(string.replace(string.join(content, ""), "\r", "\n"), "\n")
-		text = string.join(lines[1:-1], "\r")
+		lines = ''.join(content).replace("\r", "\n").split("\n")
+		text = '\r'.join(lines[1:-1])
 		if name == "glyphProgram":
 			self.glyphPrograms[attrs["name"]] = text
 		elif name == "extraProgram":
diff --git a/Lib/fontTools/ttLib/tables/_g_l_y_f.py b/Lib/fontTools/ttLib/tables/_g_l_y_f.py
index 1f3ee8f..82b14c6 100644
--- a/Lib/fontTools/ttLib/tables/_g_l_y_f.py
+++ b/Lib/fontTools/ttLib/tables/_g_l_y_f.py
@@ -57,7 +57,6 @@
 	def compile(self, ttFont):
 		if not hasattr(self, "glyphOrder"):
 			self.glyphOrder = ttFont.getGlyphOrder()
-		import string
 		locations = []
 		currentLocation = 0
 		dataList = []
@@ -69,7 +68,7 @@
 			currentLocation = currentLocation + len(glyphData)
 			dataList.append(glyphData)
 		locations.append(currentLocation)
-		data = string.join(dataList, "")
+		data = ''.join(dataList)
 		if 'loca' in ttFont:
 			ttFont['loca'].set(locations)
 		ttFont['maxp'].numGlyphs = len(self.glyphs)
diff --git a/Lib/fontTools/ttLib/tables/_h_d_m_x.py b/Lib/fontTools/ttLib/tables/_h_d_m_x.py
index 63d579a..74a67e5 100644
--- a/Lib/fontTools/ttLib/tables/_h_d_m_x.py
+++ b/Lib/fontTools/ttLib/tables/_h_d_m_x.py
@@ -1,6 +1,5 @@
 from . import DefaultTable
 from fontTools.misc import sstruct
-import string
 
 hdmxHeaderFormat = """
 	>   # big endian!
@@ -75,15 +74,15 @@
 	def fromXML(self, name, attrs, content, ttFont):
 		if name != "hdmxData":
 			return
-		content = string.join(content, "")
-		lines = string.split(content, ";")
-		topRow = string.split(lines[0])
+		content = ''.join(content)
+		lines = content.split(";")
+		topRow = lines[0].split()
 		assert topRow[0] == "ppem:", "illegal hdmx format"
 		ppems = list(map(int, topRow[1:]))
 		self.hdmx = hdmx = {}
 		for ppem in ppems:
 			hdmx[ppem] = {}
-		lines = map(string.split, lines[1:])
+		lines = (line.split() for line in lines[1:])
 		for line in lines:
 			if not line:
 				continue
diff --git a/Lib/fontTools/ttLib/tables/_h_e_a_d.py b/Lib/fontTools/ttLib/tables/_h_e_a_d.py
index 7a9f218..a819874 100644
--- a/Lib/fontTools/ttLib/tables/_h_e_a_d.py
+++ b/Lib/fontTools/ttLib/tables/_h_e_a_d.py
@@ -1,7 +1,6 @@
 from . import DefaultTable
 from fontTools.misc import sstruct
 import time
-import string
 from fontTools.misc.textTools import safeEval, num2binary, binary2num
 
 
@@ -119,13 +118,13 @@
 _weekdays = ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun']
 
 def parse_date(datestring):
-	datestring = string.lower(datestring)
-	weekday, month, day, tim, year = string.split(datestring)
+	datestring = datestring.lower()
+	weekday, month, day, tim, year = datestring.split()
 	weekday = _weekdays.index(weekday)
 	month = _months.index(month)
 	year = int(year)
 	day = int(day)
-	hour, minute, second = [int(item) for item in string.split(tim, ":")]
+	hour, minute, second = [int(item) for item in tim.split(":")]
 	t = (year, month, day, hour, minute, second, weekday, 0, 0)
 	return int(time.mktime(t) - time.timezone)
 
diff --git a/Lib/fontTools/ttLib/tables/_n_a_m_e.py b/Lib/fontTools/ttLib/tables/_n_a_m_e.py
index 4a09413..6bbb43a 100644
--- a/Lib/fontTools/ttLib/tables/_n_a_m_e.py
+++ b/Lib/fontTools/ttLib/tables/_n_a_m_e.py
@@ -2,7 +2,6 @@
 import struct
 from fontTools.misc import sstruct
 from fontTools.misc.textTools import safeEval
-import string
 
 nameRecordFormat = """
 		>	# big endian
@@ -129,7 +128,7 @@
 			s = s.strip()
 			self.string = s.encode("utf_16_be")
 		else:
-			s = string.strip(string.join(content, ""))
+			s = ''.join(content).strip()
 			self.string = unicode(s, "utf8").encode("latin1")
 	
 	def __cmp__(self, other):
diff --git a/Lib/fontTools/ttLib/tables/asciiTable.py b/Lib/fontTools/ttLib/tables/asciiTable.py
index e3a38e1..c65a3b3 100644
--- a/Lib/fontTools/ttLib/tables/asciiTable.py
+++ b/Lib/fontTools/ttLib/tables/asciiTable.py
@@ -1,4 +1,3 @@
-import string
 from . import DefaultTable
 
 
@@ -7,16 +6,16 @@
 	def toXML(self, writer, ttFont):
 		data = self.data
 		# removing null bytes. XXX needed??
-		data = string.split(data, '\0')
-		data = string.join(data, '')
+		data = data.split('\0')
+		data = ''.join(data)
 		writer.begintag("source")
 		writer.newline()
-		writer.write_noindent(string.replace(data, "\r", "\n"))
+		writer.write_noindent(data.replace("\r", "\n"))
 		writer.newline()
 		writer.endtag("source")
 		writer.newline()
 	
 	def fromXML(self, name, attrs, content, ttFont):
-		lines = string.split(string.replace(string.join(content, ""), "\r", "\n"), "\n")
-		self.data = string.join(lines[1:-1], "\r")
+		lines = ''.join(content).replace("\r", "\n").split("\n")
+		self.data = "\r".join(lines[1:-1])
 
diff --git a/Lib/fontTools/ttLib/tables/ttProgram.py b/Lib/fontTools/ttLib/tables/ttProgram.py
index 5996b5c..51c7794 100644
--- a/Lib/fontTools/ttLib/tables/ttProgram.py
+++ b/Lib/fontTools/ttLib/tables/ttProgram.py
@@ -1,7 +1,7 @@
 """ttLib.tables.ttProgram.py -- Assembler/disassembler for TrueType bytecode programs."""
 
 import array
-import re, string
+import re
 from fontTools.misc.textTools import num2binary, binary2num, readHex
 
 # first, the list of instructions that eat bytes or words from the instruction stream
@@ -242,11 +242,11 @@
 					j = 0
 					for j in range(nValues):
 						if j and not (j % 25):
-							writer.write(string.join(line, " "))
+							writer.write(' '.join(line))
 							writer.newline()
 							line = []
 						line.append(assembly[i+j])
-					writer.write(string.join(line, " "))
+					writer.write(' '.join(line))
 					writer.newline()
 					i = i + j + 1
 			writer.endtag("assembly")
@@ -258,7 +258,7 @@
 	
 	def fromXML(self, name, attrs, content, ttFont):
 		if name == "assembly":
-			self.fromAssembly(string.join(content, ""))
+			self.fromAssembly(''.join(content))
 			self._assemble()
 			del self.assembly
 		else:
@@ -266,11 +266,11 @@
 			self.fromBytecode(readHex(content))
 	
 	def _assemble(self, 
-			skipWhite=_skipWhite, mnemonicDict=mnemonicDict, strip=string.strip,
+			skipWhite=_skipWhite, mnemonicDict=mnemonicDict,
 			binary2num=binary2num):
 		assembly = self.assembly
 		if isinstance(assembly, type([])):
-			assembly = string.join(assembly, " ")
+			assembly = ' '.join(assembly)
 		bytecode = []
 		push = bytecode.append
 		lenAssembly = len(assembly)
@@ -284,7 +284,7 @@
 			if comment:
 				continue
 			
-			arg = strip(arg)
+			arg = arg.strip()
 			if mnemonic.startswith("INSTR"):
 				# Unknown instruction
 				op = int(mnemonic[5:])
diff --git a/Lib/fontTools/ttx.py b/Lib/fontTools/ttx.py
index ee49238..2c090d5 100644
--- a/Lib/fontTools/ttx.py
+++ b/Lib/fontTools/ttx.py
@@ -170,7 +170,6 @@
 
 
 def ttList(input, output, options):
-	import string
 	ttf = TTFont(input, fontNumber=options.fontNumber, lazy=True)
 	reader = ttf.reader
 	tags = sorted(reader.keys())
@@ -183,7 +182,7 @@
 		checkSum = int(entry.checkSum)
 		if checkSum < 0:
 			checkSum = checkSum + 0x100000000
-		checksum = "0x" + string.zfill(hex(checkSum)[2:-1], 8)
+		checksum = "0x%08X" % checkSum
 		print(format % (tag, checksum, entry.length, entry.offset))
 	print()
 	ttf.close()