diff --git a/decompiler/__init__.py b/decompiler/__init__.py index cf1c8d6..da79f59 100644 --- a/decompiler/__init__.py +++ b/decompiler/__init__.py @@ -131,25 +131,25 @@ def print_atl(self, ast): def print_imspec(self, imspec): if imspec[1] is not None: - begin = "expression %s" % imspec[1] + begin = f'expression {imspec[1]}' else: begin = " ".join(imspec[0]) words = WordConcatenator(begin and begin[-1] != ' ', True) if imspec[2] is not None: - words.append("as %s" % imspec[2]) + words.append(f'as {imspec[2]}') if len(imspec[6]) > 0: - words.append("behind %s" % ', '.join(imspec[6])) + words.append(f'behind {", ".join(imspec[6])}') if isinstance(imspec[4], str): - words.append("onlayer %s" % imspec[4]) + words.append(f'onlayer {imspec[4]}') if imspec[5] is not None: - words.append("zorder %s" % imspec[5]) + words.append(f'zorder {imspec[5]}') if len(imspec[3]) > 0: - words.append("at %s" % ', '.join(imspec[3])) + words.append(f'at {", ".join(imspec[3])}') self.write(begin + words.join()) return words.needs_space @@ -158,9 +158,9 @@ def print_imspec(self, imspec): def print_image(self, ast): self.require_init() self.indent() - self.write("image %s" % ' '.join(ast.imgname)) + self.write(f'image {" ".join(ast.imgname)}') if ast.code is not None: - self.write(" = %s" % ast.code.source) + self.write(f' = {ast.code.source}') else: if ast.atl is not None: self.write(":") @@ -176,8 +176,8 @@ def print_transform(self, ast): if isinstance(self.parent, renpy.ast.Init): init = self.parent if init.priority != self.init_offset and len(init.block) == 1 and not self.should_come_before(init, ast): - priority = " %d" % (init.priority - self.init_offset) - self.write("transform%s %s" % (priority, ast.varname)) + priority = f' {init.priority - self.init_offset}' + self.write(f'transform{priority} {ast.varname}') if ast.parameters is not None: self.write(reconstruct_paraminfo(ast.parameters)) @@ -197,7 +197,7 @@ def print_show(self, ast): if self.paired_with: if needs_space: self.write(" ") - self.write("with %s" % self.paired_with) + self.write(f'with {self.paired_with}') self.paired_with = True # atl attribute: since 6.10 @@ -208,10 +208,10 @@ def print_show(self, ast): @dispatch(renpy.ast.ShowLayer) def print_showlayer(self, ast): self.indent() - self.write("show layer %s" % ast.layer) + self.write(f'show layer {ast.layer}') if ast.at_list: - self.write(" at %s" % ', '.join(ast.at_list)) + self.write(f' at {", ".join(ast.at_list)}') if ast.atl is not None: self.write(":") @@ -224,7 +224,7 @@ def print_scene(self, ast): if ast.imspec is None: if isinstance(ast.layer, str): - self.write(" onlayer %s" % ast.layer) + self.write(f' onlayer {ast.layer}') needs_space = True else: self.write(" ") @@ -233,7 +233,7 @@ def print_scene(self, ast): if self.paired_with: if needs_space: self.write(" ") - self.write("with %s" % self.paired_with) + self.write(f'with {self.paired_with}') self.paired_with = True # atl attribute: since 6.10 @@ -249,7 +249,7 @@ def print_hide(self, ast): if self.paired_with: if needs_space: self.write(" ") - self.write("with %s" % self.paired_with) + self.write(f'with {self.paired_with}') self.paired_with = True @dispatch(renpy.ast.With) @@ -261,8 +261,7 @@ def print_with(self, ast): # Sanity check. check if there's a matching with statement two nodes further if not(isinstance(self.block[self.index + 2], renpy.ast.With) and self.block[self.index + 2].expr == ast.paired): - raise Exception("Unmatched paired with {0} != {1}".format( - repr(self.paired_with), repr(ast.expr))) + raise Exception(f'Unmatched paired with {self.paired_with!r} != {ast.expr!r}') self.paired_with = ast.paired @@ -270,12 +269,12 @@ def print_with(self, ast): elif self.paired_with: # Check if it was consumed by a show/scene statement if self.paired_with is not True: - self.write(" with %s" % ast.expr) + self.write(f' with {ast.expr}') self.paired_with = False else: self.advance_to_line(ast.linenumber) self.indent() - self.write("with %s" % ast.expr) + self.write(f'with {ast.expr}') self.paired_with = False @dispatch(renpy.ast.Camera) @@ -284,10 +283,10 @@ def print_camera(self, ast): self.write("camera") if ast.layer != "master": - self.write(" %s" % ast.name) + self.write(f' {ast.name}') if ast.at_list: - self.write(" at %s" % ", ".join(ast.at_list)) + self.write(f' at {", ".join(ast.at_list)}') if ast.atl is not None: self.write(":") @@ -333,10 +332,8 @@ def print_label(self, ast): missing_init = self.missing_init self.missing_init = False try: - self.write("label %s%s%s:" % ( - ast.name, - reconstruct_paraminfo(ast.parameters), - " hide" if getattr(ast, "hide", False) else "")) + self.write(f'label {ast.name}{reconstruct_paraminfo(ast.parameters)}' + f'{" hide" if getattr(ast, "hide", False) else ""}:') self.print_nodes(ast.block, 1) finally: if self.missing_init: @@ -348,7 +345,7 @@ def print_label(self, ast): @dispatch(renpy.ast.Jump) def print_jump(self, ast): self.indent() - self.write("jump %s%s" % ("expression " if ast.expression else "", ast.target)) + self.write(f'jump {"expression " if ast.expression else ""}{ast.target}') @dispatch(renpy.ast.Call) def print_call(self, ast): @@ -368,7 +365,7 @@ def print_call(self, ast): # since a Label or a Pass is always emitted after a Call. next_block = self.block[self.index + 1] if isinstance(next_block, renpy.ast.Label): - words.append("from %s" % next_block.name) + words.append(f'from {next_block.name}') self.write(words.join()) @@ -386,11 +383,11 @@ def print_return(self, ast): self.write("return") if ast.expression is not None: - self.write(" %s" % ast.expression) + self.write(f' {ast.expression}') @dispatch(renpy.ast.If) def print_if(self, ast): - statement = First("if %s:", "elif %s:") + statement = First("if", "elif") for i, (condition, block) in enumerate(ast.entries): # The unicode string "True" is used as the condition for else:. @@ -402,14 +399,14 @@ def print_if(self, ast): if(hasattr(condition, 'linenumber')): self.advance_to_line(condition.linenumber) self.indent() - self.write(statement() % condition) + self.write(f'{statement()} {condition}:') self.print_nodes(block, 1) @dispatch(renpy.ast.While) def print_while(self, ast): self.indent() - self.write("while %s:" % ast.condition) + self.write(f'while {ast.condition}:') self.print_nodes(ast.block, 1) @@ -466,7 +463,7 @@ def do_set_init_offset(linenumber): return True if offset != self.init_offset: self.indent() - self.write("init offset = %s" % offset) + self.write(f'init offset = {offset}') self.init_offset = offset return False @@ -510,7 +507,7 @@ def print_init(self, ast): self.indent() self.write("init") if ast.priority != self.init_offset: - self.write(" %d" % (ast.priority - self.init_offset)) + self.write(f' {ast.priority - self.init_offset}') if len(ast.block) == 1 and not self.should_come_before(ast, ast.block[0]): self.write(" ") @@ -528,7 +525,7 @@ def print_say_inside_menu(self): def print_menu_item(self, label, condition, block, arguments): self.indent() - self.write('"%s"' % string_escape(label)) + self.write(f'"{string_escape(label)}"') if arguments is not None: self.write(reconstruct_arginfo(arguments)) @@ -536,7 +533,7 @@ def print_menu_item(self, label, condition, block, arguments): if block is not None: # ren'py uses the unicode string "True" as condition when there isn't one. if isinstance(condition, renpy.ast.PyExpr): - self.write(" if %s" % condition) + self.write(f' if {condition}') self.write(":") self.print_nodes(block, 1) @@ -545,7 +542,7 @@ def print_menu(self, ast): self.indent() self.write("menu") if self.label_inside_menu is not None: - self.write(" %s" % self.label_inside_menu.name) + self.write(f' {self.label_inside_menu.name}') self.label_inside_menu = None # arguments attribute added in 7.1.4 @@ -557,14 +554,14 @@ def print_menu(self, ast): with self.increase_indent(): if ast.with_ is not None: self.indent() - self.write("with %s" % ast.with_) + self.write(f'with {ast.with_}') if ast.set is not None: self.indent() - self.write("set %s" % ast.set) + self.write(f'set {ast.set}') # item_arguments attribute since 7.1.4 - if hasattr(ast, "item_arguments"): + if hasattr(ast, 'item_arguments'): item_arguments = ast.item_arguments else: item_arguments = [None] * len(ast.items) @@ -633,7 +630,7 @@ def print_python(self, ast, early=False): self.write_lines(split_logical_lines(code)) else: - self.write("$ %s" % code) + self.write(f'$ {code}') @dispatch(renpy.ast.EarlyPython) def print_earlypython(self, ast): @@ -649,21 +646,23 @@ def print_define(self, ast): if isinstance(self.parent, renpy.ast.Init): init = self.parent if init.priority != self.init_offset and len(init.block) == 1 and not self.should_come_before(init, ast): - priority = " %d" % (init.priority - self.init_offset) + priority = f' {init.priority - self.init_offset}' index = "" # index attribute added in 7.4 if getattr(ast, "index", None) is not None: - index = "[%s]" % ast.index.source + index = f'[{ast.index.source}]' # operator attribute added in 7.4 operator = getattr(ast, "operator", "=") # store attribute added in 6.18.2 if getattr(ast, "store", "store") == "store": - self.write("define%s %s%s %s %s" % (priority, ast.varname, index, operator, ast.code.source)) + self.write(f'define{priority} {ast.varname}{index} {operator} {ast.code.source}') else: - self.write("define%s %s.%s%s %s %s" % (priority, ast.store[6:], ast.varname, index, operator, ast.code.source)) + self.write( + f'define{priority} {ast.store[6:]}.{ast.varname}{index} {operator} ' + f'{ast.code.source}') @dispatch(renpy.ast.Default) def print_default(self, ast): @@ -675,12 +674,12 @@ def print_default(self, ast): if isinstance(self.parent, renpy.ast.Init): init = self.parent if init.priority != self.init_offset and len(init.block) == 1 and not self.should_come_before(init, ast): - priority = " %d" % (init.priority - self.init_offset) + priority = f' {init.priority - self.init_offset}' if ast.store == "store": - self.write("default%s %s = %s" % (priority, ast.varname, ast.code.source)) + self.write(f'default{priority} {ast.varname} = {ast.code.source}') else: - self.write("default%s %s.%s = %s" % (priority, ast.store[6:], ast.varname, ast.code.source)) + self.write(f'default{priority} {ast.store[6:]}.{ast.varname} = {ast.code.source}') # Specials @@ -688,7 +687,7 @@ def print_default(self, ast): # actually belongs inside of the Menu statement. def say_belongs_to_menu(self, say, menu): return (not say.interact and say.who is not None and - say.with_ is None and + say.with_ is None and say.attributes is None and isinstance(menu, renpy.ast.Menu) and menu.items[0][2] is not None and @@ -733,30 +732,30 @@ def print_style(self, ast): # These don't store a line number, so just put them on the first line if ast.parent is not None: - keywords[ast.linenumber].append("is %s" % ast.parent) + keywords[ast.linenumber].append(f'is {ast.parent}') if ast.clear: keywords[ast.linenumber].append("clear") if ast.take is not None: - keywords[ast.linenumber].append("take %s" % ast.take) + keywords[ast.linenumber].append(f'take {ast.take}') for delname in ast.delattr: - keywords[ast.linenumber].append("del %s" % delname) + keywords[ast.linenumber].append(f'del {delname}') # These do store a line number if ast.variant is not None: if ast.variant.linenumber not in keywords: keywords[ast.variant.linenumber] = WordConcatenator(False) - keywords[ast.variant.linenumber].append("variant %s" % ast.variant) + keywords[ast.variant.linenumber].append(f'variant {ast.variant}') for key, value in ast.properties.items(): if value.linenumber not in keywords: keywords[value.linenumber] = WordConcatenator(False) - keywords[value.linenumber].append("%s %s" % (key, value)) + keywords[value.linenumber].append(f'{key} {value}') keywords = sorted([(k, v.join()) for k, v in keywords.items()], key=itemgetter(0)) self.indent() - self.write("style %s" % ast.style_name) + self.write(f'style {ast.style_name}') if keywords[0][1]: - self.write(" %s" % keywords[0][1]) + self.write(f' {keywords[0][1]}') if len(keywords) > 1: self.write(":") with self.increase_indent(): @@ -770,7 +769,7 @@ def print_style(self, ast): @dispatch(renpy.ast.Translate) def print_translate(self, ast): self.indent() - self.write("translate %s %s:" % (ast.language or "None", ast.identifier)) + self.write(f'translate {ast.language or "None"} {ast.identifier}:') self.print_nodes(ast.block, 1) @@ -787,25 +786,25 @@ def print_translatestring(self, ast): isinstance(self.block[self.index - 1], renpy.ast.TranslateString) and self.block[self.index - 1].language == ast.language): self.indent() - self.write("translate %s strings:" % ast.language or "None") + self.write(f'translate {ast.language or "None"} strings:') # TranslateString's linenumber refers to the line with "old", not to the - # line with "translate %s strings:" + # line with "translate ... strings: (above)" with self.increase_indent(): self.advance_to_line(ast.linenumber) self.indent() - self.write('old "%s"' % string_escape(ast.old)) + self.write(f'old "{string_escape(ast.old)}"') # newlock attribute since 6.99 if hasattr(ast, "newloc"): self.advance_to_line(ast.newloc[1]) self.indent() - self.write('new "%s"' % string_escape(ast.new)) + self.write(f'new "{string_escape(ast.new)}"') @dispatch(renpy.ast.TranslateBlock) @dispatch(renpy.ast.TranslateEarlyBlock) def print_translateblock(self, ast): self.indent() - self.write("translate %s " % (ast.language or "None")) + self.write(f'translate {ast.language or "None"} ') self.skip_indent_until_write = True @@ -845,7 +844,7 @@ def print_screen(self, ast): def print_testcase(self, ast): self.require_init() self.indent() - self.write('testcase %s:' % ast.label) + self.write(f'testcase {ast.label}:') self.linenumber = testcasedecompiler.pprint( self.out_file, ast.test.block, self.options, self.indent_level + 1, self.linenumber, self.skip_indent_until_write @@ -857,4 +856,4 @@ def print_testcase(self, ast): @dispatch(renpy.ast.RPY) def print_rpy_python(self, ast): self.indent() - self.write("rpy python %s" % ast.rest) + self.write(f'rpy python {ast.rest}') diff --git a/decompiler/astdump.py b/decompiler/astdump.py index 11adb6a..41baf85 100644 --- a/decompiler/astdump.py +++ b/decompiler/astdump.py @@ -58,7 +58,7 @@ def print_ast(self, ast): except ValueError: pass else: - self.p('' % self.passed_where[i]) + self.p(f'') return self.passed.append(ast) self.passed_where.append(self.linenumber) diff --git a/decompiler/atldecompiler.py b/decompiler/atldecompiler.py index fde18bc..73bf274 100644 --- a/decompiler/atldecompiler.py +++ b/decompiler/atldecompiler.py @@ -104,7 +104,7 @@ def print_atl_rawmulti(self, ast): # circles if ast.circles != "0": - words.append("circles %s" % ast.circles) + words.append(f'circles {ast.circles}') # splines spline_words = WordConcatenator(False) @@ -165,7 +165,7 @@ def print_atl_rawchoice(self, ast): self.indent() self.write("choice") if chance != "1.0": - self.write(" %s" % chance) + self.write(f' {chance}') self.write(":") self.print_block(block) if (self.index + 1 < len(self.block) and @@ -176,17 +176,17 @@ def print_atl_rawchoice(self, ast): @dispatch(renpy.atl.RawContainsExpr) def print_atl_rawcontainsexpr(self, ast): self.indent() - self.write("contains %s" % ast.expression) + self.write(f'contains {ast.expression}') @dispatch(renpy.atl.RawEvent) def print_atl_rawevent(self, ast): self.indent() - self.write("event %s" % ast.name) + self.write(f'event {ast.name}') @dispatch(renpy.atl.RawFunction) def print_atl_rawfunction(self, ast): self.indent() - self.write("function %s" % ast.expr) + self.write(f'function {ast.expr}') @dispatch(renpy.atl.RawOn) def print_atl_rawon(self, ast): @@ -194,7 +194,7 @@ def print_atl_rawon(self, ast): key=lambda i: i[1].loc[1]): self.advance_to_block(block) self.indent() - self.write("on %s:" % name) + self.write(f'on {name}:') self.print_block(block) @dispatch(renpy.atl.RawParallel) @@ -214,9 +214,9 @@ def print_atl_rawrepeat(self, ast): self.indent() self.write("repeat") if ast.repeats: - self.write(" %s" % ast.repeats) # not sure if this is even a string + self.write(f' {ast.repeats}') # not sure if this is even a string @dispatch(renpy.atl.RawTime) def print_atl_rawtime(self, ast): self.indent() - self.write("time %s" % ast.time) + self.write(f'time {ast.time}') diff --git a/decompiler/sl2decompiler.py b/decompiler/sl2decompiler.py index b1ff415..0ef95e5 100644 --- a/decompiler/sl2decompiler.py +++ b/decompiler/sl2decompiler.py @@ -62,7 +62,7 @@ def print_screen(self, ast): # Print the screen statement and create the block self.indent() - self.write("screen %s" % ast.name) + self.write(f'screen {ast.name}') # If we have parameters, print them. if ast.parameters: self.write(reconstruct_paraminfo(ast.parameters)) @@ -97,7 +97,7 @@ def _print_if(self, ast, keyword): if condition is None: self.write("else") else: - self.write("%s %s" % (keyword(), condition)) + self.write(f'{keyword()} {condition}') # Every condition has a block of type slast.SLBlock self.print_block(block, immediate_block=True) @@ -142,10 +142,10 @@ def print_for(self, ast): self.indent() if hasattr(ast, "index_expression") and ast.index_expression is not None: - self.write("for %sindex %s in %s:" % (variable, ast.index_expression, ast.expression)) + self.write(f'for {variable}index {ast.index_expression} in {ast.expression}:') else: - self.write("for %sin %s:" % (variable, ast.expression)) + self.write(f'for {variable}in {ast.expression}:') # for doesn't contain a block, but just a list of child nodes self.print_nodes(children, 1) @@ -173,7 +173,7 @@ def print_python(self, ast): with self.increase_indent(): self.write_lines(split_logical_lines(code)) else: - self.write("$ %s" % code) + self.write(f'$ {code}') @dispatch(sl2.slast.SLPass) def print_pass(self, ast): @@ -188,17 +188,17 @@ def print_use(self, ast): self.write("use ") args = reconstruct_arginfo(ast.args) if isinstance(ast.target, PyExpr): - self.write("expression %s" % ast.target) + self.write(f'expression {ast.target}') if args: self.write(" pass ") else: - self.write("%s" % ast.target) + self.write(f'{ast.target}') - self.write("%s" % args) + self.write(f'{args}') if hasattr(ast, 'id') and ast.id is not None: - self.write(" id %s" % ast.id) + self.write(f' id {ast.id}') - if hasattr(ast, 'block') and ast.block: + if hasattr(ast, "block") and ast.block: self.print_block(ast.block) @dispatch(sl2.slast.SLTransclude) @@ -210,7 +210,7 @@ def print_transclude(self, ast): def print_default(self, ast): # A default statement self.indent() - self.write("default %s = %s" % (ast.variable, ast.expression)) + self.write(f'default {ast.variable} = {ast.expression}') @dispatch(sl2.slast.SLDisplayable) def print_displayable(self, ast, has_block=False): @@ -223,7 +223,8 @@ def print_displayable(self, ast, has_block=False): if nameAndChildren is None and self.options.sl_custom_names: # check if we have a name registered for this displayable nameAndChildren = self.options.sl_custom_names.get(ast.displayable.__name__) - self.print_debug("Substituted '{}' as the name for displayable {}".format(nameAndChildren[0], ast.displayable)) + self.print_debug( + f'Substituted "{nameAndChildren[0]}" as the name for displayable {ast.displayable}') if nameAndChildren is None: # This is a (user-defined) displayable we don't know about. @@ -232,13 +233,10 @@ def print_displayable(self, ast, has_block=False): # print a debug message nameAndChildren = (ast.style, 'many') self.print_debug( - """Warning: Encountered a user-defined displayable of type '{}'. + f'''Warning: Encountered a user-defined displayable of type "{ast.displayable}". Unfortunately, the name of user-defined displayables is not recorded in the compiled file. - For now the style name '{}' will be substituted. - To check if this is correct, find the corresponding renpy.register_sl_displayable call.""".format( - ast.displayable, ast.style - ) - ) + For now the style name "{ast.style}" will be substituted. + To check if this is correct, find the corresponding renpy.register_sl_displayable call.''') # noqa (name, children) = nameAndChildren self.indent() @@ -335,9 +333,9 @@ def print_displayable(self, ast, has_block=False): def sort_keywords_and_children(self, node, immediate_block=False, ignore_children=False): # sorts the contents of a SL statement that has keywords and children # returns a list of sorted contents. - # + # # node is either a SLDisplayable, a SLScreen or a SLBlock - # + # # before this point, the name and any positional arguments of the statement have been # emitted, but the block itself has not been created yet. # immediate_block: bool, if True, nothing is on the first line @@ -346,7 +344,7 @@ def sort_keywords_and_children(self, node, immediate_block=False, ignore_childre # get all the data we need from the node keywords = node.keyword children = [] if ignore_children else node.children - + # first linenumber where we can insert content that doesn't have a clear lineno block_lineno = node.location[1] start_lineno = (block_lineno + 1) if immediate_block else block_lineno @@ -560,7 +558,7 @@ def print_keyword_or_child(self, item, first_line=False, has_block=False): for name, value in item[2]: self.write(sep()) - self.write("%s %s" % (name, value)) + self.write(f'{name} {value}') if ty == "keywords_atl": assert not has_block, "cannot start a block on the same line as an at transform block" diff --git a/decompiler/testcasedecompiler.py b/decompiler/testcasedecompiler.py index 3c3c7e5..58497e7 100644 --- a/decompiler/testcasedecompiler.py +++ b/decompiler/testcasedecompiler.py @@ -53,92 +53,92 @@ def print_python(self, ast): with self.increase_indent(): self.write_lines(split_logical_lines(code[1:])) else: - self.write("$ %s" % code) + self.write(f'$ {code}') @dispatch(testast.If) def print_if(self, ast): self.indent() - self.write('if %s:' % ast.condition) + self.write(f'if {ast.condition}:') self.print_nodes(ast.block, extra_indent=1) @dispatch(testast.Assert) def print_assert(self, ast): self.indent() - self.write('assert %s' % ast.expr) + self.write(f'assert {ast.expr}') @dispatch(testast.Jump) def print_jump(self, ast): self.indent() - self.write('jump %s' % ast.target) + self.write(f'jump {ast.target}') @dispatch(testast.Call) def print_call(self, ast): self.indent() - self.write('call %s' % ast.target) + self.write(f'call {ast.target}') @dispatch(testast.Action) def print_action(self, ast): self.indent() - self.write('run %s' % ast.expr) + self.write(f'run {ast.expr}') @dispatch(testast.Pause) def print_pause(self, ast): self.indent() - self.write('pause %s' % ast.expr) + self.write(f'pause {ast.expr}') @dispatch(testast.Label) def print_label(self, ast): self.indent() - self.write('label %s' % ast.name) + self.write(f'label {ast.name}') @dispatch(testast.Type) def print_type(self, ast): self.indent() if len(ast.keys[0]) == 1: - self.write('type "%s"' % string_escape(''.join(ast.keys))) + self.write(f'type "{string_escape("".join(ast.keys))}"') else: - self.write('type %s' % ast.keys[0]) + self.write(f'type {ast.keys[0]}') if ast.pattern is not None: - self.write(' pattern "%s"' % string_escape(ast.pattern)) + self.write(f' pattern "{string_escape(ast.pattern)}"') if hasattr(ast, 'position') and ast.position is not None: - self.write(' pos %s' % ast.position) + self.write(f' pos {ast.position}') @dispatch(testast.Drag) def print_drag(self, ast): self.indent() - self.write('drag %s' % ast.points) + self.write(f'drag {ast.points}') if ast.button != 1: - self.write(' button %d' % ast.button) + self.write(f' button {ast.button}') if ast.pattern is not None: - self.write(' pattern "%s"' % string_escape(ast.pattern)) + self.write(f' pattern "{string_escape(ast.pattern)}"') if ast.steps != 10: - self.write(' steps %d' % ast.steps) + self.write(f' steps {ast.steps}') @dispatch(testast.Move) def print_move(self, ast): self.indent() - self.write('move %s' % ast.position) + self.write(f'move {ast.position}') if ast.pattern is not None: - self.write(' pattern "%s"' % string_escape(ast.pattern)) + self.write(f' pattern "{string_escape(ast.pattern)}"') @dispatch(testast.Click) def print_click(self, ast): self.indent() if ast.pattern is not None: - self.write('"%s"' % string_escape(ast.pattern)) + self.write(f'"{string_escape(ast.pattern)}"') else: - self.write('click') + self.write("click") if hasattr(ast, 'button') and ast.button != 1: - self.write(' button %d' % ast.button) + self.write(f' button {ast.button}') if hasattr(ast, 'position') and ast.position is not None: - self.write(' pos %s' % ast.position) + self.write(f' pos {ast.position}') if hasattr(ast, 'always') and ast.always: - self.write(' always') + self.write(" always") @dispatch(testast.Scroll) def print_scroll(self, ast): self.indent() - self.write('scroll "%s"' % string_escape(ast.pattern)) + self.write(f'scroll "{string_escape(ast.pattern)}"') @dispatch(testast.Until) def print_until(self, ast): @@ -147,6 +147,6 @@ def print_until(self, ast): # Go to right's line number now since we can't go to it after we print left. self.advance_to_line(ast.right.linenumber) self.print_node(ast.left) - self.write(' until ') + self.write(" until ") self.skip_indent_until_write = True - self.print_node(ast.right) \ No newline at end of file + self.print_node(ast.right) diff --git a/decompiler/translate.py b/decompiler/translate.py index 9cad91c..2139b3d 100644 --- a/decompiler/translate.py +++ b/decompiler/translate.py @@ -52,7 +52,7 @@ def unique_identifier(self, label, digest): break i += 1 - suffix = "_{0}".format(i) + suffix = f'_{i}' return identifier @@ -69,7 +69,7 @@ def create_translate(self, block): elif isinstance(i, renpy.ast.UserStatement): code = i.line else: - raise Exception("Don't know how to get canonical code for a %s" % str(type(i))) + raise Exception(f'Don\'t know how to get canonical code for a {type(i)!s}') md5.update(code.encode("utf-8") + b"\r\n") digest = md5.hexdigest()[:8] diff --git a/decompiler/util.py b/decompiler/util.py index 82d7285..0cf97da 100644 --- a/decompiler/util.py +++ b/decompiler/util.py @@ -1,7 +1,7 @@ # Copyright (c) 2014-2024 CensoredUsername, Jackmcbarn # # Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal +# of this software and associated documentation files (the "Software'), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is @@ -189,11 +189,11 @@ def print_debug(self, message): def write_failure(self, message): self.print_debug(message) self.indent() - self.write("pass # <<>>" % message) + self.write(f'pass # <<>>') def print_unknown(self, ast): # If we encounter a placeholder note, print a warning and insert a placeholder - self.write_failure("Unknown AST node: %s" % str(type(ast))) + self.write_failure(f'Unknown AST node: {type(ast)!s}') def print_node(self, ast): raise NotImplementedError() @@ -222,7 +222,7 @@ def reconstruct_paraminfo(paraminfo): rv = ["("] sep = First("", ", ") - if hasattr(paraminfo, "positional_only"): + if hasattr(paraminfo, 'positional_only'): # ren'py 7.5-7.6 and 8.0-8.1, a slightly changed variant of 7.4 and before already_accounted = set(name for name, default in paraminfo.positional_only) @@ -267,7 +267,7 @@ def reconstruct_paraminfo(paraminfo): rv.append("**") rv.append(paraminfo.extrakw) - elif hasattr(paraminfo, "extrapos"): + elif hasattr(paraminfo, 'extrapos'): # ren'py 7.4 and below, python 2 style positional = [i for i in paraminfo.parameters if i[0] in paraminfo.positional] nameonly = [i for i in paraminfo.parameters if i not in positional] @@ -275,10 +275,10 @@ def reconstruct_paraminfo(paraminfo): rv.append(sep()) rv.append(parameter[0]) if parameter[1] is not None: - rv.append("=%s" % parameter[1]) + rv.append(f'={parameter[1]}') if paraminfo.extrapos: rv.append(sep()) - rv.append("*%s" % paraminfo.extrapos) + rv.append(f'*{paraminfo.extrapos}') if nameonly: if not paraminfo.extrapos: rv.append(sep()) @@ -287,10 +287,10 @@ def reconstruct_paraminfo(paraminfo): rv.append(sep()) rv.append(parameter[0]) if parameter[1] is not None: - rv.append("=%s" % parameter[1]) + rv.append(f'={parameter[1]}') if paraminfo.extrakw: rv.append(sep()) - rv.append("**%s" % paraminfo.extrakw) + rv.append(f'**{paraminfo.extrakw}') else: # ren'py 7.7/8.2 and above. @@ -307,7 +307,7 @@ def reconstruct_paraminfo(paraminfo): rv.append(parameter.name) if parameter.default is not None: - rv.append("=%s" % parameter.default) + rv.append(f'={parameter.default}') else: if state == 0: @@ -320,29 +320,29 @@ def reconstruct_paraminfo(paraminfo): # positional or keyword rv.append(parameter.name) if parameter.default is not None: - rv.append("=%s" % parameter.default) + rv.append(f'={parameter.default}') elif parameter.kind == 2: # *positional state = 2 - rv.append("*%s" % parameter.name) + rv.append(f'*{parameter.name}') elif parameter.kind == 3: # keyword only if state == 1: # insert the * if we didn't have a *args before state = 2 - rv.append("*") + rv.append('*') rv.append(sep()) rv.append(parameter.name) if parameter.default is not None: - rv.append("=%s" % parameter.default) + rv.append(f'={parameter.default}') elif parameter.kind == 4: # **keyword state = 3 - rv.append("**%s" % parameter.name) + rv.append(f'**{parameter.name}') rv.append(")") @@ -355,16 +355,16 @@ def reconstruct_arginfo(arginfo): rv = ["("] sep = First("", ", ") - if hasattr(arginfo, "starred_indexes"): + if hasattr(arginfo, 'starred_indexes'): # ren'py 7.5 and above, PEP 448 compliant for i, (name, val) in enumerate(arginfo.arguments): rv.append(sep()) if name is not None: - rv.append("%s=" % name) + rv.append(f'{name}=') elif i in arginfo.starred_indexes: - rv.append("*") + rv.append('*') elif i in arginfo.doublestarred_indexes: - rv.append("**") + rv.append('**') rv.append(val) else: @@ -372,14 +372,14 @@ def reconstruct_arginfo(arginfo): for (name, val) in arginfo.arguments: rv.append(sep()) if name is not None: - rv.append("%s=" % name) + rv.append(f'{name}=') rv.append(val) if arginfo.extrapos: rv.append(sep()) - rv.append("*%s" % arginfo.extrapos) + rv.append(f'*{arginfo.extrapos}') if arginfo.extrakw: rv.append(sep()) - rv.append("**%s" % arginfo.extrakw) + rv.append(f'**{arginfo.extrakw}') rv.append(")") @@ -412,7 +412,7 @@ def simple_expression_guard(s): if Lexer(s).simple_expression(): return s else: - return "(%s)" % s + return f'({s})' def split_logical_lines(s): return Lexer(s).split_logical_lines() @@ -649,12 +649,12 @@ def say_get_code(ast, inmenu=False): rv.append("nointeract") # explicit_identifier was only added in 7.7/8.2. - if hasattr(ast, "explicit_identifier") and ast.explicit_identifier: + if hasattr(ast, 'explicit_identifier') and ast.explicit_identifier: rv.append("id") rv.append(ast.identifier) # identifier was added in 7.4.1. But the way ren'py processed it # means it doesn't stored it in the pickle unless explicitly set - elif hasattr(ast, "identifier") and ast.identifier is not None: + elif hasattr(ast, 'identifier') and ast.identifier is not None: rv.append("id") rv.append(ast.identifier) diff --git a/deobfuscate.py b/deobfuscate.py index bb126b1..a63b121 100644 --- a/deobfuscate.py +++ b/deobfuscate.py @@ -286,9 +286,11 @@ def read_ast(f): try: data = extractor(f, 1) except ValueError as e: - diagnosis.append("strategy %s failed: %s" % (extractor.__name__, "\n".join(e.args))) + # inside f-string braces "\" are not allowed before py3.12, so we use chr() till + # this our minimum py is + diagnosis.append(f'strategy {extractor.__name__} failed: {chr(10).join(e.args)}') else: - diagnosis.append("strategy %s success" % extractor.__name__) + diagnosis.append(f'strategy {extractor.__name__} success') raw_datas.add(data) if not raw_datas: @@ -336,7 +338,7 @@ def try_decrypt_section(raw_data): continue else: raw_data = newdata - diagnosis.append("performed a round of %s" % decryptor.__name__) + diagnosis.append(f'performed a round of {decryptor.__name__}') break else: break diff --git a/un.rpyc/compile.py b/un.rpyc/compile.py index 6ebf98a..9c40b9f 100755 --- a/un.rpyc/compile.py +++ b/un.rpyc/compile.py @@ -250,7 +250,7 @@ def Exec(code): f.write(unrpy) if args.debug: - print("File length = {0}".format(len(unrpyc))) + print(f'File length = {len(unrpyc)}') import pickletools @@ -279,4 +279,3 @@ def Exec(code): with (PACK_FOLDER / "un.rpy.dis").open("w", encoding="utf-8") as f: pickletools.dis(p.dumps(decompiler_items, protocol), f) - diff --git a/un.rpyc/minimize.py b/un.rpyc/minimize.py index b934efa..ad34c36 100644 --- a/un.rpyc/minimize.py +++ b/un.rpyc/minimize.py @@ -125,7 +125,7 @@ def write(self, name, protected=False): def dec_global(self, name): resolution = self.resolution.get(name, None) if resolution == self.NONLOCAL: - raise SyntaxError("name '{0}' is nonlocal and global".format(name)) + raise SyntaxError(f'name "{name}" is nonlocal and global') else: self.resolution[name] = self.GLOBAL @@ -134,7 +134,7 @@ def dec_global(self, name): def dec_nonlocal(self, name): resolution = self.resolution.get(name, None) if resolution == self.GLOBAL: - raise SyntaxError("name '{0}' is nonlocal and global".format(name)) + raise SyntaxError(f'name "{name}" is nonlocal and global') else: self.resolution[name] = self.NONLOCAL @@ -193,8 +193,7 @@ def resolve_unbounds(self, builtin_scope): break parent = parent.parent_scope else: - raise SyntaxError("no binding for nonlocal '{0}' found".format( - name)) + raise SyntaxError(f'no binding for nonlocal "{name}" found') # recurse for scope in self.children: scope.resolve_unbounds(builtin_scope) @@ -597,4 +596,4 @@ def newline(self, node=None, extra=0, force=False): def maybe_break(self, node): - pass \ No newline at end of file + pass diff --git a/un.rpyc/unrpyc-compile.py b/un.rpyc/unrpyc-compile.py index 7be6c73..a1aa1f6 100644 --- a/un.rpyc/unrpyc-compile.py +++ b/un.rpyc/unrpyc-compile.py @@ -58,11 +58,11 @@ def decompile_game(): try: decompile_rpyc(data, fullpath) except Exception as e: - f.write("\nFailed at decompiling {0}\n".format(fullpath)) + f.write(f'\nFailed at decompiling {fullpath}\n') traceback = sys.modules['traceback'] traceback.print_exc(None, f) else: - f.write("\nDecompiled {0}\n".format(fullpath)) + f.write(f'\nDecompiled {fullpath}\n') f.write("\nend decompiling\n") diff --git a/unrpyc.py b/unrpyc.py index 8782103..0fb24d3 100755 --- a/unrpyc.py +++ b/unrpyc.py @@ -92,7 +92,7 @@ def read_ast_from_file(in_file): with printlock: print( - "Warning: encountered an unexpected slot structure. It is possible the \n" + "Warning: Encountered an unexpected slot structure. It is possible the \n" " file header structure has been changed.") position += 12 @@ -119,7 +119,7 @@ def read_ast_from_file(in_file): with printlock: print( "Warning: analysis found signs that this .rpyc file was generated by ren'py \n" - f" version {version} or below, while this unrpyc version targets ren'py version 8. \n" + f' version {version} or below, while this unrpyc version targets ren\'py version 8. \n' " Decompilation will still be attempted, but errors or incorrect \n" " decompilation might occur. ") @@ -141,7 +141,7 @@ def decompile_rpyc(input_filename, overwrite=False, dump=False, out_filename = input_filename.with_suffix(ext) with printlock: - print("Decompiling %s to %s..." % (input_filename, out_filename)) + print(f'Decompiling {input_filename} to {out_filename.name}...') if not overwrite and out_filename.exists(): print("Output file already exists. Pass --clobber to overwrite.") @@ -166,7 +166,7 @@ def decompile_rpyc(input_filename, overwrite=False, dump=False, def extract_translations(input_filename, language): with printlock: - print("Extracting translations from %s..." % input_filename) + print(f'Extracting translations from {input_filename}...') with input_filename.open('rb') as in_file: ast = read_ast_from_file(in_file) @@ -184,7 +184,7 @@ def parse_sl_custom_names(unparsed_arguments): for argument in unparsed_arguments: content = argument.split("=") if len(content) != 2: - raise Exception("Bad format in custom sl displayable registration: '{}'".format(argument)) + raise Exception(f'Bad format in custom sl displayable registration: "{argument}"') classname, name = content split = name.split("-") @@ -200,10 +200,12 @@ def parse_sl_custom_names(unparsed_arguments): elif amount == "many": pass else: - raise Exception("Bad child node count in custom sl displayable registration: '{}'".format(argument)) + raise Exception( + f'Bad child node count in custom sl displayable registration: "{argument}"') else: - raise Exception("Bad format in custom sl displayable registration: '{}'".format(argument)) + raise Exception( + f'Bad format in custom sl displayable registration: "{argument}"') parsed_arguments[classname] = (name, amount) @@ -227,7 +229,7 @@ def worker(arg_tup): sl_custom_names=args.sl_custom_names) except Exception as e: with printlock: - print("Error while decompiling %s:" % filename) + print(f'Error while decompiling {filename}:') print(traceback.format_exc()) return False @@ -235,7 +237,7 @@ def worker(arg_tup): def main(): if not sys.version_info[:2] >= (3, 9): raise Exception("Must be executed in Python 3.9 or later.\n" - f"You are running {sys.version}") + f'You are running {sys.version}') # argparse usage: python3 unrpyc.py [-c] [--try-harder] [-d] [-p] file [file ...] cc_num = cpu_count() @@ -366,7 +368,7 @@ def glob_or_complain(inpath): """Expands wildcards and casts output to pathlike state.""" retval = [Path(elem).resolve(strict=True) for elem in glob.glob(inpath)] if not retval: - print(f"Input path not found: {inpath}") + print(f'Input path not found: {inpath}') return retval def traverse(inpath): @@ -406,7 +408,7 @@ def traverse(inpath): results = list(map(worker, worklist)) if args.write_translation_file: - print("Writing translations to %s..." % args.write_translation_file) + print(f'Writing translations to {args.write_translation_file}...') translated_dialogue = {} translated_strings = {} good = 0 @@ -427,11 +429,13 @@ def traverse(inpath): bad = results.count(False) if bad == 0: - print("Decompilation of %d script file%s successful" % (good, 's' if good>1 else '')) + print(f'Decompilation of {good} script file{"s" if good>1 else ""} successful') elif good == 0: - print("Decompilation of %d file%s failed" % (bad, 's' if bad>1 else '')) + print(f'Decompilation of {bad} file{"s" if bad>1 else ""} failed') else: - print("Decompilation of %d file%s successful, but decompilation of %d file%s failed" % (good, 's' if good>1 else '', bad, 's' if bad>1 else '')) + print(f'Decompilation of {good} file{"s" if good>1 else ""} successful\n' + f'but decompilation of {bad} file{"s" if bad>1 else ""} failed') + if __name__ == '__main__': main()