SF patch# 1761465 by Jeffrey Yasskin.
Fix test_aepack and test_applesingle.
diff --git a/Lib/plat-mac/Carbon/AppleEvents.py b/Lib/plat-mac/Carbon/AppleEvents.py
index e23c079..33ee3b3 100644
--- a/Lib/plat-mac/Carbon/AppleEvents.py
+++ b/Lib/plat-mac/Carbon/AppleEvents.py
@@ -1,6 +1,6 @@
 # Generated from 'AEDataModel.h'
 
-def FOUR_CHAR_CODE(x): return x
+def FOUR_CHAR_CODE(x): return bytes(x)
 typeBoolean = FOUR_CHAR_CODE('bool')
 typeChar = FOUR_CHAR_CODE('TEXT')
 typeSInt16 = FOUR_CHAR_CODE('shor')
diff --git a/Lib/plat-mac/aepack.py b/Lib/plat-mac/aepack.py
index d7cbbce..aa0f2cd 100644
--- a/Lib/plat-mac/aepack.py
+++ b/Lib/plat-mac/aepack.py
@@ -25,30 +25,36 @@
 # These ones seem to be missing from AppleEvents
 # (they're in AERegistry.h)
 
-#typeColorTable = 'clrt'
-#typeDrawingArea = 'cdrw'
-#typePixelMap = 'cpix'
-#typePixelMapMinus = 'tpmm'
-#typeRotation = 'trot'
-#typeTextStyles = 'tsty'
-#typeStyledText = 'STXT'
-#typeAEText = 'tTXT'
-#typeEnumeration = 'enum'
+#typeColorTable = b'clrt'
+#typeDrawingArea = b'cdrw'
+#typePixelMap = b'cpix'
+#typePixelMapMinus = b'tpmm'
+#typeRotation = b'trot'
+#typeTextStyles = b'tsty'
+#typeStyledText = b'STXT'
+#typeAEText = b'tTXT'
+#typeEnumeration = b'enum'
 
+def b2i(byte_string):
+    result = 0
+    for byte in byte_string:
+        result <<= 8
+        result += byte
+    return result
 #
 # Some AE types are immedeately coerced into something
 # we like better (and which is equivalent)
 #
 unpacker_coercions = {
-    typeComp : typeFloat,
-    typeColorTable : typeAEList,
-    typeDrawingArea : typeAERecord,
-    typeFixed : typeFloat,
-    typeExtended : typeFloat,
-    typePixelMap : typeAERecord,
-    typeRotation : typeAERecord,
-    typeStyledText : typeAERecord,
-    typeTextStyles : typeAERecord,
+    b2i(typeComp) : typeFloat,
+    b2i(typeColorTable) : typeAEList,
+    b2i(typeDrawingArea) : typeAERecord,
+    b2i(typeFixed) : typeFloat,
+    b2i(typeExtended) : typeFloat,
+    b2i(typePixelMap) : typeAERecord,
+    b2i(typeRotation) : typeAERecord,
+    b2i(typeStyledText) : typeAERecord,
+    b2i(typeTextStyles) : typeAERecord,
 };
 
 #
@@ -72,33 +78,35 @@
     """Pack a python object into an AE descriptor"""
 
     if forcetype:
-        if isinstance(x, str):
+        if isinstance(x, bytes):
             return AE.AECreateDesc(forcetype, x)
         else:
             return pack(x).AECoerceDesc(forcetype)
 
     if x == None:
-        return AE.AECreateDesc('null', '')
+        return AE.AECreateDesc(b'null', '')
 
     if isinstance(x, AEDescType):
         return x
     if isinstance(x, FSSType):
-        return AE.AECreateDesc('fss ', x.data)
+        return AE.AECreateDesc(b'fss ', x.data)
     if isinstance(x, FSRefType):
-        return AE.AECreateDesc('fsrf', x.data)
+        return AE.AECreateDesc(b'fsrf', x.data)
     if isinstance(x, AliasType):
-        return AE.AECreateDesc('alis', x.data)
+        return AE.AECreateDesc(b'alis', x.data)
     if isinstance(x, int):
-        return AE.AECreateDesc('long', struct.pack('l', x))
+        return AE.AECreateDesc(b'long', struct.pack('l', x))
     if isinstance(x, float):
