def write_utf8_traceback_list(out, l): """ Given the traceback list l, writes it to out as utf-8. """ ul = [ ] for filename, line, what, text in l: # Filename is either unicode or an fsecoded string. if not isinstance(filename, six.text_type): filename = six.text_type(filename, FSENCODING, "replace") # Line is a number. # Assume what is in a unicode encoding, since it is either python, # or comes from inside Ren'Py. if isinstance(text, str): text = text.decode("utf-8", "replace") ul.append((filename, line, what, text)) for t in traceback.format_list(ul): out.write(t.encode("utf-8", "replace"))
def safe_utf8(e): try: m = six.text_type(e) except: try: if len(e.args) == 0: m = "" elif len(e.args) == 1: m = e.args[0] else: m = " ".join(e.args) except: try: m = repr(e) except: m = "<Could not encode exception.>" if isinstance(m, six.text_type): return m.encode("utf-8", "replace") else: return m
def __format__(self, spec): return format(six.text_type(self), spec)
def __str__(self): return six.text_type(self).encode("utf-8")
def bootstrap(renpy_base): global renpy # W0602 import renpy.log # @UnusedImport # Remove a legacy environment setting. if os.environ.get(b"SDL_VIDEODRIVER", "") == "windib": del os.environ[b"SDL_VIDEODRIVER"] renpy_base = six.text_type(renpy_base, FSENCODING, "replace") # If environment.txt exists, load it into the os.environ dictionary. if os.path.exists(renpy_base + "/environment.txt"): evars = {} with open(renpy_base + "/environment.txt", "rb") as f: code = compile(f.read(), renpy_base + "/environment.txt", 'exec') exec(code, evars) for k, v in six.iteritems(evars): if k not in os.environ: os.environ[k] = str(v) # Also look for it in an alternate path (the path that contains the # .app file.), if on a mac. alt_path = os.path.abspath("renpy_base") if ".app" in alt_path: alt_path = alt_path[:alt_path.find(".app") + 4] if os.path.exists(alt_path + "/environment.txt"): evars = {} with open(alt_path + "/environment.txt", "rb") as f: code = compile(f.read(), alt_path + "/environment.txt", 'exec') exec(code, evars) for k, v in six.iteritems(evars): if k not in os.environ: os.environ[k] = str(v) # Get a working name for the game. name = os.path.basename(sys.argv[0]) if name.find(".") != -1: name = name[:name.find(".")] # Parse the arguments. import renpy.arguments args = renpy.arguments.bootstrap() if args.trace: enable_trace(args.trace) if args.basedir: basedir = os.path.abspath(args.basedir).decode(FSENCODING) else: basedir = renpy_base if not os.path.exists(basedir): sys.stderr.write("Base directory %r does not exist. Giving up.\n" % (basedir, )) sys.exit(1) gamedirs = [name] game_name = name while game_name: prefix = game_name[0] game_name = game_name[1:] if prefix == ' ' or prefix == '_': gamedirs.append(game_name) gamedirs.extend(['game', 'data', 'launcher/game']) for i in gamedirs: if i == "renpy": continue gamedir = basedir + "/" + i if os.path.isdir(gamedir): break else: gamedir = basedir sys.path.insert(0, basedir) if renpy.macintosh: # If we're on a mac, install our own os.start. os.startfile = mac_start # Are we starting from inside a mac app resources directory? if basedir.endswith("Contents/Resources/autorun"): renpy.macapp = True # Check that we have installed pygame properly. This also deals with # weird cases on Windows and Linux where we can't import modules. (On # windows ";" is a directory separator in PATH, so if it's in a parent # directory, we won't get the libraries in the PATH, and hence pygame # won't import.) try: import pygame_sdl2 if not ("pygame" in sys.modules): pygame_sdl2.import_as_pygame() except: 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), file=sys.stderr) raise # If we're not given a command, show the presplash. if args.command == "run" and not renpy.mobile: import renpy.display.presplash # @Reimport renpy.display.presplash.start(basedir, gamedir) # Ditto for the Ren'Py module. try: import _renpy _renpy except: 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), file=sys.stderr) raise # Load up all of Ren'Py, in the right order. import renpy # @Reimport renpy.import_all() renpy.loader.init_importer() exit_status = None try: while exit_status is None: exit_status = 1 try: renpy.game.args = args renpy.config.renpy_base = renpy_base renpy.config.basedir = basedir renpy.config.gamedir = gamedir renpy.config.args = [] if renpy.android: renpy.config.logdir = os.environ['ANDROID_PUBLIC'] else: renpy.config.logdir = basedir if not os.path.exists(renpy.config.logdir): os.makedirs(renpy.config.logdir, 0o777) renpy.main.main() exit_status = 0 except KeyboardInterrupt: raise except renpy.game.UtterRestartException: # On an UtterRestart, reload Ren'Py. renpy.reload_all() exit_status = None except renpy.game.QuitException as e: exit_status = e.status if e.relaunch: if hasattr(sys, "renpy_executable"): subprocess.Popen([sys.renpy_executable] + sys.argv[1:]) else: subprocess.Popen([sys.executable, "-EO"] + sys.argv) except renpy.game.ParseErrorException: pass except Exception as e: renpy.error.report_exception(e) pass sys.exit(exit_status) finally: if "RENPY_SHUTDOWN_TRACE" in os.environ: enable_trace(int(os.environ["RENPY_SHUTDOWN_TRACE"])) renpy.display.im.cache.quit() if renpy.display.draw: renpy.display.draw.quit() renpy.audio.audio.quit() # Prevent subprocess from throwing errors while trying to run it's # __del__ method during shutdown. if not renpy.emscripten: subprocess.Popen.__del__ = popen_del
def add(msg, *args): if not msg in added: added[msg] = True msg = six.text_type(msg) % args print(msg.encode('utf-8'))
def lint(): """ The master lint function, that's responsible for staging all of the other checks. """ ap = renpy.arguments.ArgumentParser(description="Checks the script for errors and prints script statistics.", require_command=False) ap.add_argument("filename", nargs='?', action="store", help="The file to write to.") args = ap.parse_args() if args.filename: f = open(args.filename, "w") sys.stdout = f renpy.game.lint = True print(codecs.BOM_UTF8) print(six.text_type(renpy.version + " lint report, generated at: " + time.ctime()).encode("utf-8")) # This supports check_hide. global image_prefixes image_prefixes = { } for k in renpy.display.image.images: image_prefixes[k[0]] = True # Iterate through every statement in the program, processing # them. We sort them in filename, linenumber order. all_stmts = [ (i.filename, i.linenumber, i) for i in renpy.game.script.all_stmts ] all_stmts.sort() # The current count. counts = collections.defaultdict(Count) # The current language. language = None menu_count = 0 screen_count = 0 image_count = 0 global report_node for _fn, _ln, node in all_stmts: if isinstance(node, (renpy.ast.Show, renpy.ast.Scene)): precheck_show(node) for _fn, _ln, node in all_stmts: if common(node): continue report_node = node if isinstance(node, renpy.ast.Image): image_count += 1 check_image(node) elif isinstance(node, renpy.ast.Show): check_show(node, False) elif isinstance(node, renpy.ast.Scene): check_show(node, True) elif isinstance(node, renpy.ast.Hide): check_hide(node) elif isinstance(node, renpy.ast.With): check_with(node) elif isinstance(node, renpy.ast.Say): check_say(node) counts[language].add(node.what) elif isinstance(node, renpy.ast.Menu): check_menu(node) menu_count += 1 elif isinstance(node, renpy.ast.Jump): check_jump(node) elif isinstance(node, renpy.ast.Call): check_call(node) elif isinstance(node, renpy.ast.While): check_while(node) elif isinstance(node, renpy.ast.If): check_if(node) elif isinstance(node, renpy.ast.UserStatement): check_user(node) elif isinstance(node, renpy.ast.Label): check_label(node) elif isinstance(node, renpy.ast.Translate): language = node.language elif isinstance(node, renpy.ast.EndTranslate): language = None elif isinstance(node, renpy.ast.Screen): screen_count += 1 check_screen(node) elif isinstance(node, renpy.ast.Define): check_define(node, "define") elif isinstance(node, renpy.ast.Default): check_define(node, "default") report_node = None check_styles() check_filename_encodings() for f in renpy.config.lint_hooks: f() lines = [ ] def report_language(language): count = counts[language] if count.blocks <= 0: return if language is None: s = "The game" else: s = "The {0} translation".format(language) s += """ contains {0} dialogue blocks, containing {1} words and {2} characters, for an average of {3:.1f} words and {4:.0f} characters per block. """.format( humanize(count.blocks), humanize(count.words), humanize(count.characters), 1.0 * count.words / count.blocks, 1.0 * count.characters / count.blocks) lines.append(s) print() print() print("Statistics:") print() languages = list(counts) languages.sort() for i in languages: report_language(i) lines.append("The game contains {0} menus, {1} images, and {2} screens.".format( humanize(menu_count), humanize(image_count), humanize(screen_count))) for l in lines: for ll in textwrap.wrap(l, 78): print(ll.encode("utf-8")) print() for i in renpy.config.lint_stats_callbacks: i() print() if renpy.config.developer and (renpy.config.original_developer != "auto"): 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.") return False