From 5cccb9b5213228be4de17bc7b75e53a940967e7f Mon Sep 17 00:00:00 2001 From: Jared Miller Date: Thu, 12 Feb 2026 19:59:00 -0500 Subject: [PATCH] Convert format calls to f-strings --- art.py | 56 +++++++------- art_export.py | 11 +-- art_import.py | 4 +- camera.py | 2 +- charset.py | 36 +++------ collision.py | 8 +- cursor.py | 6 +- edit_command.py | 16 ++-- formats/in_bitmap.py | 2 +- formats/in_bitmap_sequence.py | 8 +- formats/out_png.py | 2 +- formats/out_png_set.py | 6 +- game_object.py | 38 ++++------ game_room.py | 20 ++--- game_util_objects.py | 12 +-- game_world.py | 68 +++++++---------- games/crawler/scripts/player.py | 2 +- games/fireplace/scripts/fireplace.py | 14 +--- games/flood/scripts/game.py | 2 +- games/maze/scripts/objects.py | 6 +- games/wildflowers/scripts/flower.py | 6 +- games/wildflowers/scripts/wildflowers.py | 2 +- image_convert.py | 6 +- image_export.py | 4 +- input_handler.py | 24 +++--- palette.py | 34 ++++----- playscii.py | 93 ++++++++++-------------- renderable.py | 24 ++---- renderable_line.py | 6 +- renderable_sprite.py | 2 +- shader.py | 24 ++---- ui.py | 16 ++-- ui_art_dialog.py | 12 +-- ui_button.py | 12 +-- ui_chooser_dialog.py | 2 +- ui_console.py | 18 ++--- ui_edit_panel.py | 7 +- ui_element.py | 10 +-- ui_file_chooser_dialog.py | 14 ++-- ui_game_menu_pulldown_item.py | 2 +- ui_info_dialog.py | 2 +- ui_menu_bar.py | 2 +- ui_menu_pulldown.py | 4 +- ui_menu_pulldown_item.py | 36 +++++---- ui_object_panel.py | 8 +- ui_popup.py | 31 ++++---- ui_status_bar.py | 20 +++-- ui_swatch.py | 4 +- ui_tool.py | 5 +- vector.py | 2 +- 50 files changed, 293 insertions(+), 458 deletions(-) diff --git a/art.py b/art.py index b367943..a51055e 100644 --- a/art.py +++ b/art.py @@ -107,8 +107,8 @@ class Art: def __init__(self, filename, app, charset, palette, width, height): "Creates a new, blank document with given parameters." self.valid = False - if filename and not filename.endswith(".{}".format(ART_FILE_EXTENSION)): - filename += ".{}".format(ART_FILE_EXTENSION) + if filename and not filename.endswith(f".{ART_FILE_EXTENSION}"): + filename += f".{ART_FILE_EXTENSION}" self.filename = filename self.app = app # save "time loaded" for menu sorting @@ -162,11 +162,11 @@ class Art: def log_init(self): self.app.log("created new document:") - self.app.log(" character set: {}".format(self.charset.name)) - self.app.log(" palette: {}".format(self.palette.name)) - self.app.log(" width/height: {} x {}".format(self.width, self.height)) - self.app.log(" frames: {}".format(self.frames)) - self.app.log(" layers: {}".format(self.layers)) + self.app.log(f" character set: {self.charset.name}") + self.app.log(f" palette: {self.palette.name}") + self.app.log(f" width/height: {self.width} x {self.height}") + self.app.log(f" frames: {self.frames}") + self.app.log(f" layers: {self.layers}") def init_layers(self): self.layers = 1 @@ -218,7 +218,7 @@ class Art: if self.app.ui and self is self.app.ui.active_art: self.app.ui.set_active_frame(index) if log: - self.app.log("Created new frame at index {}".format(str(index))) + self.app.log(f"Created new frame at index {str(index)}") def add_frame_to_end(self, delay=DEFAULT_FRAME_DELAY, log=True): "Add a blank frame at the end of the current animation." @@ -245,9 +245,7 @@ class Art: if self is self.app.ui.active_art: self.app.ui.set_active_frame(dest_frame_index - 1) self.app.log( - "Duplicated frame {} at frame {}".format( - src_frame_index + 1, dest_frame_index - ) + f"Duplicated frame {src_frame_index + 1} at frame {dest_frame_index}" ) def delete_frame_at(self, index): @@ -307,7 +305,7 @@ class Art: z = z if z is not None else self.layers_z[src_index] self.layers_z.append(z) self.layers_visibility.append(True) - new_name = new_name or "Copy of {}".format(self.layer_names[src_index]) + new_name = new_name or f"Copy of {self.layer_names[src_index]}" self.layer_names.append(new_name) # rebuild geo with added verts for new layer self.geo_changed = True @@ -316,7 +314,7 @@ class Art: self.app.ui.set_active_layer(self.layers - 1) # don't log new layers created on the fly in game mode if not self.app.game_mode: - self.app.log("Added new layer {}".format(new_name)) + self.app.log(f"Added new layer {new_name}") self.set_unsaved_changes(True) def clear_frame_layer(self, frame, layer, bg_color=0, fg_color=None): @@ -367,7 +365,7 @@ class Art: self.geo_changed = True if log: self.app.ui.message_line.post_line( - "Character set changed to {}".format(self.charset.name) + f"Character set changed to {self.charset.name}" ) def set_charset_by_name(self, new_charset_name): @@ -383,7 +381,7 @@ class Art: self.set_unsaved_changes(True) if log: self.app.ui.message_line.post_line( - "Color palette changed to {}".format(self.palette.name) + f"Color palette changed to {self.palette.name}" ) def set_palette_by_name(self, new_palette_name): @@ -870,7 +868,7 @@ class Art: json.dump(d, open(self.filename, "w"), sort_keys=True, indent=1) self.set_unsaved_changes(False) # self.app.log('saved %s to disk in %.5f seconds' % (self.filename, end_time - start_time)) - self.app.log("saved {}".format(self.filename)) + self.app.log(f"saved {self.filename}") # remove old thumbnail thumb_dir = self.app.cache_dir + THUMBNAIL_CACHE_DIR if os.path.exists(self.filename): @@ -935,9 +933,7 @@ class Art: json.dump(d, open(self.filename + "2", "w"), sort_keys=True, indent=None) end_time = time.time() self.app.log( - "ALT saved {} to disk in {:.5f} seconds".format( - self.filename, end_time - start_time - ) + f"ALT saved {self.filename} to disk in {end_time - start_time:.5f} seconds" ) def set_unsaved_changes(self, new_status): @@ -985,13 +981,13 @@ class Art: exec(open(script_filename).read()) # (assume script changed art) self.unsaved_changes = True - logline = "Executed {}".format(script_filename) + logline = f"Executed {script_filename}" if log: self.app.log(logline) error = False except Exception: error = True - logline = "Error executing {}:".format(script_filename) + logline = f"Error executing {script_filename}:" self.app.log(logline) # skip first 3 lines of callstack before artscript exec for line in traceback.format_exc().split("\n")[3:]: @@ -1021,7 +1017,7 @@ class Art: if not script_filename: return if script_filename in self.scripts: - self.app.log("script {} is already running.".format(script_filename)) + self.app.log(f"script {script_filename} is already running.") return # add to "scripts currently running" list self.scripts.append(script_filename) @@ -1037,7 +1033,7 @@ class Art: if not script_filename: return if script_filename not in self.scripts: - self.app.log("script {} exists but isn't running.".format(script_filename)) + self.app.log(f"script {script_filename} exists but isn't running.") return script_index = self.scripts.index(script_filename) self.scripts.pop(script_index) @@ -1240,12 +1236,12 @@ class ArtFromDisk(Art): self.valid = True def log_init(self): - self.app.log("Loaded {} from disk:".format(filename)) - self.app.log(" character set: {}".format(self.charset.name)) - self.app.log(" palette: {}".format(self.palette.name)) - self.app.log(" width/height: {} x {}".format(self.width, self.height)) - self.app.log(" frames: {}".format(self.frames)) - self.app.log(" layers: {}".format(self.layers)) + self.app.log(f"Loaded {filename} from disk:") + self.app.log(f" character set: {self.charset.name}") + self.app.log(f" palette: {self.palette.name}") + self.app.log(f" width/height: {self.width} x {self.height}") + self.app.log(f" frames: {self.frames}") + self.app.log(f" layers: {self.layers}") def init_layers(self): frames = self.loaded_data["frames"] @@ -1256,7 +1252,7 @@ class ArtFromDisk(Art): self.layers_z.append(layer["z"]) self.layers_visibility.append(bool(layer.get("visible", 1))) layer_num = str(i + 1) - self.layer_names.append(layer.get("name", "Layer {}".format(layer_num))) + self.layer_names.append(layer.get("name", f"Layer {layer_num}")) active_layer = self.loaded_data.get("active_layer", 0) self.set_active_layer(active_layer) diff --git a/art_export.py b/art_export.py index 19d9251..4a33cd0 100644 --- a/art_export.py +++ b/art_export.py @@ -23,10 +23,8 @@ class ArtExporter: self.app = app self.art = self.app.ui.active_art # add file extension to output filename if not present - if self.file_extension and not out_filename.endswith( - ".{}".format(self.file_extension) - ): - out_filename += ".{}".format(self.file_extension) + if self.file_extension and not out_filename.endswith(f".{self.file_extension}"): + out_filename += f".{self.file_extension}" # output filename in documents/art dir if not out_filename.startswith(self.app.documents_dir + ART_DIR): out_filename = self.app.documents_dir + ART_DIR + out_filename @@ -41,10 +39,7 @@ class ArtExporter: if self.run_export(out_filename, options): self.success = True else: - line = "{} failed to export {}, see console for errors".format( - self.__class__.__name__, - out_filename, - ) + line = f"{self.__class__.__name__} failed to export {out_filename}, see console for errors" self.app.log(line) self.app.ui.message_line.post_line(line, hold_time=10, error=True) except Exception: diff --git a/art_import.py b/art_import.py index 4eeee01..135590d 100644 --- a/art_import.py +++ b/art_import.py @@ -32,9 +32,7 @@ class ArtImporter: def __init__(self, app, in_filename, options={}): self.app = app - new_filename = "{}.{}".format( - os.path.splitext(in_filename)[0], ART_FILE_EXTENSION - ) + new_filename = f"{os.path.splitext(in_filename)[0]}.{ART_FILE_EXTENSION}" self.art = self.app.new_art(new_filename) # use charset and palette of existing art charset = ( diff --git a/camera.py b/camera.py index e3027b9..62daa3c 100644 --- a/camera.py +++ b/camera.py @@ -312,4 +312,4 @@ class Camera: self.mouse_panned = False def log_loc(self): - self.app.log("camera x={}, y={}, z={}".format(self.x, self.y, self.z)) + self.app.log(f"camera x={self.x}, y={self.y}, z={self.z}") diff --git a/charset.py b/charset.py index dbb301e..28d838e 100644 --- a/charset.py +++ b/charset.py @@ -32,22 +32,16 @@ class CharacterSetLord: success = charset.load_char_data() if success: self.app.log( - "CharacterSetLord: success reloading {}".format( - charset.filename - ) + f"CharacterSetLord: success reloading {charset.filename}" ) else: self.app.log( - "CharacterSetLord: failed reloading {}".format( - charset.filename - ), + f"CharacterSetLord: failed reloading {charset.filename}", True, ) except Exception: self.app.log( - "CharacterSetLord: failed reloading {}".format( - charset.filename - ), + f"CharacterSetLord: failed reloading {charset.filename}", True, ) @@ -62,7 +56,7 @@ class CharacterSet: src_filename, CHARSET_DIR, CHARSET_FILE_EXTENSION ) if not self.filename: - self.app.log("Couldn't find character set data {}".format(self.filename)) + self.app.log(f"Couldn't find character set data {self.filename}") return self.name = os.path.basename(self.filename) self.name = os.path.splitext(self.name)[0] @@ -76,9 +70,7 @@ class CharacterSet: return # report if log and not self.app.game_mode: - self.app.log( - "loaded charmap '{}' from {}:".format(self.name, self.filename) - ) + self.app.log(f"loaded charmap '{self.name}' from {self.filename}:") self.report() self.init_success = True @@ -97,9 +89,7 @@ class CharacterSet: char_data.pop(0).strip(), CHARSET_DIR, "png" ) if not img_filename: - self.app.log( - "Couldn't find character set image {}".format(self.image_filename) - ) + self.app.log(f"Couldn't find character set image {self.image_filename}") return False self.image_filename = img_filename # now that we know the image file's name, store its last modified time @@ -176,19 +166,13 @@ class CharacterSet: def report(self): self.app.log( - " source texture {} is {} x {} pixels".format( - self.image_filename, self.image_width, self.image_height - ) + f" source texture {self.image_filename} is {self.image_width} x {self.image_height} pixels" ) self.app.log( - " char pixel width/height is {} x {}".format( - self.char_width, self.char_height - ) + f" char pixel width/height is {self.char_width} x {self.char_height}" ) - self.app.log( - " char map width/height is {} x {}".format(self.map_width, self.map_height) - ) - self.app.log(" last character index: {}".format(self.last_index)) + self.app.log(f" char map width/height is {self.map_width} x {self.map_height}") + self.app.log(f" last character index: {self.last_index}") def has_updated(self): "return True if source image file has changed since last check" diff --git a/collision.py b/collision.py index c18af9a..8d065f7 100644 --- a/collision.py +++ b/collision.py @@ -307,9 +307,7 @@ class Collideable: frame = self.go.renderable.frame if self.go.col_layer_name not in self.go.art.layer_names: self.go.app.dev_log( - "{}: Couldn't find collision layer with name '{}'".format( - self.go.name, self.go.col_layer_name - ) + f"{self.go.name}: Couldn't find collision layer with name '{self.go.col_layer_name}'" ) return layer = self.go.art.layer_names.index(self.go.col_layer_name) @@ -443,9 +441,7 @@ class CollisionLord: def report(self): print( - "{}: {} dynamic shapes, {} static shapes".format( - self, len(self.dynamic_shapes), len(self.static_shapes) - ) + f"{self}: {len(self.dynamic_shapes)} dynamic shapes, {len(self.static_shapes)} static shapes" ) def reset(self): diff --git a/cursor.py b/cursor.py index 4cd2776..d71a701 100644 --- a/cursor.py +++ b/cursor.py @@ -141,9 +141,7 @@ class Cursor: self.app.keyboard_editing = True if self.logg: self.app.log( - "Cursor: {},{},{} scale {:.2f},{:.2f}".format( - self.x, self.y, self.z, self.scale_x, self.scale_y - ) + f"Cursor: {self.x},{self.y},{self.z} scale {self.scale_x:.2f},{self.scale_y:.2f}" ) def set_scale(self, new_scale): @@ -186,7 +184,7 @@ class Cursor: x0, y0 = self.x, -self.y x1, y1 = self.last_x, -self.last_y tiles = vector.get_tiles_along_line(x0, y0, x1, y1) - print("drag from {},{} to {},{}:".format(x0, y0, x1, y1)) + print(f"drag from {x0},{y0} to {x1},{y1}:") print(tiles) return tiles diff --git a/edit_command.py b/edit_command.py index e470e14..4904b06 100644 --- a/edit_command.py +++ b/edit_command.py @@ -23,11 +23,7 @@ class EditCommand: # get unique-ish ID from memory address addr = self.__repr__() addr = addr[addr.find("0") : -1] - s = "EditCommand_{}: {} tiles, time {}".format( - addr, - self.get_number_of_commands(), - self.finish_time, - ) + s = f"EditCommand_{addr}: {self.get_number_of_commands()} tiles, time {self.finish_time}" return s def add_command_tiles(self, new_command_tiles): @@ -95,7 +91,7 @@ class EntireArtCommand: for atype in self.array_types: # save list as eg "b_chars" for "character data before operation" src_data = getattr(self.art, atype) - var_name = "{}_{}".format(prefix, atype) + var_name = f"{prefix}_{atype}" # deep copy each frame's data, else before == after new_data = [] for frame in src_data: @@ -152,10 +148,8 @@ class EditCommandTile: str(self.y).rjust(2, "0"), self.creation_time, ) - s += "c{} f{} b{} x{} -> ".format( - self.b_char, self.b_fg, self.b_bg, self.b_xform - ) - s += "c{} f{} b{} x{}".format(self.a_char, self.a_fg, self.a_bg, self.a_xform) + s += f"c{self.b_char} f{self.b_fg} b{self.b_bg} x{self.b_xform} -> " + s += f"c{self.a_char} f{self.a_fg} b{self.a_bg} x{self.a_xform}" return s def __eq__(self, value): @@ -261,7 +255,7 @@ class CommandStack: self.undo_commands, self.redo_commands = [], [] def __str__(self): - s = "stack for {}:\n".format(self.art.filename) + s = f"stack for {self.art.filename}:\n" s += "===\nundo:\n" for cmd in self.undo_commands: s += str(cmd) + "\n" diff --git a/formats/in_bitmap.py b/formats/in_bitmap.py index 08902ef..741f6fb 100644 --- a/formats/in_bitmap.py +++ b/formats/in_bitmap.py @@ -100,7 +100,7 @@ class ConvertImageOptionsDialog(ImportOptionsDialog): # can't assume any art is open, use defaults if needed w = self.ui.active_art.width if self.ui.active_art else DEFAULT_WIDTH h = self.ui.active_art.height if self.ui.active_art else DEFAULT_HEIGHT - label %= "{} x {}".format(w, h) + label %= f"{w} x {h}" elif field_index == 7: # scale # might not be valid valid, _ = self.is_input_valid() diff --git a/formats/in_bitmap_sequence.py b/formats/in_bitmap_sequence.py index c91a3d2..f285afc 100644 --- a/formats/in_bitmap_sequence.py +++ b/formats/in_bitmap_sequence.py @@ -50,7 +50,7 @@ class ImageSequenceConverter: self.app.update_window_title() def fail(self): - self.app.log("Bad frame {}".format(self.image_filenames[0]), error=True) + self.app.log(f"Bad frame {self.image_filenames[0]}", error=True) self.finish(True) def update(self): @@ -65,9 +65,7 @@ class ImageSequenceConverter: time_taken = time.time() - self.start_time (verb, error) = ("cancelled", True) if cancelled else ("finished", False) self.app.log( - "Conversion of image sequence {} {} after {:.3f} seconds".format( - self.image_name, verb, time_taken - ), + f"Conversion of image sequence {self.image_name} {verb} after {time_taken:.3f} seconds", error, ) self.app.converter = None @@ -97,7 +95,7 @@ image chosen. bicubic_scale = options["bicubic_scale"] # get dir listing with full pathname in_dir = os.path.dirname(in_filename) - in_files = ["{}/{}".format(in_dir, f) for f in os.listdir(in_dir)] + in_files = [f"{in_dir}/{f}" for f in os.listdir(in_dir)] in_files.sort() # assume numeric sequence starts from chosen file in_files = in_files[in_files.index(in_filename) :] diff --git a/formats/out_png.py b/formats/out_png.py index e6695da..e408384 100644 --- a/formats/out_png.py +++ b/formats/out_png.py @@ -37,7 +37,7 @@ class PNGExportOptionsDialog(ExportOptionsDialog): scale = int(self.field_texts[0]) width = art.charset.char_width * art.width * scale height = art.charset.char_height * art.height * scale - label %= "{} x {}".format(width, height) + label %= f"{width} x {height}" return label def is_input_valid(self): diff --git a/formats/out_png_set.py b/formats/out_png_set.py index 8683c75..62ad337 100644 --- a/formats/out_png_set.py +++ b/formats/out_png_set.py @@ -24,12 +24,12 @@ def get_full_filename( if use_frame: fn += "_{}".format(str(frame).rjust(4, "0")) if use_layer: - fn += "_{}".format(layer_name) + fn += f"_{layer_name}" # strip unfriendly chars from output filename for forbidden_char in ["\\", "/", "*", ":"]: fn = fn.replace(forbidden_char, "") # add path and extension for final mutated filename - return "{}/{}.{}".format(dirname, fn, FILE_EXTENSION) + return f"{dirname}/{fn}.{FILE_EXTENSION}" class PNGSetExportOptionsDialog(ExportOptionsDialog): @@ -78,7 +78,7 @@ class PNGSetExportOptionsDialog(ExportOptionsDialog): scale = int(self.field_texts[0]) width = art.charset.char_width * art.width * scale height = art.charset.char_height * art.height * scale - label %= "{} x {}".format(width, height) + label %= f"{width} x {height}" # show how many images exported set will be elif field_index == 4: export_frames = bool(self.field_texts[2].strip()) diff --git a/game_object.py b/game_object.py index 01a67bc..38d49f9 100644 --- a/game_object.py +++ b/game_object.py @@ -243,9 +243,7 @@ class GameObject: if v not in obj_data: if self.log_load: self.app.dev_log( - "Serialized property '{}' not found for {}".format( - v, self.name - ) + f"Serialized property '{v}' not found for {self.name}" ) continue # if value is in data and serialized list but undeclared, do so @@ -288,7 +286,7 @@ class GameObject: "Dict of all Arts this object can reference, eg for states" # if art_src not specified, create a new art according to dimensions if self.generate_art: - self.art_src = "{}_art".format(self.name) + self.art_src = f"{self.name}_art" self.art = self.app.new_art( self.art_src, self.art_width, @@ -308,7 +306,7 @@ class GameObject: self.art = self.arts[art] break if not self.art: - self.app.log("Couldn't spawn GameObject with art {}".format(self.art_src)) + self.app.log(f"Couldn't spawn GameObject with art {self.art_src}") return self.renderable = GameObjectRenderable(self.app, self.art, self) self.renderable.alpha = self.alpha @@ -345,9 +343,7 @@ class GameObject: self.start_animating() if self.log_spawn: self.app.log( - "Spawned {} with Art {}".format( - self.name, os.path.basename(self.art.filename) - ) + f"Spawned {self.name} with Art {os.path.basename(self.art.filename)}" ) def get_unique_name(self): @@ -379,13 +375,13 @@ class GameObject: if self.facing_changes_art: # load each facing for each state for facing in FACINGS.values(): - art_name = "{}_{}_{}".format(self.art_src, state, facing) + art_name = f"{self.art_src}_{state}_{facing}" art = self.app.load_art(art_name, False) if art: self.arts[art_name] = art else: # load each state - art_name = "{}_{}".format(self.art_src, state) + art_name = f"{self.art_src}_{state}" art = self.app.load_art(art_name, False) if art: self.arts[art_name] = art @@ -667,14 +663,14 @@ class GameObject: "Return Art (and 'flip X' bool) that best represents current state" # use current state if none specified state = self.state if state is None else state - art_state_name = "{}_{}".format(self.art_src, self.state) + art_state_name = f"{self.art_src}_{self.state}" # simple case: no facing, just state if not self.facing_changes_art: # return art for current state, use default if not available if art_state_name in self.arts: return self.arts[art_state_name], False else: - default_name = "{}_{}".format(self.art_src, self.state or DEFAULT_STATE) + default_name = f"{self.art_src}_{self.state or DEFAULT_STATE}" # assert(default_name in self.arts # don't assert - if base+state name available, use that if default_name in self.arts: @@ -685,7 +681,7 @@ class GameObject: # more complex case: art determined by both state and facing facing_suffix = FACINGS[self.facing] # first see if anim exists for this exact state, skip subsequent logic - exact_name = "{}_{}".format(art_state_name, facing_suffix) + exact_name = f"{art_state_name}_{facing_suffix}" if exact_name in self.arts: return self.arts[exact_name], False # see what anims are available and try to choose best for facing @@ -696,11 +692,11 @@ class GameObject: break # if NO anims for current state, fall back to default if not has_state: - default_name = "{}_{}".format(self.art_src, DEFAULT_STATE) + default_name = f"{self.art_src}_{DEFAULT_STATE}" art_state_name = default_name - front_name = "{}_{}".format(art_state_name, FACINGS[GOF_FRONT]) - left_name = "{}_{}".format(art_state_name, FACINGS[GOF_LEFT]) - right_name = "{}_{}".format(art_state_name, FACINGS[GOF_RIGHT]) + front_name = f"{art_state_name}_{FACINGS[GOF_FRONT]}" + left_name = f"{art_state_name}_{FACINGS[GOF_LEFT]}" + right_name = f"{art_state_name}_{FACINGS[GOF_RIGHT]}" has_front = front_name in self.arts has_left = left_name in self.arts has_right = right_name in self.arts @@ -991,9 +987,7 @@ class GameObject: or self.timer_functions_post_update.get(timer_name, None) ) if not timer: - self.app.log( - "Timer named {} not found on object {}".format(timer_name, self.name) - ) + self.app.log(f"Timer named {timer_name} not found on object {self.name}") d = [ self.timer_functions_pre_update, self.timer_functions_update, @@ -1120,9 +1114,7 @@ class GameObject: or abs(self.y) > self.kill_distance_from_origin ): self.app.log( - "{} reached {} from origin, destroying.".format( - self.name, self.kill_distance_from_origin - ) + f"{self.name} reached {self.kill_distance_from_origin} from origin, destroying." ) self.destroy() diff --git a/game_room.py b/game_room.py index 583e24e..c10751d 100644 --- a/game_room.py +++ b/game_room.py @@ -44,9 +44,7 @@ class GameRoom: for v in self.serialized: if v not in room_data: self.world.app.dev_log( - "Serialized property '{}' not found for room {}".format( - v, self.name - ) + f"Serialized property '{v}' not found for room {self.name}" ) continue if not hasattr(self, v): @@ -92,9 +90,7 @@ class GameRoom: def set_camera_marker_name(self, marker_name): if marker_name not in self.world.objects: - self.world.app.log( - "Couldn't find camera marker with name {}".format(marker_name) - ) + self.world.app.log(f"Couldn't find camera marker with name {marker_name}") return self.camera_marker_name = marker_name if self is self.world.current_room: @@ -109,7 +105,7 @@ class GameRoom: def entered(self, old_room): "Run when the player enters this room." if self.log_changes: - self.world.app.log('Room "{}" entered'.format(self.name)) + self.world.app.log(f'Room "{self.name}" entered') # set camera if marker is set if self.world.room_camera_changes_enabled: self.use_camera_marker() @@ -124,7 +120,7 @@ class GameRoom: def exited(self, new_room): "Run when the player exits this room." if self.log_changes: - self.world.app.log('Room "{}" exited'.format(self.name)) + self.world.app.log(f'Room "{self.name}" exited') # tell objects in this room player has exited for obj in self.objects.values(): obj.room_exited(self, new_room) @@ -133,7 +129,7 @@ class GameRoom: "Add object with given name to this room." obj = self.world.objects.get(obj_name, None) if not obj: - self.world.app.log("Couldn't find object named {}".format(obj_name)) + self.world.app.log(f"Couldn't find object named {obj_name}") return self.add_object(obj) @@ -146,7 +142,7 @@ class GameRoom: "Remove object with given name from this room." obj = self.world.objects.get(obj_name, None) if not obj: - self.world.app.log("Couldn't find object named {}".format(obj_name)) + self.world.app.log(f"Couldn't find object named {obj_name}") return self.remove_object(obj) @@ -156,13 +152,13 @@ class GameRoom: self.objects.pop(obj.name) else: self.world.app.log( - "GameRoom {} doesn't contain GameObject {}".format(self.name, obj.name) + f"GameRoom {self.name} doesn't contain GameObject {obj.name}" ) if self.name in obj.rooms: obj.rooms.pop(self.name) else: self.world.app.log( - "GameObject {} not found in GameRoom {}".format(obj.name, self.name) + f"GameObject {obj.name} not found in GameRoom {self.name}" ) def get_dict(self): diff --git a/game_util_objects.py b/game_util_objects.py index 900f43f..230a4d1 100644 --- a/game_util_objects.py +++ b/game_util_objects.py @@ -369,9 +369,7 @@ class WarpTrigger(StaticTileTrigger): marker = self.world.objects.get(self.destination_marker_name, None) if not marker: self.app.log( - "Warp destination object {} not found".format( - self.destination_marker_name - ) + f"Warp destination object {self.destination_marker_name} not found" ) return other.set_loc(marker.x, marker.y, marker.z) @@ -384,9 +382,7 @@ class WarpTrigger(StaticTileTrigger): and room.name != self.destination_room_name ): self.app.log( - "Marker {}'s room differs from destination room {}".format( - marker.name, self.destination_room_name - ) + f"Marker {marker.name}'s room differs from destination room {self.destination_room_name}" ) self.world.change_room(room.name) other.last_warp_update = self.world.updates @@ -504,9 +500,7 @@ class SoundBlaster(LocationMarker): self.sound_filenames[self.sound_name] = filename return self.world.app.log( - "Couldn't find sound file {} for SoundBlaster {}".format( - self.sound_name, self.name - ) + f"Couldn't find sound file {self.sound_name} for SoundBlaster {self.name}" ) def room_entered(self, room, old_room): diff --git a/game_world.py b/game_world.py index 675ed0a..9a7f8ae 100644 --- a/game_world.py +++ b/game_world.py @@ -220,7 +220,7 @@ class GameWorld: new_obj = self.spawn_object_of_class(self.classname_to_spawn, x, y) if self.current_room: self.current_room.add_object(new_obj) - self.app.ui.message_line.post_line("Spawned {}".format(new_obj.name)) + self.app.ui.message_line.post_line(f"Spawned {new_obj.name}") return objects = self.get_objects_at(x, y) next_obj = self.pick_next_object_at(x, y) @@ -408,7 +408,7 @@ class GameWorld: self.unload_game() new_dir = self.app.documents_dir + TOP_GAME_DIR + new_game_dir + "/" if os.path.exists(new_dir): - self.app.log("Game dir {} already exists!".format(new_game_dir)) + self.app.log(f"Game dir {new_game_dir} already exists!") return False os.mkdir(new_dir) os.mkdir(new_dir + ART_DIR) @@ -514,7 +514,7 @@ class GameWorld: self.game_name = dir_name if not d.endswith("/"): self.game_dir += "/" - self.app.log("Game data folder is now {}".format(self.game_dir)) + self.app.log(f"Game data folder is now {self.game_dir}") # set sounds dir before loading state; some obj inits depend on it self.sounds_dir = self.game_dir + SOUNDS_DIR if reset: @@ -526,7 +526,7 @@ class GameWorld: self.classes = self._get_all_loaded_classes() break if not self.game_dir: - self.app.log("Couldn't find game directory {}".format(dir_name)) + self.app.log(f"Couldn't find game directory {dir_name}") def _remove_non_current_game_modules(self): """ @@ -535,7 +535,7 @@ class GameWorld: """ modules_to_remove = [] games_dir_prefix = TOP_GAME_DIR.replace("/", "") - this_game_dir_prefix = "{}.{}".format(games_dir_prefix, self.game_name) + this_game_dir_prefix = f"{games_dir_prefix}.{self.game_name}" for module_name in sys.modules: # remove any module that isn't for this game or part of its path if ( @@ -758,7 +758,7 @@ class GameWorld: and line.strip() != "method()" ): self.app.log(line.rstrip()) - s = "Error in {}.{}! See console.".format(obj.name, method.__name__) + s = f"Error in {obj.name}.{method.__name__}! See console." self.app.ui.message_line.post_line(s, 10, True) def pre_update(self): @@ -938,14 +938,14 @@ class GameWorld: if filename and filename != "": if not filename.endswith(STATE_FILE_EXTENSION): filename += "." + STATE_FILE_EXTENSION - filename = "{}{}".format(self.game_dir, filename) + filename = f"{self.game_dir}{filename}" else: # state filename example: # games/mytestgame2/1431116386.gs timestamp = int(time.time()) - filename = "{}{}.{}".format(self.game_dir, timestamp, STATE_FILE_EXTENSION) + filename = f"{self.game_dir}{timestamp}.{STATE_FILE_EXTENSION}" json.dump(d, open(filename, "w"), sort_keys=True, indent=1) - self.app.log("Saved game state {} to disk.".format(filename)) + self.app.log(f"Saved game state {filename} to disk.") self.app.update_window_title() def _get_all_loaded_classes(self): @@ -982,7 +982,7 @@ class GameWorld: obj_class = obj.__class__.__name__ spawned = self.spawn_object_of_class(obj_class, x, y) if spawned: - self.app.log("{} reset to class defaults".format(obj.name)) + self.app.log(f"{obj.name} reset to class defaults") if obj is self.player: self.player = spawned obj.destroy() @@ -994,9 +994,9 @@ class GameWorld: new_objects.append(self.duplicate_object(obj)) # report on objects created if len(new_objects) == 1: - self.app.log("{} created from {}".format(new_objects[0].name, obj.name)) + self.app.log(f"{new_objects[0].name} created from {obj.name}") elif len(new_objects) > 1: - self.app.log("{} new objects created".format(len(new_objects))) + self.app.log(f"{len(new_objects)} new objects created") def duplicate_object(self, obj): "Create a duplicate of given object." @@ -1025,9 +1025,7 @@ class GameWorld: for other_obj in self.objects.values(): if other_obj is not self and other_obj.name == new_name: self.app.ui.message_line.post_line( - "Can't rename {} to {}, name already in use".format( - obj.name, new_name - ) + f"Can't rename {obj.name} to {new_name}, name already in use" ) return self.objects.pop(obj.name) @@ -1068,7 +1066,7 @@ class GameWorld: def add_room(self, new_room_name, new_room_classname="GameRoom"): "Add a new Room with given name of (optional) given class." if new_room_name in self.rooms: - self.log("Room called {} already exists!".format(new_room_name)) + self.log(f"Room called {new_room_name} already exists!") return new_room_class = self.classes[new_room_classname] new_room = new_room_class(self, new_room_name) @@ -1086,7 +1084,7 @@ class GameWorld: def change_room(self, new_room_name): "Set world's current active room to Room with given name." if new_room_name not in self.rooms: - self.app.log("Couldn't change to missing room {}".format(new_room_name)) + self.app.log(f"Couldn't change to missing room {new_room_name}") return old_room = self.current_room self.current_room = self.rooms[new_room_name] @@ -1124,7 +1122,7 @@ class GameWorld: d = json.load(open(filename)) # self.app.log('Loading game state %s...' % filename) except Exception: - self.app.log("Couldn't load game state from {}".format(filename)) + self.app.log(f"Couldn't load game state from {filename}") # self.app.log(sys.exc_info()) return errors = False @@ -1161,7 +1159,7 @@ class GameWorld: self.hud = hud_class(self) self.hud_class_name = hud_class.__name__ if not errors and self.app.init_success: - self.app.log("Loaded game state from {}".format(filename)) + self.app.log(f"Loaded game state from {filename}") self.last_state_loaded = filename self.set_for_all_objects("show_collision", self.show_collision_all) self.set_for_all_objects("show_bounds", self.show_bounds_all) @@ -1172,13 +1170,13 @@ class GameWorld: def report(self): "Print (not log) information about current world state." - print("--------------\n{} report:".format(self)) + print(f"--------------\n{self} report:") obj_arts, obj_rends, obj_dbg_rends, obj_cols, obj_col_rends = 0, 0, 0, 0, 0 attachments = 0 # create merged dict of existing and just-spawned objects all_objects = self.objects.copy() all_objects.update(self.new_objects) - print("{} objects:".format(len(all_objects))) + print(f"{len(all_objects)} objects:") for obj in all_objects.values(): obj_arts += len(obj.arts) if obj.renderable is not None: @@ -1192,30 +1190,18 @@ class GameWorld: obj_col_rends += len(obj.collision.renderables) attachments += len(obj.attachments) print( - """ - {} arts in objects, {} arts loaded, - {} HUD arts, {} HUD renderables, - {} renderables, {} debug renderables, - {} collideables, {} collideable viz renderables, - {} attachments""".format( - obj_arts, - len(self.art_loaded), - len(self.hud.arts), - len(self.hud.renderables), - obj_rends, - obj_dbg_rends, - obj_cols, - obj_col_rends, - attachments, - ) + f""" + {obj_arts} arts in objects, {len(self.art_loaded)} arts loaded, + {len(self.hud.arts)} HUD arts, {len(self.hud.renderables)} HUD renderables, + {obj_rends} renderables, {obj_dbg_rends} debug renderables, + {obj_cols} collideables, {obj_col_rends} collideable viz renderables, + {attachments} attachments""" ) self.cl.report() print( - "{} charsets loaded, {} palettes".format( - len(self.app.charsets), len(self.app.palettes) - ) + f"{len(self.app.charsets)} charsets loaded, {len(self.app.palettes)} palettes" ) - print("{} arts loaded for edit".format(len(self.app.art_loaded_for_edit))) + print(f"{len(self.app.art_loaded_for_edit)} arts loaded for edit") def toggle_all_origin_viz(self): "Toggle visibility of XYZ markers for all object origins." diff --git a/games/crawler/scripts/player.py b/games/crawler/scripts/player.py index 67fcc01..af3e4cc 100644 --- a/games/crawler/scripts/player.py +++ b/games/crawler/scripts/player.py @@ -55,7 +55,7 @@ class CrawlPlayer(Player): if key == "up" else DIR_NAMES[OPPOSITE_DIRS[self.direction]] ) - self.app.log("can't go {}!".format(dir_name)) + self.app.log(f"can't go {dir_name}!") else: self.x, self.y = self.maze.x + new_x, self.maze.y - new_y # update art to show facing diff --git a/games/fireplace/scripts/fireplace.py b/games/fireplace/scripts/fireplace.py index 0e8c4b3..6a2b929 100644 --- a/games/fireplace/scripts/fireplace.py +++ b/games/fireplace/scripts/fireplace.py @@ -79,7 +79,7 @@ class Fireplace(GameObject): self.credit_screen = None self.music_exists = False if os.path.exists(self.world.sounds_dir + MUSIC_FILENAME): - self.app.log("{} found in {}".format(MUSIC_FILENAME, self.world.sounds_dir)) + self.app.log(f"{MUSIC_FILENAME} found in {self.world.sounds_dir}") self.world.play_music(MUSIC_FILENAME) self.music_paused = False self.music_exists = True @@ -88,9 +88,7 @@ class Fireplace(GameObject): self.credit_screen.z = 1.1 self.credit_screen.set_scale(0.75, 0.75, 1) else: - self.app.log( - "No {} found in {}".format(MUSIC_FILENAME, self.world.sounds_dir) - ) + self.app.log(f"No {MUSIC_FILENAME} found in {self.world.sounds_dir}") self.set_new_message_time() def update(self): @@ -191,16 +189,12 @@ class Fireplace(GameObject): self.app.fb.toggle_crt() elif key == "=" or key == "+": self.target_particles += 10 - self.art.write_string( - 0, 0, 0, 0, "Embers: {}".format(self.target_particles), 15, 1 - ) + self.art.write_string(0, 0, 0, 0, f"Embers: {self.target_particles}", 15, 1) elif key == "-": if self.target_particles <= 10: return self.target_particles -= 10 - self.art.write_string( - 0, 0, 0, 0, "Embers: {}".format(self.target_particles), 15, 1 - ) + self.art.write_string(0, 0, 0, 0, f"Embers: {self.target_particles}", 15, 1) class FireParticle: diff --git a/games/flood/scripts/game.py b/games/flood/scripts/game.py index 6fc86ee..ac0b809 100644 --- a/games/flood/scripts/game.py +++ b/games/flood/scripts/game.py @@ -79,7 +79,7 @@ class Board(GameObject): self.reset() return # get list of valid keys from length of tile_colors - valid_keys = ["{}".format(str(i + 1)) for i in range(len(TILE_COLORS))] + valid_keys = [f"{str(i + 1)}" for i in range(len(TILE_COLORS))] if key not in valid_keys: return key = int(key) - 1 diff --git a/games/maze/scripts/objects.py b/games/maze/scripts/objects.py index 8739438..e7bc301 100644 --- a/games/maze/scripts/objects.py +++ b/games/maze/scripts/objects.py @@ -88,7 +88,7 @@ class MazePickup(GameObject): def picked_up(self, new_holder): self.holder = new_holder - self.world.hud.post_msg("got {}!".format(self.display_name)) + self.world.hud.post_msg(f"got {self.display_name}!") self.disable_collision() self.play_sound("pickup") @@ -167,9 +167,7 @@ class MazeLock(StaticTileBG): if other.held_object and type(other.held_object) is self.key_type: self.unlocked(other) else: - self.world.hud.post_msg( - "blocked - need {}!".format(self.key_type.display_name) - ) + self.world.hud.post_msg(f"blocked - need {self.key_type.display_name}!") def unlocked(self, other): self.disable_collision() diff --git a/games/wildflowers/scripts/flower.py b/games/wildflowers/scripts/flower.py index 1c143b3..8bd8804 100644 --- a/games/wildflowers/scripts/flower.py +++ b/games/wildflowers/scripts/flower.py @@ -89,10 +89,8 @@ class FlowerObject(GameObject): # track # of growth updates we've had self.grows = 0 # create an art document we can add frames to and later export - self.export_filename = "{}{}wildflower_{}".format( - self.app.documents_dir, - ART_DIR, - self.seed, + self.export_filename = ( + f"{self.app.documents_dir}{ART_DIR}wildflower_{self.seed}" ) self.exportable_art = self.app.new_art( self.export_filename, diff --git a/games/wildflowers/scripts/wildflowers.py b/games/wildflowers/scripts/wildflowers.py index f5615f9..0543f5f 100644 --- a/games/wildflowers/scripts/wildflowers.py +++ b/games/wildflowers/scripts/wildflowers.py @@ -69,7 +69,7 @@ class FlowerGlobals(WorldGlobalsObject): scale=4, bg_color=self.world.bg_color, ) - self.app.log("Exported {}.png".format(self.flower.export_filename)) + self.app.log(f"Exported {self.flower.export_filename}.png") class SeedDisplay(GameObject): diff --git a/image_convert.py b/image_convert.py index a74e0a7..bcf3109 100644 --- a/image_convert.py +++ b/image_convert.py @@ -38,7 +38,7 @@ class ImageConverter: self.init_success = False image_filename = app.find_filename_path(image_filename) if not image_filename or not os.path.exists(image_filename): - app.log("ImageConverter: Couldn't find image {}".format(image_filename)) + app.log(f"ImageConverter: Couldn't find image {image_filename}") app.converter = None return self.app = app @@ -266,9 +266,7 @@ class ImageConverter: time_taken = time.time() - self.start_time verb = "cancelled" if cancelled else "finished" self.app.log( - "Conversion of image {} {} after {:.3f} seconds".format( - self.image_filename, verb, time_taken - ) + f"Conversion of image {self.image_filename} {verb} after {time_taken:.3f} seconds" ) self.app.converter = None self.preview_sprite = None diff --git a/image_export.py b/image_export.py index 8f883df..45ed419 100644 --- a/image_export.py +++ b/image_export.py @@ -14,9 +14,7 @@ def get_frame_image(app, art, frame, allow_crt=True, scale=1, bg_color=(0, 0, 0, # error out if over max texture size if w > app.max_texture_size or h > app.max_texture_size: app.log( - "ERROR: Image output size ({} x {}) exceeds your hardware's max supported texture size ({} x {})!".format( - w, h, app.max_texture_size, app.max_texture_size - ), + f"ERROR: Image output size ({w} x {h}) exceeds your hardware's max supported texture size ({app.max_texture_size} x {app.max_texture_size})!", error=True, ) app.log( diff --git a/input_handler.py b/input_handler.py index 506144b..66554bd 100644 --- a/input_handler.py +++ b/input_handler.py @@ -89,13 +89,13 @@ class InputLord: ) < os.path.getmtime(BINDS_TEMPLATE_FILENAME) if not binds_outdated and os.path.exists(binds_filename): exec(open(binds_filename).read()) - self.app.log("Loaded key binds from {}".format(binds_filename)) + self.app.log(f"Loaded key binds from {binds_filename}") else: default_data = open(BINDS_TEMPLATE_FILENAME).readlines()[1:] new_binds = open(binds_filename, "w") new_binds.writelines(default_data) new_binds.close() - self.app.log("Created new key binds file {}".format(binds_filename)) + self.app.log(f"Created new key binds file {binds_filename}") exec("".join(default_data)) if not self.edit_bind_src: self.app.log("No bind data found, Is binds.cfg.default present?") @@ -109,9 +109,9 @@ class InputLord: # bind data could be a single item (string) or a list/tuple bind_data = self.edit_bind_src[bind_string] if type(bind_data) is str: - bind_fnames = ["BIND_{}".format(bind_data)] + bind_fnames = [f"BIND_{bind_data}"] else: - bind_fnames = ["BIND_{}".format(s) for s in bind_data] + bind_fnames = [f"BIND_{s}" for s in bind_data] bind_functions = [] for bind_fname in bind_fnames: if not hasattr(self, bind_fname): @@ -123,7 +123,7 @@ class InputLord: js_init = sdl2.SDL_InitSubSystem(sdl2.SDL_INIT_JOYSTICK) if js_init != 0: self.app.log( - "SDL2: Couldn't initialize joystick subsystem, code {}".format(js_init) + f"SDL2: Couldn't initialize joystick subsystem, code {js_init}" ) return sticks = sdl2.SDL_NumJoysticks() @@ -137,9 +137,7 @@ class InputLord: pad_axes = sdl2.SDL_JoystickNumAxes(pad) pad_buttons = sdl2.SDL_JoystickNumButtons(pad) self.app.log( - "Gamepad found: {} with {} axes, {} buttons".format( - pad_name, pad_axes, pad_buttons - ) + f"Gamepad found: {pad_name} with {pad_axes} axes, {pad_buttons} buttons" ) self.gamepad = pad # before main loop begins, set initial mouse position - @@ -205,7 +203,7 @@ class InputLord: if not hasattr(button, "menu_data"): continue for item in button.menu_data.items: - if function.__name__ == "BIND_{}".format(item.command): + if function.__name__ == f"BIND_{item.command}": items.append(item) return items @@ -1225,14 +1223,10 @@ class InputLord: for obj in self.app.gw.selected_objects: if obj.orig_collision_type and obj.collision_type == CT_NONE: obj.enable_collision() - self.ui.message_line.post_line( - "Collision enabled for {}".format(obj.name) - ) + self.ui.message_line.post_line(f"Collision enabled for {obj.name}") elif obj.collision_type != CT_NONE: obj.disable_collision() - self.ui.message_line.post_line( - "Collision disabled for {}".format(obj.name) - ) + self.ui.message_line.post_line(f"Collision disabled for {obj.name}") def BIND_toggle_game_edit_ui(self): self.ui.toggle_game_edit_ui() diff --git a/palette.py b/palette.py index 16db86f..c338d50 100644 --- a/palette.py +++ b/palette.py @@ -32,12 +32,10 @@ class PaletteLord: if palette.has_updated(): try: palette.load_image() - self.app.log( - "PaletteLord: success reloading {}".format(palette.filename) - ) + self.app.log(f"PaletteLord: success reloading {palette.filename}") except Exception: self.app.log( - "PaletteLord: failed reloading {}".format(palette.filename), + f"PaletteLord: failed reloading {palette.filename}", True, ) @@ -50,7 +48,7 @@ class Palette: src_filename, PALETTE_DIR, PALETTE_EXTENSIONS ) if self.filename is None: - self.app.log("Couldn't find palette image {}".format(src_filename)) + self.app.log(f"Couldn't find palette image {src_filename}") return self.last_image_change = os.path.getmtime(self.filename) self.name = os.path.basename(self.filename) @@ -58,12 +56,10 @@ class Palette: self.load_image() self.base_filename = os.path.splitext(os.path.basename(self.filename))[0] if log and not self.app.game_mode: - self.app.log( - "loaded palette '{}' from {}:".format(self.name, self.filename) - ) - self.app.log(" unique colors found: {}".format(int(len(self.colors) - 1))) - self.app.log(" darkest color index: {}".format(self.darkest_index)) - self.app.log(" lightest color index: {}".format(self.lightest_index)) + self.app.log(f"loaded palette '{self.name}' from {self.filename}:") + self.app.log(f" unique colors found: {int(len(self.colors) - 1)}") + self.app.log(f" darkest color index: {self.darkest_index}") + self.app.log(f" lightest color index: {self.lightest_index}") self.init_success = True def load_image(self): @@ -222,7 +218,7 @@ class PaletteFromList(Palette): self.init_success = False self.app = app # generate a unique non-user-facing palette name - name = "PaletteFromList_{}".format(time.time()) + name = f"PaletteFromList_{time.time()}" self.filename = self.name = self.base_filename = name colors = [] for color in src_color_list: @@ -250,10 +246,10 @@ class PaletteFromList(Palette): x += 1 self.texture = Texture(img.tobytes(), MAX_COLORS, 1) if log and not self.app.game_mode: - self.app.log("generated new palette '{}'".format(self.name)) - self.app.log(" unique colors: {}".format(int(len(self.colors) - 1))) - self.app.log(" darkest color index: {}".format(self.darkest_index)) - self.app.log(" lightest color index: {}".format(self.lightest_index)) + self.app.log(f"generated new palette '{self.name}'") + self.app.log(f" unique colors: {int(len(self.colors) - 1)}") + self.app.log(f" darkest color index: {self.darkest_index}") + self.app.log(f" lightest color index: {self.lightest_index}") def has_updated(self): "No bitmap source for this type of palette, so no hot-reload" @@ -265,7 +261,7 @@ class PaletteFromFile(Palette): self.init_success = False src_filename = app.find_filename_path(src_filename) if not src_filename: - app.log("Couldn't find palette source image {}".format(src_filename)) + app.log(f"Couldn't find palette source image {src_filename}") return # dither source image, re-save it, use that as the source for a palette src_img = Image.open(src_filename) @@ -283,9 +279,7 @@ class PaletteFromFile(Palette): # if new filename exists, add a number to avoid overwriting if os.path.exists(palette_path + palette_filename + ".png"): i = 0 - while os.path.exists( - "{}{}{}.png".format(palette_path, palette_filename, str(i)) - ): + while os.path.exists(f"{palette_path}{palette_filename}{str(i)}.png"): i += 1 palette_filename += str(i) # (re-)add path and PNG extension diff --git a/playscii.py b/playscii.py index e343752..d131b7c 100755 --- a/playscii.py +++ b/playscii.py @@ -284,7 +284,7 @@ class Application: gpu_renderer = GL.glGetString(GL.GL_RENDERER).decode("utf-8") except Exception: gpu_renderer = "[couldn't detect renderer]" - self.log(" GPU: {} - {}".format(gpu_vendor, gpu_renderer)) + self.log(f" GPU: {gpu_vendor} - {gpu_renderer}") try: # try single-argument GL2.0 version first gl_ver = GL.glGetString(GL.GL_VERSION) @@ -293,7 +293,7 @@ class Application: gl_ver = gl_ver.decode("utf-8") except Exception: gl_ver = "[couldn't detect GL version]" - self.log(" OpenGL detected: {}".format(gl_ver)) + self.log(f" OpenGL detected: {gl_ver}") # GL 1.1 doesn't even habla shaders, quit if we fail GLSL version check try: glsl_ver = GL.glGetString(GL.GL_SHADING_LANGUAGE_VERSION) @@ -306,7 +306,7 @@ class Application: self.should_quit = True return glsl_ver = glsl_ver.decode("utf-8") if glsl_ver != None else None - self.log(" GLSL detected: {}".format(glsl_ver) or "[unknown]") + self.log(f" GLSL detected: {glsl_ver}" or "[unknown]") # verify that we got at least a 2.1 context majorv, minorv = ctypes.c_int(0), ctypes.c_int(0) video.SDL_GL_GetAttribute(video.SDL_GL_CONTEXT_MAJOR_VERSION, majorv) @@ -343,43 +343,31 @@ class Application: GL.glGetIntegerv(GL.GL_MAX_TEXTURE_SIZE, mts) self.max_texture_size = mts.value self.log( - " Maximum supported texture size: {} x {}".format( - self.max_texture_size, self.max_texture_size - ) + f" Maximum supported texture size: {self.max_texture_size} x {self.max_texture_size}" ) self.log( - " Detected screen resolution: {:.0f} x {:.0f}, window: {} x {}".format( - screen_width, screen_height, self.window_width, self.window_height - ) + f" Detected screen resolution: {screen_width:.0f} x {screen_height:.0f}, window: {self.window_width} x {self.window_height}" ) self.log("Detecting software environment...") - self.log(" OS: {}".format(platform.platform())) + self.log(f" OS: {platform.platform()}") py_version = " ".join(sys.version.split("\n")) # report 32 vs 64 bit as it's not clear from sys.version or OS bitness = platform.architecture()[0] # on linux, report whether we're running x11 or wayland if platform.system() == "Linux": driver = sdl2.SDL_GetCurrentVideoDriver().decode("utf-8") - self.log(' Linux SDL2 "video driver": {}'.format(driver)) - self.log(" Python: {} ({})".format(py_version, bitness)) - module_versions = "PySDL2 {}, ".format(sdl2.__version__) - module_versions += "numpy {}, ".format(numpy.__version__) - module_versions += "PyOpenGL {}, ".format(OpenGL.__version__) - module_versions += "appdirs {}, ".format(appdirs.__version__) - module_versions += "PIL {}".format(PIL.__version__) - self.log(" Modules: {}".format(module_versions)) - sdl_version = "{}.{}.{} ".format( - sdl2.version.SDL_MAJOR_VERSION, - sdl2.version.SDL_MINOR_VERSION, - sdl2.version.SDL_PATCHLEVEL, - ) + self.log(f' Linux SDL2 "video driver": {driver}') + self.log(f" Python: {py_version} ({bitness})") + module_versions = f"PySDL2 {sdl2.__version__}, " + module_versions += f"numpy {numpy.__version__}, " + module_versions += f"PyOpenGL {OpenGL.__version__}, " + module_versions += f"appdirs {appdirs.__version__}, " + module_versions += f"PIL {PIL.__version__}" + self.log(f" Modules: {module_versions}") + sdl_version = f"{sdl2.version.SDL_MAJOR_VERSION}.{sdl2.version.SDL_MINOR_VERSION}.{sdl2.version.SDL_PATCHLEVEL} " sdl_version += sdl2.version.SDL_GetRevision().decode("utf-8") - sdl_version += ", SDLmixer: {}.{}.{}".format( - sdlmixer.SDL_MIXER_MAJOR_VERSION, - sdlmixer.SDL_MIXER_MINOR_VERSION, - sdlmixer.SDL_MIXER_PATCHLEVEL, - ) - self.log(" SDL: {}".format(sdl_version)) + sdl_version += f", SDLmixer: {sdlmixer.SDL_MIXER_MAJOR_VERSION}.{sdlmixer.SDL_MIXER_MINOR_VERSION}.{sdlmixer.SDL_MIXER_PATCHLEVEL}" + self.log(f" SDL: {sdl_version}") # draw black screen while doing other init GL.glClearColor(0.0, 0.0, 0.0, 1.0) GL.glClear(GL.GL_COLOR_BUFFER_BIT) @@ -566,7 +554,7 @@ class Application: and "_bootstrap._gcd_import" not in line ): self.log(line.rstrip()) - s = "Error importing module {}! See console.".format(module_name) + s = f"Error importing module {module_name}! See console." if self.ui: self.ui.message_line.post_line(s, 10, True) @@ -589,7 +577,7 @@ class Application: art = None if not valid_filename: if autocreate: - self.log("Creating new art {}".format(filename)) + self.log(f"Creating new art {filename}") return self.new_art(filename) else: # self.log("Couldn't find art %s" % filename) @@ -641,7 +629,7 @@ class Application: self.edit_renderables.remove(r) if art is self.ui.active_art: self.ui.active_art = None - self.log("Unloaded {}".format(art.filename)) + self.log(f"Unloaded {art.filename}") if len(self.art_loaded_for_edit) > 0: self.ui.set_active_art(self.art_loaded_for_edit[0]) self.update_window_title() @@ -698,7 +686,7 @@ class Application: extensions = [extensions] for dirname in dirnames: for ext in extensions: - f = "{}{}".format(dirname, filename) + f = f"{dirname}{filename}" # filename passed in might already have intended extension, # eg from a directory listing if ext and ext != "" and not filename.endswith(ext): @@ -727,7 +715,7 @@ class Application: if basename in self.converter_modules: m = importlib.reload(self.converter_modules[basename]) else: - m = importlib.import_module("formats.{}".format(basename)) + m = importlib.import_module(f"formats.{basename}") self.converter_modules[basename] = m except Exception as e: self.log_import_exception(e, basename) @@ -782,7 +770,7 @@ class Application: def set_window_title(self, text=None): # if editing is locked, don't even show Playscii name - new_title = "{} - {}".format(APP_NAME, text) if self.can_edit else str(text) + new_title = f"{APP_NAME} - {text}" if self.can_edit else str(text) new_title = bytes(new_title, "utf-8") sdl2.SDL_SetWindowTitle(self.window, new_title) @@ -837,7 +825,7 @@ class Application: def screenshot(self): "saves a date + time-stamped screenshot" timestamp = time.strftime("%Y-%m-%d_%H-%M-%S") - output_filename = "playscii_{}.png".format(timestamp) + output_filename = f"playscii_{timestamp}.png" w, h = self.window_width, self.window_height pixels = GL.glReadPixels( 0, 0, w, h, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, outputType=None @@ -845,8 +833,8 @@ class Application: pixel_bytes = pixels.flatten().tobytes() img = Image.frombytes(mode="RGBA", size=(w, h), data=pixel_bytes) img = img.transpose(Image.FLIP_TOP_BOTTOM) - img.save("{}{}".format(self.documents_dir + SCREENSHOT_DIR, output_filename)) - self.log("Saved screenshot {}".format(output_filename)) + img.save(f"{self.documents_dir + SCREENSHOT_DIR}{output_filename}") + self.log(f"Saved screenshot {output_filename}") def enter_game_mode(self): self.game_mode = True @@ -964,17 +952,12 @@ class Application: def debug_onion_frames(self): "debug function to log onion renderable state" # TODO: remove this once it's served its purpose - debug = ["current frame: {}".format(self.ui.active_art.active_frame), ""] + debug = [f"current frame: {self.ui.active_art.active_frame}", ""] debug.append("onion_renderables_prev:") def get_onion_info(i, r): visible = "VISIBLE" if r.visible else "" - return "{}: {} frame {} {}".format( - i, - r.art.filename.ljust(20), - r.frame, - visible, - ) + return f"{i}: {r.art.filename.ljust(20)} frame {r.frame} {visible}" for i, r in enumerate(self.onion_renderables_prev): debug.append(get_onion_info(i, r)) @@ -995,7 +978,7 @@ class Application: if line.strip(): self.log(line.rstrip()) return - self.log("Using {} as overlay image.".format(image_filename)) + self.log(f"Using {image_filename} as overlay image.") self.overlay_renderable = r self.ui.size_and_position_overlay_image() self.draw_overlay = True @@ -1062,7 +1045,7 @@ class Application: # setting already found, remove this redundant line self.config_lines.remove(line) # get current value from top-level scope and write it to end of cfg - self.config_lines += "{} = {}\n".format(setting_name, setting_value) + self.config_lines += f"{setting_name} = {setting_value}\n" def save_persistent_config(self): "write options we want to persist across sessions to config file" @@ -1130,7 +1113,7 @@ class Application: editor_bin = os.environ.get("EDITOR", None) if not editor_bin: return - cmd = '{} "{}"'.format(editor_bin, cfg_path) + cmd = f'{editor_bin} "{cfg_path}"' os.system(cmd) # update resident cfg file lines, which will be saved out on exit self.config_lines = open(cfg_path).readlines() @@ -1140,7 +1123,7 @@ class Application: def open_local_url(self, url): "opens given local (this file system) URL in a cross-platform way" - webbrowser.open("file://{}/{}".format(os.getcwd(), url)) + webbrowser.open(f"file://{os.getcwd()}/{url}") def open_help_docs(self): self.open_local_url(WEBSITE_HELP_URL) @@ -1206,7 +1189,7 @@ def get_paths(): if os.path.exists(documents_dir + DOCUMENTS_SUBDIR): documents_dir += DOCUMENTS_SUBDIR # add Playscii/ to documents path - documents_dir += "/{}/".format(APP_NAME) + documents_dir += f"/{APP_NAME}/" # create Playscii dir AND subdirs for user art, charsets etc if not present for subdir in [ "", @@ -1246,7 +1229,7 @@ class Logger: self.log_file = open(config_dir + LOG_FILENAME, "w", bufsize) def log(self, new_line): - self.log_file.write("{}\n".format(new_line)) + self.log_file.write(f"{new_line}\n") self.lines.append(str(new_line)) print(new_line) @@ -1261,7 +1244,7 @@ def get_app(): # start logger even before Application has initialized so we can write to it # startup message: application and version # logger = Logger(config_dir) - logger.log("{} v{}".format(APP_NAME, get_version())) + logger.log(f"{APP_NAME} v{get_version()}") # see if "autoplay this game" file exists and has anything in it autoplay_game = None if os.path.exists(AUTOPLAY_GAME_FILENAME): @@ -1271,7 +1254,7 @@ def get_app(): # load in config - may change above values and submodule class defaults cfg_filename = config_dir + CONFIG_FILENAME if os.path.exists(cfg_filename): - logger.log("Loading config from {}...".format(cfg_filename)) + logger.log(f"Loading config from {cfg_filename}...") # execute cfg line by line so we can continue past lines with errors. # this does mean that commenting out blocks with triple-quotes fails, # but that's not a good practice anyway. @@ -1291,7 +1274,7 @@ def get_app(): if "Error" in el: error = el break - logger.log(" Removing line {} with {}".format(i, error)) + logger.log(f" Removing line {i} with {error}") new_cfg = open(cfg_filename, "w") new_cfg.writelines(new_cfg_lines) new_cfg.close() @@ -1304,7 +1287,7 @@ def get_app(): new_cfg.writelines(default_data) new_cfg.close() exec("".join(default_data)) - logger.log("Created new config file {}".format(cfg_filename)) + logger.log(f"Created new config file {cfg_filename}") art_to_load, game_dir_to_load, state_to_load = None, None, None # usage: # playscii.py [artfile] | [-game gamedir [-state statefile | artfile]] diff --git a/renderable.py b/renderable.py index 6efd905..38056f0 100644 --- a/renderable.py +++ b/renderable.py @@ -97,7 +97,7 @@ class TileRenderable: if self.app.use_vao: GL.glBindVertexArray(0) if self.log_create_destroy: - self.app.log("created: {}".format(self)) + self.app.log(f"created: {self}") def __str__(self): "for debug purposes, return a concise unique name" @@ -107,7 +107,7 @@ class TileRenderable: break else: i = 0 - return "{} {} {}".format(self.art.get_simple_name(), self.__class__.__name__, i) + return f"{self.art.get_simple_name()} {self.__class__.__name__} {i}" def create_buffers(self): # vertex positions and elements @@ -232,15 +232,7 @@ class TileRenderable: ): if self.log_buffer_updates: self.app.log( - "update_buffer: {}, {}, {}, {}, {}, {}, {}".format( - buffer_index, - array, - target, - buffer_type, - data_type, - attrib_name, - attrib_size, - ) + f"update_buffer: {buffer_index}, {array}, {target}, {buffer_type}, {data_type}, {attrib_name}, {attrib_size}" ) GL.glBindBuffer(target, buffer_index) GL.glBufferData(target, array.nbytes, array, buffer_type) @@ -269,9 +261,7 @@ class TileRenderable: self.frame = new_frame_index % self.art.frames self.update_tile_buffers(True, True, True, True) if self.log_animation: - self.app.log( - "{} animating from frames {} to {}".format(self, old_frame, self.frame) - ) + self.app.log(f"{self} animating from frames {old_frame} to {self.frame}") def start_animating(self): "Start animation playback." @@ -322,9 +312,7 @@ class TileRenderable: self.goal_x, self.goal_y, self.goal_z = x, y, z if self.log_animation: self.app.log( - "{} will move to {},{}".format( - self.art.filename, self.goal_x, self.goal_y - ) + f"{self.art.filename} will move to {self.goal_x},{self.goal_y}" ) def snap_to(self, x, y, z): @@ -413,7 +401,7 @@ class TileRenderable: if self.art and self in self.art.renderables: self.art.renderables.remove(self) if self.log_create_destroy: - self.app.log("destroyed: {}".format(self)) + self.app.log(f"destroyed: {self}") def get_projection_matrix(self): """ diff --git a/renderable_line.py b/renderable_line.py index 02da38d..5559678 100644 --- a/renderable_line.py +++ b/renderable_line.py @@ -27,7 +27,7 @@ class LineRenderable: self.app = app # we may be attached to a game object self.go = game_object - self.unique_name = "{}_{}".format(int(time.time()), self.__class__.__name__) + self.unique_name = f"{int(time.time())}_{self.__class__.__name__}" self.quad_size_ref = quad_size_ref self.x, self.y, self.z = 0, 0, 0 self.scale_x, self.scale_y = 1, 1 @@ -94,7 +94,7 @@ class LineRenderable: if self.app.use_vao: GL.glBindVertexArray(0) if self.log_create_destroy: - self.app.log("created: {}".format(self)) + self.app.log(f"created: {self}") def __str__(self): "for debug purposes, return a unique name" @@ -178,7 +178,7 @@ class LineRenderable: GL.glDeleteVertexArrays(1, [self.vao]) GL.glDeleteBuffers(3, [self.vert_buffer, self.elem_buffer, self.color_buffer]) if self.log_create_destroy: - self.app.log("destroyed: {}".format(self)) + self.app.log(f"destroyed: {self}") def render(self): if not self.visible: diff --git a/renderable_sprite.py b/renderable_sprite.py index 1cdbbd5..0127a84 100644 --- a/renderable_sprite.py +++ b/renderable_sprite.py @@ -23,7 +23,7 @@ class SpriteRenderable: def __init__(self, app, texture_filename=None, image_data=None): self.app = app - self.unique_name = "{}_{}".format(int(time.time()), self.__class__.__name__) + self.unique_name = f"{int(time.time())}_{self.__class__.__name__}" self.x, self.y, self.z = self.get_initial_position() self.scale_x, self.scale_y, self.scale_z = self.get_initial_scale() if self.app.use_vao: diff --git a/shader.py b/shader.py index 5c62172..539dd02 100644 --- a/shader.py +++ b/shader.py @@ -65,34 +65,26 @@ class Shader: self.last_vert_change = time.time() vert_source = self.get_shader_source(self.vert_source_file) if self.log_compile: - self.sl.app.log( - "Compiling vertex shader {}...".format(self.vert_source_file) - ) + self.sl.app.log(f"Compiling vertex shader {self.vert_source_file}...") self.vert_shader = self.try_compile_shader( vert_source, GL.GL_VERTEX_SHADER, self.vert_source_file ) if self.log_compile and self.vert_shader: self.sl.app.log( - "Compiled vertex shader {} in {:.6f} seconds".format( - self.vert_source_file, time.time() - self.last_vert_change - ) + f"Compiled vertex shader {self.vert_source_file} in {time.time() - self.last_vert_change:.6f} seconds" ) # fragment shader self.frag_source_file = frag_source_file self.last_frag_change = time.time() frag_source = self.get_shader_source(self.frag_source_file) if self.log_compile: - self.sl.app.log( - "Compiling fragment shader {}...".format(self.frag_source_file) - ) + self.sl.app.log(f"Compiling fragment shader {self.frag_source_file}...") self.frag_shader = self.try_compile_shader( frag_source, GL.GL_FRAGMENT_SHADER, self.frag_source_file ) if self.log_compile and self.frag_shader: self.sl.app.log( - "Compiled fragment shader {} in {:.6f} seconds".format( - self.frag_source_file, time.time() - self.last_frag_change - ) + f"Compiled fragment shader {self.frag_source_file} in {time.time() - self.last_frag_change:.6f} seconds" ) # shader program if self.vert_shader and self.frag_shader: @@ -109,7 +101,7 @@ class Shader: shader_version = self.glsl_version_macos else: shader_version = self.glsl_version_unix - version_string = "#version {}\n".format(shader_version) + version_string = f"#version {shader_version}\n" src = bytes(version_string, "utf-8") + src return src @@ -118,7 +110,7 @@ class Shader: try: shader = shaders.compileShader(source, shader_type) except Exception as e: - self.sl.app.log("{}: ".format(source_filename)) + self.sl.app.log(f"{source_filename}: ") lines = e.args[0].split("\\n") # salvage block after "shader compile failure" enclosed in b"" pre = lines.pop(0).split('b"') @@ -148,9 +140,9 @@ class Shader: try: new_shader = shaders.compileShader(new_shader_source, shader_type) # TODO: use try_compile_shader instead here, make sure exception passes thru ok - self.sl.app.log("ShaderLord: success reloading {}".format(file_to_reload)) + self.sl.app.log(f"ShaderLord: success reloading {file_to_reload}") except Exception: - self.sl.app.log("ShaderLord: failed reloading {}".format(file_to_reload)) + self.sl.app.log(f"ShaderLord: failed reloading {file_to_reload}") return # recompile program with new shader if shader_type == GL.GL_VERTEX_SHADER: diff --git a/ui.py b/ui.py index 806d667..403aa7d 100644 --- a/ui.py +++ b/ui.py @@ -120,7 +120,7 @@ class UI: # create tools for t in self.tool_classes: new_tool = t(self) - tool_name = "{}_tool".format(new_tool.name) + tool_name = f"{new_tool.name}_tool" setattr(self, tool_name, new_tool) # stick in a list for popup tool tab self.tools.append(new_tool) @@ -208,9 +208,7 @@ class UI: self.set_elements_scale() if self.scale != old_scale: self.message_line.post_line( - "UI scale is now {} ({:.3f} x {:.3f})".format( - self.scale, self.width_tiles, self.height_tiles - ) + f"UI scale is now {self.scale} ({self.width_tiles:.3f} x {self.height_tiles:.3f})" ) def set_elements_scale(self): @@ -283,7 +281,7 @@ class UI: self.app.update_window_title() if self.app.can_edit: self.message_line.post_line( - "{} {}".format(self.art_selected_log, self.active_art.filename) + f"{self.art_selected_log} {self.active_art.filename}" ) def set_active_art_by_filename(self, art_filename): @@ -349,9 +347,7 @@ class UI: if self.menu_bar.active_menu_name and not cycled_fill: self.menu_bar.close_active_menu() self.message_line.post_line( - "{} {}".format( - self.selected_tool.get_button_caption(), self.tool_selected_log - ) + f"{self.selected_tool.get_button_caption()} {self.tool_selected_log}" ) def cycle_fill_tool_mode(self): @@ -380,7 +376,7 @@ class UI: self.selected_xform = new_xform self.popup.set_xform(new_xform) self.tool_settings_changed = True - line = "{} {}".format(self.xform_selected_log, uv_names[self.selected_xform]) + line = f"{self.xform_selected_log} {uv_names[self.selected_xform]}" self.message_line.post_line(line) def cycle_selected_xform(self, back=False): @@ -598,7 +594,7 @@ class UI: command = EntireArtCommand(art, min_x, min_y) command.save_tiles(before=True) art.resize(w, h, min_x, min_y) - self.app.log("Resized {} to {} x {}".format(art.filename, w, h)) + self.app.log(f"Resized {art.filename} to {w} x {h}") art.set_unsaved_changes(True) # clear selection to avoid having tiles we know are OoB selected self.select_tool.selected_tiles = {} diff --git a/ui_art_dialog.py b/ui_art_dialog.py index ee7e1ae..ac48cc2 100644 --- a/ui_art_dialog.py +++ b/ui_art_dialog.py @@ -74,7 +74,7 @@ class NewArtDialog(BaseFileDialog): def get_initial_field_text(self, field_number): if field_number == 0: - return "new{}".format(len(self.ui.app.art_loaded_for_edit)) + return f"new{len(self.ui.app.art_loaded_for_edit)}" elif field_number == 2: return str(DEFAULT_WIDTH) elif field_number == 4: @@ -116,7 +116,7 @@ class NewArtDialog(BaseFileDialog): name = self.field_texts[0] w, h = int(self.field_texts[2]), int(self.field_texts[4]) self.ui.app.new_art_for_edit(name, w, h) - self.ui.app.log("Created {}.psci with size {} x {}".format(name, w, h)) + self.ui.app.log(f"Created {name}.psci with size {w} x {h}") self.dismiss() @@ -266,7 +266,7 @@ class ImportOptionsDialog(UIDialog): importer = app.importer(app, filename, options) if importer.success: if app.importer.completes_instantly: - app.log("Imported {} successfully.".format(filename)) + app.log(f"Imported {filename} successfully.") app.importer = None @@ -280,7 +280,7 @@ class ExportOptionsDialog(UIDialog): # if importer needs no options, run it exporter = app.exporter(app, filename, options) if exporter.success: - app.log("Exported {} successfully.".format(exporter.out_filename)) + app.log(f"Exported {exporter.out_filename} successfully.") class ExportFileDialog(ConvertFileDialog): @@ -606,7 +606,7 @@ class AddLayerDialog(UIDialog): def get_initial_field_text(self, field_number): if field_number == 0: - return "Layer {}".format(str(self.ui.active_art.layers + 1)) + return f"Layer {str(self.ui.active_art.layers + 1)}" elif field_number == 1: return str( self.ui.active_art.layers_z[self.ui.active_art.active_layer] @@ -761,7 +761,7 @@ class SetCameraZoomDialog(UIDialog): def get_initial_field_text(self, field_number): if field_number == 0: - return "{:.1f}".format(self.ui.app.camera.get_current_zoom_pct()) + return f"{self.ui.app.camera.get_current_zoom_pct():.1f}" return "" def is_input_valid(self): diff --git a/ui_button.py b/ui_button.py index 326dfa1..05c2bf3 100644 --- a/ui_button.py +++ b/ui_button.py @@ -52,17 +52,13 @@ class UIButton: "common code for button event logging" if self.element.ui.logg: self.element.ui.app.log( - "UIButton: {}'s {} {}".format( - self.element.__class__.__name__, self.__class__.__name__, event_type - ) + f"UIButton: {self.element.__class__.__name__}'s {self.__class__.__name__} {event_type}" ) def set_state(self, new_state): if new_state not in BUTTON_STATES: self.element.ui.app.log( - "Unrecognized state for button {}: {}".format( - self.__class__.__name__, new_state - ) + f"Unrecognized state for button {self.__class__.__name__}: {new_state}" ) return self.dimmed = new_state == "dimmed" @@ -70,8 +66,8 @@ class UIButton: self.set_state_colors() def get_state_colors(self, state): - fg = getattr(self, "{}_fg_color".format(state)) - bg = getattr(self, "{}_bg_color".format(state)) + fg = getattr(self, f"{state}_fg_color") + bg = getattr(self, f"{state}_bg_color") return fg, bg def set_state_colors(self): diff --git a/ui_chooser_dialog.py b/ui_chooser_dialog.py index 1eebf28..5aa4081 100644 --- a/ui_chooser_dialog.py +++ b/ui_chooser_dialog.py @@ -178,7 +178,7 @@ class ChooserDialog(UIDialog): try: os.listdir(new_dir) except PermissionError: - line = "No permission to access {}!".format(os.path.abspath(new_dir)) + line = f"No permission to access {os.path.abspath(new_dir)}!" self.ui.message_line.post_line(line, error=True) return False self.current_dir = new_dir diff --git a/ui_console.py b/ui_console.py index 4bf2c71..27b92ad 100644 --- a/ui_console.py +++ b/ui_console.py @@ -138,11 +138,9 @@ class ImportCommand(ConsoleCommand): if c.__name__ == importer_classname: importer_class = c if not importer_class: - console.ui.app.log( - "Couldn't find importer class {}".format(importer_classname) - ) + console.ui.app.log(f"Couldn't find importer class {importer_classname}") if not os.path.exists(filename): - console.ui.app.log("Couldn't find file {}".format(filename)) + console.ui.app.log(f"Couldn't find file {filename}") importer_class(console.ui.app, filename) @@ -159,9 +157,7 @@ class ExportCommand(ConsoleCommand): if c.__name__ == exporter_classname: exporter_class = c if not exporter_class: - console.ui.app.log( - "Couldn't find exporter class {}".format(exporter_classname) - ) + console.ui.app.log(f"Couldn't find exporter class {exporter_classname}") exporter_class(console.ui.app, filename) @@ -231,7 +227,7 @@ class CommandListCommand(ConsoleCommand): command_list.sort() for command in command_list: desc = commands[command].description - console.ui.app.log(" {} - {}".format(command, desc)) + console.ui.app.log(f" {command} - {desc}") class RunArtScriptCommand(ConsoleCommand): @@ -421,7 +417,7 @@ class ConsoleUI(UIElement): "draw current user input on second to last line, with >_ prompt" # clear entire user line first self.art.write_string(0, 0, 0, -2, " " * self.width, self.text_color) - self.art.write_string(0, 0, 0, -2, "{} ".format(self.prompt), self.text_color) + self.art.write_string(0, 0, 0, -2, f"{self.prompt} ", self.text_color) # if first item of line is a valid command, change its color items = self.current_line.split() if len(items) > 0 and items[0] in commands: @@ -491,7 +487,7 @@ class ConsoleUI(UIElement): self.toggle() return elif keystr == "Return": - line = "{} {}".format(self.prompt, self.current_line) + line = f"{self.prompt} {self.current_line}" self.ui.app.log(line) # if command is same as last, don't repeat it if len(self.command_history) == 0 or ( @@ -583,7 +579,7 @@ class ConsoleUI(UIElement): output = str(eval(line)) except Exception as e: # try to output useful error text - output = "{}: {}".format(e.__class__.__name__, str(e)) + output = f"{e.__class__.__name__}: {str(e)}" # commands CAN return None, so only log if there's something if output and output != "None": self.ui.app.log(output) diff --git a/ui_edit_panel.py b/ui_edit_panel.py index b807d2a..881a86f 100644 --- a/ui_edit_panel.py +++ b/ui_edit_panel.py @@ -296,10 +296,7 @@ class EditListPanel(GamePanel): self.list_scroll_index = min(self.list_scroll_index, len(self.items)) def get_label(self): - label = "{} ({})".format( - self.list_operation_labels[self.list_operation], - self.cancel_tip, - ) + label = f"{self.list_operation_labels[self.list_operation]} ({self.cancel_tip})" # some labels contain variables if "%s" in label: if self.list_operation == LO_SET_ROOM_OBJECTS: @@ -475,7 +472,7 @@ class EditListPanel(GamePanel): items = self.list_rooms() # prefix room names with "ROOM:" for item in items: - item.name = "ROOM: {}".format(item.name) + item.name = f"ROOM: {item.name}" items += self.list_objects() return items diff --git a/ui_element.py b/ui_element.py index cfdc4ee..d2d4c76 100644 --- a/ui_element.py +++ b/ui_element.py @@ -37,7 +37,7 @@ class UIElement: self.ui = ui self.hovered_buttons = [] # generate a unique name - art_name = "{}_{}".format(int(time.time()), self.__class__.__name__) + art_name = f"{int(time.time())}_{self.__class__.__name__}" self.art = UIArt( art_name, self.ui.app, @@ -135,9 +135,7 @@ class UIElement: mouse_button = mouse_button or "[n/a]" if self.ui.logg: self.ui.app.log( - "UIElement: {} {} with mouse button {}".format( - self.__class__.__name__, event_type, mouse_button - ) + f"UIElement: {self.__class__.__name__} {event_type} with mouse button {mouse_button}" ) def is_visible(self): @@ -302,11 +300,11 @@ class FPSCounterUI(UIElement): color = self.ui.colors.yellow if self.ui.app.fps < 10: color = self.ui.colors.red - text = "{:.1f} fps".format(self.ui.app.fps) + text = f"{self.ui.app.fps:.1f} fps" x = self.tile_width - 1 self.art.write_string(0, 0, x, 0, text, color, None, True) # display last tick time; frame_time includes delay, is useless - text = "{:.1f} ms ".format(self.ui.app.frame_time) + text = f"{self.ui.app.frame_time:.1f} ms " self.art.write_string(0, 0, x, 1, text, color, None, True) def render(self): diff --git a/ui_file_chooser_dialog.py b/ui_file_chooser_dialog.py index 8c5d28e..9fe939b 100644 --- a/ui_file_chooser_dialog.py +++ b/ui_file_chooser_dialog.py @@ -144,15 +144,15 @@ class ArtChooserItem(BaseFileChooserItem): return [] mod_time = time.gmtime(self.art_mod_time) mod_time = time.strftime("%Y-%m-%d %H:%M:%S", mod_time) - lines = ["last change: {}".format(mod_time)] - line = "{} x {}, ".format(self.art_width, self.art_height) - line += "{} frame".format(self.art_frames) + lines = [f"last change: {mod_time}"] + line = f"{self.art_width} x {self.art_height}, " + line += f"{self.art_frames} frame" # pluralize properly line += "s" if self.art_frames > 1 else "" - line += ", {} layer".format(self.art_layers) + line += f", {self.art_layers} layer" line += "s" if self.art_layers > 1 else "" lines += [line] - lines += ["char: {}, pal: {}".format(self.art_charset, self.art_palette)] + lines += [f"char: {self.art_charset}, pal: {self.art_palette}"] return lines def get_preview_texture(self, app): @@ -312,7 +312,7 @@ class PaletteChooserItem(BaseFileChooserItem): def get_description_lines(self): colors = len(self.palette.colors) - return ["Unique colors: {}".format(str(colors - 1))] + return [f"Unique colors: {str(colors - 1)}"] def get_preview_texture(self, app): return self.palette.src_texture @@ -370,7 +370,7 @@ class CharsetChooserItem(BaseFileChooserItem): if line.startswith("//"): lines.append(line[2:]) break - lines.append("Characters: {}".format(str(self.charset.last_index))) + lines.append(f"Characters: {str(self.charset.last_index)}") return lines def get_preview_texture(self, app): diff --git a/ui_game_menu_pulldown_item.py b/ui_game_menu_pulldown_item.py index b92d54b..f077e07 100644 --- a/ui_game_menu_pulldown_item.py +++ b/ui_game_menu_pulldown_item.py @@ -443,7 +443,7 @@ class GameRoomMenuData(PulldownMenuData): item = TempMenuItemClass # leave spaces for mark - item.label = " {}".format(room_name) + item.label = f" {room_name}" # pad, put Z depth on far right item.label = item.label.ljust(longest_line) # trim to keep below a max length diff --git a/ui_info_dialog.py b/ui_info_dialog.py index 9833aaf..701c0dd 100644 --- a/ui_info_dialog.py +++ b/ui_info_dialog.py @@ -131,5 +131,5 @@ class AboutDialog(PagedInfoDialog): all_modes_visible = True def __init__(self, ui, options): - self.title += " {}".format(ui.app.version) + self.title += f" {ui.app.version}" PagedInfoDialog.__init__(self, ui, options) diff --git a/ui_menu_bar.py b/ui_menu_bar.py index a1011da..3a8140b 100644 --- a/ui_menu_bar.py +++ b/ui_menu_bar.py @@ -217,7 +217,7 @@ class MenuBar(UIElement): button.width = len(button.caption) + 2 button.x = x x += button.width + self.button_padding - setattr(self, "{}_button".format(button.name), button) + setattr(self, f"{button.name}_button", button) # NOTE: callback already defined in MenuButton class, # menu data for pulldown with set in MenuButton subclass button.pulldown = self.ui.pulldown diff --git a/ui_menu_pulldown.py b/ui_menu_pulldown.py index a690238..3f78834 100644 --- a/ui_menu_pulldown.py +++ b/ui_menu_pulldown.py @@ -173,7 +173,7 @@ class PulldownMenu(UIElement): for bind_tuple in binds: command_functions = binds[bind_tuple] for f in command_functions: - if f.__name__ == "BIND_{}".format(menu_item.command): + if f.__name__ == f"BIND_{menu_item.command}": shortcut = "" # shift, alt, ctrl if bind_tuple[1]: @@ -187,5 +187,5 @@ class PulldownMenu(UIElement): if not (bind_tuple[0].startswith("_") and len(bind_tuple[0]) > 1): shortcut += bind_tuple[0] return shortcut, f - self.ui.app.log("Shortcut/command not found: {}".format(menu_item.command)) + self.ui.app.log(f"Shortcut/command not found: {menu_item.command}") return "", null diff --git a/ui_menu_pulldown_item.py b/ui_menu_pulldown_item.py index aa59909..70098e9 100644 --- a/ui_menu_pulldown_item.py +++ b/ui_menu_pulldown_item.py @@ -249,42 +249,42 @@ class ToolToggleArtToolbar(ArtModePulldownMenuItem): class ToolPaintItem(ArtModePulldownMenuItem): # two spaces in front of each label to leave room for mark - label = " {}".format(PencilTool.button_caption) + label = f" {PencilTool.button_caption}" command = "select_pencil_tool" class ToolEraseItem(ArtModePulldownMenuItem): - label = " {}".format(EraseTool.button_caption) + label = f" {EraseTool.button_caption}" command = "select_erase_tool" class ToolRotateItem(ArtModePulldownMenuItem): - label = " {}".format(RotateTool.button_caption) + label = f" {RotateTool.button_caption}" command = "select_rotate_tool" class ToolGrabItem(ArtModePulldownMenuItem): - label = " {}".format(GrabTool.button_caption) + label = f" {GrabTool.button_caption}" command = "select_grab_tool" class ToolTextItem(ArtModePulldownMenuItem): - label = " {}".format(TextTool.button_caption) + label = f" {TextTool.button_caption}" command = "select_text_tool" class ToolSelectItem(ArtModePulldownMenuItem): - label = " {}".format(SelectTool.button_caption) + label = f" {SelectTool.button_caption}" command = "select_select_tool" class ToolPasteItem(ArtModePulldownMenuItem): - label = " {}".format(PasteTool.button_caption) + label = f" {PasteTool.button_caption}" command = "select_paste_tool" class ToolFillItem(ArtModePulldownMenuItem): - label = " {}".format(FillTool.button_caption) + label = f" {FillTool.button_caption}" command = "select_fill_tool" @@ -301,7 +301,7 @@ class ToolIncreaseBrushSizeItem(ArtModePulldownMenuItem): if not app.ui.selected_tool.brush_size: return "Increase brush size" size = app.ui.selected_tool.brush_size + 1 - return "Increase brush size to {}".format(size) + return f"Increase brush size to {size}" class ToolDecreaseBrushSizeItem(ArtModePulldownMenuItem): @@ -317,7 +317,7 @@ class ToolDecreaseBrushSizeItem(ArtModePulldownMenuItem): if not app.ui.selected_tool.brush_size: return "Decrease brush size" size = app.ui.selected_tool.brush_size - 1 - return "Decrease brush size to {}".format(size) + return f"Decrease brush size to {size}" class ToolSettingsItem(ArtModePulldownMenuItem): @@ -368,9 +368,7 @@ class ToolSetFillBoundariesItem(ArtModePulldownMenuItem): return type(app.ui.selected_tool) is not FillTool def get_label(app): - return "Fill tool bounded by: {}".format( - app.ui.fill_tool.boundary_mode_names[app.ui.fill_tool.boundary_mode] - ) + return f"Fill tool bounded by: {app.ui.fill_tool.boundary_mode_names[app.ui.fill_tool.boundary_mode]}" # @@ -600,7 +598,7 @@ class FrameCycleOnionFramesItem(ArtModePulldownMenuItem): return not app.ui.active_art or app.ui.active_art.frames < 2 def get_label(app): - return "Number of onion frames: {}".format(app.onion_show_frames) + return f"Number of onion frames: {app.onion_show_frames}" class FrameCycleOnionDisplayItem(ArtModePulldownMenuItem): @@ -617,7 +615,7 @@ class FrameCycleOnionDisplayItem(ArtModePulldownMenuItem): display = "Previous" else: display = "Next" - return "Onion frames show: {}".format(display) + return f"Onion frames show: {display}" class FrameAddFrameItem(ArtModePulldownMenuItem): @@ -872,7 +870,7 @@ class ToolMenuData(PulldownMenuData): # if it's a tool setting toggle, use its own mark check function if item.__bases__[0] is ToolSettingsItem or hasattr(item, "should_mark"): return item.should_mark(ui) - return item.label == " {}".format(ui.selected_tool.button_caption) + return item.label == f" {ui.selected_tool.button_caption}" class ViewMenuData(PulldownMenuData): @@ -933,7 +931,7 @@ class ArtMenuData(PulldownMenuData): item = TempMenuItemClass # leave spaces for mark - item.label = " {}".format(art.filename) + item.label = f" {art.filename}" item.command = "art_switch_to" item.cb_arg = art.filename # order list by art's time loaded @@ -1008,7 +1006,7 @@ class LayerMenuData(PulldownMenuData): item = TempMenuItemClass # leave spaces for mark - item.label = " {}".format(layer_name) + item.label = f" {layer_name}" if not app.ui.active_art.layers_visibility[i]: item.label += " (hidden)" # pad, put Z depth on far right @@ -1016,7 +1014,7 @@ class LayerMenuData(PulldownMenuData): # trim to keep below a max length item.label = item.label[:longest_line] # spaces between layer name and z depth - item.label += "z:{:.2f}".format(app.ui.active_art.layers_z[i]) + item.label += f"z:{app.ui.active_art.layers_z[i]:.2f}" # tell PulldownMenu's button creation process not to auto-pad item.no_pad = True item.command = "layer_switch_to" diff --git a/ui_object_panel.py b/ui_object_panel.py index c2ca0c0..3769c3b 100644 --- a/ui_object_panel.py +++ b/ui_object_panel.py @@ -64,7 +64,7 @@ class PropertyItem: def set_value(self, value): # convert value to a button-friendly string if type(value) is float: - valstr = "{:.3f}".format(value) + valstr = f"{value:.3f}" # non-fixed decimal version may be shorter, if so use it if len(str(value)) < len(valstr): valstr = str(value) @@ -178,7 +178,7 @@ class EditObjectPanel(GamePanel): elif selected == 1 and self.world.selected_objects[0]: return self.world.selected_objects[0].name else: - return "[{} selected]".format(selected) + return f"[{selected} selected]" def refresh_items(self): if len(self.world.selected_objects) == 0: @@ -222,14 +222,14 @@ class EditObjectPanel(GamePanel): button.can_hover = False return # set button caption, width, x based on value - button.caption = "{} ".format(item.prop_value) + button.caption = f"{item.prop_value} " button.width = len(button.caption) + 1 button.x = self.tile_width - button.width button.cb_arg = item button.can_hover = True # set non-button text to the left correctly x = button.x + 1 - label = "{}: ".format(item.prop_name) + label = f"{item.prop_name}: " self.art.write_string(0, 0, x, y, label, UIColors.darkgrey, None, True) def update(self): diff --git a/ui_popup.py b/ui_popup.py index 7b77427..33b74c2 100644 --- a/ui_popup.py +++ b/ui_popup.py @@ -261,10 +261,10 @@ class ToolPopup(UIElement): for tool in self.ui.tools: tool_button = ToolButton(self) # caption: 1-space padding from left - tool_button.caption = " {}".format(tool.button_caption) - tool_button_name = "{}_tool_button".format(tool.name) + tool_button.caption = f" {tool.button_caption}" + tool_button_name = f"{tool.name}_tool_button" setattr(self, tool_button_name, tool_button) - cb_name = "{}_pressed".format(tool_button_name) + cb_name = f"{tool_button_name}_pressed" tool_button.callback = getattr(self, cb_name) # set a special property UI can refer to tool_button.tool_name = tool.name @@ -280,9 +280,9 @@ class ToolPopup(UIElement): buttons = [] for button_class in button_dict: button = button_class(self) - button_name = "{}_button".format(button_dict[button_class]) + button_name = f"{button_dict[button_class]}_button" setattr(self, button_name, button) - cb_name = "{}_pressed".format(button_name) + cb_name = f"{button_name}_pressed" button.callback = getattr(self, cb_name) buttons.append(button) return buttons @@ -439,13 +439,12 @@ class ToolPopup(UIElement): # position & caption charset button y = self.tab_height + 1 self.choose_charset_button.y = y - self.choose_charset_button.caption = " {} {} ".format( - CharSetChooserButton.caption, - charset.name, + self.choose_charset_button.caption = ( + f" {CharSetChooserButton.caption} {charset.name} " ) self.choose_charset_button.width = len(self.choose_charset_button.caption) # charset scale - charset_scale = "{:.2f}x".format(self.charset_swatch.char_scale) + charset_scale = f"{self.charset_swatch.char_scale:.2f}x" x = -self.scale_charset_up_button.width * 2 self.art.write_string(0, 0, x, y, charset_scale, None, None, True) # transform labels and buttons, eg @@ -460,9 +459,8 @@ class ToolPopup(UIElement): pal_caption_y = (cqh * charset.map_height) / self.art.quad_height pal_caption_y += self.tab_height + 5 self.choose_palette_button.y = int(pal_caption_y) - self.choose_palette_button.caption = " {} {} ".format( - PaletteChooserButton.caption, - palette.name, + self.choose_palette_button.caption = ( + f" {PaletteChooserButton.caption} {palette.name} " ) self.choose_palette_button.width = len(self.choose_palette_button.caption) # set button states so captions draw properly @@ -495,10 +493,7 @@ class ToolPopup(UIElement): # draw current tool settings x = TOOL_PANE_WIDTH + 1 y = self.tab_height + 1 - label = "{} {}".format( - self.ui.selected_tool.button_caption, - self.tool_settings_label, - ) + label = f"{self.ui.selected_tool.button_caption} {self.tool_settings_label}" self.art.write_string(0, 0, x, y, label) x += 1 y += 2 @@ -510,7 +505,7 @@ class ToolPopup(UIElement): # calculate X of + and - buttons based on size string self.brush_size_down_button.x = TOOL_PANE_WIDTH + len(label) + 2 label += " " * (self.brush_size_down_button.width + 1) - label += "{}".format(self.ui.selected_tool.brush_size) + label += f"{self.ui.selected_tool.brush_size}" self.brush_size_up_button.x = TOOL_PANE_WIDTH + len(label) + 3 self.art.write_string(0, 0, x, y, label) else: @@ -546,7 +541,7 @@ class ToolPopup(UIElement): (self.affects_xform_label, self.ui.selected_tool.affects_xform) ] for label, toggle in label_toggle_pairs: - self.art.write_string(0, 0, x + w + 1, y, "{}".format(label)) + self.art.write_string(0, 0, x + w + 1, y, f"{label}") # self.art.set_tile_at(0, 0, x, y, get_affects_char(toggle), 4, 2) self.art.set_char_index_at(0, 0, x + 1, y, get_affects_char(toggle)) y += 1 diff --git a/ui_status_bar.py b/ui_status_bar.py index d1c13f7..8b92d6f 100644 --- a/ui_status_bar.py +++ b/ui_status_bar.py @@ -29,7 +29,7 @@ class CharToggleButton(StatusBarToggleButton): tooltip_on_hover = True def get_tooltip_text(self): - return "character index: {}".format(self.element.ui.selected_char) + return f"character index: {self.element.ui.selected_char}" def get_tooltip_location(self): return 1, self.element.get_tile_y() - 1 @@ -54,7 +54,7 @@ class FGToggleButton(StatusBarToggleButton): tooltip_on_hover = True def get_tooltip_text(self): - return "foreground color index: {}".format(self.element.ui.selected_fg_color) + return f"foreground color index: {self.element.ui.selected_fg_color}" def get_tooltip_location(self): return 8, self.element.get_tile_y() - 1 @@ -78,7 +78,7 @@ class BGToggleButton(StatusBarToggleButton): tooltip_on_hover = True def get_tooltip_text(self): - return "background color index: {}".format(self.element.ui.selected_bg_color) + return f"background color index: {self.element.ui.selected_bg_color}" def get_tooltip_location(self): return 15, self.element.get_tile_y() - 1 @@ -188,7 +188,7 @@ class StatusBarUI(UIElement): art = ui.active_art self.ui = ui # create 3 custom Arts w/ source charset and palette, renderables for each - art_name = "{}_{}".format(int(time.time()), self.__class__.__name__) + art_name = f"{int(time.time())}_{self.__class__.__name__}" self.char_art = UIArt( art_name, ui.app, art.charset, art.palette, self.swatch_width, 1 ) @@ -225,7 +225,7 @@ class StatusBarUI(UIElement): for button_class, button_name in self.button_names.items(): button = button_class(self) setattr(self, button_name + "_button", button) - cb_name = "{}_button_pressed".format(button_name) + cb_name = f"{button_name}_button_pressed" button.callback = getattr(self, cb_name) self.buttons.append(button) # keep a mapping of button names to buttons, for eg tooltip updates @@ -436,17 +436,15 @@ class StatusBarUI(UIElement): # NOTE: button X offsets will be set in write_right_elements null = "---" layers = art.layers if art else 0 - layer = "{}/{}".format(art.active_layer + 1, layers) if art else null + layer = f"{art.active_layer + 1}/{layers}" if art else null self.layer_cycle_button.caption = layer self.layer_cycle_button.width = len(self.layer_cycle_button.caption) frames = art.frames if art else 0 - frame = "{}/{}".format(art.active_frame + 1, frames) if art else null + frame = f"{art.active_frame + 1}/{frames}" if art else null self.frame_cycle_button.caption = frame self.frame_cycle_button.width = len(self.frame_cycle_button.caption) # zoom % - zoom = ( - "{:.1f}".format(self.ui.app.camera.get_current_zoom_pct()) if art else null - ) + zoom = f"{self.ui.app.camera.get_current_zoom_pct():.1f}" if art else null self.zoom_set_button.caption = zoom[:5] # maintain size def update(self): @@ -514,7 +512,7 @@ class StatusBarUI(UIElement): color = self.dim_color tile_x = str(tile_x).rjust(3) tile_y = str(tile_y).rjust(3) - tile = "{},{}".format(tile_x, tile_y) + tile = f"{tile_x},{tile_y}" self.art.write_string(0, 0, x, 0, tile, color, dark, True) # tile label x -= len(tile) diff --git a/ui_swatch.py b/ui_swatch.py index 61831ab..58bcc30 100644 --- a/ui_swatch.py +++ b/ui_swatch.py @@ -20,7 +20,7 @@ class UISwatch(UIElement): self.tile_width, self.tile_height = self.get_size() art = self.ui.active_art # generate a unique name for debug purposes - art_name = "{}_{}".format(int(time.time()), self.__class__.__name__) + art_name = f"{int(time.time())}_{self.__class__.__name__}" self.art = UIArt( art_name, self.ui.app, @@ -405,7 +405,7 @@ class PaletteSwatch(UISwatch): class ColorSelectionLabelArt(UIArt): def __init__(self, ui, letter): letter_index = ui.charset.get_char_index(letter) - art_name = "{}_{}".format(int(time.time()), self.__class__.__name__) + art_name = f"{int(time.time())}_{self.__class__.__name__}" UIArt.__init__(self, art_name, ui.app, ui.charset, ui.palette, 1, 1) label_color = ui.colors.white label_bg_color = 0 diff --git a/ui_tool.py b/ui_tool.py index b89bf82..52429b9 100644 --- a/ui_tool.py +++ b/ui_tool.py @@ -586,7 +586,4 @@ class FillTool(UITool): ] def get_button_caption(self): - return "{} ({} bounded)".format( - self.button_caption, - self.boundary_mode_names[self.boundary_mode], - ) + return f"{self.button_caption} ({self.boundary_mode_names[self.boundary_mode]} bounded)" diff --git a/vector.py b/vector.py index cf6ef27..5c0a29b 100644 --- a/vector.py +++ b/vector.py @@ -11,7 +11,7 @@ class Vec3: self.x, self.y, self.z = x, y, z def __str__(self): - return "Vec3 {:.4f}, {:.4f}, {:.4f}".format(self.x, self.y, self.z) + return f"Vec3 {self.x:.4f}, {self.y:.4f}, {self.z:.4f}" def __sub__(self, b): "Return a new vector subtracted from given other vector."