-        return AE.AECreateDesc('doub', struct.pack('d', x))
+        return AE.AECreateDesc(b'doub', struct.pack('d', x))
+    if isinstance(x, (bytes, str8)):
+        return AE.AECreateDesc(b'TEXT', x)
     if isinstance(x, str):
-        return AE.AECreateDesc('TEXT', x)
-    if isinstance(x, unicode):
+        # See http://developer.apple.com/documentation/Carbon/Reference/Apple_Event_Manager/Reference/reference.html#//apple_ref/doc/constant_group/typeUnicodeText
+        # for the possible encodings.
         data = x.encode('utf16')
         if data[:2] == '\xfe\xff':
             data = data[2:]
-        return AE.AECreateDesc('utxt', data)
+        return AE.AECreateDesc(b'utxt', data)
     if isinstance(x, list):
         lst = AE.AECreateList('', 0)
         for item in x:
@@ -112,37 +120,37 @@
         return record
     if isinstance(x, type) and issubclass(x, ObjectSpecifier):
         # Note: we are getting a class object here, not an instance
-        return AE.AECreateDesc('type', x.want)
+        return AE.AECreateDesc(b'type', x.want)
     if hasattr(x, '__aepack__'):
         return x.__aepack__()
     if hasattr(x, 'which'):
-        return AE.AECreateDesc('TEXT', x.which)
+        return AE.AECreateDesc(b'TEXT', x.which)
     if hasattr(x, 'want'):
-        return AE.AECreateDesc('TEXT', x.want)
-    return AE.AECreateDesc('TEXT', repr(x)) # Copout
+        return AE.AECreateDesc(b'TEXT', x.want)
+    return AE.AECreateDesc(b'TEXT', repr(x)) # Copout
 
 def unpack(desc, formodulename=""):
     """Unpack an AE descriptor to a python object"""
     t = desc.type
 
-    if t in unpacker_coercions:
-        desc = desc.AECoerceDesc(unpacker_coercions[t])
+    if b2i(t) in unpacker_coercions:
+        desc = desc.AECoerceDesc(unpacker_coercions[b2i(t)])
         t = desc.type # This is a guess by Jack....
 
     if t == typeAEList:
         l = []
         for i in range(desc.AECountItems()):
-            keyword, item = desc.AEGetNthDesc(i+1, '****')
+            keyword, item = desc.AEGetNthDesc(i+1, b'****')
             l.append(unpack(item, formodulename))
         return l
     if t == typeAERecord:
         d = {}
         for i in range(desc.AECountItems()):
-            keyword, item = desc.AEGetNthDesc(i+1, '****')
-            d[keyword] = unpack(item, formodulename)
+            keyword, item = desc.AEGetNthDesc(i+1, b'****')
+            d[b2i(keyword)] = unpack(item, formodulename)
         return d
     if t == typeAEText:
-        record = desc.AECoerceDesc('reco')
+        record = desc.AECoerceDesc(b'reco')
         return mkaetext(unpack(record, formodulename))
     if t == typeAlias:
         return Carbon.File.Alias(rawdata=desc.data)
@@ -170,7 +178,7 @@
     if t == typeFSRef:
         return Carbon.File.FSRef(rawdata=desc.data)
     if t == typeInsertionLoc:
-        record = desc.AECoerceDesc('reco')
+        record = desc.AECoerceDesc(b'reco')
         return mkinsertionloc(unpack(record, formodulename))
     # typeInteger equal to typeLongInteger
     if t == typeIntlText:
@@ -194,7 +202,7 @@
             v = 0x100000000 + v
         return v
     if t == typeObjectSpecifier:
-        record = desc.AECoerceDesc('reco')
+        record = desc.AECoerceDesc(b'reco')
         # If we have been told the name of the module we are unpacking aedescs for,
         # we can attempt to create the right type of python object from that module.
         if formodulename:
@@ -234,14 +242,14 @@
     #
     # The following are special
     #
-    if t == 'rang':
-        record = desc.AECoerceDesc('reco')
+    if t == b'rang':
+        record = desc.AECoerceDesc(b'reco')
         return mkrange(unpack(record, formodulename))
-    if t == 'cmpd':
-        record = desc.AECoerceDesc('reco')
+    if t == b'cmpd':
+        record = desc.AECoerceDesc(b'reco')
         return mkcomparison(unpack(record, formodulename))
