From 8f3733a26fae6667355988269731d62dfba294e1 Mon Sep 17 00:00:00 2001 From: Andreas Grapentin Date: Sat, 9 Feb 2019 15:17:27 +0100 Subject: pcr/renpy-python3: unmaintained, unbuilt. removed --- pcr/renpy-python3/python3.patch | 5504 --------------------------------------- 1 file changed, 5504 deletions(-) delete mode 100644 pcr/renpy-python3/python3.patch (limited to 'pcr/renpy-python3/python3.patch') diff --git a/pcr/renpy-python3/python3.patch b/pcr/renpy-python3/python3.patch deleted file mode 100644 index aa25f7772..000000000 --- a/pcr/renpy-python3/python3.patch +++ /dev/null @@ -1,5504 +0,0 @@ -diff --git a/launcher/game/EasyDialogsWin.py b/launcher/game/EasyDialogsWin.py -index aea17ed..f63c883 100644 ---- a/launcher/game/EasyDialogsWin.py -+++ b/launcher/game/EasyDialogsWin.py -@@ -19,8 +19,6 @@ This module uses DLOG resources 260 and on. - Based upon STDWIN dialogs with the same names and functions. - """ - --from __future__ import division -- - import os - - import ctypes -@@ -606,7 +604,7 @@ def AskFileForOpen( - ofn.lpstrTitle = windowTitle - ofn.lpstrInitialDir = defaultLocation - -- if typeList and filter(None, typeList): -+ if typeList and [_f for _f in typeList if _f]: - lpstrFilter = '' - for typeSpec in typeList: - try: -@@ -672,10 +670,10 @@ def AskFileForOpen( - ofn.lpfnHook = LPOFNHOOKPROC(hookProc) - - if fn(ctypes.byref(ofn)): -- filenames = filter(None, filename.split('\0')) -+ filenames = [_f for _f in filename.split('\0') if _f] - if len(filenames) > 1: - dir, filenames = filenames[0], filenames[1:] -- return map(lambda fn: os.path.join(dir, fn), filenames) -+ return [os.path.join(dir, fn) for fn in filenames] - elif multiple: - return filenames - else: -@@ -771,7 +769,7 @@ def AskFolder( - def BrowseCallback(hwnd, uMsg, lParam, lpData): - if uMsg == BFFM_INITIALIZED: - if actionButtonLabel: -- label = unicode(actionButtonLabel, errors='replace') -+ label = str(actionButtonLabel, errors='replace') - user32.SendMessageW(hwnd, BFFM_SETOKTEXT, 0, label) - if cancelButtonLabel: - cancelButton = user32.GetDlgItem(hwnd, IDCANCEL) -@@ -995,14 +993,14 @@ def GetArgv(optionlist=None, commandlist=None, addoldfile=1, addnewfile=1, addfo - if item[0] == '"': - while item[-1] != '"': - if not tmplist: -- raise RuntimeError, "Unterminated quoted argument" -+ raise RuntimeError("Unterminated quoted argument") - item = item + ' ' + tmplist[0] - del tmplist[0] - item = item[1:-1] - if item[0] == "'": - while item[-1] != "'": - if not tmplist: -- raise RuntimeError, "Unterminated quoted argument" -+ raise RuntimeError("Unterminated quoted argument") - item = item + ' ' + tmplist[0] - del tmplist[0] - item = item[1:-1] -@@ -1029,7 +1027,7 @@ def test(): - argv = GetArgv(optionlist=optionlist, commandlist=commandlist, addoldfile=0) - Message("Command line: %s"%' '.join(argv)) - for i in range(len(argv)): -- print 'arg[%d] = %r' % (i, argv[i]) -+ print('arg[%d] = %r' % (i, argv[i])) - ok = AskYesNoCancel("Do you want to proceed?") - ok = AskYesNoCancel("Do you want to identify?", yes="Identify", no="No") - if ok > 0: -@@ -1053,11 +1051,11 @@ def test(): - try: - if hasattr(MacOS, 'SchedParams'): - appsw = MacOS.SchedParams(1, 0) -- for i in xrange(20): -+ for i in range(20): - bar.inc() - time.sleep(0.05) - bar.set(0,100) -- for i in xrange(100): -+ for i in range(100): - bar.set(i) - time.sleep(0.05) - if i % 10 == 0: -diff --git a/launcher/game/change_icon.py b/launcher/game/change_icon.py -index 900cff6..23caaab 100644 ---- a/launcher/game/change_icon.py -+++ b/launcher/game/change_icon.py -@@ -62,9 +62,9 @@ class BinFile(object): - def name(self): - c = self.u16() - -- rv = u"" -+ rv = "" - for _i in range(c): -- rv += unichr(self.u16()) -+ rv += chr(self.u16()) - - return rv - -@@ -143,11 +143,11 @@ def parse_directory(bf, offset): - def show_resources(d, prefix): - - if not isinstance(d, dict): -- print prefix, "Codepage", d[0], "length", len(d[1]) -+ print(prefix, "Codepage", d[0], "length", len(d[1])) - return - - for k in d: -- print prefix, k -+ print(prefix, k) - show_resources(d[k], prefix + " ") - - ############################################################################## -@@ -201,8 +201,8 @@ class Packer(object): - return rv - - def pack_dict(self, d, offset): -- name_entries = sorted((a, b) for a, b in d.iteritems() if isinstance(a, unicode)) -- id_entries = sorted((a, b) for a, b in d.iteritems() if isinstance(a, int)) -+ name_entries = sorted((a, b) for a, b in d.items() if isinstance(a, str)) -+ id_entries = sorted((a, b) for a, b in d.items() if isinstance(a, int)) - - rv = struct.pack("', warning -+ print('>', warning) - - - def full_load(self): -@@ -1705,7 +1705,7 @@ class PE: - for entry in self.FileInfo: - if hasattr(entry, 'StringTable'): - for st_entry in entry.StringTable: -- for key, entry in st_entry.entries.items(): -+ for key, entry in list(st_entry.entries.items()): - - offsets = st_entry.entries_offsets[key] - lengths = st_entry.entries_lengths[key] -@@ -1738,12 +1738,12 @@ class PE: - file_data[ - offsets[1] + len(entry)*2 : - offsets[1] + lengths[1]*2 ] = [ -- u'\0' ] * remainder*2 -+ '\0' ] * remainder*2 - - new_file_data = ''.join( [ chr(ord(c)) for c in file_data] ) - - if filename: -- f = file(filename, 'wb+') -+ f = open(filename, 'wb+') - f.write(new_file_data) - f.close() - else: -@@ -1767,7 +1767,7 @@ class PE: - - self.sections = [] - -- for i in xrange(self.FILE_HEADER.NumberOfSections): -+ for i in range(self.FILE_HEADER.NumberOfSections): - section = SectionStructure(self.__IMAGE_SECTION_HEADER_format__) - if not section: - break -@@ -1846,7 +1846,7 @@ class PE: - matching the filter "flag_filter". - """ - -- return [(f[0], f[1]) for f in flag_dict.items() if -+ return [(f[0], f[1]) for f in list(flag_dict.items()) if - isinstance(f[0], str) and f[0].startswith(flag_filter)] - - -@@ -1956,7 +1956,7 @@ class PE: - rva += bnd_descr.sizeof() - - forwarder_refs = [] -- for idx in xrange(bnd_descr.NumberOfModuleForwarderRefs): -+ for idx in range(bnd_descr.NumberOfModuleForwarderRefs): - # Both structures IMAGE_BOUND_IMPORT_DESCRIPTOR and - # IMAGE_BOUND_FORWARDER_REF have the same size. - bnd_frwd_ref = self.__unpack_data__( -@@ -2092,7 +2092,7 @@ class PE: - data = self.get_data(data_rva, size) - - entries = [] -- for idx in xrange(len(data)/2): -+ for idx in range(len(data)/2): - word = struct.unpack('>12) - reloc_offset = (word&0x0fff) -@@ -2110,10 +2110,10 @@ class PE: - dbg_size = Structure(self.__IMAGE_DEBUG_DIRECTORY_format__).sizeof() - - debug = [] -- for idx in xrange(size/dbg_size): -+ for idx in range(size/dbg_size): - try: - data = self.get_data(rva+dbg_size*idx, dbg_size) -- except PEFormatError, e: -+ except PEFormatError as e: - self.__warnings.append( - 'Invalid debug information. Can\'t read ' + - 'data at RVA: 0x%x' % rva) -@@ -2167,7 +2167,7 @@ class PE: - # If the RVA is invalid all would blow up. Some EXEs seem to be - # specially nasty and have an invalid RVA. - data = self.get_data(rva, Structure(self.__IMAGE_RESOURCE_DIRECTORY_format__).sizeof() ) -- except PEFormatError, e: -+ except PEFormatError as e: - self.__warnings.append( - 'Invalid resources directory. Can\'t read ' + - 'directory data at RVA: 0x%x' % rva) -@@ -2201,7 +2201,7 @@ class PE: - - strings_to_postprocess = list() - -- for idx in xrange(number_of_entries): -+ for idx in range(number_of_entries): - - res = self.parse_resource_entry(rva) - if res is None: -@@ -2227,7 +2227,7 @@ class PE: - entry_name = UnicodeStringWrapperPostProcessor(self, ustr_offset) - strings_to_postprocess.append(entry_name) - -- except PEFormatError, excp: -+ except PEFormatError as excp: - self.__warnings.append( - 'Error parsing the resources directory, ' + - 'attempting to read entry name. ' + -@@ -2328,7 +2328,7 @@ class PE: - # If the RVA is invalid all would blow up. Some EXEs seem to be - # specially nasty and have an invalid RVA. - data = self.get_data(rva, Structure(self.__IMAGE_RESOURCE_DATA_ENTRY_format__).sizeof() ) -- except PEFormatError, excp: -+ except PEFormatError as excp: - self.__warnings.append( - 'Error parsing a resource directory data entry, ' + - 'the RVA is invalid: 0x%x' % ( rva ) ) -@@ -2353,13 +2353,13 @@ class PE: - return None - - #resource.NameIsString = (resource.Name & 0x80000000L) >> 31 -- resource.NameOffset = resource.Name & 0x7FFFFFFFL -+ resource.NameOffset = resource.Name & 0x7FFFFFFF - -- resource.__pad = resource.Name & 0xFFFF0000L -- resource.Id = resource.Name & 0x0000FFFFL -+ resource.__pad = resource.Name & 0xFFFF0000 -+ resource.Id = resource.Name & 0x0000FFFF - -- resource.DataIsDirectory = (resource.OffsetToData & 0x80000000L) >> 31 -- resource.OffsetToDirectory = resource.OffsetToData & 0x7FFFFFFFL -+ resource.DataIsDirectory = (resource.OffsetToData & 0x80000000) >> 31 -+ resource.OffsetToDirectory = resource.OffsetToData & 0x7FFFFFFF - - return resource - -@@ -2407,7 +2407,7 @@ class PE: - ustr_offset = version_struct.OffsetToData + versioninfo_struct.sizeof() - try: - versioninfo_string = self.get_string_u_at_rva( ustr_offset ) -- except PEFormatError, excp: -+ except PEFormatError as excp: - self.__warnings.append( - 'Error parsing the version information, ' + - 'attempting to read VS_VERSION_INFO string. Can\'t ' + -@@ -2418,7 +2418,7 @@ class PE: - - # If the structure does not contain the expected name, it's assumed to be invalid - # -- if versioninfo_string != u'VS_VERSION_INFO': -+ if versioninfo_string != 'VS_VERSION_INFO': - - self.__warnings.append('Invalid VS_VERSION_INFO block') - return -@@ -2487,7 +2487,7 @@ class PE: - stringfileinfo_offset + versioninfo_struct.sizeof() ) - try: - stringfileinfo_string = self.get_string_u_at_rva( ustr_offset ) -- except PEFormatError, excp: -+ except PEFormatError as excp: - self.__warnings.append( - 'Error parsing the version information, ' + - 'attempting to read StringFileInfo string. Can\'t ' + -@@ -2506,7 +2506,7 @@ class PE: - - # Parse a StringFileInfo entry - # -- if stringfileinfo_string.startswith(u'StringFileInfo'): -+ if stringfileinfo_string.startswith('StringFileInfo'): - - if stringfileinfo_struct.Type == 1 and stringfileinfo_struct.ValueLength == 0: - -@@ -2533,7 +2533,7 @@ class PE: - stringtable_struct.sizeof() ) - try: - stringtable_string = self.get_string_u_at_rva( ustr_offset ) -- except PEFormatError, excp: -+ except PEFormatError as excp: - self.__warnings.append( - 'Error parsing the version information, ' + - 'attempting to read StringTable string. Can\'t ' + -@@ -2568,7 +2568,7 @@ class PE: - try: - key = self.get_string_u_at_rva( ustr_offset ) - key_offset = self.get_offset_from_rva( ustr_offset ) -- except PEFormatError, excp: -+ except PEFormatError as excp: - self.__warnings.append( - 'Error parsing the version information, ' + - 'attempting to read StringTable Key string. Can\'t ' + -@@ -2584,7 +2584,7 @@ class PE: - value = self.get_string_u_at_rva( ustr_offset, - max_length = string_struct.ValueLength ) - value_offset = self.get_offset_from_rva( ustr_offset ) -- except PEFormatError, excp: -+ except PEFormatError as excp: - self.__warnings.append( - 'Error parsing the version information, ' + - 'attempting to read StringTable Value string. ' + -@@ -2629,7 +2629,7 @@ class PE: - - # Parse a VarFileInfo entry - # -- elif stringfileinfo_string.startswith( u'VarFileInfo' ): -+ elif stringfileinfo_string.startswith( 'VarFileInfo' ): - - varfileinfo_struct = stringfileinfo_struct - varfileinfo_struct.name = 'VarFileInfo' -@@ -2659,7 +2659,7 @@ class PE: - var_struct.sizeof() ) - try: - var_string = self.get_string_u_at_rva( ustr_offset ) -- except PEFormatError, excp: -+ except PEFormatError as excp: - self.__warnings.append( - 'Error parsing the version information, ' + - 'attempting to read VarFileInfo Var string. ' + -@@ -2681,7 +2681,7 @@ class PE: - raw_data[varword_offset+2:varword_offset+4], 0) - varword_offset += 4 - -- if isinstance(word1, (int, long)) and isinstance(word1, (int, long)): -+ if isinstance(word1, int) and isinstance(word1, int): - var_struct.entry = {var_string: '0x%04x 0x%04x' % (word1, word2)} - - var_offset = self.dword_align( -@@ -2750,7 +2750,7 @@ class PE: - - exports = [] - -- for i in xrange(export_dir.NumberOfNames): -+ for i in range(export_dir.NumberOfNames): - - - symbol_name = self.get_string_at_rva( -@@ -2787,7 +2787,7 @@ class PE: - - ordinals = [exp.ordinal for exp in exports] - -- for idx in xrange(export_dir.NumberOfFunctions): -+ for idx in range(export_dir.NumberOfFunctions): - - if not idx+export_dir.Base in ordinals: - symbol_address = self.get_dword_from_data( -@@ -2828,7 +2828,7 @@ class PE: - # If the RVA is invalid all would blow up. Some PEs seem to be - # specially nasty and have an invalid RVA. - data = self.get_data( rva, Structure(self.__IMAGE_DELAY_IMPORT_DESCRIPTOR_format__).sizeof() ) -- except PEFormatError, e: -+ except PEFormatError as e: - self.__warnings.append( - 'Error parsing the Delay import directory at RVA: 0x%x' % ( rva ) ) - break -@@ -2850,7 +2850,7 @@ class PE: - import_desc.pINT, - import_desc.pIAT, - None) -- except PEFormatError, e: -+ except PEFormatError as e: - self.__warnings.append( - 'Error parsing the Delay import directory. ' + - 'Invalid import data at RVA: 0x%x' % ( rva ) ) -@@ -2881,7 +2881,7 @@ class PE: - # If the RVA is invalid all would blow up. Some EXEs seem to be - # specially nasty and have an invalid RVA. - data = self.get_data(rva, Structure(self.__IMAGE_IMPORT_DESCRIPTOR_format__).sizeof() ) -- except PEFormatError, e: -+ except PEFormatError as e: - self.__warnings.append( - 'Error parsing the Import directory at RVA: 0x%x' % ( rva ) ) - break -@@ -2901,7 +2901,7 @@ class PE: - import_desc.OriginalFirstThunk, - import_desc.FirstThunk, - import_desc.ForwarderChain) -- except PEFormatError, excp: -+ except PEFormatError as excp: - self.__warnings.append( - 'Error parsing the Import directory. ' + - 'Invalid Import data at RVA: 0x%x' % ( rva ) ) -@@ -2934,7 +2934,7 @@ class PE: - imported_symbols = [] - imports_section = self.get_section_by_rva(first_thunk) - if not imports_section: -- raise PEFormatError, 'Invalid/corrupt imports.' -+ raise PEFormatError('Invalid/corrupt imports.') - - - # Import Lookup Table. Contains ordinals or pointers to strings. -@@ -2961,7 +2961,7 @@ class PE: - return None - - -- for idx in xrange(len(table)): -+ for idx in range(len(table)): - - imp_ord = None - imp_hint = None -@@ -2989,7 +2989,7 @@ class PE: - # Get the Hint - imp_hint = self.get_word_from_data(data, 0) - imp_name = self.get_string_at_rva(table[idx].AddressOfData+2) -- except PEFormatError, e: -+ except PEFormatError as e: - pass - - imp_address = first_thunk+self.OPTIONAL_HEADER.ImageBase+idx*4 -@@ -3030,7 +3030,7 @@ class PE: - - try: - data = self.get_data( rva, Structure(format).sizeof() ) -- except PEFormatError, e: -+ except PEFormatError as e: - self.__warnings.append( - 'Error parsing the import table. ' + - 'Invalid data at RVA: 0x%x' % ( rva ) ) -@@ -3135,7 +3135,7 @@ class PE: - end = None - return self.header[rva:end] - -- raise PEFormatError, 'data at RVA can\'t be fetched. Corrupt header?' -+ raise PEFormatError('data at RVA can\'t be fetched. Corrupt header?') - - return s.get_data(rva, length) - -@@ -3158,7 +3158,7 @@ class PE: - s = self.get_section_by_rva(rva) - if not s: - -- raise PEFormatError, 'data at RVA can\'t be fetched. Corrupt header?' -+ raise PEFormatError('data at RVA can\'t be fetched. Corrupt header?') - - return s.get_offset_from_rva(rva) - -@@ -3205,21 +3205,21 @@ class PE: - # If the RVA is invalid all would blow up. Some EXEs seem to be - # specially nasty and have an invalid RVA. - self.get_data(rva, 2) -- except PEFormatError, e: -+ except PEFormatError as e: - return None - - #length = struct.unpack('split) { -@@ -5671,7 +5671,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_12linebreak_debug(CYTHON_UN - * if g.split == SPLIT_INSTEAD: - * rv += "|" # <<<<<<<<<<<<<< - * elif g.split == SPLIT_BEFORE: -- * rv += "[" + unichr(g.character) -+ * rv += "[" + chr(g.character) - */ - __pyx_t_3 = PyNumber_InPlaceAdd(__pyx_v_rv, __pyx_kp_s__2); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 393; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_3); -@@ -5683,7 +5683,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_12linebreak_debug(CYTHON_UN - * if g.split == SPLIT_INSTEAD: - * rv += "|" - * elif g.split == SPLIT_BEFORE: # <<<<<<<<<<<<<< -- * rv += "[" + unichr(g.character) -+ * rv += "[" + chr(g.character) - * else: - */ - case __pyx_e_5renpy_4text_11textsupport_SPLIT_BEFORE: -@@ -5691,9 +5691,9 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_12linebreak_debug(CYTHON_UN - /* "renpy/text/textsupport.pyx":395 - * rv += "|" - * elif g.split == SPLIT_BEFORE: -- * rv += "[" + unichr(g.character) # <<<<<<<<<<<<<< -+ * rv += "[" + chr(g.character) # <<<<<<<<<<<<<< - * else: -- * rv += unichr(g.character) -+ * rv += chr(g.character) - */ - __pyx_t_3 = __Pyx_PyInt_From_unsigned_int(__pyx_v_g->character); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 395; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_3); -@@ -5702,7 +5702,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_12linebreak_debug(CYTHON_UN - PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_3); - __Pyx_GIVEREF(__pyx_t_3); - __pyx_t_3 = 0; -- __pyx_t_3 = __Pyx_PyObject_Call(__pyx_builtin_unichr, __pyx_t_4, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 395; __pyx_clineno = __LINE__; goto __pyx_L1_error;} -+ __pyx_t_3 = __Pyx_PyObject_Call(__pyx_builtin_chr, __pyx_t_4, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 395; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - __pyx_t_4 = PyNumber_Add(__pyx_kp_s__3, __pyx_t_3); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 395; __pyx_clineno = __LINE__; goto __pyx_L1_error;} -@@ -5717,9 +5717,9 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_12linebreak_debug(CYTHON_UN - default: - - /* "renpy/text/textsupport.pyx":397 -- * rv += "[" + unichr(g.character) -+ * rv += "[" + chr(g.character) - * else: -- * rv += unichr(g.character) # <<<<<<<<<<<<<< -+ * rv += chr(g.character) # <<<<<<<<<<<<<< - * - * return rv - */ -@@ -5730,7 +5730,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_12linebreak_debug(CYTHON_UN - PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_3); - __Pyx_GIVEREF(__pyx_t_3); - __pyx_t_3 = 0; -- __pyx_t_3 = __Pyx_PyObject_Call(__pyx_builtin_unichr, __pyx_t_4, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 397; __pyx_clineno = __LINE__; goto __pyx_L1_error;} -+ __pyx_t_3 = __Pyx_PyObject_Call(__pyx_builtin_chr, __pyx_t_4, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 397; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - __pyx_t_4 = PyNumber_InPlaceAdd(__pyx_v_rv, __pyx_t_3); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 397; __pyx_clineno = __LINE__; goto __pyx_L1_error;} -@@ -5752,7 +5752,7 @@ static PyObject *__pyx_pf_5renpy_4text_11textsupport_12linebreak_debug(CYTHON_UN - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - - /* "renpy/text/textsupport.pyx":399 -- * rv += unichr(g.character) -+ * rv += chr(g.character) - * - * return rv # <<<<<<<<<<<<<< - * -@@ -10826,7 +10826,7 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = { - {&__pyx_n_s_tokenize, __pyx_k_tokenize, sizeof(__pyx_k_tokenize), 0, 0, 1, 1}, - {&__pyx_n_s_tpg, __pyx_k_tpg, sizeof(__pyx_k_tpg), 0, 0, 1, 1}, - {&__pyx_n_s_tweak_glyph_spacing, __pyx_k_tweak_glyph_spacing, sizeof(__pyx_k_tweak_glyph_spacing), 0, 0, 1, 1}, -- {&__pyx_n_s_unichr, __pyx_k_unichr, sizeof(__pyx_k_unichr), 0, 0, 1, 1}, -+ {&__pyx_n_s_chr, __pyx_k_chr, sizeof(__pyx_k_chr), 0, 0, 1, 1}, - {&__pyx_n_s_w, __pyx_k_w, sizeof(__pyx_k_w), 0, 0, 1, 1}, - {&__pyx_n_s_width, __pyx_k_width, sizeof(__pyx_k_width), 0, 0, 1, 1}, - {&__pyx_n_s_x, __pyx_k_x, sizeof(__pyx_k_x), 0, 0, 1, 1}, -@@ -10838,7 +10838,7 @@ static int __Pyx_InitCachedBuiltins(void) { - __pyx_builtin_range = __Pyx_GetBuiltinName(__pyx_n_s_range); if (!__pyx_builtin_range) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 152; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __pyx_builtin_Exception = __Pyx_GetBuiltinName(__pyx_n_s_Exception); if (!__pyx_builtin_Exception) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 98; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __pyx_builtin_ord = __Pyx_GetBuiltinName(__pyx_n_s_ord); if (!__pyx_builtin_ord) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 175; __pyx_clineno = __LINE__; goto __pyx_L1_error;} -- __pyx_builtin_unichr = __Pyx_GetBuiltinName(__pyx_n_s_unichr); if (!__pyx_builtin_unichr) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 395; __pyx_clineno = __LINE__; goto __pyx_L1_error;} -+ __pyx_builtin_chr = __Pyx_GetBuiltinName(__pyx_n_s_chr); if (!__pyx_builtin_chr) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 395; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - return 0; - __pyx_L1_error:; - return -1; -diff --git a/module/generate_linebreak.py b/module/generate_linebreak.py -index 670adb7..8914199 100644 ---- a/module/generate_linebreak.py -+++ b/module/generate_linebreak.py -@@ -41,24 +41,24 @@ other_classes = " PITCH AI BK CB CJ CR LF NL SA SG SP XX" - - lines = breaking.split("\n") - --print "# This is generated code. Do not edit." --print -+print("# This is generated code. Do not edit.") -+print() - - # A map from character class to the number that represents it. - cl = { } - - - for i, j in enumerate((lines[0] + other_classes).split()): -- print "cdef char BC_{} = {}".format(j, i) -+ print("cdef char BC_{} = {}".format(j, i)) - cl[j] = i - --print "CLASSES = {" -+print("CLASSES = {") - - for i, j in enumerate((lines[0] + other_classes).split()): -- print " \"{}\" : {},".format(j, i) -+ print(" \"{}\" : {},".format(j, i)) - cl[j] = i - --print "}" -+print("}") - - rules = [ ] - -@@ -66,12 +66,12 @@ for l in lines[1:]: - for c in l.split()[1:]: - rules.append(c) - --print --print "cdef char *break_rules = \"" + "".join(rules) + "\"" -+print() -+print("cdef char *break_rules = \"" + "".join(rules) + "\"") - - cc = [ 'XX' ] * 65536 - --for l in file("LineBreak.txt"): -+for l in open("LineBreak.txt"): - m = re.match("(\w+)\.\.(\w+);(\w\w)", l) - if m: - start = int(m.group(1), 16) -@@ -108,7 +108,7 @@ def generate(name, func): - assert "CJ" not in ncc - assert "AI" not in ncc - -- print "cdef char *break_" + name + " = \"" + "".join("\\x%02x" % cl[i] for i in ncc) + "\"" -+ print("cdef char *break_" + name + " = \"" + "".join("\\x%02x" % cl[i] for i in ncc) + "\"") - - def western(i, cl): - if cl == "CJ": -diff --git a/module/generate_styles.py b/module/generate_styles.py -index e8f6957..f2942ca 100644 ---- a/module/generate_styles.py -+++ b/module/generate_styles.py -@@ -19,17 +19,13 @@ - # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - --from __future__ import print_function, unicode_literals, division, absolute_import -- --str = unicode # @ReservedAssignment -- - import collections - import os - - try: - from io import StringIO - except: -- from StringIO import StringIO -+ from io import StringIO - - # Paths - BASE = os.path.dirname(os.path.abspath(__file__)) -@@ -335,7 +331,7 @@ synthetic_properties = sorted_dict( - - all_properties = collections.OrderedDict() - --for k, v in style_properties.items(): -+for k, v in list(style_properties.items()): - all_properties[k] = [ (k, None) ] - - all_properties.update(synthetic_properties) -@@ -372,7 +368,7 @@ class CodeGen(object): - return - - with open(self.filename, "wb") as f: -- f.write(text) -+ f.write(bytes(text, "utf-8")) - - def write(self, s, *args, **kwargs): - out = " " * self.depth -@@ -403,7 +399,7 @@ def generate_constants(): - g.write("DEF PREFIX_COUNT = {}", PREFIX_COUNT) - g.write("DEF STYLE_PROPERTY_COUNT = {}", style_property_count) - -- for p in prefixes.values(): -+ for p in list(prefixes.values()): - if p.index < 0: - continue - -@@ -460,13 +456,13 @@ def generate_property_functions(): - This generates code that defines the property functions. - """ - -- for prefix in sorted(prefixes.values(), key=lambda p : p.index): -+ for prefix in sorted(list(prefixes.values()), key=lambda p : p.index): - g = CodeGen("module/gen/style_{}functions.pyx".format(prefix.name)) - - g.write('include "style_common.pxi"') - g.write('') - -- for propname, proplist in all_properties.items(): -+ for propname, proplist in list(all_properties.items()): - generate_property_function(g, prefix, propname, proplist) - - g.close() -@@ -522,13 +518,13 @@ def generate_sets(): - - ap = collections.OrderedDict() - -- for k, v in all_properties.items(): -+ for k, v in list(all_properties.items()): - ap[k] = [ i[0] for i in v ] - - prefix_priority = collections.OrderedDict() - prefix_alts = collections.OrderedDict() - -- for p in prefixes.values(): -+ for p in list(prefixes.values()): - prefix_priority[p.name] = p.priority - prefix_alts[p.name] = p.alt_names - -diff --git a/module/maketegl.py b/module/maketegl.py -index b5e1bda..4b9edc6 100644 ---- a/module/maketegl.py -+++ b/module/maketegl.py -@@ -26,8 +26,6 @@ - # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - # SUCH DAMAGE. - --from __future__ import print_function -- - # Modified in 2010,2014 by PyTom to generate Cython code that uses glew. - - VERSION = "0.1" -diff --git a/module/pysdlsound/__init__.py b/module/pysdlsound/__init__.py -index 8f2c8e9..a349a0d 100644 ---- a/module/pysdlsound/__init__.py -+++ b/module/pysdlsound/__init__.py -@@ -9,7 +9,7 @@ except: - pass - - try: -- import linmixer #@UnresolvedImport -+ from . import linmixer #@UnresolvedImport - sys.modules['linmixer'] = sys.modules['pysdlsound.linmixer'] - except: - pass -diff --git a/module/setup.py b/module/setup.py -index 38854d0..ea390e2 100644 ---- a/module/setup.py -+++ b/module/setup.py -@@ -103,7 +103,7 @@ if has_fribidi and (not android) and (not ios): - try: - # Some versions of fribidi require glib, and it doesn't hurt to include it in - # our path. -- glib_flags = subprocess.check_output(["pkg-config", "--cflags", "glib-2.0"]) -+ glib_flags = subprocess.check_output(["pkg-config", "--cflags", "glib-2.0"]).decode("utf-8") - setuplib.extra_compile_args.extend(glib_flags.split()) - except: - pass -@@ -232,4 +232,4 @@ import renpy - setuplib.setup("Ren'Py", renpy.version[7:]) - - if not has_fribidi: -- print "Warning: Did not include fribidi." -+ print("Warning: Did not include fribidi.") -diff --git a/module/setuplib.py b/module/setuplib.py -index 3b27819..c2b6eee 100644 ---- a/module/setuplib.py -+++ b/module/setuplib.py -@@ -96,9 +96,9 @@ def include(header, directory=None, optional=True): - return False - - if directory is None: -- print "Could not find required header {0}.".format(header) -+ print("Could not find required header {0}.".format(header)) - else: -- print "Could not find required header {0}/{1}.".format(directory, header) -+ print("Could not find required header {0}/{1}.".format(directory, header)) - - sys.exit(-1) - -@@ -133,7 +133,7 @@ def library(name, optional=False): - if optional: - return False - -- print "Could not find required library {0}.".format(name) -+ print("Could not find required library {0}.".format(name)) - sys.exit(-1) - - # A list of extension objects that we use. -@@ -182,7 +182,7 @@ def cython(name, source=[], libs=[], compile_if=True, define_macros=[], pyx=None - elif os.path.exists(fn): - pass - else: -- print "Could not find {0}.".format(fn) -+ print("Could not find {0}.".format(fn)) - sys.exit(-1) - - module_dir = os.path.dirname(fn) -@@ -190,7 +190,7 @@ def cython(name, source=[], libs=[], compile_if=True, define_macros=[], pyx=None - # Figure out what it depends on. - deps = [ fn ] - -- f = file(fn) -+ f = open(fn) - for l in f: - - m = re.search(r'from\s*([\w.]+)\s*cimport', l) -@@ -243,19 +243,19 @@ def cython(name, source=[], libs=[], compile_if=True, define_macros=[], pyx=None - elif os.path.exists(dep_fn): - pass - else: -- print "{0} depends on {1}, which can't be found.".format(fn, dep_fn) -+ print("{0} depends on {1}, which can't be found.".format(fn, dep_fn)) - sys.exit(-1) - - if os.path.getmtime(dep_fn) > c_mtime: - out_of_date = True - - if out_of_date and not cython_command: -- print "WARNING:", name, "is out of date, but RENPY_CYTHON isn't set." -+ print("WARNING:", name, "is out of date, but RENPY_CYTHON isn't set.") - out_of_date = False - - # If the file is out of date, regenerate it. - if out_of_date: -- print name, "is out of date." -+ print(name, "is out of date.") - - try: - import subprocess -@@ -280,10 +280,10 @@ def cython(name, source=[], libs=[], compile_if=True, define_macros=[], pyx=None - "-o", - c_fn]) - -- except subprocess.CalledProcessError, e: -- print -- print str(e) -- print -+ except subprocess.CalledProcessError as e: -+ print() -+ print(str(e)) -+ print() - sys.exit(-1) - - # Build the module normally once we have the c file. -@@ -299,7 +299,7 @@ def find_unnecessary_gen(): - if i in necessary_gen: - continue - -- print "Unnecessary file", os.path.join("gen", i) -+ print("Unnecessary file", os.path.join("gen", i)) - - - py_modules = [ ] -@@ -326,14 +326,14 @@ def copyfile(source, dest, replace=None, replace_with=None): - if os.path.getmtime(sfn) <= os.path.getmtime(dfn): - return - -- sf = file(sfn, "rb") -+ sf = open(sfn, "rb") - data = sf.read() - sf.close() - - if replace: - data = data.replace(replace, replace_with) - -- df = file(dfn, "wb") -+ df = open(dfn, "wb") - df.write("# This file was automatically generated from " + source + "\n") - df.write("# Modifications will be automatically overwritten.\n\n") - df.write(data) -diff --git a/renpy/__init__.py b/renpy/__init__.py -index e6f5310..91a6f24 100644 ---- a/renpy/__init__.py -+++ b/renpy/__init__.py -@@ -27,7 +27,7 @@ import os - import copy - import types - import threading --import cPickle -+import pickle - - ################################################################################ - # Version information -@@ -200,14 +200,14 @@ class Backup(): - if mobile: - return - -- for m in sys.modules.values(): -+ for m in list(sys.modules.values()): - if m is None: - continue - - self.backup_module(m) - - # A pickled version of self.objects. -- self.objects_pickle = cPickle.dumps(self.objects, cPickle.HIGHEST_PROTOCOL) -+ self.objects_pickle = pickle.dumps(self.objects, pickle.HIGHEST_PROTOCOL) - - self.objects = None - -@@ -229,7 +229,7 @@ class Backup(): - - self.names[mod] = set(vars(mod).keys()) - -- for k, v in vars(mod).iteritems(): -+ for k, v in vars(mod).items(): - - if k.startswith("__") and k.endswith("__"): - continue -@@ -248,10 +248,10 @@ class Backup(): - # If we have a problem pickling things, uncomment the next block. - - try: -- cPickle.dumps(v, cPickle.HIGHEST_PROTOCOL) -+ pickle.dumps(v, pickle.HIGHEST_PROTOCOL) - except: -- print "Cannot pickle", name + "." + k, "=", repr(v) -- print "Reduce Ex is:", repr(v.__reduce_ex__(cPickle.HIGHEST_PROTOCOL)) -+ print("Cannot pickle", name + "." + k, "=", repr(v)) -+ print("Reduce Ex is:", repr(v.__reduce_ex__(pickle.HIGHEST_PROTOCOL))) - - def restore(self): - """ -@@ -263,15 +263,15 @@ class Backup(): - return - - # Remove new variables from the module. -- for mod, names in self.names.iteritems(): -+ for mod, names in self.names.items(): - modvars = vars(mod) - for name in set(modvars.keys()) - names: - del modvars[name] - - -- objects = cPickle.loads(self.objects_pickle) -+ objects = pickle.loads(self.objects_pickle) - -- for k, v in self.variables.iteritems(): -+ for k, v in self.variables.items(): - mod, field = k - setattr(mod, field, objects[v]) - -@@ -473,12 +473,12 @@ def post_import(): - import subprocess - sys.modules['renpy.subprocess'] = subprocess - -- for k, v in renpy.defaultstore.__dict__.iteritems(): -+ for k, v in renpy.defaultstore.__dict__.items(): - renpy.store.__dict__.setdefault(k, v) - - # Import everything into renpy.exports, provided it isn't - # already there. -- for k, v in globals().iteritems(): -+ for k, v in globals().items(): - vars(renpy.exports).setdefault(k, v) - - -@@ -519,7 +519,7 @@ def reload_all(): - renpy.display.interface = None - - # Delete the store modules. -- for i in sys.modules.keys(): -+ for i in list(sys.modules.keys()): - if i.startswith("store") or i == "renpy.store": - m = sys.modules[i] - -diff --git a/renpy/add_from.py b/renpy/add_from.py -index 9935b29..5b2e3b5 100644 ---- a/renpy/add_from.py -+++ b/renpy/add_from.py -@@ -82,7 +82,7 @@ def process_file(fn): - consumed = 0 - - # The output. -- output = u"" -+ output = "" - - for position, target in edits: - output += data[consumed:position] -diff --git a/renpy/ast.py b/renpy/ast.py -index ec2cbf5..286c54a 100644 ---- a/renpy/ast.py -+++ b/renpy/ast.py -@@ -30,7 +30,8 @@ import renpy.display - - import re - import time --import md5 -+import hashlib -+import collections - - def statement_name(name): - """ -@@ -102,7 +103,7 @@ class ParameterInfo(object): - - extrapos = tuple(args[len(self.positional):]) - -- for name, value in kwargs.iteritems(): -+ for name, value in kwargs.items(): - if name in values: - if not ignore_errors: - raise Exception("Parameter %s has two values." % name) -@@ -133,7 +134,7 @@ class ParameterInfo(object): - if self.extrakw: - rv[self.extrakw] = values - elif values and not ignore_errors: -- raise Exception("Unknown keyword arguments: %s" % ( ", ".join(values.keys()))) -+ raise Exception("Unknown keyword arguments: %s" % ( ", ".join(list(values.keys())))) - - return rv - -@@ -192,7 +193,7 @@ def __newobj__(cls, *args): - return cls.__new__(cls, *args) - - # This represents a string containing python code. --class PyExpr(unicode): -+class PyExpr(str): - - __slots__ = [ - 'filename', -@@ -200,14 +201,14 @@ class PyExpr(unicode): - ] - - def __new__(cls, s, filename, linenumber): -- self = unicode.__new__(cls, s) -+ self = str.__new__(cls, s) - self.filename = filename - self.linenumber = linenumber - - return self - - def __getnewargs__(self): -- return (unicode(self), self.filename, self.linenumber) # E1101 -+ return (str(self), self.filename, self.linenumber) # E1101 - - class PyCode(object): - -@@ -261,7 +262,7 @@ class PyCode(object): - if isinstance(code, renpy.python.ast.AST): #@UndefinedVariable - code = renpy.python.ast.dump(code) #@UndefinedVariable - -- self.hash = chr(renpy.bytecode_version) + md5.md5(repr(self.location) + code.encode("utf-8")).digest() -+ self.hash = chr(renpy.bytecode_version) + hashlib.md5(repr(self.location) + code.encode("utf-8")).digest() - return self.hash - - -@@ -291,7 +292,7 @@ class Scry(object): - def __getattr__(self, name): - return None - -- def next(self): #@ReservedAssignment -+ def __next__(self): #@ReservedAssignment - if self._next is None: - return None - else: -@@ -382,7 +383,7 @@ class Node(object): - node. - """ - -- if self.next is old: -+ if self.__next__ is old: - self.next = new - - def execute(self): -@@ -409,8 +410,8 @@ class Node(object): - renpy.display.predict.screen to be called as necessary. - """ - -- if self.next: -- return [ self.next ] -+ if self.__next__: -+ return [ self.__next__ ] - else: - return [ ] - -@@ -421,7 +422,7 @@ class Node(object): - """ - - rv = Scry() -- rv._next = self.next # W0201 -+ rv._next = self.__next__ # W0201 - return rv - - def restructure(self, callback): -@@ -573,7 +574,7 @@ class Say(Node): - - def execute(self): - -- next_node(self.next) -+ next_node(self.__next__) - statement_name("say") - - try: -@@ -584,8 +585,8 @@ class Say(Node): - - if not ( - (who is None) or -- callable(who) or -- isinstance(who, basestring) ): -+ isinstance(who, collections.Callable) or -+ isinstance(who, str) ): - - raise Exception("Sayer %s is not a function or string." % self.who.encode("utf-8")) - -@@ -630,7 +631,7 @@ class Say(Node): - finally: - renpy.game.context().say_attributes = old_attributes - -- return [ self.next ] -+ return [ self.__next__ ] - - def scry(self): - rv = Node.scry(self) -@@ -685,7 +686,7 @@ class Init(Node): - chain_block(self.block, None) - - def execute(self): -- next_node(self.next) -+ next_node(self.__next__) - statement_name("init") - - def restructure(self, callback): -@@ -743,14 +744,14 @@ class Label(Node): - self.next = next - - def execute(self): -- next_node(self.next) -+ next_node(self.__next__) - statement_name("label") - - renpy.game.context().mark_seen() - - values = apply_arguments(self.parameters, renpy.store._args, renpy.store._kwargs) - -- for k, v in values.iteritems(): -+ for k, v in values.items(): - renpy.exports.dynamic(k) - setattr(renpy.store, k, v) - -@@ -798,7 +799,7 @@ class Python(Node): - renpy.python.create_store(self.store) - - def execute(self): -- next_node(self.next) -+ next_node(self.__next__) - statement_name("python") - - try: -@@ -845,7 +846,7 @@ class EarlyPython(Node): - return (EarlyPython, self.code.source) - - def execute(self): -- next_node(self.next) -+ next_node(self.__next__) - statement_name("python early") - - def early_execute(self): -@@ -889,7 +890,7 @@ class Image(Node): - # Note: We should always check that self.code is None before - # accessing self.atl, as self.atl may not always exist. - -- next_node(self.next) -+ next_node(self.__next__) - statement_name("image") - - if self.code is not None: -@@ -933,7 +934,7 @@ class Transform(Node): - - def execute(self): - -- next_node(self.next) -+ next_node(self.__next__) - statement_name("transform") - - parameters = getattr(self, "parameters", None) -@@ -1058,14 +1059,14 @@ class Show(Node): - return (Show, tuple(self.imspec[0])) - - def execute(self): -- next_node(self.next) -+ next_node(self.__next__) - statement_name("show") - - show_imspec(self.imspec, atl=getattr(self, "atl", None)) - - def predict(self): - predict_imspec(self.imspec, atl=getattr(self, "atl", None)) -- return [ self.next ] -+ return [ self.__next__ ] - - def analyze(self): - if getattr(self, 'atl', None) is not None: -@@ -1091,7 +1092,7 @@ class ShowLayer(Node): - return (ShowLayer, self.layer) - - def execute(self): -- next_node(self.next) -+ next_node(self.__next__) - statement_name("show layer") - - at_list = [ renpy.python.py_eval(i) for i in self.at_list ] -@@ -1103,7 +1104,7 @@ class ShowLayer(Node): - renpy.exports.layer_at_list(at_list, layer=self.layer) - - def predict(self): -- return [ self.next ] -+ return [ self.__next__ ] - - def analyze(self): - if self.atl is not None: -@@ -1142,7 +1143,7 @@ class Scene(Node): - - def execute(self): - -- next_node(self.next) -+ next_node(self.__next__) - statement_name("scene") - - renpy.config.scene(self.layer) -@@ -1155,7 +1156,7 @@ class Scene(Node): - if self.imspec: - predict_imspec(self.imspec, atl=getattr(self, "atl", None), scene=True) - -- return [ self.next ] -+ return [ self.__next__ ] - - def analyze(self): - if getattr(self, 'atl', None) is not None: -@@ -1204,11 +1205,11 @@ class Hide(Node): - - renpy.game.context().images.predict_hide(tag, layer) - -- return [ self.next ] -+ return [ self.__next__ ] - - def execute(self): - -- next_node(self.next) -+ next_node(self.__next__) - statement_name("hide") - - if len(self.imspec) == 3: -@@ -1252,7 +1253,7 @@ class With(Node): - - def execute(self): - -- next_node(self.next) -+ next_node(self.__next__) - statement_name("with") - - trans = renpy.python.py_eval(self.expr) -@@ -1276,7 +1277,7 @@ class With(Node): - pass - - -- return [ self.next ] -+ return [ self.__next__ ] - - - class Call(Node): -@@ -1423,7 +1424,7 @@ class Menu(Node): - - def execute(self): - -- next_node(self.next) -+ next_node(self.__next__) - statement_name("menu") - - choices = [ ] -@@ -1452,7 +1453,7 @@ class Menu(Node): - if choice is not None: - next_node(self.items[choice][2][0]) - else: -- next_node(self.next) -+ next_node(self.__next__) - - - def predict(self): -@@ -1547,7 +1548,7 @@ class Pass(Node): - return (Pass,) - - def execute(self): -- next_node(self.next) -+ next_node(self.__next__) - statement_name("pass") - - -@@ -1585,14 +1586,14 @@ class While(Node): - - def execute(self): - -- next_node(self.next) -+ next_node(self.__next__) - statement_name("while") - - if renpy.python.py_eval(self.condition): - next_node(self.block[0]) - - def predict(self): -- return [ self.block[0], self.next ] -+ return [ self.block[0], self.__next__ ] - - def scry(self): - rv = Node.scry(self) -@@ -1640,7 +1641,7 @@ class If(Node): - - def execute(self): - -- next_node(self.next) -+ next_node(self.__next__) - statement_name("if") - - for condition, block in self.entries: -@@ -1651,7 +1652,7 @@ class If(Node): - def predict(self): - - return [ block[0] for _condition, block in self.entries ] + \ -- [ self.next ] -+ [ self.__next__ ] - - def scry(self): - rv = Node.scry(self) -@@ -1726,7 +1727,7 @@ class UserStatement(Node): - if rv is not None: - return renpy.game.script.lookup(rv) - else: -- return self.next -+ return self.__next__ - - def scry(self): - rv = Node.scry(self) -@@ -1787,7 +1788,7 @@ class Define(Node): - - def execute(self): - -- next_node(self.next) -+ next_node(self.__next__) - statement_name("define") - - value = renpy.python.py_eval_bytecode(self.code.bytecode) -@@ -1834,7 +1835,7 @@ class Default(Node): - - def execute(self): - -- next_node(self.next) -+ next_node(self.__next__) - statement_name("default") - - default_statements.append(self) -@@ -1889,7 +1890,7 @@ class Screen(Node): - return (Screen, self.screen.name) - - def execute(self): -- next_node(self.next) -+ next_node(self.__next__) - statement_name("screen") - - self.screen.define((self.filename, self.linenumber)) -@@ -1956,7 +1957,7 @@ class Translate(Node): - statement_name("translate") - - if self.language is not None: -- next_node(self.next) -+ next_node(self.__next__) - raise Exception("Translation nodes cannot be run directly.") - - if self.identifier not in renpy.game.persistent._seen_translates: # @UndefinedVariable -@@ -2000,7 +2001,7 @@ class EndTranslate(Node): - return (EndTranslate,) - - def execute(self): -- next_node(self.next) -+ next_node(self.__next__) - statement_name("end translate") - - renpy.game.context().translate_identifier = None -@@ -2030,7 +2031,7 @@ class TranslateString(Node): - return (TranslateString,) - - def execute(self): -- next_node(self.next) -+ next_node(self.__next__) - statement_name("translate string") - - renpy.translation.add_string_translation(self.language, self.old, self.new) -@@ -2066,7 +2067,7 @@ class TranslatePython(Node): - return (TranslatePython, self.code.source) - - def execute(self): -- next_node(self.next) -+ next_node(self.__next__) - statement_name("translate_python") - - # def early_execute(self): -@@ -2106,7 +2107,7 @@ class TranslateBlock(Node): - chain_block(self.block, None) - - def execute(self): -- next_node(self.next) -+ next_node(self.__next__) - statement_name("translate_block") - - def restructure(self, callback): -@@ -2156,7 +2157,7 @@ class Style(Node): - return (Style, self.style_name) - - def execute(self): -- next_node(self.next) -+ next_node(self.__next__) - statement_name("style") - - if self.variant is not None: -@@ -2180,7 +2181,7 @@ class Style(Node): - - if self.properties: - properties = { } -- for name, expr in self.properties.items(): -+ for name, expr in list(self.properties.items()): - properties[name] = renpy.python.py_eval(expr) - - s.add_properties(properties) -diff --git a/renpy/atl.py b/renpy/atl.py -index d0f9d31..582f531 100644 ---- a/renpy/atl.py -+++ b/renpy/atl.py -@@ -39,7 +39,7 @@ def executing(loc): - warpers = { } - - def atl_warper(f): -- name = f.func_name -+ name = f.__name__ - warpers[name] = f - return f - -@@ -135,7 +135,7 @@ def interpolate(t, a, b, type): #@ReservedAssignment - return tuple(interpolate(t, i, j, ty) for i, j, ty in zip(a, b, type)) - - # Deal with booleans, nones, etc. -- elif b is None or isinstance(b, (bool, basestring)): -+ elif b is None or isinstance(b, (bool, str)): - if t >= 1.0: - return b - else: -@@ -375,7 +375,7 @@ class ATLTransformBase(renpy.object.Object): - raise Exception("Too many arguments passed to ATL transform.") - - # Handle keyword arguments. -- for k, v in kwargs.iteritems(): -+ for k, v in kwargs.items(): - - if k in positional: - positional.remove(k) -@@ -1113,7 +1113,7 @@ class Interpolation(Statement): - linear, revolution, splines = state - - # Linearly interpolate between the things in linear. -- for k, (old, new) in linear.iteritems(): -+ for k, (old, new) in linear.items(): - value = interpolate(complete, old, new, PROPERTIES[k]) - - setattr(trans.state, k, value) -@@ -1356,19 +1356,19 @@ class RawOn(RawStatement): - - handlers = { } - -- for k, v in self.handlers.iteritems(): -+ for k, v in self.handlers.items(): - handlers[k] = v.compile(ctx) - - return On(self.loc, handlers) - - def predict(self, ctx): -- for i in self.handlers.itervalues(): -+ for i in self.handlers.values(): - i.predict(ctx) - - def mark_constant(self): - constant = GLOBAL_CONST - -- for block in self.handlers.itervalues(): -+ for block in self.handlers.values(): - block.mark_constant() - constant = min(constant, block.constant) - -@@ -1450,7 +1450,7 @@ class On(Statement): - return "event", (name, arg), None - - def visit(self): -- return [ j for i in self.handlers.itervalues() for j in i.visit() ] -+ return [ j for i in self.handlers.values() for j in i.visit() ] - - - # Event statement. -diff --git a/renpy/audio/androidhw.py b/renpy/audio/androidhw.py -index 1c3b6ed..e487b56 100644 ---- a/renpy/audio/androidhw.py -+++ b/renpy/audio/androidhw.py -@@ -79,7 +79,7 @@ class AndroidVideoChannel(object): - - filename = self.queue.pop(0) - -- print "Playing", filename -+ print("Playing", filename) - - f = renpy.loader.load(filename) - -diff --git a/renpy/audio/audio.py b/renpy/audio/audio.py -index d265a3a..f322aab 100644 ---- a/renpy/audio/audio.py -+++ b/renpy/audio/audio.py -@@ -803,7 +803,7 @@ def pause_all(): - Pause all playback channels. - """ - -- for c in channels.values(): -+ for c in list(channels.values()): - c.pause() - - def unpause_all(): -@@ -811,5 +811,5 @@ def unpause_all(): - Unpause all playback channels. - """ - -- for c in channels.values(): -+ for c in list(channels.values()): - c.unpause() -diff --git a/renpy/audio/music.py b/renpy/audio/music.py -index bf959b5..9ccce1c 100644 ---- a/renpy/audio/music.py -+++ b/renpy/audio/music.py -@@ -76,7 +76,7 @@ def play(filenames, channel="music", loop=None, fadeout=None, synchro_start=Fals - if filenames is None: - return - -- if isinstance(filenames, basestring): -+ if isinstance(filenames, str): - filenames = [ filenames ] - - try: -@@ -151,7 +151,7 @@ def queue(filenames, channel="music", loop=None, clear_queue=True, fadein=0, tig - filenames = [ ] - loop = False - -- if isinstance(filenames, basestring): -+ if isinstance(filenames, str): - filenames = [ filenames ] - - try: -diff --git a/renpy/bootstrap.py b/renpy/bootstrap.py -index 9dbe2e0..9261c2b 100644 ---- a/renpy/bootstrap.py -+++ b/renpy/bootstrap.py -@@ -64,8 +64,8 @@ def extra_imports(): - import compiler; compiler - import textwrap; textwrap - import copy; copy -- import urllib; urllib -- import urllib2; urllib2 -+ import urllib.request, urllib.parse, urllib.error; urllib -+ import urllib.request, urllib.error, urllib.parse; urllib2 - import codecs; codecs - import rsa; rsa - import decimal; decimal -@@ -102,14 +102,14 @@ trace_local = None - - def trace_function(frame, event, arg): - fn = os.path.basename(frame.f_code.co_filename) -- print >>trace_file, fn, frame.f_lineno, frame.f_code.co_name, event -+ print(fn, frame.f_lineno, frame.f_code.co_name, event, file=trace_file) - return trace_local - - def enable_trace(level): - global trace_file - global trace_local - -- trace_file = file("trace.txt", "w", 1) -+ trace_file = open("trace.txt", "w", 1) - - if level > 1: - trace_local = trace_function -@@ -137,13 +137,13 @@ def bootstrap(renpy_base): - if os.environ.get("SDL_VIDEODRIVER", "") == "windib": - del os.environ["SDL_VIDEODRIVER"] - -- renpy_base = unicode(renpy_base, FSENCODING, "replace") -+ renpy_base = str(renpy_base.encode(errors="replace"), FSENCODING, "replace") - - # If environment.txt exists, load it into the os.environ dictionary. - if os.path.exists(renpy_base + "/environment.txt"): - evars = { } -- execfile(renpy_base + "/environment.txt", evars) -- for k, v in evars.iteritems(): -+ exec(compile(open(renpy_base + "/environment.txt").read(), renpy_base + "/environment.txt", 'exec'), evars) -+ for k, v in evars.items(): - if k not in os.environ: - os.environ[k] = str(v) - -@@ -155,8 +155,8 @@ def bootstrap(renpy_base): - - if os.path.exists(alt_path + "/environment.txt"): - evars = { } -- execfile(alt_path + "/environment.txt", evars) -- for k, v in evars.iteritems(): -+ exec(compile(open(alt_path + "/environment.txt").read(), alt_path + "/environment.txt", 'exec'), evars) -+ for k, v in evars.items(): - if k not in os.environ: - os.environ[k] = str(v) - -@@ -226,14 +226,14 @@ def bootstrap(renpy_base): - import pygame_sdl2 - pygame_sdl2.import_as_pygame() - except: -- print >>sys.stderr, """\ -+ print("""\ - Could not import pygame_sdl2. Please ensure that this program has been built - and unpacked properly. Also, make sure that the directories containing - this program do not contain : or ; in their names. - - You may be using a system install of python. Please run {0}.sh, - {0}.exe, or {0}.app instead. --""".format(name) -+""".format(name), file=sys.stderr) - - raise - -@@ -241,13 +241,13 @@ You may be using a system install of python. Please run {0}.sh, - try: - import _renpy; _renpy - except: -- print >>sys.stderr, """\ -+ print("""\ - Could not import _renpy. Please ensure that this program has been built - and unpacked properly. - - You may be using a system install of python. Please run {0}.sh, - {0}.exe, or {0}.app instead. --""".format(name) -+""".format(name), file=sys.stderr) - raise - - # Load up all of Ren'Py, in the right order. -@@ -276,7 +276,7 @@ You may be using a system install of python. Please run {0}.sh, - renpy.config.logdir = basedir - - if not os.path.exists(renpy.config.logdir): -- os.makedirs(renpy.config.logdir, 0777) -+ os.makedirs(renpy.config.logdir, 0o777) - - renpy.main.main() - -@@ -304,7 +304,7 @@ You may be using a system install of python. Please run {0}.sh, - except renpy.game.ParseErrorException: - pass - -- except Exception, e: -+ except Exception as e: - renpy.error.report_exception(e) - pass - -diff --git a/renpy/character.py b/renpy/character.py -index 2d36bbc..1fc049d 100644 ---- a/renpy/character.py -+++ b/renpy/character.py -@@ -56,12 +56,12 @@ class DialogueTextTags(object): - while True: - - try: -- self.text += i.next() -+ self.text += next(i) - -- quoted = i.next() -- full_tag = i.next() -- tag = i.next() -- value = i.next() -+ quoted = next(i) -+ full_tag = next(i) -+ tag = next(i) -+ value = next(i) - - if value is not None: - value = float(value) -@@ -152,7 +152,7 @@ def compute_widget_properties(who_args, what_args, window_args, variant=None): - - style = d["style"] - -- if isinstance(style, basestring): -+ if isinstance(style, str): - style = getattr(renpy.store.style, style) - - if variant is not None: -@@ -230,7 +230,7 @@ def show_display_say(who, what, who_args={}, what_args={}, window_args={}, - - def merge_style(style, properties): - -- if isinstance(style, basestring): -+ if isinstance(style, str): - style = getattr(renpy.store.style, style) - - if variant is not None: -@@ -764,7 +764,7 @@ class ADVCharacter(object): - if not (self.condition is None or renpy.python.py_eval(self.condition)): - return True - -- if not isinstance(what, basestring): -+ if not isinstance(what, str): - raise Exception("Character expects its what argument to be a string, got %r." % (what,)) - - self.resolve_say_attributes(False) -@@ -831,7 +831,7 @@ class ADVCharacter(object): - self.do_done(who, what) - - # Finally, log this line of dialogue. -- if who and isinstance(who, (str, unicode)): -+ if who and isinstance(who, str): - renpy.exports.log(who) - renpy.exports.log(what) - renpy.exports.log("") -diff --git a/renpy/color.py b/renpy/color.py -index 4bde2af..8df0c64 100644 ---- a/renpy/color.py -+++ b/renpy/color.py -@@ -123,7 +123,7 @@ class Color(tuple): - if len(c) == 3: - return tuple.__new__(cls, c + (int(255 * alpha),)) - -- if isinstance(c, basestring): -+ if isinstance(c, str): - if c[0] == '#': - c = c[1:] - -@@ -308,7 +308,7 @@ class Color(tuple): - `other` may be a string, Color or an HSV tuple. - """ - -- if isinstance(other, basestring): -+ if isinstance(other, str): - other = Color(other, alpha=self.alpha) - elif not isinstance(other, Color): - other = Color(hsv=other, alpha=self.alpha) -@@ -330,7 +330,7 @@ class Color(tuple): - `other` may be a string, Color or an HLS tuple. - """ - -- if isinstance(other, basestring): -+ if isinstance(other, str): - other = Color(other, alpha=self.alpha) - elif not isinstance(other, Color): - other = Color(hls=other, alpha=self.alpha) -diff --git a/renpy/common/00updater.rpy b/renpy/common/00updater.rpy -index b18dce0..6a35d66 100644 ---- a/renpy/common/00updater.rpy -+++ b/renpy/common/00updater.rpy -@@ -93,7 +93,7 @@ init -1500 python in updater: - time.sleep(3) - - try: -- log = file(DEFERRED_UPDATE_LOG, "ab") -+ log = open(DEFERRED_UPDATE_LOG, "ab") - except: - log = StringIO.StringIO() - -@@ -919,7 +919,7 @@ init -1500 python in updater: - break - - try: -- f = file(new_fn + ".part", "rb") -+ f = open(new_fn + ".part", "rb") - except: - self.log.write("partfile does not exist\n") - continue -@@ -1046,7 +1046,7 @@ init -1500 python in updater: - # Extract regular files. - tff = tf.extractfile(info) - new_path = path + ".new" -- f = file(new_path, "wb") -+ f = open(new_path, "wb") - - while True: - data = tff.read(1024 * 1024) -diff --git a/renpy/common/_developer/developer.rpym b/renpy/common/_developer/developer.rpym -index 27922d0..d3377c4 100644 ---- a/renpy/common/_developer/developer.rpym -+++ b/renpy/common/_developer/developer.rpym -@@ -496,7 +496,7 @@ label _filename_list: - - python hide: - import os -- f = file("files.txt", "w") -+ f = open("files.txt", "w") - - for dirname, dirs, files in os.walk(config.gamedir): - -diff --git a/renpy/curry.py b/renpy/curry.py -index f7266bf..4b47eaa 100644 ---- a/renpy/curry.py -+++ b/renpy/curry.py -@@ -35,7 +35,7 @@ class Curry(object): - - def __call__(self, *args, **kwargs): - return self.callable(*(self.args + args), -- **dict(self.kwargs.items() + kwargs.items())) -+ **dict(list(self.kwargs.items()) + list(kwargs.items()))) - def __repr__(self): - return "" % (self.callable, self.args, self.kwargs) - -diff --git a/renpy/display/anim.py b/renpy/display/anim.py -index 70c8fe4..fc31002 100644 ---- a/renpy/display/anim.py -+++ b/renpy/display/anim.py -@@ -120,7 +120,7 @@ class Edge(object): - self.prob = prob - - def add(self, sma): -- for _i in xrange(0, self.prob): -+ for _i in range(0, self.prob): - sma.edges.setdefault(self.old, []).append(self) - - -@@ -201,7 +201,7 @@ class SMAnimation(renpy.display.core.Displayable): - self.state = None - - def visit(self): -- return [ i.image for i in self.states.itervalues() ] -+ return [ i.image for i in self.states.values() ] - - def pick_edge(self, state): - """ -@@ -304,10 +304,10 @@ class SMAnimation(renpy.display.core.Displayable): - - args = [ ] - -- for state in self.states.itervalues(): -+ for state in self.states.values(): - args.append(state.motion_copy(child)) - -- for edges in self.edges.itervalues(): -+ for edges in self.edges.values(): - args.extend(edges) - - return SMAnimation(self.initial, delay=self.delay, *args, **self.properties) -diff --git a/renpy/display/behavior.py b/renpy/display/behavior.py -index e325abb..7c8849b 100644 ---- a/renpy/display/behavior.py -+++ b/renpy/display/behavior.py -@@ -30,6 +30,7 @@ from renpy.display.render import render, Render - import pygame_sdl2 as pygame - - import math -+import collections - - def compile_event(key, keydown): - """ -@@ -395,7 +396,7 @@ class Keymap(renpy.display.layout.Null): - - def event(self, ev, x, y, st): - -- for name, action in self.keymap.iteritems(): -+ for name, action in self.keymap.items(): - if map_event(ev, name): - - if self.style.activate_sound: -@@ -409,7 +410,7 @@ class Keymap(renpy.display.layout.Null): - raise renpy.display.core.IgnoreEvent() - - def predict_one_action(self): -- for i in self.keymap.itervalues(): -+ for i in self.keymap.values(): - predict_action(i) - - -@@ -634,7 +635,7 @@ class Button(renpy.display.layout.Window): - predict_action(self.alternate) - - if self.keymap: -- for v in self.keymap.itervalues(): -+ for v in self.keymap.values(): - predict_action(v) - - def render(self, width, height, st, at): -@@ -663,7 +664,7 @@ class Button(renpy.display.layout.Window): - try: - mask = renpy.display.render.render(mask, rv.width, rv.height, st, at) - except: -- if callable(mask): -+ if isinstance(mask, collections.Callable): - mask = mask - else: - raise Exception("Focus_mask must be None, True, a displayable, or a callable.") -@@ -776,7 +777,7 @@ class Button(renpy.display.layout.Window): - return None - - # Check the keymap. -- for name, action in self.keymap.iteritems(): -+ for name, action in self.keymap.items(): - if map_event(ev, name): - return run(action) - -@@ -881,7 +882,7 @@ class ImageButton(Button): - **properties) - - def visit(self): -- return self.state_children.values() -+ return list(self.state_children.values()) - - def get_child(self): - return self.style.child or self.state_children[self.style.prefix] -@@ -910,8 +911,8 @@ class Input(renpy.text.text.Text): #@UndefinedVariable - caret_pos = 0 - old_caret_pos = 0 - pixel_width = None -- default = u"" -- edit_text = u"" -+ default = "" -+ edit_text = "" - - def __init__(self, - default="", -@@ -930,7 +931,7 @@ class Input(renpy.text.text.Text): #@UndefinedVariable - - super(Input, self).__init__("", style=style, replaces=replaces, substitute=False, **properties) - -- self.default = unicode(default) -+ self.default = str(default) - self.content = self.default - - self.length = length -@@ -1017,7 +1018,7 @@ class Input(renpy.text.text.Text): #@UndefinedVariable - def set_content(content): - - if content == "": -- content = u"\u200b" -+ content = "\u200b" - - if editable: - l = len(content) -@@ -1131,8 +1132,8 @@ class Input(renpy.text.text.Text): #@UndefinedVariable - raw_text = ev.text - - elif ev.type == pygame.KEYDOWN: -- if ev.unicode and ord(ev.unicode[0]) >= 32: -- raw_text = ev.unicode -+ if ev.str and ord(ev.str[0]) >= 32: -+ raw_text = ev.str - elif renpy.display.interface.text_event_in_queue(): - raw_text = '' - -diff --git a/renpy/display/core.py b/renpy/display/core.py -index 5462336..3b708b8 100644 ---- a/renpy/display/core.py -+++ b/renpy/display/core.py -@@ -31,7 +31,7 @@ import pygame_sdl2 as pygame - import sys - import os - import time --import cStringIO -+import io - import threading - - import_time = time.time() -@@ -276,7 +276,7 @@ class Displayable(renpy.object.Object): - return self.__class__.__name__ - - def __repr__(self): -- return "<{} at {:x}>".format(unicode(self).encode("utf-8"), id(self)) -+ return "<{} at {:x}>".format(str(self).encode("utf-8"), id(self)) - - def find_focusable(self, callback, focus_name): - -@@ -963,7 +963,7 @@ class SceneLists(renpy.object.Object): - """ - - rv = [ ] -- for l in self.layers.itervalues(): -+ for l in self.layers.values(): - for sle in l: - rv.append(sle.displayable) - -@@ -976,7 +976,7 @@ class SceneLists(renpy.object.Object): - be displayed, or everything will be removed. - """ - -- for i in reversed(xrange(len(self.layers[layer]))): -+ for i in reversed(range(len(self.layers[layer]))): - - sle = self.layers[layer][i] - -@@ -1031,7 +1031,7 @@ class SceneLists(renpy.object.Object): - - # Have to iterate in reverse order, since otherwise - # the indexes might change. -- for i in reversed(xrange(len(self.layers[layer]))): -+ for i in reversed(range(len(self.layers[layer]))): - self.hide_or_replace(layer, i, hide) - - self.at_list[layer].clear() -@@ -1047,10 +1047,10 @@ class SceneLists(renpy.object.Object): - time with the given time. - """ - -- for l, (t, list) in self.layer_at_list.items(): #@ReservedAssignment -+ for l, (t, list) in list(self.layer_at_list.items()): #@ReservedAssignment - self.layer_at_list[l] = (t or time, list) - -- for l, ll in self.layers.iteritems(): -+ for l, ll in self.layers.items(): - self.layers[l] = [ i.update_time(time) for i in ll ] - - def showing(self, layer, name): -@@ -1590,7 +1590,7 @@ class Interface(object): - renpy.display.log.write(s) - - if renpy.android and not renpy.config.log_to_stdout: -- print s -+ print(s) - - def post_init(self): - """ -@@ -1893,7 +1893,7 @@ class Interface(object): - - self.screenshot_surface = surf - -- sio = cStringIO.StringIO() -+ sio = io.StringIO() - renpy.display.module.save_png(surf, sio, 0) - self.screenshot = sio.getvalue() - sio.close() -@@ -2006,7 +2006,7 @@ class Interface(object): - scene_lists = renpy.game.context().scene_lists - - # Compute the scene. -- for layer, d in self.compute_scene(scene_lists).iteritems(): -+ for layer, d in self.compute_scene(scene_lists).items(): - if layer not in self.transition: - self.old_scene[layer] = d - -@@ -2243,7 +2243,7 @@ class Interface(object): - - renpy.exports.free_memory() - -- print "Entered background." -+ print("Entered background.") - - while True: - ev = pygame.event.wait() -@@ -2254,7 +2254,7 @@ class Interface(object): - if ev.type == pygame.APP_TERMINATING: - sys.exit(0) - -- print "Entering foreground." -+ print("Entering foreground.") - - # Since we came back to life, we can get rid of the - # auto-reload. -@@ -2583,7 +2583,7 @@ class Interface(object): - renpy.display.tts.set_root(scene[None]) - - # If necessary, load all images here. -- for w in scene.itervalues(): -+ for w in scene.values(): - try: - renpy.display.predict.displayable(w) - except: -@@ -2766,7 +2766,7 @@ class Interface(object): - - if first_pass: - scene_lists.set_times(self.interact_time) -- for k, v in self.transition_time.iteritems(): -+ for k, v in self.transition_time.items(): - if v is None: - self.transition_time[k] = self.interact_time - -@@ -2777,8 +2777,8 @@ class Interface(object): - new_time = get_time() - - if self.profile_once or (new_time - self.profile_time > .015): -- print "Profile: Redraw took %.3f ms." % (1000 * (new_time - self.frame_time)) -- print "Profile: %.3f ms to complete event." % (1000 * (new_time - self.profile_time)) -+ print("Profile: Redraw took %.3f ms." % (1000 * (new_time - self.frame_time))) -+ print("Profile: %.3f ms to complete event." % (1000 * (new_time - self.profile_time))) - - self.profile_once = False - -diff --git a/renpy/display/dragdrop.py b/renpy/display/dragdrop.py -index 8816ee0..34aed98 100644 ---- a/renpy/display/dragdrop.py -+++ b/renpy/display/dragdrop.py -@@ -28,6 +28,7 @@ from renpy.display.core import absolute - from renpy.display.behavior import map_event, run, run_unhovered - - import pygame_sdl2 as pygame -+import collections - - def default_drag_group(): - """ -@@ -449,7 +450,7 @@ class Drag(renpy.display.core.Displayable, renpy.python.RevertableObject): - try: - mask = renpy.display.render.render(mask, fw, fh, st, at) - except: -- if callable(mask): -+ if isinstance(mask, collections.Callable): - mask = mask - else: - raise Exception("Focus_mask must be None, True, a displayable, or a callable.") -diff --git a/renpy/display/im.py b/renpy/display/im.py -index de4a043..52f22d5 100644 ---- a/renpy/display/im.py -+++ b/renpy/display/im.py -@@ -27,7 +27,7 @@ import renpy.display - - import math - import zipfile --import cStringIO -+import io - import threading - import time - -@@ -266,7 +266,7 @@ class Cache(object): - # If we're outside the cache limit, we need to go and start - # killing off some of the entries until we're back inside it. - -- for ce in sorted(self.cache.itervalues(), key=lambda a : a.time): -+ for ce in sorted(iter(self.cache.values()), key=lambda a : a.time): - - if ce.time == self.time: - # If we're bigger than the limit, and there's nothing -@@ -375,7 +375,7 @@ class Cache(object): - - # Remove things that are not in the workset from the pin cache, - # and remove things that are in the workset from pin cache. -- for i in self.pin_cache.keys(): -+ for i in list(self.pin_cache.keys()): - - if i in workset: - workset.remove(i) -@@ -509,9 +509,9 @@ class Image(ImageBase): - - def __unicode__(self): - if len(self.filename) < 20: -- return u"Image %r" % self.filename -+ return "Image %r" % self.filename - else: -- return u"Image \u2026%s" % self.filename[-20:] -+ return "Image \u2026%s" % self.filename[-20:] - - - def get_hash(self): -@@ -530,7 +530,7 @@ class Image(ImageBase): - - return surf - -- except Exception, e: -+ except Exception as e: - - if renpy.config.missing_image_callback: - im = renpy.config.missing_image_callback(self.filename) -@@ -565,7 +565,7 @@ class ZipFileImage(ImageBase): - try: - zf = zipfile.ZipFile(self.zipfilename, 'r') - data = zf.read(self.filename) -- sio = cStringIO.StringIO(data) -+ sio = io.StringIO(data) - rv = renpy.display.pgrender.load_image(sio, self.filename) - zf.close() - return rv -@@ -1562,7 +1562,7 @@ def image(arg, loose=False, **properties): - if isinstance(arg, ImageBase): - return arg - -- elif isinstance(arg, basestring): -+ elif isinstance(arg, str): - return Image(arg, **properties) - - elif isinstance(arg, renpy.display.image.ImageReference): -@@ -1608,7 +1608,7 @@ def load_surface(im): - - - def reset_module(): -- print "Resetting cache." -+ print("Resetting cache.") - - global cache - cache = Cache() -diff --git a/renpy/display/image.py b/renpy/display/image.py -index e5ae353..64574c3 100644 ---- a/renpy/display/image.py -+++ b/renpy/display/image.py -@@ -45,7 +45,7 @@ def get_available_image_tags(): - Returns a list of image tags that have been defined. - """ - -- return [ k for k, v in image_attributes.items() if v ] -+ return [ k for k, v in list(image_attributes.items()) if v ] - - def get_available_image_attributes(tag, attributes=()): - """ -@@ -149,7 +149,7 @@ class ImageReference(renpy.display.core.Displayable): - self.name = name - - def __unicode__(self): -- return u"".format(self.name) -+ return "".format(self.name) - - def __hash__(self): - return hash(self.name) -@@ -215,7 +215,7 @@ class ImageReference(renpy.display.core.Displayable): - - self.param_target = self.target - -- except Exception, e: -+ except Exception as e: - if renpy.config.debug: - raise - -@@ -323,7 +323,7 @@ class DynamicImage(renpy.display.core.Displayable): - return self.find_target(scope, update) - - def __unicode__(self): -- return u"DynamicImage {!r}".format(self.name) -+ return "DynamicImage {!r}".format(self.name) - - def __hash__(self): - return hash(self.name) -@@ -514,7 +514,7 @@ class ShownImageInfo(renpy.object.Object): - if layer is None: - layer = 'master' - -- for l, t in self.attributes.keys(): -+ for l, t in list(self.attributes.keys()): - if l == layer: - del self.attributes[l, t] - -diff --git a/renpy/display/imagelike.py b/renpy/display/imagelike.py -index d8b9201..3f9a6b3 100644 ---- a/renpy/display/imagelike.py -+++ b/renpy/display/imagelike.py -@@ -275,8 +275,8 @@ class Frame(renpy.display.core.Displayable): - newcr = Render(cdw, cdh) - newcr.clipping = True - -- for x in xrange(0, cdw, csw): -- for y in xrange(0, cdh, csh): -+ for x in range(0, cdw, csw): -+ for y in range(0, cdh, csh): - newcr.blit(cr, (x, y)) - - cr = newcr -diff --git a/renpy/display/layout.py b/renpy/display/layout.py -index 7ded388..3b2fd9f 100644 ---- a/renpy/display/layout.py -+++ b/renpy/display/layout.py -@@ -180,7 +180,7 @@ class Container(renpy.display.core.Displayable): - if len(offsets) != len(children): - return None - -- for i in xrange(len(offsets) - 1, -1, -1): -+ for i in range(len(offsets) - 1, -1, -1): - - d = children[i] - xo, yo = offsets[i] -@@ -641,9 +641,9 @@ class MultiBox(Container): - rv = None - - if self.style.order_reverse: -- iterator = zip(reversed(self.children), reversed(csts), reversed(cats)) -+ iterator = list(zip(reversed(self.children), reversed(csts), reversed(cats))) - else: -- iterator = zip(self.children, csts, cats) -+ iterator = list(zip(self.children, csts, cats)) - - for child, cst, cat in iterator: - -@@ -889,7 +889,7 @@ class MultiBox(Container): - - def event(self, ev, x, y, st): - -- children_offsets = zip(self.children, self.offsets, self.start_times) -+ children_offsets = list(zip(self.children, self.offsets, self.start_times)) - - if not self.style.order_reverse: - children_offsets.reverse() -@@ -1126,7 +1126,7 @@ class DynamicDisplayable(renpy.display.core.Displayable): - super(DynamicDisplayable, self).__init__() - self.child = None - -- if isinstance(function, basestring): -+ if isinstance(function, str): - args = ( function, ) - kwargs = { } - function = dynamic_displayable_compat -@@ -1669,7 +1669,7 @@ class Side(Container): - - super(Side, self).__init__(style=style, **properties) - -- if isinstance(positions, basestring): -+ if isinstance(positions, str): - positions = positions.split() - - seen = set() -diff --git a/renpy/display/module.py b/renpy/display/module.py -index 24c0f7d..de7ad91 100644 ---- a/renpy/display/module.py -+++ b/renpy/display/module.py -@@ -172,11 +172,11 @@ def twomap(src, dst, white, black): - wb + 1, - wa + 1) - else: -- map(src, dst, -+ list(map(src, dst, - ramp(br, wr), - ramp(bg, wg), - ramp(bb, wb), -- ramp(0, wa)) -+ ramp(0, wa))) - - - def alpha_munge(src, dst, amap): -diff --git a/renpy/display/motion.py b/renpy/display/motion.py -index c80ae9e..d24b2d8 100644 ---- a/renpy/display/motion.py -+++ b/renpy/display/motion.py -@@ -542,7 +542,7 @@ class Transform(Container): - self.arguments = { } - - # Fill self.arguments with a -- for k, v in kwargs.iteritems(): -+ for k, v in kwargs.items(): - - prefix = "" - prop = k -@@ -568,7 +568,7 @@ class Transform(Container): - prefix = new_prefix - - if "" in self.arguments: -- for k, v in self.arguments[""].iteritems(): -+ for k, v in self.arguments[""].items(): - setattr(self.state, k, v) - - else: -@@ -627,7 +627,7 @@ class Transform(Container): - if d is None: - continue - -- for k, v in d.iteritems(): -+ for k, v in d.items(): - setattr(state, k, v) - - return None -@@ -803,7 +803,7 @@ class Transform(Container): - if not offsets: - return None - -- for i in xrange(len(self.children)-1, -1, -1): -+ for i in range(len(self.children)-1, -1, -1): - - d = children[i] - xo, yo = offsets[i] -@@ -1221,10 +1221,11 @@ class Revolver(object): - self.pos = pos - self.child = child - -- def __call__(self, t, (w, h, cw, ch)): -+ def __call__(self, t, xxx_todo_changeme): - - # Converts a float to an integer in the given range, passes - # integers through unchanged. -+ (w, h, cw, ch) = xxx_todo_changeme - def fti(x, r): - if x is None: - x = 0 -diff --git a/renpy/display/particle.py b/renpy/display/particle.py -index f821dc8..959fce1 100644 ---- a/renpy/display/particle.py -+++ b/renpy/display/particle.py -@@ -295,7 +295,7 @@ class SpriteManager(renpy.display.core.Displayable): - return rv - - def event(self, ev, x, y, st): -- for i in xrange(len(self.children) -1, -1, -1): -+ for i in range(len(self.children) -1, -1, -1): - s = self.children[i] - - if s.events: -@@ -432,7 +432,7 @@ class SnowBlossomFactory(renpy.python.NoRollback): - self.init() - - def init(self): -- self.starts = [ random.uniform(0, self.start) for _i in xrange(0, self.count) ] # W0201 -+ self.starts = [ random.uniform(0, self.start) for _i in range(0, self.count) ] # W0201 - self.starts.append(self.start) - self.starts.sort() - -@@ -447,7 +447,7 @@ class SnowBlossomFactory(renpy.python.NoRollback): - if (st == 0) and not particles and self.fast: - rv = [ ] - -- for _i in xrange(0, self.count): -+ for _i in range(0, self.count): - rv.append(SnowBlossomParticle(self.image, - ranged(self.xspeed), - ranged(self.yspeed), -diff --git a/renpy/display/pgrender.py b/renpy/display/pgrender.py -index 9418095..c86000e 100644 ---- a/renpy/display/pgrender.py -+++ b/renpy/display/pgrender.py -@@ -87,14 +87,14 @@ class Surface(pygame.Surface): - rv = pygame.Surface.subsurface(self, rect) - return rv - --def surface((width, height), alpha): -+def surface(xxx_todo_changeme, alpha): - """ - Constructs a new surface. The allocated surface is actually a subsurface - of a surface that has a 2 pixel border in all directions. - - `alpha` - True if the new surface should have an alpha channel. - """ -- -+ (width, height) = xxx_todo_changeme - if isinstance(alpha, pygame.Surface): - alpha = alpha.get_masks()[3] - -diff --git a/renpy/display/predict.py b/renpy/display/predict.py -index 2b37a9f..305e0b5 100644 ---- a/renpy/display/predict.py -+++ b/renpy/display/predict.py -@@ -120,7 +120,7 @@ def prediction_coroutine(root_widget): - if len(renpy.game.contexts) >= 2: - sls = renpy.game.contexts[-2].scene_lists - -- for l in sls.layers.itervalues(): -+ for l in sls.layers.values(): - for sle in l: - try: - displayable(sle.displayable) -@@ -138,7 +138,7 @@ def prediction_coroutine(root_widget): - - - # Predict screens given with renpy.start_predict_screen. -- for name, value in renpy.store._predict_screen.items(): -+ for name, value in list(renpy.store._predict_screen.items()): - args, kwargs = value - - renpy.display.screen.predict_screen(name, *args, **kwargs) -diff --git a/renpy/display/screen.py b/renpy/display/screen.py -index 585c6bf..622ba60 100644 ---- a/renpy/display/screen.py -+++ b/renpy/display/screen.py -@@ -103,7 +103,7 @@ class ScreenProfile(renpy.object.Object): - self.const = const - - if name is not None: -- if isinstance(name, basestring): -+ if isinstance(name, str): - name = tuple(name.split()) - profile[name] = self - -@@ -116,7 +116,7 @@ def get_profile(name): - A string or tuple. - """ - -- if isinstance(name, basestring): -+ if isinstance(name, str): - name = tuple(name.split()) - - if name in profile: -@@ -202,7 +202,7 @@ class Screen(renpy.object.Object): - location=None): - - # The name of this screen. -- if isinstance(name, basestring): -+ if isinstance(name, str): - name = tuple(name.split()) - - self.name = name -@@ -700,7 +700,7 @@ def get_all_screen_variants(name): - - rv = [ ] - -- for k, v in screens.iteritems(): -+ for k, v in screens.items(): - if k[0] == name: - rv.append((k[1], v)) - -@@ -733,7 +733,7 @@ def sort_screens(): - # For each screen, the set of screens that use it. - reverse = collections.defaultdict(set) - -- for k, v in screens.items(): -+ for k, v in list(screens.items()): - - name = k[0] - -@@ -751,7 +751,7 @@ def sort_screens(): - - rv = [ ] - -- workset = { k for k, v in depends.items() if not len(v) } -+ workset = { k for k, v in list(depends.items()) if not len(v) } - - while workset: - name = workset.pop() -@@ -782,7 +782,7 @@ def sorted_variants(): - rv = [ ] - - for name in sort_screens(): -- rv.extend(screens_by_name[name].values()) -+ rv.extend(list(screens_by_name[name].values())) - - return rv - -@@ -892,7 +892,7 @@ def get_screen(name, layer="screens"): - - """ - -- if isinstance(name, basestring): -+ if isinstance(name, str): - name = (name, ) - - sl = renpy.exports.scene_lists() -@@ -1057,7 +1057,7 @@ def predict_screen(_screen_name, *_args, **kwargs): - if renpy.config.debug_image_cache: - import traceback - -- print "While predicting screen", _screen_name -+ print("While predicting screen", _screen_name) - traceback.print_exc() - - renpy.ui.reset() -@@ -1175,7 +1175,7 @@ def before_restart(): - longer defined. - """ - -- for k, layer in renpy.display.interface.old_scene.iteritems(): -+ for k, layer in renpy.display.interface.old_scene.items(): - if k is None: - continue - -diff --git a/renpy/display/swdraw.py b/renpy/display/swdraw.py -index 1f620f1..a90e524 100644 ---- a/renpy/display/swdraw.py -+++ b/renpy/display/swdraw.py -@@ -303,7 +303,7 @@ def draw_special(what, dest, x, y): - - ramp = "\x00" * 256 - -- for i in xrange(0, ramplen): -+ for i in range(0, ramplen): - ramp += chr(255 * i / ramplen) - - ramp += "\xff" * 256 -diff --git a/renpy/dump.py b/renpy/dump.py -index f047146..c01a960 100644 ---- a/renpy/dump.py -+++ b/renpy/dump.py -@@ -113,14 +113,14 @@ def dump(error): - # Labels. - label = location["label"] = { } - -- for name, n in renpy.game.script.namemap.iteritems(): -+ for name, n in renpy.game.script.namemap.items(): - filename = n.filename - line = n.linenumber - -- if not isinstance(name, basestring): -+ if not isinstance(name, str): - continue - -- if not filter(name, filename): -+ if not list(filter(name, filename)): - continue - - label[name] = [ filename, line ] -@@ -130,7 +130,7 @@ def dump(error): - define = location["define"] = { } - - for name, filename, line in definitions: -- if not filter(name, filename): -+ if not list(filter(name, filename)): - continue - - define[name] = [ filename, line ] -@@ -139,7 +139,7 @@ def dump(error): - screen = location["screen"] = { } - - for name, filename, line in screens: -- if not filter(name, filename): -+ if not list(filter(name, filename)): - continue - - screen[name] = [ filename, line ] -@@ -148,7 +148,7 @@ def dump(error): - transform = location["transform"] = { } - - for name, filename, line in transforms: -- if not filter(name, filename): -+ if not list(filter(name, filename)): - continue - - transform[name] = [ filename, line ] -@@ -166,16 +166,16 @@ def dump(error): - """ - - if inspect.isfunction(o): -- return inspect.getfile(o), o.func_code.co_firstlineno -+ return inspect.getfile(o), o.__code__.co_firstlineno - - if inspect.ismethod(o): -- return get_line(o.im_func) -+ return get_line(o.__func__) - - return None, None - - code = location["callable"] = { } - -- for modname, mod in sys.modules.items(): -+ for modname, mod in list(sys.modules.items()): - - if mod is None: - continue -@@ -187,7 +187,7 @@ def dump(error): - else: - continue - -- for name, o in mod.__dict__.items(): -+ for name, o in list(mod.__dict__.items()): - - if inspect.isfunction(o): - try: -@@ -199,7 +199,7 @@ def dump(error): - if filename is None: - continue - -- if not filter(name, filename): -+ if not list(filter(name, filename)): - continue - - code[prefix + name] = [ filename, line ] -@@ -208,7 +208,7 @@ def dump(error): - - if inspect.isclass(o): - -- for methname, method in o.__dict__.iteritems(): -+ for methname, method in o.__dict__.items(): - - try: - if inspect.getmodule(method) != mod: -@@ -219,10 +219,10 @@ def dump(error): - if filename is None: - continue - -- if not filter(name, filename): -+ if not list(filter(name, filename)): - continue - -- if not filter(methname, filename): -+ if not list(filter(methname, filename)): - continue - - code[prefix + name + "." + methname] = [ filename, line ] -@@ -236,7 +236,7 @@ def dump(error): - pass - - if args.json_dump != "-": -- with file(args.json_dump, "w") as f: -+ with open(args.json_dump, "w") as f: - json.dump(result, f) - else: - json.dump(result, sys.stdout, indent=2) -diff --git a/renpy/easy.py b/renpy/easy.py -index 6aacea1..85f3d17 100644 ---- a/renpy/easy.py -+++ b/renpy/easy.py -@@ -36,7 +36,7 @@ def displayable_or_none(d, scope=None): - if d is None: - return d - -- if isinstance(d, basestring): -+ if isinstance(d, str): - if not d: - raise Exception("An empty string cannot be used as a displayable.") - elif ("[" in d) and renpy.config.dynamic_images: -@@ -70,7 +70,7 @@ def displayable(d, scope=None): - if isinstance(d, renpy.display.core.Displayable): - return d - -- if isinstance(d, basestring): -+ if isinstance(d, str): - if not d: - raise Exception("An empty string cannot be used as a displayable.") - elif ("[" in d) and renpy.config.dynamic_images: -@@ -97,7 +97,7 @@ def dynamic_image(d, scope=None): - Substitutes a scope into `d`, then returns a displayable. - """ - -- if isinstance(d, basestring): -+ if isinstance(d, str): - d = renpy.substitutions.substitute(d, scope=scope, force=True, translate=False)[0] - - return displayable_or_none(d) -@@ -114,7 +114,7 @@ def predict(d): - def timed(name): - start = time.time() - yield -- print "{0}: {1:.2f} ms".format(name, (time.time() - start) * 1000.0) -+ print("{0}: {1:.2f} ms".format(name, (time.time() - start) * 1000.0)) - - - def split_properties(properties, *prefixes): -@@ -145,7 +145,7 @@ def split_properties(properties, *prefixes): - - prefix_d = list(zip(prefixes, rv)) - -- for k, v in properties.iteritems(): -+ for k, v in properties.items(): - for prefix, d in prefix_d: - if k.startswith(prefix): - d[k[len(prefix):]] = v -diff --git a/renpy/editor.py b/renpy/editor.py -index 7be4c32..bac80f7 100644 ---- a/renpy/editor.py -+++ b/renpy/editor.py -@@ -114,7 +114,7 @@ def init(): - return - - scope = { "__file__" : path } -- execfile(path, scope, scope) -+ exec(compile(open(path).read(), path, 'exec'), scope, scope) - - if "Editor" in scope: - editor = scope["Editor"]() -diff --git a/renpy/error.py b/renpy/error.py -index d70fe2a..513cd73 100644 ---- a/renpy/error.py -+++ b/renpy/error.py -@@ -23,7 +23,7 @@ - - import traceback - import sys --import cStringIO -+import io - import platform - import linecache - -@@ -43,8 +43,8 @@ def write_utf8_traceback_list(out, l): - for filename, line, what, text in l: - - # Filename is either unicode or an fsecoded string. -- if not isinstance(filename, unicode): -- filename = unicode(filename, FSENCODING, "replace") -+ if not isinstance(filename, str): -+ filename = str(filename, FSENCODING, "replace") - - # Line is a number. - -@@ -52,12 +52,12 @@ def write_utf8_traceback_list(out, l): - # or comes from inside Ren'Py. - - if isinstance(text, str): -- text = text.decode("utf-8", "replace") -+ text = text.encode(errors="replace").decode("utf-8", "replace") - - ul.append((filename, line, what, text)) - - for t in traceback.format_list(ul): -- out.write(t.encode("utf-8", "replace")) -+ out.write(str(t.encode("utf-8", "replace"), errors="replace")) - - - def traceback_list(tb): -@@ -127,13 +127,13 @@ def open_error_file(fn, mode): - - try: - new_fn = os.path.join(renpy.config.logdir, fn) -- f = file(new_fn, mode) -+ f = open(new_fn, mode) - return f, new_fn - except: - pass - - try: -- f = file(fn, mode) -+ f = open(fn, mode) - return f, fn - except: - pass -@@ -141,7 +141,7 @@ def open_error_file(fn, mode): - import tempfile - - new_fn = os.path.join(tempfile.gettempdir(), "renpy-" + fn) -- return file(new_fn, mode), new_fn -+ return open(new_fn, mode), new_fn - - def report_exception(e, editor=True): - """ -@@ -157,11 +157,11 @@ def report_exception(e, editor=True): - - type, _value, tb = sys.exc_info() #@ReservedAssignment - -- print(repr(e)) -+ print((repr(e))) - - def safe_utf8(e): - try: -- m = unicode(e) -+ m = str(e) - except: - try: - if len(e.args) == 0: -@@ -176,27 +176,27 @@ def report_exception(e, editor=True): - except: - m = "" - -- if isinstance(m, unicode): -+ if isinstance(m, str): - return m.encode("utf-8", "replace") - else: - return m - - # Return values - which can be displayed to the user. -- simple = cStringIO.StringIO() -- full = cStringIO.StringIO() -+ simple = io.StringIO() -+ full = io.StringIO() - - full_tl = traceback_list(tb) - simple_tl = filter_traceback_list(full_tl) - -- print >>simple, renpy.game.exception_info -+ print(renpy.game.exception_info, file=simple) - write_utf8_traceback_list(simple, simple_tl) -- print >>simple, type.__name__ + ":", -- print >>simple, safe_utf8(e) -+ print(type.__name__ + ":", end=' ', file=simple) -+ print(safe_utf8(e), file=simple) - -- print >>full, "Full traceback:" -+ print("Full traceback:", file=full) - write_utf8_traceback_list(full, full_tl) -- print >>full, type.__name__ + ":", -- print >>full, safe_utf8(e) -+ print(type.__name__ + ":", end=' ', file=full) -+ print(safe_utf8(e), file=full) - - # Write to stdout/stderr. - sys.stdout.write("\n") -@@ -204,11 +204,11 @@ def report_exception(e, editor=True): - sys.stdout.write("\n") - sys.stdout.write(simple.getvalue()) - -- print >>full -+ print(file=full) - try: -- print >>full, platform.platform() -- print >>full, renpy.version -- print >>full, renpy.config.name + " " + renpy.config.version -+ print(platform.platform(), file=full) -+ print(renpy.version, file=full) -+ print(renpy.config.name + " " + renpy.config.version, file=full) - except: - pass - -@@ -223,14 +223,14 @@ def report_exception(e, editor=True): - - f.write(codecs.BOM_UTF8) - -- print >>f, "I'm sorry, but an uncaught exception occurred." -- print >>f -+ print("I'm sorry, but an uncaught exception occurred.", file=f) -+ print(file=f) - - f.write(simple) - -- print >>f -- print >>f, "-- Full Traceback ------------------------------------------------------------" -- print >>f -+ print(file=f) -+ print("-- Full Traceback ------------------------------------------------------------", file=f) -+ print(file=f) - - f.write(full) - f.close() -@@ -249,6 +249,6 @@ def report_exception(e, editor=True): - except: - pass - -- return simple.decode("utf-8", "replace"), full.decode("utf-8", "replace"), traceback_fn -+ return simple.encode(errors="replace").decode("utf-8", "replace"), full.encode(errors="replace").decode("utf-8", "replace"), traceback_fn - - -diff --git a/renpy/execution.py b/renpy/execution.py -index 224c631..a41b59a 100644 ---- a/renpy/execution.py -+++ b/renpy/execution.py -@@ -210,7 +210,7 @@ class Context(renpy.object.Object): - - vars(self.info).update(vars(context.info)) - -- for k, v in context.music.iteritems(): -+ for k, v in context.music.items(): - self.music[k] = v.copy() - - self.images = renpy.display.image.ShownImageInfo(context.images) -@@ -279,7 +279,7 @@ class Context(renpy.object.Object): - - dynamic = self.dynamic_stack.pop() - -- for k, v in dynamic.iteritems(): -+ for k, v in dynamic.items(): - if isinstance(v, Delete): - del store[k] - else: -@@ -390,14 +390,14 @@ class Context(renpy.object.Object): - if developer and self.next_node: - self.check_stacks() - -- except renpy.game.CONTROL_EXCEPTIONS, e: -+ except renpy.game.CONTROL_EXCEPTIONS as e: - - # An exception ends the current translation. - self.translate_interaction = None - - raise - -- except Exception, e: -+ except Exception as e: - self.translate_interaction = None - - exc_info = sys.exc_info() -@@ -408,18 +408,18 @@ class Context(renpy.object.Object): - self.exception_handler(short, full, traceback_fn) - elif renpy.display.error.report_exception(short, full, traceback_fn): - raise -- except renpy.game.CONTROL_EXCEPTIONS, ce: -+ except renpy.game.CONTROL_EXCEPTIONS as ce: - raise ce -- except Exception, ce: -- raise exc_info[0], exc_info[1], exc_info[2] -+ except Exception as ce: -+ raise exc_info[0](exc_info[1]).with_traceback(exc_info[2]) - - node = self.next_node - -- except renpy.game.JumpException, e: -+ except renpy.game.JumpException as e: - node = renpy.game.script.lookup(e.args[0]) - self.abnormal = True - -- except renpy.game.CallException, e: -+ except renpy.game.CallException as e: - - if self.next_node is None: - raise Exception("renpy.call can't be used when the next node is undefined.") -@@ -495,7 +495,7 @@ class Context(renpy.object.Object): - if renpy.game.script.has_label(self.return_stack[-1]): - node = renpy.game.script.lookup(self.return_stack[-1]) - elif renpy.game.script.has_label(self.call_location_stack[-1]): -- node = renpy.game.script.lookup(self.call_location_stack[-1]).next -+ node = renpy.game.script.lookup(self.call_location_stack[-1]).__next__ - - if node is None: - -@@ -629,9 +629,9 @@ class Context(renpy.object.Object): - if renpy.config.debug_image_cache: - import traceback - -- print -+ print() - traceback.print_exc() -- print "While predicting images." -+ print("While predicting images.") - - self.images = old_images - self.predict_return_stack = None -diff --git a/renpy/exports.py b/renpy/exports.py -index faccd36..82bc282 100644 ---- a/renpy/exports.py -+++ b/renpy/exports.py -@@ -25,7 +25,7 @@ - # alone as part of the api. - - # Remember the real file. --_file = file -+_file = open - - import renpy.display - import renpy.audio -@@ -39,7 +39,7 @@ def renpy_pure(fn): - - name = fn - -- if not isinstance(name, basestring): -+ if not isinstance(name, str): - name = fn.__name__ - - pure("renpy." + name) -@@ -371,7 +371,7 @@ def copy_images(old, new): - - lenold = len(old) - -- for k, v in renpy.display.image.images.items(): -+ for k, v in list(renpy.display.image.images.items()): - if len(k) < lenold: - continue - -@@ -495,7 +495,7 @@ def predict_show(name, layer=None, what=None, tag=None, at_list=[ ]): - - if what is None: - what = name -- elif isinstance(what, basestring): -+ elif isinstance(what, str): - what = tuple(what.split()) - - if isinstance(what, renpy.display.core.Displayable): -@@ -593,7 +593,7 @@ def show(name, at_list=[ ], layer=None, what=None, zorder=None, tag=None, behind - - if what is None: - what = name -- elif isinstance(what, basestring): -+ elif isinstance(what, str): - what = tuple(what.split()) - - if isinstance(what, renpy.display.core.Displayable): -@@ -740,7 +740,7 @@ def input(prompt, default='', allow=None, exclude='{}', length=None, with_none=N - renpy.exports.mode('input') - - roll_forward = renpy.exports.roll_forward_info() -- if not isinstance(roll_forward, basestring): -+ if not isinstance(roll_forward, str): - roll_forward = None - - # use previous data in rollback -@@ -1038,7 +1038,7 @@ class TagQuotingDict(object): - if key in store: - rv = store[key] - -- if isinstance(rv, (str, unicode)): -+ if isinstance(rv, str): - rv = rv.replace("{", "{{") - - return rv -@@ -1060,7 +1060,7 @@ def predict_say(who, what): - if who is None: - who = renpy.store.narrator # E1101 @UndefinedVariable - -- if isinstance(who, (str, unicode)): -+ if isinstance(who, str): - return renpy.store.predict_say(who, what) - - predict = getattr(who, 'predict', None) -@@ -1115,7 +1115,7 @@ def say(who, what, interact=True): - if who is None: - who = renpy.store.narrator # E1101 @UndefinedVariable - -- if isinstance(who, (str, unicode)): -+ if isinstance(who, str): - renpy.store.say(who, what, interact=interact) - else: - who(what, interact=interact) -@@ -1444,8 +1444,8 @@ def get_all_labels(): - """ - rv = [ ] - -- for i in renpy.game.script.namemap.iterkeys(): -- if isinstance(i, basestring): -+ for i in renpy.game.script.namemap.keys(): -+ if isinstance(i, str): - rv.append(i) - - return renpy.python.RevertableSet(rv) -@@ -1792,7 +1792,7 @@ def log(msg): - - import textwrap - -- print >>logfile, textwrap.fill(msg, renpy.config.log_width).encode("utf-8") -+ print(textwrap.fill(msg, renpy.config.log_width).encode("utf-8"), file=logfile) - logfile.flush() - - except: -@@ -1908,7 +1908,7 @@ def seen_image(name): - return name in renpy.game.persistent._seen_images # @UndefinedVariable - - --def file(fn): #@ReservedAssignment -+def open(fn): #@ReservedAssignment - """ - :doc: file - -@@ -1958,7 +1958,7 @@ def get_at_list(name, layer=None): - If `layer` is None, uses the default layer for the given tag. - """ - -- if isinstance(name, basestring): -+ if isinstance(name, str): - name = tuple(name.split()) - - tag = name[0] -@@ -2173,7 +2173,7 @@ def load_string(s, filename=""): - old_locked = renpy.config.locked - renpy.config.locked = False - -- stmts, initcode = renpy.game.script.load_string(filename, unicode(s)) -+ stmts, initcode = renpy.game.script.load_string(filename, str(s)) - - if stmts is None: - return None -@@ -2459,7 +2459,7 @@ def call_screen(_screen_name, *args, **kwargs): - - try: - rv = renpy.ui.interact(mouse="screen", type="screen", roll_forward=roll_forward) -- except (renpy.game.JumpException, renpy.game.CallException), e: -+ except (renpy.game.JumpException, renpy.game.CallException) as e: - rv = e - - renpy.exports.checkpoint(rv) -@@ -2616,7 +2616,7 @@ def variant(name): - returns True if any of the variants is selected. - """ - -- if isinstance(name, basestring): -+ if isinstance(name, str): - return name in renpy.config.variants - else: - for n in name: -@@ -2745,7 +2745,7 @@ def fsencode(s): - Converts s from unicode to the filesystem encoding. - """ - -- if not isinstance(s, unicode): -+ if not isinstance(s, str): - return s - - fsencoding = sys.getfilesystemencoding() or "utf-8" -diff --git a/renpy/game.py b/renpy/game.py -index d66800c..1ba0fe5 100644 ---- a/renpy/game.py -+++ b/renpy/game.py -@@ -264,7 +264,7 @@ def invoke_in_new_context(callable, *args, **kwargs): #@ReservedAssignment - - return callable(*args, **kwargs) - -- except renpy.game.JumpOutException, e: -+ except renpy.game.JumpOutException as e: - - raise renpy.game.JumpException(e.args[0]) - -@@ -312,7 +312,7 @@ def call_in_new_context(label, *args, **kwargs): - context.goto_label(label) - return renpy.execution.run_context(False) - -- except renpy.game.JumpOutException, e: -+ except renpy.game.JumpOutException as e: - - raise renpy.game.JumpException(e.args[0]) - -@@ -350,7 +350,7 @@ def call_replay(label, scope={}): - - renpy.exports.execute_default_statement(True) - -- for k, v in scope.iteritems(): -+ for k, v in scope.items(): - setattr(renpy.store, k, v) - - renpy.store._in_replay = label -diff --git a/renpy/lint.py b/renpy/lint.py -index 088b89c..b6f131c 100644 ---- a/renpy/lint.py -+++ b/renpy/lint.py -@@ -28,9 +28,9 @@ import sys - import collections - import textwrap - --import __builtin__ -+import builtins - --python_builtins = set(dir(__builtin__)) -+python_builtins = set(dir(builtins)) - renpy_builtins = set() - - image_prefixes = None -@@ -53,13 +53,13 @@ report_node = None - # Reports a message to the user. - def report(msg, *args): - if report_node: -- out = u"%s:%d " % (renpy.parser.unicode_filename(report_node.filename), report_node.linenumber) -+ out = "%s:%d " % (renpy.parser.unicode_filename(report_node.filename), report_node.linenumber) - else: - out = "" - - out += msg % args -- print -- print out.encode('utf-8') -+ print() -+ print(out.encode('utf-8')) - - added = { } - -@@ -68,7 +68,7 @@ added = { } - def add(msg): - if not msg in added: - added[msg] = True -- print unicode(msg).encode('utf-8') -+ print(str(msg).encode('utf-8')) - - - # Trys to evaluate an expression, announcing an error if it fails. -@@ -473,7 +473,7 @@ def check_define(node, kind): - def check_style(name, s): - - for p in s.properties: -- for k, v in p.iteritems(): -+ for k, v in p.items(): - - kname = name + ", property " + k - -@@ -504,7 +504,7 @@ def check_label(node): - - - def check_styles(): -- for full_name, s in renpy.style.styles.iteritems(): # @UndefinedVariable -+ for full_name, s in renpy.style.styles.items(): # @UndefinedVariable - name = "style." + full_name[0] - for i in full_name[1:]: - name += "[{!r}]".format(i) -@@ -588,8 +588,8 @@ def lint(): - - renpy.game.lint = True - -- print codecs.BOM_UTF8 -- print unicode(renpy.version + " lint report, generated at: " + time.ctime()).encode("utf-8") -+ print(codecs.BOM_UTF8) -+ print(str(renpy.version + " lint report, generated at: " + time.ctime()).encode("utf-8")) - - # This supports check_hide. - global image_prefixes -@@ -723,10 +723,10 @@ characters per block. """.format( - lines.append(s) - - -- print -- print -- print "Statistics:" -- print -+ print() -+ print() -+ print("Statistics:") -+ print() - - languages = list(counts) - languages.sort() -@@ -738,17 +738,17 @@ characters per block. """.format( - - for l in lines: - for ll in textwrap.wrap(l, 78): -- print ll.encode("utf-8") -+ print(ll.encode("utf-8")) - -- print -+ print() - -- print -+ print() - if renpy.config.developer: -- print "Remember to set config.developer to False before releasing." -- print -+ print("Remember to set config.developer to False before releasing.") -+ print() - -- print "Lint is not a substitute for thorough testing. Remember to update Ren'Py" -- print "before releasing. New releases fix bugs and improve compatibility." -+ print("Lint is not a substitute for thorough testing. Remember to update Ren'Py") -+ print("before releasing. New releases fix bugs and improve compatibility.") - - return False - -diff --git a/renpy/loader.py b/renpy/loader.py -index 0760219..f3a7a7b 100644 ---- a/renpy/loader.py -+++ b/renpy/loader.py -@@ -22,7 +22,7 @@ - import renpy - import os.path - from pickle import loads --from cStringIO import StringIO -+from io import StringIO - import sys - import types - import threading -@@ -30,7 +30,7 @@ import zlib - - # Ensure the utf-8 codec is loaded, to prevent recursion when we use it - # to look up filenames. --u"".encode("utf-8") -+"".encode("utf-8") - - - ################################################################# Physical Paths -@@ -61,7 +61,7 @@ try: - - expansion = os.environ.get("ANDROID_EXPANSION", None) - if expansion is not None: -- print "Using expansion file", expansion -+ print("Using expansion file", expansion) - - apks = [ - android.apk.APK(apk=expansion, prefix='assets/x-game/'), -@@ -71,7 +71,7 @@ try: - game_apks = [ apks[0] ] - - else: -- print "Not using expansion file." -+ print("Not using expansion file.") - - apks = [ - android.apk.APK(prefix='assets/x-game/'), -@@ -121,7 +121,7 @@ def index_archives(): - - try: - fn = transfn(prefix + ".rpa") -- f = file(fn, "rb") -+ f = open(fn, "rb") - l = f.readline() - - # 3.0 Branch. -@@ -133,7 +133,7 @@ def index_archives(): - - # Deobfuscate the index. - -- for k in index.keys(): -+ for k in list(index.keys()): - - if len(index[k][0]) == 2: - index[k] = [ (offset ^ key, dlen ^ key) for offset, dlen in index[k] ] -@@ -158,7 +158,7 @@ def index_archives(): - f.close() - - fn = transfn(prefix + ".rpi") -- index = loads(file(fn, "rb").read().decode("zlib")) -+ index = loads(open(fn, "rb").read().decode("zlib")) - archives.append((prefix, index)) - except: - raise -@@ -253,7 +253,7 @@ def scandirfiles(): - files = game_files - - for _prefix, index in archives: -- for j in index.iterkeys(): -+ for j in index.keys(): - add(None, j) - - -@@ -380,7 +380,7 @@ class SubFile(object): - def __iter__(self): - return self - -- def next(self): #@ReservedAssignment -+ def __next__(self): #@ReservedAssignment - rv = self.readline() - - if not rv: -@@ -489,7 +489,7 @@ def load_core(name): - - # Compatibility path. - else: -- f = file(afn, "rb") -+ f = open(afn, "rb") - - for offset, dlen in index[name]: - f.seek(offset) -@@ -684,13 +684,13 @@ class RenpyImporter(object): - mod.__path__ = [ filename[:-len("__init__.py")] ] - - source = load(filename).read().decode("utf8") -- if source and source[0] == u'\ufeff': -+ if source and source[0] == '\ufeff': - source = source[1:] - source = source.encode("raw_unicode_escape") - - source = source.replace("\r", "") - code = compile(source, filename, 'exec') -- exec code in mod.__dict__ -+ exec(code, mod.__dict__) - return mod - - def get_data(self, filename): -@@ -773,7 +773,7 @@ def auto_thread_function(): - if auto_quit_flag: - return - -- items = auto_mtimes.items() -+ items = list(auto_mtimes.items()) - - for fn, mtime in items: - -diff --git a/renpy/loadsave.py b/renpy/loadsave.py -index 862105d..07fd357 100644 ---- a/renpy/loadsave.py -+++ b/renpy/loadsave.py -@@ -22,9 +22,9 @@ - # This file contains functions that load and save the game state. - - import pickle --import cPickle -+import pickle - --from cStringIO import StringIO -+from io import StringIO - - import zipfile - import re -@@ -40,13 +40,13 @@ from json import dumps as json_dumps - # Dump that chooses which pickle to use: - def dump(o, f): - if renpy.config.use_cpickle: -- cPickle.dump(o, f, cPickle.HIGHEST_PROTOCOL) -+ pickle.dump(o, f, pickle.HIGHEST_PROTOCOL) - else: - pickle.dump(o, f, pickle.HIGHEST_PROTOCOL) - - def loads(s): - if renpy.config.use_cpickle: -- return cPickle.loads(s) -+ return pickle.loads(s) - else: - return pickle.loads(s) - -@@ -71,10 +71,10 @@ def save_dump(roots, log): - f.write("{0: 7d} {1} = alias {2}\n".format(0, path, o_repr_cache[ido])) - return 0 - -- if isinstance(o, (int, float, types.NoneType, types.ModuleType, types.ClassType)): -+ if isinstance(o, (int, float, type(None), types.ModuleType, type)): - o_repr = repr(o) - -- elif isinstance(o, (str, unicode)): -+ elif isinstance(o, str): - if len(o) <= 80: - o_repr = repr(o).encode("utf-8") - else: -@@ -87,7 +87,7 @@ def save_dump(roots, log): - o_repr = "<" + o.__class__.__name__ + ">" - - elif isinstance(o, types.MethodType): -- o_repr = "".format(o.im_class.__name__, o.im_func.__name__) -+ o_repr = "".format(o.__self__.__class__.__name__, o.__func__.__name__) - - elif isinstance(o, object): - o_repr = "<{0}>".format(type(o).__name__) -@@ -98,10 +98,10 @@ def save_dump(roots, log): - - o_repr_cache[ido] = o_repr - -- if isinstance(o, (int, float, types.NoneType, types.ModuleType, types.ClassType)): -+ if isinstance(o, (int, float, type(None), types.ModuleType, type)): - size = 1 - -- elif isinstance(o, (str, unicode)): -+ elif isinstance(o, str): - size = len(o) / 40 + 1 - - elif isinstance(o, (tuple, list)): -@@ -112,12 +112,12 @@ def save_dump(roots, log): - - elif isinstance(o, dict): - size = 2 -- for k, v in o.iteritems(): -+ for k, v in o.items(): - size += 2 - size += visit(v, "{0}[{1!r}]".format(path, k)) - - elif isinstance(o, types.MethodType): -- size = 1 + visit(o.im_self, path + ".im_self") -+ size = 1 + visit(o.__self__, path + ".im_self") - - else: - -@@ -141,7 +141,7 @@ def save_dump(roots, log): - - state = get(2, { }) - if isinstance(state, dict): -- for k, v in state.iteritems(): -+ for k, v in state.items(): - size += 2 - size += visit(v, path + "." + k) - else: -@@ -166,7 +166,7 @@ def save_dump(roots, log): - - return size - -- f = file("save_dump.txt", "w") -+ f = open("save_dump.txt", "w") - - visit(roots, "roots") - visit(log, "log") -@@ -712,7 +712,7 @@ def clear_cache(): - Clears the entire cache. - """ - -- for c in cache.values(): -+ for c in list(cache.values()): - c.clear() - - newest_slot_cache.clear() -diff --git a/renpy/log.py b/renpy/log.py -index 87f349e..8f34999 100644 ---- a/renpy/log.py -+++ b/renpy/log.py -@@ -86,7 +86,7 @@ class LogFile(object): - altfn = os.path.join(tempfile.gettempdir(), "renpy-" + self.name + ".txt") - - if renpy.android: -- print "Logging to", fn -+ print("Logging to", fn) - - if self.append: - mode = "a" -@@ -132,7 +132,7 @@ class LogFile(object): - s = s % args - s += "\n" - -- if not isinstance(s, unicode): -+ if not isinstance(s, str): - s = s.decode("latin-1") - - s = s.replace("\n", "\r\n") -diff --git a/renpy/main.py b/renpy/main.py -index f8bee19..721eecc 100644 ---- a/renpy/main.py -+++ b/renpy/main.py -@@ -39,7 +39,7 @@ def log_clock(s): - - renpy.display.log.write(s) - if renpy.android and not renpy.config.log_to_stdout: -- print s -+ print(s) - - last_clock = now - -@@ -146,7 +146,7 @@ def load_rpe(fn): - zfn.close() - - sys.path.insert(0, fn) -- exec autorun in dict() -+ exec(autorun, dict()) - - def choose_variants(): - -@@ -174,10 +174,10 @@ def choose_variants(): - manufacturer = Build.MANUFACTURER - model = Build.MODEL - -- print "Manufacturer", manufacturer, "model", model -+ print("Manufacturer", manufacturer, "model", model) - - if manufacturer == "Amazon" and model.startswith("AFT"): -- print "Running on a Fire TV." -+ print("Running on a Fire TV.") - renpy.config.variants.insert(0, "firetv") - except: - pass -@@ -186,7 +186,7 @@ def choose_variants(): - package_manager = android.activity.getPackageManager() - - if package_manager.hasSystemFeature("android.hardware.type.television"): -- print "Running on a television." -+ print("Running on a television.") - renpy.config.variants.insert(0, "tv") - renpy.config.variants.insert(0, "small") - return -@@ -198,7 +198,7 @@ def choose_variants(): - - info = renpy.display.get_info() - diag = math.hypot(info.current_w, info.current_h) / android.get_dpi() -- print "Screen diagonal is", diag, "inches." -+ print("Screen diagonal is", diag, "inches.") - - if diag >= 6: - renpy.config.variants.insert(0, 'tablet') -@@ -216,7 +216,7 @@ def choose_variants(): - - idiom = UIDevice.currentDevice().userInterfaceIdiom - -- print "iOS device idiom", idiom -+ print("iOS device idiom", idiom) - - # idiom 0 is iPhone, 1 is iPad. We assume any bigger idiom will - # be tablet-like. -@@ -359,7 +359,7 @@ def main(): - renpy.game.script = renpy.script.Script() - renpy.game.script.load_script() - -- print time.time() - start -+ print(time.time() - start) - sys.exit(0) - - renpy.game.exception_info = 'After loading the script.' -@@ -470,7 +470,7 @@ def main(): - restart = (renpy.config.end_game_transition, "_invoke_main_menu", "_main_menu") - renpy.persistent.update(True) - -- except game.FullRestartException, e: -+ except game.FullRestartException as e: - restart = e.reason - - finally: -diff --git a/renpy/memory.py b/renpy/memory.py -index 7751db1..c127e3f 100644 ---- a/renpy/memory.py -+++ b/renpy/memory.py -@@ -83,7 +83,7 @@ def walk_memory(roots, seen=None): - get_referents = gc.get_referents - worklist_append = worklist.append - -- ignore_types = (types.ModuleType, types.ClassType, types.FunctionType) -+ ignore_types = (types.ModuleType, type, types.FunctionType) - - while worklist: - name, o = worklist.pop(0) -@@ -133,7 +133,7 @@ def profile_memory_common(packages=[ "renpy", "store" ]): - if mod_name.startswith("renpy.store"): - continue - -- for name, o in mod.__dict__.items(): -+ for name, o in list(mod.__dict__.items()): - roots.append((mod_name + "." + name, o)) - - return walk_memory(roots) -@@ -169,7 +169,7 @@ def profile_memory(fraction=1.0, minimum=0): - write("Memory profile at " + time.ctime() + ":") - write("") - -- usage = [ (v, k) for (k, v) in profile_memory_common()[0].items() ] -+ usage = [ (v, k) for (k, v) in list(profile_memory_common()[0].items()) ] - usage.sort() - - # The total number of bytes allocated. -@@ -223,7 +223,7 @@ def diff_memory(update=True): - - diff = [ ] - -- for k, v in usage.iteritems(): -+ for k, v in usage.items(): - diff.append(( - v - old_usage.get(k, 0), - k)) -@@ -275,8 +275,8 @@ def profile_rollback(): - # Walk the log, finding new roots and rollback information. - for rb in log: - -- for store_name, store in rb.stores.iteritems(): -- for var_name, o in store.iteritems(): -+ for store_name, store in rb.stores.items(): -+ for var_name, o in store.items(): - name = store_name + "." + var_name - id_o = id(o) - -@@ -300,7 +300,7 @@ def profile_rollback(): - - sizes = walk_memory(roots, seen)[0] - -- usage = [ (v, k) for (k, v) in sizes.iteritems() ] -+ usage = [ (v, k) for (k, v) in sizes.items() ] - usage.sort() - - write("Total Bytes".rjust(13) + " " + "Per Rollback".rjust(13)) -@@ -344,15 +344,15 @@ def find_parents(cls): - - objects.append(o) - -- print prefix + str(id(o)), type(o), -+ print(prefix + str(id(o)), type(o), end=' ') - - try: - if isinstance(o, dict) and "__name__" in o: -- print "with name", o["__name__"] -+ print("with name", o["__name__"]) - else: -- print repr(o)#[:1000] -+ print(repr(o))#[:1000] - except: -- print "Bad repr." -+ print("Bad repr.") - - found = False - -@@ -364,7 +364,7 @@ def find_parents(cls): - continue - - if isinstance(o, weakref.WeakKeyDictionary): -- for k, v in o.data.items(): -+ for k, v in list(o.data.items()): - if v is objects[-4]: - k = k() - seen.add(id(k)) -@@ -390,7 +390,7 @@ def find_parents(cls): - break - - if not found: -- print "" -+ print("") - - o, prefix = queue.pop() - -@@ -399,8 +399,8 @@ def find_parents(cls): - import random - if random.random() < .1: - -- print -- print "===================================================" -- print -+ print() -+ print("===================================================") -+ print() - - print_path(o) -diff --git a/renpy/parser.py b/renpy/parser.py -index 0b48859..1001749 100644 ---- a/renpy/parser.py -+++ b/renpy/parser.py -@@ -37,7 +37,7 @@ parse_errors = [ ] - class ParseError(Exception): - - def __init__(self, filename, number, msg, line=None, pos=None, first=False): -- message = u"File \"%s\", line %d: %s" % (unicode_filename(filename), number, msg) -+ message = "File \"%s\", line %d: %s" % (unicode_filename(filename), number, msg) - - if line: - lines = line.split('\n') -@@ -97,7 +97,7 @@ def unicode_filename(fn): - Converts the supplied filename to unicode. - """ - -- if isinstance(fn, unicode): -+ if isinstance(fn, str): - return fn - - # Windows. -@@ -200,7 +200,7 @@ def list_logical_lines(filename, filedata=None, linenumber=1): - pos = 0 - - # Skip the BOM, if any. -- if len(data) and data[0] == u'\ufeff': -+ if len(data) and data[0] == '\ufeff': - pos += 1 - - if renpy.game.context().init_phase: -@@ -480,7 +480,7 @@ ESCAPED_OPERATORS = [ - - operator_regexp = "|".join([ re.escape(i) for i in OPERATORS ] + ESCAPED_OPERATORS) - --word_regexp = ur'[a-zA-Z_\u00a0-\ufffd][0-9a-zA-Z_\u00a0-\ufffd]*' -+word_regexp = r'[a-zA-Z_\u00a0-\ufffd][0-9a-zA-Z_\u00a0-\ufffd]*' - - class Lexer(object): - """ -@@ -564,7 +564,7 @@ class Lexer(object): - - # print self.text[self.pos].encode('unicode_escape') - -- self.match_regexp(ur"(\s+|\\\n)+") -+ self.match_regexp(r"(\s+|\\\n)+") - - def match(self, regexp): - """ -@@ -689,7 +689,7 @@ class Lexer(object): - s = s.replace("\\[", "[[") - s = s.replace("\\%", "%%") - s = re.sub(r'\\u([0-9a-fA-F]{1,4})', -- lambda m : unichr(int(m.group(1), 16)), s) -+ lambda m : chr(int(m.group(1), 16)), s) - s = re.sub(r'\\(.)', r'\1', s) - - return s -@@ -1005,7 +1005,7 @@ class Lexer(object): - name = name or thing - rv = self.match(thing) - else: -- name = name or thing.im_func.func_name -+ name = name or thing.__func__.__name__ - rv = thing() - - if rv is None: -@@ -2315,7 +2315,7 @@ def parse_block(l): - else: - rv.append(stmt) - -- except ParseError, e: -+ except ParseError as e: - parse_errors.append(e.message) - l.advance() - -@@ -2339,7 +2339,7 @@ def parse(fn, filedata=None, linenumber=1): - try: - lines = list_logical_lines(fn, filedata, linenumber) - nested = group_logical_lines(lines) -- except ParseError, e: -+ except ParseError as e: - parse_errors.append(e.message) - return None - -@@ -2369,11 +2369,11 @@ def report_parse_errors(): - full_text = "" - - f, error_fn = renpy.error.open_error_file("errors.txt", "w") -- f.write(codecs.BOM_UTF8) -+ f.write(str(codecs.BOM_UTF8)) - -- print >>f, "I'm sorry, but errors were detected in your script. Please correct the" -- print >>f, "errors listed below, and try again." -- print >>f -+ print("I'm sorry, but errors were detected in your script. Please correct the", file=f) -+ print("errors listed below, and try again.", file=f) -+ print(file=f) - - for i in parse_errors: - -@@ -2385,14 +2385,14 @@ def report_parse_errors(): - except: - pass - -- print -- print >>f -- print i -- print >>f, i -+ print() -+ print(file=f) -+ print(i) -+ print(i, file=f) - - -- print >>f -- print >>f, "Ren'Py Version:", renpy.version -+ print(file=f) -+ print("Ren'Py Version:", renpy.version, file=f) - - f.close() - -diff --git a/renpy/persistent.py b/renpy/persistent.py -index 2201010..8e81dd2 100644 ---- a/renpy/persistent.py -+++ b/renpy/persistent.py -@@ -26,7 +26,7 @@ import time - import renpy - - from renpy.loadsave import dump, loads --from cPickle import dumps -+from pickle import dumps - - # The class that's used to hold the persistent data. - class Persistent(object): -@@ -178,7 +178,7 @@ def load(filename): - - # Unserialize the persistent data. - try: -- f = file(filename, "rb") -+ f = open(filename, "rb") - s = f.read().decode("zlib") - f.close() - persistent = loads(s) -@@ -207,7 +207,7 @@ def init(): - # Create the backup of the persistent data. - v = vars(persistent) - -- for k, v in vars(persistent).iteritems(): -+ for k, v in vars(persistent).items(): - backup[k] = safe_deepcopy(v) - - return persistent -@@ -401,7 +401,7 @@ class _MultiPersistent(object): - def save(self): - - fn = self._filename -- f = file(fn + ".new", "wb") -+ f = open(fn + ".new", "wb") - dump(self, f) - f.close() - -@@ -451,7 +451,7 @@ def MultiPersistent(name): - break - - try: -- rv = loads(file(fn).read()) -+ rv = loads(open(fn).read()) - except: - rv = _MultiPersistent() - -diff --git a/renpy/pyanalysis.py b/renpy/pyanalysis.py -index f5267bb..041ea8d 100644 ---- a/renpy/pyanalysis.py -+++ b/renpy/pyanalysis.py -@@ -19,11 +19,6 @@ - # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - --from __future__ import print_function --from __future__ import unicode_literals --from __future__ import division --from __future__ import absolute_import -- - import renpy # @UnusedImport - from renpy.python import py_compile - -@@ -31,7 +26,7 @@ from renpy.python import py_compile - import ast - - import zlib --from cPickle import loads, dumps -+from pickle import loads, dumps - - # The set of names that should be treated as constants. - always_constants = { 'True', 'False', 'None' } -@@ -45,7 +40,7 @@ pure_functions = { - "getattr", "globals", "hasattr", "hash", "hex", "int", "isinstance", - "len", "list", "long", "map", "max", "min", "oct", "ord", "pow", - "range", "reduce", "repr", "round", "set", "sorted", -- "str", "sum", "tuple", "unichr", "unicode", "vars", "zip", -+ "str", "sum", "tuple", "vars", "zip", - - # enumerator and reversed return iterators at the moment. - -@@ -137,7 +132,7 @@ def pure(fn): - - name = fn - -- if not isinstance(name, basestring): -+ if not isinstance(name, str): - name = fn.__name__ - - if name not in not_constants: -@@ -297,7 +292,7 @@ class Analysis(object): - not changed since the last time we called this function. - """ - -- for i in self.children.values(): -+ for i in list(self.children.values()): - if not i.at_fixed_point(): - return False - -diff --git a/renpy/python.py b/renpy/python.py -index 22e7405..22f5ecb 100644 ---- a/renpy/python.py -+++ b/renpy/python.py -@@ -30,7 +30,6 @@ import marshal - import random - import weakref - import re --import sets - import sys - - import renpy.audio -@@ -121,7 +120,7 @@ class StoreDict(dict): - if k not in self.old: - rv[k] = deleted - -- for k, v in self.old.iteritems(): -+ for k, v in self.old.items(): - - new_v = self.get(k, deleted) - -@@ -168,7 +167,7 @@ def create_store(name): - # Set up the default contents of the store. - eval("1", d) - -- for k, v in renpy.minstore.__dict__.iteritems(): -+ for k, v in renpy.minstore.__dict__.items(): - if k not in d: - d[k] = v - -@@ -200,14 +199,14 @@ class StoreBackup(): - self.ever_been_changed = { } - - -- for k, v in store_dicts.iteritems(): -+ for k, v in store_dicts.items(): - self.store[k] = dict(v) - self.old[k] = dict(v.old) - self.ever_been_changed[k] = set(v.ever_been_changed) - - def restore(self): - -- for k, sd in store_dicts.iteritems(): -+ for k, sd in store_dicts.items(): - - sd.clear() - sd.update(self.store[k]) -@@ -229,7 +228,7 @@ def make_clean_stores(): - - global clean_store_backup - -- for _k, v in store_dicts.iteritems(): -+ for _k, v in store_dicts.items(): - - v.old.clear() - v.ever_been_changed.clear() -@@ -294,14 +293,14 @@ def reached(obj, reachable, wait): - - try: - # Treat as fields, indexed by strings. -- for v in vars(obj).itervalues(): -+ for v in vars(obj).values(): - reached(v, reachable, wait) - except: - pass - - try: - # Treat as iterable -- if not isinstance(obj, basestring): -+ if not isinstance(obj, str): - for v in obj.__iter__(): - reached(v, reachable, wait) - except: -@@ -309,7 +308,7 @@ def reached(obj, reachable, wait): - - try: - # Treat as dict. -- for v in obj.itervalues(): -+ for v in obj.values(): - reached(v, reachable, wait) - except: - pass -@@ -326,14 +325,14 @@ def reached_vars(store, reachable, wait): - the path by which the object was reached. - """ - -- for v in store.itervalues(): -+ for v in store.values(): - reached(v, reachable, wait) - - for c in renpy.game.contexts: - reached(c.info, reachable, wait) - reached(c.music, reachable, wait) - for d in c.dynamic_stack: -- for v in d.itervalues(): -+ for v in d.values(): - reached(v, reachable, wait) - - -@@ -417,7 +416,7 @@ def set_filename(filename, offset, tree): - worklist.extend(node.getChildNodes()) - - --unicode_re = re.compile(ur'[\u0080-\uffff]') -+unicode_re = re.compile(r'[\u0080-\uffff]') - - def unicode_sub(m): - """ -@@ -483,7 +482,7 @@ def py_compile(source, mode, filename='', lineno=1, ast_node=False): - filename = source.filename - lineno = source.linenumber - -- source = unicode(source) -+ source = str(source) - source = source.replace("\r", "") - source = escape_unicode(source) - -@@ -504,7 +503,7 @@ def py_compile(source, mode, filename='', lineno=1, ast_node=False): - - return compile(tree, filename, mode) - -- except SyntaxError, e: -+ except SyntaxError as e: - - if e.lineno is not None: - e.lineno += line_offset -@@ -558,7 +557,6 @@ class RevertableList(list): - list.__init__(self, *args) - - __delitem__ = mutator(list.__delitem__) -- __delslice__ = mutator(list.__delslice__) - __setitem__ = mutator(list.__setitem__) - __iadd__ = mutator(list.__iadd__) - __imul__ = mutator(list.__imul__) -@@ -577,7 +575,6 @@ class RevertableList(list): - return newmethod - - __add__ = wrapper(list.__add__) -- __getslice__ = wrapper(list.__getslice__) - __mul__ = wrapper(list.__mul__) - __rmul__ = wrapper(list.__rmul__) - -@@ -590,7 +587,7 @@ class RevertableList(list): - self[:] = old - - def revertable_range(*args): -- return RevertableList(range(*args)) -+ return RevertableList(list(range(*args))) - - def revertable_sorted(*args, **kwargs): - return RevertableList(sorted(*args, **kwargs)) -@@ -630,7 +627,7 @@ class RevertableDict(dict): - return rv - - def get_rollback(self): -- return self.items() -+ return list(self.items()) - - def rollback(self, old): - self.clear() -@@ -638,7 +635,7 @@ class RevertableDict(dict): - for k, v in old: - self[k] = v - --class RevertableSet(sets.Set): -+class RevertableSet(set): - - def __init__(self, *args): - log = renpy.game.log -@@ -646,44 +643,43 @@ class RevertableSet(sets.Set): - if log is not None: - log.mutated[id(self)] = None - -- sets.Set.__init__(self, *args) -- -- __iand__ = mutator(sets.Set.__iand__) -- __ior__ = mutator(sets.Set.__ior__) -- __isub__ = mutator(sets.Set.__isub__) -- __ixor__ = mutator(sets.Set.__ixor__) -- add = mutator(sets.Set.add) -- clear = mutator(sets.Set.clear) -- difference_update = mutator(sets.Set.difference_update) -- discard = mutator(sets.Set.discard) -- intersection_update = mutator(sets.Set.intersection_update) -- pop = mutator(sets.Set.pop) -- remove = mutator(sets.Set.remove) -- symmetric_difference_update = mutator(sets.Set.symmetric_difference_update) -- union_update = mutator(sets.Set.union_update) -- update = mutator(sets.Set.update) -+ set.__init__(self, *args) -+ -+ __iand__ = mutator(set.__iand__) -+ __ior__ = mutator(set.__ior__) -+ __isub__ = mutator(set.__isub__) -+ __ixor__ = mutator(set.__ixor__) -+ add = mutator(set.add) -+ clear = mutator(set.clear) -+ difference_update = mutator(set.difference_update) -+ discard = mutator(set.discard) -+ intersection_update = mutator(set.intersection_update) -+ pop = mutator(set.pop) -+ remove = mutator(set.remove) -+ symmetric_difference_update = mutator(set.symmetric_difference_update) -+ union = mutator(set.union) -+ update = mutator(set.update) - - def wrapper(method): # E0213 @NoSelf - def newmethod(*args, **kwargs): - rv = method(*args, **kwargs) # E1102 -- if isinstance(rv, sets.Set): -+ if isinstance(rv, set): - return RevertableSet(rv) - else: - return rv - - return newmethod - -- __and__ = wrapper(sets.Set.__and__) -- __copy__ = wrapper(sets.Set.__copy__) -- __deepcopy__ = wrapper(sets.Set.__deepcopy__) -- __sub__ = wrapper(sets.Set.__sub__) -- __xor__ = wrapper(sets.Set.__xor__) -- __or__ = wrapper(sets.Set.__or__) -- copy = wrapper(sets.Set.copy) -- difference = wrapper(sets.Set.difference) -- intersection = wrapper(sets.Set.intersection) -- symmetric_difference = wrapper(sets.Set.symmetric_difference) -- union = wrapper(sets.Set.union) -+ __and__ = wrapper(set.__and__) -+ copy = wrapper(set.copy) -+ __sub__ = wrapper(set.__sub__) -+ __xor__ = wrapper(set.__xor__) -+ __or__ = wrapper(set.__or__) -+ copy = wrapper(set.copy) -+ difference = wrapper(set.difference) -+ intersection = wrapper(set.intersection) -+ symmetric_difference = wrapper(set.symmetric_difference) -+ union = wrapper(set.union) - - del wrapper - -@@ -691,8 +687,8 @@ class RevertableSet(sets.Set): - return list(self) - - def rollback(self, old): -- sets.Set.clear(self) -- sets.Set.update(self, old) -+ set.clear(self) -+ set.update(self, old) - - - class RevertableObject(object): -@@ -869,15 +865,15 @@ class Rollback(renpy.object.Object): - - # Add objects reachable from the stores. (Objects that might be - # unreachable at the moment.) -- for changes in self.stores.itervalues(): -- for _k, v in changes.iteritems(): -+ for changes in self.stores.values(): -+ for _k, v in changes.items(): - if v is not deleted: - reached(v, reachable, wait) - - # Add in objects reachable through the context. - reached(self.context.info, reachable, wait) - for d in self.context.dynamic_stack: -- for v in d.itervalues(): -+ for v in d.values(): - reached(v, reachable, wait) - - # Add in objects reachable through displayables. -@@ -892,7 +888,7 @@ class Rollback(renpy.object.Object): - reached(rb, reachable, wait) - else: - if renpy.config.debug: -- print "Removing unreachable:", o -+ print("Removing unreachable:", o) - - pass - -@@ -911,12 +907,12 @@ class Rollback(renpy.object.Object): - if roll is not None: - obj.rollback(roll) - -- for name, changes in self.stores.iteritems(): -+ for name, changes in self.stores.items(): - store = store_dicts.get(name, None) - if store is None: - return - -- for name, value in changes.iteritems(): -+ for name, value in changes.items(): - if value is deleted: - if name in store: - del store[name] -@@ -1045,7 +1041,7 @@ class RollbackLog(renpy.object.Object): - self.rolled_forward = False - - # Reset the point that changes are relative to. -- for sd in store_dicts.itervalues(): -+ for sd in store_dicts.values(): - sd.begin() - - def complete(self): -@@ -1059,18 +1055,18 @@ class RollbackLog(renpy.object.Object): - - # Update self.current.stores with the changes from each store. - # Also updates .ever_been_changed. -- for name, sd in store_dicts.iteritems(): -+ for name, sd in store_dicts.items(): - self.current.stores[name] = sd.get_changes() - - # Update the list of mutated objects and what we need to do to - # restore them. - -- for _i in xrange(4): -+ for _i in range(4): - - self.current.objects = [ ] - - try: -- for _k, v in self.mutated.iteritems(): -+ for _k, v in self.mutated.items(): - - if v is None: - continue -@@ -1102,7 +1098,7 @@ class RollbackLog(renpy.object.Object): - - rv = { } - -- for store_name, sd in store_dicts.iteritems(): -+ for store_name, sd in store_dicts.items(): - for name in sd.ever_been_changed: - if name in sd: - rv[store_name + "." + name] = sd[name] -@@ -1300,7 +1296,7 @@ class RollbackLog(renpy.object.Object): - - # Otherwise, just give up. - -- print "Can't find a place to rollback to. Not rolling back." -+ print("Can't find a place to rollback to. Not rolling back.") - - revlog.reverse() - self.log = self.log + revlog -@@ -1422,7 +1418,7 @@ class RollbackLog(renpy.object.Object): - clean_stores() - renpy.translation.init_translation() - -- for name, value in roots.iteritems(): -+ for name, value in roots.items(): - - if "." in name: - store_name, name = name.rsplit(".", 1) -@@ -1458,7 +1454,7 @@ def py_exec_bytecode(bytecode, hide=False, globals=None, locals=None, store="sto - if locals is None: - locals = globals #@ReservedAssignment - -- exec bytecode in globals, locals -+ exec(bytecode, globals, locals) - - - def py_exec(source, hide=False, store=None): -@@ -1471,7 +1467,7 @@ def py_exec(source, hide=False, store=None): - else: - locals = store #@ReservedAssignment - -- exec py_compile(source, 'exec') in store, locals -+ exec(py_compile(source, 'exec'), store, locals) - - - def py_eval_bytecode(bytecode, globals=None, locals=None): #@ReservedAssignment -@@ -1485,7 +1481,7 @@ def py_eval_bytecode(bytecode, globals=None, locals=None): #@ReservedAssignment - return eval(bytecode, globals, locals) - - def py_eval(code, globals=None, locals=None): #@ReservedAssignment -- if isinstance(code, basestring): -+ if isinstance(code, str): - code = py_compile(code, 'eval') - return py_eval_bytecode(code, globals, locals) - -@@ -1505,7 +1501,7 @@ def raise_at_location(e, loc): - code = compile(node, filename, 'exec') - - # PY3 - need to change to exec(). -- exec code in { "e" : e } -+ exec(code, { "e" : e }) - - - # This was used to proxy accesses to the store. Now it's kept around to deal -@@ -1524,18 +1520,18 @@ class StoreProxy(object): - - # Code for pickling bound methods. - def method_pickle(method): -- name = method.im_func.__name__ -+ name = method.__func__.__name__ - -- obj = method.im_self -+ obj = method.__self__ - - if obj is None: -- obj = method.im_class -+ obj = method.__self__.__class__ - - return method_unpickle, (obj, name) - - def method_unpickle(obj, name): - return getattr(obj, name) - --import copy_reg -+import copyreg - import types --copy_reg.pickle(types.MethodType, method_pickle, method_unpickle) -+copyreg.pickle(types.MethodType, method_pickle, method_unpickle) -diff --git a/renpy/savelocation.py b/renpy/savelocation.py -index 9fc813a..567ccc5 100644 ---- a/renpy/savelocation.py -+++ b/renpy/savelocation.py -@@ -113,7 +113,7 @@ class FileLocation(object): - - self.mtimes = new_mtimes - -- for slotname, mtime in new_mtimes.iteritems(): -+ for slotname, mtime in new_mtimes.items(): - if old_mtimes.get(slotname, None) != mtime: - clear_slot(slotname) - -diff --git a/renpy/screenlang.py b/renpy/screenlang.py -index 4a537eb..b393a53 100644 ---- a/renpy/screenlang.py -+++ b/renpy/screenlang.py -@@ -231,12 +231,12 @@ class Parser(object): - and expr instances, and adjusts the line number. - """ - -- if isinstance(expr, unicode): -+ if isinstance(expr, str): - expr = renpy.python.escape_unicode(expr) - - try: - rv = ast.parse(expr, 'eval').body[0].value -- except SyntaxError, e: -+ except SyntaxError as e: - raise renpy.parser.ParseError( - filename, - lineno + e[1][1] - 1, -@@ -254,12 +254,12 @@ class Parser(object): - adjusts the line number. Returns a list of statements. - """ - -- if isinstance(code, unicode): -+ if isinstance(code, str): - code = renpy.python.escape_unicode(code) - - try: - rv = ast.parse(code, 'exec') -- except SyntaxError, e: -+ except SyntaxError as e: - - raise renpy.parser.ParseError( - filename, -diff --git a/renpy/script.py b/renpy/script.py -index 61d6b5f..5f31183 100644 ---- a/renpy/script.py -+++ b/renpy/script.py -@@ -27,13 +27,13 @@ import renpy - import os - import imp - import difflib --import md5 -+import hashlib - import time - import marshal - import struct - import zlib - --from cPickle import loads, dumps -+from pickle import loads, dumps - import shutil - - # The version of the dumped script. -@@ -103,7 +103,7 @@ class Script(object): - renpy.game.script = self - - if os.path.exists(renpy.config.renpy_base + "/lock.txt"): -- self.key = file(renpy.config.renpy_base + "/lock.txt", "rb").read() -+ self.key = open(renpy.config.renpy_base + "/lock.txt", "rb").read() - else: - self.key = None - -@@ -130,7 +130,8 @@ class Script(object): - - self.serial = 0 - -- self.digest = md5.md5(renpy.version_only) -+ self.digest = hashlib.md5(renpy.version_only.encode()) -+ self.md5 = hashlib.md5 - - self.loaded_rpy = False - self.backup_list = [ ] -@@ -195,7 +196,7 @@ class Script(object): - continue - - try: -- os.makedirs(os.path.dirname(target_fn), 0700) -+ os.makedirs(os.path.dirname(target_fn), 0o700) - except: - pass - -@@ -402,7 +403,7 @@ class Script(object): - name = node.name - - if name in self.namemap: -- if not isinstance(bad_name, basestring): -+ if not isinstance(bad_name, str): - bad_name = name - bad_node = node - old_node = self.namemap[name] -@@ -566,7 +567,7 @@ class Script(object): - self.assign_names(stmts, fullfn) - - try: -- f = file(rpycfn, "wb") -+ f = open(rpycfn, "wb") - - self.write_rpyc_header(f) - self.write_rpyc_data(f, 1, dumps((data, stmts), 2)) -@@ -579,7 +580,7 @@ class Script(object): - self.write_rpyc_data(f, 2, dumps((data, stmts), 2)) - - with open(fullfn, "rU") as fullf: -- rpydigest = md5.md5(fullf.read()).digest() -+ rpydigest = hashlib.md5(fullf.read().encode()).digest() - - self.write_rpyc_md5(f, rpydigest) - -@@ -615,7 +616,7 @@ class Script(object): - return None, None - - if data is None: -- print "Failed to load", fn -+ print("Failed to load", fn) - return None, None - - if not isinstance(data, dict): -@@ -652,8 +653,8 @@ class Script(object): - raise Exception("Could not load from archive %s." % (lastfn,)) - - f = renpy.loader.load(fn + compiled) -- f.seek(-md5.digest_size, 2) -- digest = f.read(md5.digest_size) -+ f.seek(-self.md5.digest_size, 2) -+ digest = f.read(self.md5.digest_size) - f.close() - - else: -@@ -667,15 +668,15 @@ class Script(object): - - if os.path.exists(rpyfn): - with open(rpyfn, "rU") as f: -- rpydigest = md5.md5(f.read()).digest() -+ rpydigest = hashlib.md5(f.read().encode()).digest() - else: - rpydigest = None - - try: - if os.path.exists(rpycfn): - with open(rpycfn, "rb") as f: -- f.seek(-md5.digest_size, 2) -- rpycdigest = f.read(md5.digest_size) -+ f.seek(-self.md5.digest_size, 2) -+ rpycdigest = f.read(self.md5.digest_size) - else: - rpycdigest = None - except: -@@ -698,11 +699,11 @@ class Script(object): - data, stmts = self.load_file(dir, fn + compiled) - - if data is None: -- print "Could not load " + rpycfn -+ print("Could not load " + rpycfn) - - except: - if "RENPY_RPYC_EXCEPTIONS" in os.environ: -- print "While loading", rpycfn -+ print("While loading", rpycfn) - raise - - pass -@@ -763,7 +764,7 @@ class Script(object): - # bytecode. - for i in self.all_pycode: - -- key = i.get_hash() + MAGIC -+ key = i.get_hash() + str(MAGIC) - - code = self.bytecode_oldcache.get(key, None) - -@@ -781,7 +782,7 @@ class Script(object): - elif i.mode == 'eval': - code = renpy.python.py_compile_eval_bytecode(i.source, filename=i.location[0], lineno=i.location[1]) - -- except SyntaxError, e: -+ except SyntaxError as e: - - text = e.text - -@@ -789,9 +790,9 @@ class Script(object): - text = '' - - try: -- text = text.decode("utf-8") -+ text = text.encode().decode("utf-8") - except: -- text = text.decode("latin-1") -+ text = text.encode().decode("latin-1") - - pem = renpy.parser.ParseError( - filename = e.filename, -diff --git a/renpy/scriptedit.py b/renpy/scriptedit.py -index 92994d0..6818c59 100644 ---- a/renpy/scriptedit.py -+++ b/renpy/scriptedit.py -@@ -90,7 +90,7 @@ def adjust_line_locations(filename, linenumber, char_offset, line_offset): - - new_lines = { } - -- for key, line in lines.iteritems(): -+ for key, line in lines.items(): - - (fn, ln) = key - -@@ -204,13 +204,13 @@ def first_and_last_nodes(nodes): - - for i in nodes: - for j in nodes: -- if j.next is i: -+ if j.__next__ is i: - break - else: - firsts.append(i) - - for j in nodes: -- if i.next is j: -+ if i.__next__ is j: - break - - else: -@@ -288,7 +288,7 @@ def remove_from_ast(filename, linenumber): - if i in nodes: - continue - -- i.replace_next(first, last.next) -+ i.replace_next(first, last.__next__) - - new_stmts.append(i) - -diff --git a/renpy/sl2/slast.py b/renpy/sl2/slast.py -index defd86f..78c2f01 100644 ---- a/renpy/sl2/slast.py -+++ b/renpy/sl2/slast.py -@@ -30,7 +30,7 @@ - import ast - import collections - import linecache --from cPickle import loads, dumps -+from pickle import loads, dumps - import zlib - - import renpy.display -@@ -43,7 +43,8 @@ from renpy.display.predict import displayable as predict_displayable - - from renpy.python import py_eval_bytecode - from renpy.pyanalysis import Analysis, NOT_CONST, GLOBAL_CONST, ccache --import md5 -+import hashlib -+md5 = hashlib.md5 - - # This file contains the abstract syntax tree for a screen language - # screen. -@@ -1398,7 +1399,7 @@ class SLFor(SLBlock): - if c is None: - return - -- for child_cache in c.values(): -+ for child_cache in list(c.values()): - for i in self.children: - i.copy_on_change(child_cache) - -@@ -1422,7 +1423,7 @@ class SLPython(SLNode): - analysis.python(self.code.source) - - def execute(self, context): -- exec self.code.bytecode in context.globals, context.scope -+ exec(self.code.bytecode, context.globals, context.scope) - - def prepare(self, analysis): - self.constant = NOT_CONST -diff --git a/renpy/styledata/styleutil.py b/renpy/styledata/styleutil.py -index fcd65c1..054f7c8 100644 ---- a/renpy/styledata/styleutil.py -+++ b/renpy/styledata/styleutil.py -@@ -22,6 +22,7 @@ - # Utility functions used by the various property functions: - - import renpy -+import collections - - def none_is_null(o): - if o is None: -@@ -36,7 +37,7 @@ def expand_focus_mask(v): - return v - elif v is True: - return v -- elif callable(v): -+ elif isinstance(v, collections.Callable): - return v - else: - return renpy.easy.displayable(v) -diff --git a/renpy/text/extras.py b/renpy/text/extras.py -index 2fa4d49..75e2f3f 100644 ---- a/renpy/text/extras.py -+++ b/renpy/text/extras.py -@@ -73,7 +73,7 @@ def check_text_tags(s): - else: - all_tags = text_tags - -- tokens = textsupport.tokenize(unicode(s)) -+ tokens = textsupport.tokenize(str(s)) - - tag_stack = [ ] - -diff --git a/renpy/text/font.py b/renpy/text/font.py -index 07ac3ab..12e4d0f 100644 ---- a/renpy/text/font.py -+++ b/renpy/text/font.py -@@ -92,7 +92,7 @@ class ImageFont(object): - return - - for g in glyphs: -- c = unichr(g.character) -+ c = chr(g.character) - - cxo, cyo = self.offsets[c] - x = g.x + xo + cxo -@@ -143,20 +143,20 @@ class SFont(ImageFont): - self.baseline = height # W0201 - - # Create space characters. -- self.chars[u' '] = renpy.display.pgrender.surface((self.spacewidth, height), True) -- self.width[u' '] = self.spacewidth -- self.advance[u' '] = self.spacewidth -- self.offsets[u' '] = (0, 0) -+ self.chars[' '] = renpy.display.pgrender.surface((self.spacewidth, height), True) -+ self.width[' '] = self.spacewidth -+ self.advance[' '] = self.spacewidth -+ self.offsets[' '] = (0, 0) - -- self.chars[u'\u200b'] = renpy.display.pgrender.surface((0, height), True) -- self.width[u'\u200b'] = 0 -- self.advance[u'\u200b'] = 0 -- self.offsets[u'\u200b'] = (0, 0) -+ self.chars['\u200b'] = renpy.display.pgrender.surface((0, height), True) -+ self.width['\u200b'] = 0 -+ self.advance['\u200b'] = 0 -+ self.offsets['\u200b'] = (0, 0) - -- self.chars[u'\u00a0'] = self.chars[u' '] -- self.width[u'\u00a0'] = self.width[u' '] -- self.advance[u'\u00a0'] = self.advance[u' '] -- self.offsets[u'\u00a0'] = self.offsets[u' '] -+ self.chars['\u00a0'] = self.chars[' '] -+ self.width['\u00a0'] = self.width[' '] -+ self.advance['\u00a0'] = self.advance[' '] -+ self.offsets['\u00a0'] = self.offsets[' '] - - # The color key used to separate characters. - i = 0 -@@ -234,7 +234,7 @@ class MudgeFont(ImageFont): - if char < 0: - continue - -- c = unichr(char) -+ c = chr(char) - x = int(e.attrib["x"]) - y = int(e.attrib["y"]) - w = int(e.attrib["width"]) -@@ -254,22 +254,22 @@ class MudgeFont(ImageFont): - self.baseline = height # W0201 - - # Create space characters. -- if u' ' not in self.chars: -- self.chars[u' '] = renpy.display.pgrender.surface((self.spacewidth, height), True) -- self.width[u' '] = self.spacewidth -- self.advance[u' '] = self.spacewidth -- self.offsets[u' '] = (0, 0) -+ if ' ' not in self.chars: -+ self.chars[' '] = renpy.display.pgrender.surface((self.spacewidth, height), True) -+ self.width[' '] = self.spacewidth -+ self.advance[' '] = self.spacewidth -+ self.offsets[' '] = (0, 0) - -- if u'\u00a0' not in self.chars: -- self.chars[u'\u00a0'] = self.chars[u' '] -- self.width[u'\u00a0'] = self.width[u' '] -- self.advance[u'\u00a0'] = self.advance[u' '] -- self.offsets[u'\u00a0'] = self.offsets[u' '] -+ if '\u00a0' not in self.chars: -+ self.chars['\u00a0'] = self.chars[' '] -+ self.width['\u00a0'] = self.width[' '] -+ self.advance['\u00a0'] = self.advance[' '] -+ self.offsets['\u00a0'] = self.offsets[' '] - -- self.chars[u'\u200b'] = renpy.display.pgrender.surface((0, height), True) -- self.width[u'\u200b'] = 0 -- self.advance[u'\u200b'] = 0 -- self.offsets[u'\u200b'] = (0, 0) -+ self.chars['\u200b'] = renpy.display.pgrender.surface((0, height), True) -+ self.width['\u200b'] = 0 -+ self.advance['\u200b'] = 0 -+ self.offsets['\u200b'] = (0, 0) - - - -@@ -330,7 +330,7 @@ class BMFont(ImageFont): - elif kind == "page": - pages[int(args["id"])] = renpy.display.im.Image(args["file"]).load(unscaled=True) - elif kind == "char": -- c = unichr(int(args["id"])) -+ c = chr(int(args["id"])) - x = int(args["x"]) - y = int(args["y"]) - w = int(args["width"]) -@@ -350,17 +350,17 @@ class BMFont(ImageFont): - - f.close() - -- if u'\u00a0' not in self.chars: -- self.chars[u'\u00a0'] = self.chars[u' '] -- self.width[u'\u00a0'] = self.width[u' '] -- self.advance[u'\u00a0'] = self.advance[u' '] -- self.offsets[u'\u00a0'] = self.offsets[u' '] -+ if '\u00a0' not in self.chars: -+ self.chars['\u00a0'] = self.chars[' '] -+ self.width['\u00a0'] = self.width[' '] -+ self.advance['\u00a0'] = self.advance[' '] -+ self.offsets['\u00a0'] = self.offsets[' '] - - -- self.chars[u'\u200b'] = renpy.display.pgrender.surface((0, self.height), True) -- self.width[u'\u200b'] = 0 -- self.advance[u'\u200b'] = 0 -- self.offsets[u'\u200b'] = (0, 0) -+ self.chars['\u200b'] = renpy.display.pgrender.surface((0, self.height), True) -+ self.width['\u200b'] = 0 -+ self.advance['\u200b'] = 0 -+ self.offsets['\u200b'] = (0, 0) - - class ScaledImageFont(ImageFont): - """ -@@ -376,14 +376,14 @@ class ScaledImageFont(ImageFont): - self.baseline = scale(parent.baseline) - self.default_kern = scale(parent.default_kern) - -- self.width = { k : scale(v) for k, v in parent.width.iteritems() } -- self.advance = { k : scale(v) for k, v in parent.advance.iteritems() } -- self.offsets = { k : (scale(v[0]), scale(v[1])) for k, v in parent.offsets.iteritems() } -- self.kerns = { k : scale(v) for k, v in parent.kerns.iteritems() } -+ self.width = { k : scale(v) for k, v in parent.width.items() } -+ self.advance = { k : scale(v) for k, v in parent.advance.items() } -+ self.offsets = { k : (scale(v[0]), scale(v[1])) for k, v in parent.offsets.items() } -+ self.kerns = { k : scale(v) for k, v in parent.kerns.items() } - - self.chars = { } - -- for k, v in parent.chars.iteritems(): -+ for k, v in parent.chars.items(): - w, h = v.get_size() - nw = scale(w) - nh = scale(h) -@@ -392,7 +392,7 @@ class ScaledImageFont(ImageFont): - - def register_sfont(name=None, size=None, bold=False, italics=False, underline=False, - filename=None, spacewidth=10, default_kern=0, kerns={}, -- charset=u"!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"): -+ charset="!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"): - - """ - :doc: image_fonts -@@ -570,12 +570,12 @@ def load_face(fn): - - pygame.sysfont.initsysfonts() - -- for v in pygame.sysfont.Sysfonts.itervalues(): -+ for v in pygame.sysfont.Sysfonts.values(): - if v is not None: -- for _flags, ffn in v.iteritems(): -+ for _flags, ffn in v.items(): - for i in fonts: - if ffn.lower().endswith(i): -- font_file = file(ffn, "rb") -+ font_file = open(ffn, "rb") - break - - if font_file: -@@ -661,7 +661,7 @@ def free_memory(): - - - def load_image_fonts(): -- for i in image_fonts.itervalues(): -+ for i in image_fonts.values(): - i.load() - - -diff --git a/renpy/text/text.py b/renpy/text/text.py -index 0d78ddf..748dbbd 100644 ---- a/renpy/text/text.py -+++ b/renpy/text/text.py -@@ -844,7 +844,7 @@ class Layout(object): - if isinstance(i[0], (TextSegment, SpaceSegment, DisplayableSegment)): - return - -- line.extend(tss[-1].subsegment(u" ")) -+ line.extend(tss[-1].subsegment(" ")) - - for type, text in tokens: #@ReservedAssignment - -@@ -864,7 +864,7 @@ class Layout(object): - continue - - elif type == DISPLAYABLE: -- line.append((DisplayableSegment(tss[-1], text, renders), u"")) -+ line.append((DisplayableSegment(tss[-1], text, renders), "")) - continue - - # Otherwise, we have a text tag. -@@ -896,7 +896,7 @@ class Layout(object): - - elif tag == "space": - width = self.scale_int(int(value)) -- line.append((SpaceSegment(tss[-1], width=width), u"")) -+ line.append((SpaceSegment(tss[-1], width=width), "")) - - elif tag == "vspace": - # Duplicates from the newline tag. -@@ -906,7 +906,7 @@ class Layout(object): - if line: - paragraphs.append(line) - -- line = [ (SpaceSegment(tss[-1], height=height), u"") ] -+ line = [ (SpaceSegment(tss[-1], height=height), "") ] - paragraphs.append(line) - - line = [ ] -@@ -1295,7 +1295,7 @@ class Text(renpy.display.core.Displayable): - - # Check that the text is all text-able things. - for i in text: -- if not isinstance(i, (basestring, renpy.display.core.Displayable)): -+ if not isinstance(i, (str, renpy.display.core.Displayable)): - if renpy.config.developer: - raise Exception("Cannot display {0!r} as text.".format(i)) - else: -@@ -1345,15 +1345,15 @@ class Text(renpy.display.core.Displayable): - s = "" - - for i in self.text: -- if isinstance(i, basestring): -+ if isinstance(i, str): - s += i - - if len(s) > 25: -- s = s[:24] + u"\u2026" -+ s = s[:24] + "\u2026" - break - - s = s.replace("\\", "\\\\").replace("\"", "\\\"").replace("\n", "\\n") -- return u"Text \"{}\"".format(s) -+ return "Text \"{}\"".format(s) - - def _scope(self, scope, update=True): - """ -@@ -1377,12 +1377,12 @@ class Text(renpy.display.core.Displayable): - - # Perform substitution as necessary. - for i in text: -- if isinstance(i, basestring): -+ if isinstance(i, str): - if substitute is not False: - i, did_sub = renpy.substitutions.substitute(i, scope, substitute) - uses_scope = uses_scope or did_sub - -- i = unicode(i) -+ i = str(i) - - new_text.append(i) - -@@ -1482,7 +1482,7 @@ class Text(renpy.display.core.Displayable): - - for i in self.text: - -- if not isinstance(i, basestring): -+ if not isinstance(i, str): - continue - - rv.append(i) -@@ -1826,11 +1826,11 @@ class Text(renpy.display.core.Displayable): - - for i in text: - -- if isinstance(i, unicode): -+ if isinstance(i, str): - tokens.extend(textsupport.tokenize(i)) - - elif isinstance(i, str): -- tokens.extend(textsupport.tokenize(unicode(i))) -+ tokens.extend(textsupport.tokenize(str(i))) - - elif isinstance(i, renpy.display.core.Displayable): - tokens.append((DISPLAYABLE, i)) -@@ -1854,7 +1854,7 @@ class Text(renpy.display.core.Displayable): - kind, text = t - - if kind == TEXT and renpy.config.replace_text: -- rv.append((TEXT, unicode(renpy.config.replace_text(text)))) -+ rv.append((TEXT, str(renpy.config.replace_text(text)))) - - elif kind != TAG: - rv.append(t) -@@ -1906,7 +1906,7 @@ class Text(renpy.display.core.Displayable): - - for kind2, text2 in new_contents: - if isinstance(text2, str): -- text2 = unicode(text2) -+ text2 = str(text2) - - new_tokens.append((kind2, text2)) - -diff --git a/renpy/text/textsupport.pyx b/renpy/text/textsupport.pyx -index feabbc3..5b31613 100644 ---- a/renpy/text/textsupport.pyx -+++ b/renpy/text/textsupport.pyx -@@ -392,9 +392,9 @@ def linebreak_debug(list glyphs): - if g.split == SPLIT_INSTEAD: - rv += "|" - elif g.split == SPLIT_BEFORE: -- rv += "[" + unichr(g.character) -+ rv += "[" + chr(g.character) - else: -- rv += unichr(g.character) -+ rv += chr(g.character) - - return rv - -diff --git a/renpy/translation.py b/renpy/translation.py -index 3b62fee..0cd1150 100644 ---- a/renpy/translation.py -+++ b/renpy/translation.py -@@ -101,7 +101,7 @@ class ScriptTranslator(object): - continue - - if n.name.__class__ is not tuple: -- if isinstance(n.name, basestring): -+ if isinstance(n.name, str): - label = n.name - - type_n = n.__class__ -@@ -360,16 +360,16 @@ class StringTranslator(object): - - f = open_tl_file(fn) - -- f.write(u"translate {} strings:\n".format(language)) -- f.write(u"\n") -+ f.write("translate {} strings:\n".format(language)) -+ f.write("\n") - - for i in self.unknown: - - i = quote_unicode(i) - -- f.write(u" old \"{}\"\n".format(i)) -- f.write(u" new \"{}\"\n".format(i)) -- f.write(u"\n") -+ f.write(" old \"{}\"\n".format(i)) -+ f.write(" new \"{}\"\n".format(i)) -+ f.write("\n") - - f.close() - -@@ -597,13 +597,13 @@ def open_tl_file(fn): - pass - - f = io.open(fn, "a", encoding="utf-8") -- f.write(u"\ufeff") -+ f.write("\ufeff") - - else: - f = io.open(fn, "a", encoding="utf-8") - -- f.write(u"# TODO: Translation updated at {}\n".format(time.strftime("%Y-%m-%d %H:%M"))) -- f.write(u"\n") -+ f.write("# TODO: Translation updated at {}\n".format(time.strftime("%Y-%m-%d %H:%M"))) -+ f.write("\n") - - return f - -@@ -682,17 +682,17 @@ class TranslateFile(object): - if label is None: - label = "" - -- self.f.write(u"# {}:{}\n".format(t.filename, t.linenumber)) -- self.f.write(u"translate {} {}:\n".format(self.language, t.identifier)) -- self.f.write(u"\n") -+ self.f.write("# {}:{}\n".format(t.filename, t.linenumber)) -+ self.f.write("translate {} {}:\n".format(self.language, t.identifier)) -+ self.f.write("\n") - - for n in t.block: -- self.f.write(u" # " + n.get_code() + "\n") -+ self.f.write(" # " + n.get_code() + "\n") - - for n in t.block: -- self.f.write(u" " + n.get_code(self.filter) + "\n") -+ self.f.write(" " + n.get_code(self.filter) + "\n") - -- self.f.write(u"\n") -+ self.f.write("\n") - - def write_strings(self): - """ -@@ -715,15 +715,15 @@ class TranslateFile(object): - started = True - - self.open() -- self.f.write(u"translate {} strings:\n".format(self.language)) -- self.f.write(u"\n") -+ self.f.write("translate {} strings:\n".format(self.language)) -+ self.f.write("\n") - - fs = self.filter(s) - -- self.f.write(u" # {}:{}\n".format(filename, line)) -- self.f.write(u" old \"{}\"\n".format(quote_unicode(s))) -- self.f.write(u" new \"{}\"\n".format(quote_unicode(fs))) -- self.f.write(u"\n") -+ self.f.write(" # {}:{}\n".format(filename, line)) -+ self.f.write(" old \"{}\"\n".format(quote_unicode(s))) -+ self.f.write(" new \"{}\"\n".format(quote_unicode(fs))) -+ self.f.write("\n") - - def null_filter(s): - return s -diff --git a/renpy/ui.py b/renpy/ui.py -index 464440b..26ee95d 100644 ---- a/renpy/ui.py -+++ b/renpy/ui.py -@@ -477,7 +477,7 @@ class Wrapper(renpy.object.Object): - - try: - w = self.function(*args, **keyword) -- except TypeError, e: -+ except TypeError as e: - etype, e, tb = sys.exc_info(); etype - - if tb.tb_next is None: -@@ -799,9 +799,9 @@ def menu(menuitems, - text = choice_chosen_style - button = choice_chosen_button_style - -- if isinstance(button, basestring): -+ if isinstance(button, str): - button = getattr(renpy.game.style, button) -- if isinstance(text, basestring): -+ if isinstance(text, str): - text = getattr(renpy.game.style, text) - - button = button[label] -@@ -826,7 +826,7 @@ def imagemap_compat(ground, - button_style='hotspot', - **properties): - -- if isinstance(button_style, basestring): -+ if isinstance(button_style, str): - button_style = getattr(renpy.game.style, button_style) - - fixed(style=style, **properties) -@@ -995,7 +995,7 @@ def _bar(*args, **properties): - else: - style = value.get_style()[0] - -- if isinstance(style, basestring): -+ if isinstance(style, str): - style = style_group_style(style, NoStyleGroupGiven) - - properties["style"] = style -@@ -1038,7 +1038,7 @@ def viewport(scrollbars=None, **properties): - viewport_properties = { } - side_properties = { } - -- for k, v in properties.iteritems(): -+ for k, v in properties.items(): - if k.startswith("side_"): - side_properties[k[5:]] = v - else: -@@ -1293,7 +1293,7 @@ returns = renpy.curry.curry(_returns) - - def _jumps(label, transition=None): - -- if isinstance(transition, basestring): -+ if isinstance(transition, str): - transition = getattr(renpy.config, transition) - - if transition is not None: -@@ -1343,6 +1343,6 @@ def screen_id(id_, d): - - # Update the wrappers to have names. - k, v = None, None --for k, v in globals().iteritems(): -+for k, v in globals().items(): - if isinstance(v, Wrapper): - v.name = k -diff --git a/renpy/warp.py b/renpy/warp.py -index 41bd1be..8675c4e 100644 ---- a/renpy/warp.py -+++ b/renpy/warp.py -@@ -24,7 +24,6 @@ - # location. - - import renpy --import sets - - warp_spec = None - -@@ -56,7 +55,7 @@ def warp(): - - prev = { } - -- workset = sets.Set([ n for n in renpy.game.script.namemap.itervalues() if isinstance(n, renpy.ast.Scene) ]) -+ workset = sets.Set([ n for n in renpy.game.script.namemap.values() if isinstance(n, renpy.ast.Scene) ]) - seenset = sets.Set(workset) - - # This is called to indicate that next can be executed following node. -@@ -100,7 +99,7 @@ def warp(): - add(n, n.get_next()) - - elif getattr(n, 'next', None) is not None: -- add(n, n.next) -+ add(n, n.__next__) - - # Now, attempt to find a statement preceding the line that the - # user wants to warp to. -diff --git a/renpy.py b/renpy.py -index 7548cf6..847b8d0 100644 ---- a/renpy.py -+++ b/renpy.py -@@ -68,7 +68,7 @@ def path_to_saves(gamedir, save_directory=None): - if os.path.isdir(rv) and test_writable(rv): - break - -- print "Saving to", rv -+ print("Saving to", rv) - - # We return the last path as the default. - -@@ -94,7 +94,7 @@ def path_to_saves(gamedir, save_directory=None): - except: - rv = url.path.UTF8String().decode("utf-8") - -- print "Saving to", rv -+ print("Saving to", rv) - return rv - - # No save directory given. -@@ -151,7 +151,7 @@ try: - import ast; ast - except: - raise -- print "Ren'Py requires at least python 2.6." -+ print("Ren'Py requires at least python 2.6.") - sys.exit(0) - - android = ("ANDROID_PRIVATE" in os.environ) -@@ -186,8 +186,8 @@ def main(): - try: - import renpy.bootstrap - except ImportError: -- print >>sys.stderr, "Could not import renpy.bootstrap. Please ensure you decompressed Ren'Py" -- print >>sys.stderr, "correctly, preserving the directory structure." -+ print("Could not import renpy.bootstrap. Please ensure you decompressed Ren'Py", file=sys.stderr) -+ print("correctly, preserving the directory structure.", file=sys.stderr) - raise - - renpy.bootstrap.bootstrap(renpy_base) -diff --git a/tutorial/game/examples.rpy b/tutorial/game/examples.rpy -index 6612f99..216ffd2 100644 ---- a/tutorial/game/examples.rpy -+++ b/tutorial/game/examples.rpy -@@ -128,7 +128,7 @@ init python hide: - - for fn in files: - -- f = file(fn, "r") -+ f = open(fn, "r") - - open_examples = set() - -- cgit v1.2.3