-    if t == 'logi':
-        record = desc.AECoerceDesc('reco')
+    if t == b'logi':
+        record = desc.AECoerceDesc(b'reco')
         return mklogical(unpack(record, formodulename))
     return mkunknown(desc.type, desc.data)
 
@@ -297,39 +305,44 @@
     return aetypes.Keyword(keyword)
 
 def mkrange(dict):
-    return aetypes.Range(dict['star'], dict['stop'])
+    return aetypes.Range(dict[b2i(b'star')], dict[b2i(b'stop')])
 
 def mkcomparison(dict):
-    return aetypes.Comparison(dict['obj1'], dict['relo'].enum, dict['obj2'])
+    return aetypes.Comparison(dict[b2i(b'obj1')],
+                              dict[b2i(b'relo')].enum,
+                              dict[b2i(b'obj2')])
 
 def mklogical(dict):
-    return aetypes.Logical(dict['logc'], dict['term'])
+    return aetypes.Logical(dict[b2i(b'logc')], dict[b2i(b'term')])
 
 def mkstyledtext(dict):
-    return aetypes.StyledText(dict['ksty'], dict['ktxt'])
+    return aetypes.StyledText(dict[b2i(b'ksty')], dict[b2i(b'ktxt')])
 
 def mkaetext(dict):
-    return aetypes.AEText(dict[keyAEScriptTag], dict[keyAEStyles], dict[keyAEText])
+    return aetypes.AEText(dict[b2i(keyAEScriptTag)],
+                          dict[b2i(keyAEStyles)],
+                          dict[b2i(keyAEText)])
 
 def mkinsertionloc(dict):
-    return aetypes.InsertionLoc(dict[keyAEObject], dict[keyAEPosition])
+    return aetypes.InsertionLoc(dict[b2i(keyAEObject)],
+                                dict[b2i(keyAEPosition)])
 
 def mkobject(dict):
-    want = dict['want'].type
-    form = dict['form'].enum
-    seld = dict['seld']
-    fr   = dict['from']
-    if form in ('name', 'indx', 'rang', 'test'):
-        if want == 'text': return aetypes.Text(seld, fr)
-        if want == 'cha ': return aetypes.Character(seld, fr)
-        if want == 'cwor': return aetypes.Word(seld, fr)
-        if want == 'clin': return aetypes.Line(seld, fr)
-        if want == 'cpar': return aetypes.Paragraph(seld, fr)
-        if want == 'cwin': return aetypes.Window(seld, fr)
-        if want == 'docu': return aetypes.Document(seld, fr)
-        if want == 'file': return aetypes.File(seld, fr)
-        if want == 'cins': return aetypes.InsertionPoint(seld, fr)
-    if want == 'prop' and form == 'prop' and aetypes.IsType(seld):
+    want = dict[b2i(b'want')].type
+    form = dict[b2i(b'form')].enum
+    seld = dict[b2i(b'seld')]
+    fr   = dict[b2i(b'from')]
+    if form in (b'name', b'indx', b'rang', b'test'):
+        if want == b'text': return aetypes.Text(seld, fr)
+        if want == b'cha ': return aetypes.Character(seld, fr)
+        if want == b'cwor': return aetypes.Word(seld, fr)
+        if want == b'clin': return aetypes.Line(seld, fr)
+        if want == b'cpar': return aetypes.Paragraph(seld, fr)
+        if want == b'cwin': return aetypes.Window(seld, fr)
+        if want == b'docu': return aetypes.Document(seld, fr)
+        if want == b'file': return aetypes.File(seld, fr)
+        if want == b'cins': return aetypes.InsertionPoint(seld, fr)
+    if want == b'prop' and form == b'prop' and aetypes.IsType(seld):
         return aetypes.Property(seld.type, fr)
     return aetypes.ObjectSpecifier(want, form, seld, fr)
 
@@ -338,14 +351,15 @@
 # to __class__ is safe. Moreover, shouldn't there be a better
 # initializer for the classes in the suites?
 def mkobjectfrommodule(dict, modulename):
-    if isinstance(dict['want'], type) and issubclass(dict['want'], ObjectSpecifier):
+    if (isinstance(dict[b2i(b'want')], type) and
+        issubclass(dict[b2i(b'want')], ObjectSpecifier)):
         # The type has already been converted to Python. Convert back:-(
-        classtype = dict['want']
-        dict['want'] = aetypes.mktype(classtype.want)
-    want = dict['want'].type
+        classtype = dict[b2i(b'want')]
+        dict[b2i(b'want')] = aetypes.mktype(classtype.want)
+    want = dict[b2i(b'want')].type
     module = __import__(modulename)
     codenamemapper = module._classdeclarations
-    classtype = codenamemapper.get(want, None)
+    classtype = codenamemapper.get(b2i(want), None)
     newobj = mkobject(dict)
     if classtype:
         assert issubclass(classtype, ObjectSpecifier)
@@ -356,7 +370,7 @@
     if modulename:
         module = __import__(modulename)
         codenamemapper = module._classdeclarations
-        classtype = codenamemapper.get(typecode, None)
+        classtype = codenamemapper.get(b2i(typecode), None)
         if classtype:
             return classtype
     return aetypes.mktype(typecode)
diff --git a/Lib/plat-mac/aetypes.py b/Lib/plat-mac/aetypes.py
index aacea55..162b69f 100644
--- a/Lib/plat-mac/aetypes.py
+++ b/Lib/plat-mac/aetypes.py
@@ -16,6 +16,14 @@
     if isinstance(s, str): return repr(s)
     else: return str(s)
 
+def _four_char_code(four_chars):
+    """Convert a str or bytes object into a 4-byte array.
+
+    four_chars must contain only ASCII characters.
+
+    """
+    return bytes("%-4.4s" % str(four_chars))
+
 class Unknown:
     """An uninterpreted AE object"""
 
@@ -33,13 +41,13 @@
     """An AE enumeration value"""
 
     def __init__(self, enum):
-        self.enum = "%-4.4s" % str(enum)
+        self.enum = _four_char_code(enum)
 
     def __repr__(self):
         return "Enum(%r)" % (self.enum,)
 
     def __str__(self):
-        return self.enum.strip()
+        return self.enum.strip(b' ')
 
     def __aepack__(self):
         return pack(self.enum, typeEnumeration)
@@ -100,7 +108,7 @@
     """An AE 4-char typename object"""
 
     def __init__(self, type):
-        self.type = "%-4.4s" % str(type)
+        self.type = _four_char_code(type)
 
     def __repr__(self):
         return "Type(%r)" % (self.type,)
@@ -123,7 +131,7 @@
     """An AE 4-char keyword object"""
 
     def __init__(self, keyword):
-        self.keyword = "%-4.4s" % str(keyword)
+        self.keyword = _four_char_code(keyword)
 
     def __repr__(self):
         return "Keyword(%r)" % self.keyword
@@ -161,7 +169,7 @@
 
     def __init__(self, obj1, relo, obj2):
         self.obj1 = obj1
-        self.relo = "%-4.4s" % str(relo)
+        self.relo = _four_char_code(relo)
         self.obj2 = obj2
 
     def __repr__(self):
@@ -190,7 +198,7 @@
 
     def __init__(self, abso):
 #       self.obj1 = obj1
-        self.abso = "%-4.4s" % str(abso)
+        self.abso = _four_char_code(abso)
 
     def __repr__(self):
         return "Ordinal(%r)" % (self.abso,)
@@ -214,7 +222,7 @@
     """An AE logical expression object"""
 
     def __init__(self, logc, term):
-        self.logc = "%-4.4s" % str(logc)
+        self.logc = _four_char_code(logc)
         self.term = term
 
     def __repr__(self):
@@ -554,12 +562,12 @@
 class %s(ComponentItem): want = '%s'
 """
 
-exec(template % ("Text", 'text'))
-exec(template % ("Character", 'cha '))
-exec(template % ("Word", 'cwor'))
-exec(template % ("Line", 'clin'))
-exec(template % ("paragraph", 'cpar'))
-exec(template % ("Window", 'cwin'))
-exec(template % ("Document", 'docu'))
-exec(template % ("File", 'file'))
-exec(template % ("InsertionPoint", 'cins'))
+exec(template % ("Text", b'text'))
+exec(template % ("Character", b'cha '))
+exec(template % ("Word", b'cwor'))
+exec(template % ("Line", b'clin'))
+exec(template % ("paragraph", b'cpar'))
+exec(template % ("Window", b'cwin'))
+exec(template % ("Document", b'docu'))
+exec(template % ("File", b'file'))
+exec(template % ("InsertionPoint", b'cins'))
diff --git a/Lib/test/test_aepack.py b/Lib/test/test_aepack.py
index 8a4b035..79e59a1 100755
--- a/Lib/test/test_aepack.py
+++ b/Lib/test/test_aepack.py
@@ -8,18 +8,18 @@
 
 class TestAepack(unittest.TestCase):
     OBJECTS = [
-        aetypes.Enum('enum'),
-        aetypes.Type('type'),
-        aetypes.Keyword('kwrd'),
+        aetypes.Enum(b'enum'),
+        aetypes.Type(b'type'),
+        aetypes.Keyword(b'kwrd'),
         aetypes.Range(1, 10),
-        aetypes.Comparison(1, '<   ', 10),
-        aetypes.Logical('not ', 1),
-        aetypes.IntlText(0, 0, 'international text'),
+        aetypes.Comparison(1, b'<   ', 10),
+        aetypes.Logical(b'not ', 1),
+        aetypes.IntlText(0, 0, b'international text'),
         aetypes.IntlWritingCode(0,0),
         aetypes.QDPoint(50,100),
         aetypes.QDRectangle(50,100,150,200),
         aetypes.RGBColor(0x7000, 0x6000, 0x5000),
-        aetypes.Unknown('xxxx', 'unknown type data'),
+        aetypes.Unknown(b'xxxx', b'unknown type data'),
         aetypes.Character(1),
         aetypes.Character(2, aetypes.Line(2)),
     ]
diff --git a/Lib/test/test_applesingle.py b/Lib/test/test_applesingle.py
index d533f1a..96450e3 100644
--- a/Lib/test/test_applesingle.py
+++ b/Lib/test/test_applesingle.py
@@ -12,8 +12,8 @@
 
 AS_MAGIC=0x00051600
 AS_VERSION=0x00020000
-dataforkdata = 'hello\r\0world\n'
-resourceforkdata = 'goodbye\ncruel\0world\r'
+dataforkdata = b'hello\r\0world\n'
+resourceforkdata = b'goodbye\ncruel\0world\r'
 
 applesingledata = struct.pack(">ll16sh", AS_MAGIC, AS_VERSION, "foo", 2) + \
     struct.pack(">llllll", 1, 50, len(dataforkdata),
@@ -25,7 +25,7 @@
 class TestApplesingle(unittest.TestCase):
 
     def setUp(self):
-        fp = open(test_support.TESTFN, 'w')
+        fp = open(test_support.TESTFN, 'wb')
         fp.write(applesingledata)
         fp.close()
 
diff --git a/Mac/Modules/ae/_AEmodule.c b/Mac/Modules/ae/_AEmodule.c
index de7c25e..3442619 100644
--- a/Mac/Modules/ae/_AEmodule.c
+++ b/Mac/Modules/ae/_AEmodule.c
@@ -835,9 +835,9 @@
 	OSErr err;
 
 	size = AEGetDescDataSize(&self->ob_itself);
-	if ( (res = PyString_FromStringAndSize(NULL, size)) == NULL )
+	if ( (res = PyBytes_FromStringAndSize(NULL, size)) == NULL )
 		return NULL;
-	if ( (ptr = PyString_AsString(res)) == NULL )
+	if ( (ptr = PyBytes_AsString(res)) == NULL )
 		return NULL;
 	if ( (err=AEGetDescData(&self->ob_itself, ptr, size)) < 0 )
 		return PyMac_Error(err);
diff --git a/Python/mactoolboxglue.c b/Python/mactoolboxglue.c
index 85acb51..0714cff 100644
--- a/Python/mactoolboxglue.c
+++ b/Python/mactoolboxglue.c
@@ -194,7 +194,7 @@
 PyMac_BuildOSType(OSType t)
 {
 	uint32_t tmp = htonl((uint32_t)t);
-	return PyString_FromStringAndSize((char *)&tmp, 4);
+	return PyBytes_FromStringAndSize((char *)&tmp, 4);
 }
 
 /* Convert an NumVersion value to a 4-element tuple */
@@ -215,7 +215,7 @@
 	if (PyUnicode_Check(v)) {
 		v = _PyUnicode_AsDefaultEncodedString(v, NULL);
 		if (v == NULL)
-			return NULL;
+			return 0;
 	}
 	if (PyString_Check(v)) {
 		ptr = PyString_AS_STRING(v);