From 0e3b594edb910ccb811bd5ac1998868d9ec72ea1 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 27 Apr 2024 16:02:36 +1000 Subject: [PATCH] Refactor: scripts under scripts/startup/ to use `str.format` Part of modernizing scripts in Blender, where the previous convention was to use percentage formatting which has become the "old" way to format strings in Python. See proposal for details #120453. Ref !120552 --- .../Video_Editing/__init__.py | 2 +- scripts/startup/bl_operators/anim.py | 62 ++++--- scripts/startup/bl_operators/assets.py | 2 +- scripts/startup/bl_operators/clip.py | 6 +- scripts/startup/bl_operators/console.py | 8 +- scripts/startup/bl_operators/file.py | 9 +- scripts/startup/bl_operators/freestyle.py | 4 +- scripts/startup/bl_operators/image.py | 13 +- scripts/startup/bl_operators/mesh.py | 27 +-- scripts/startup/bl_operators/node.py | 2 +- scripts/startup/bl_operators/object.py | 63 +++---- .../bl_operators/object_quick_effects.py | 2 +- scripts/startup/bl_operators/presets.py | 28 +-- .../bl_operators/screen_play_rendered_anim.py | 12 +- scripts/startup/bl_operators/sequencer.py | 4 +- scripts/startup/bl_operators/userpref.py | 56 +++--- .../startup/bl_operators/uvcalc_lightmap.py | 2 +- scripts/startup/bl_operators/wm.py | 170 +++++++++--------- scripts/startup/bl_ui/node_add_menu.py | 2 +- scripts/startup/bl_ui/properties_data_mesh.py | 8 +- .../bl_ui/properties_grease_pencil_common.py | 2 +- scripts/startup/bl_ui/properties_output.py | 4 +- scripts/startup/bl_ui/properties_particle.py | 22 ++- scripts/startup/bl_ui/properties_workspace.py | 2 +- scripts/startup/bl_ui/space_clip.py | 6 +- scripts/startup/bl_ui/space_image.py | 2 +- scripts/startup/bl_ui/space_node.py | 2 +- scripts/startup/bl_ui/space_sequencer.py | 33 ++-- scripts/startup/bl_ui/space_text.py | 4 +- .../startup/bl_ui/space_toolsystem_common.py | 8 +- .../startup/bl_ui/space_toolsystem_toolbar.py | 26 +-- scripts/startup/bl_ui/space_topbar.py | 4 +- scripts/startup/bl_ui/space_userpref.py | 18 +- scripts/startup/bl_ui/space_view3d.py | 14 +- scripts/startup/bl_ui/temp_anim_layers.py | 2 +- scripts/startup/keyingsets_builtins.py | 2 +- scripts/startup/nodeitems_builtins.py | 2 +- 37 files changed, 333 insertions(+), 302 deletions(-) diff --git a/scripts/startup/bl_app_templates_system/Video_Editing/__init__.py b/scripts/startup/bl_app_templates_system/Video_Editing/__init__.py index e5f957c19a0..b21e7a247c0 100644 --- a/scripts/startup/bl_app_templates_system/Video_Editing/__init__.py +++ b/scripts/startup/bl_app_templates_system/Video_Editing/__init__.py @@ -21,7 +21,7 @@ def update_factory_startup_ffmpeg_preset(): preset = "H264_in_MP4" preset_filepath = bpy.utils.preset_find(preset, preset_path="ffmpeg") if not preset_filepath: - print("Preset %r not found" % preset) + print("Preset {!r} not found".format(preset)) for scene in bpy.data.scenes: render = scene.render diff --git a/scripts/startup/bl_operators/anim.py b/scripts/startup/bl_operators/anim.py index 07bc492e048..6d60c004604 100644 --- a/scripts/startup/bl_operators/anim.py +++ b/scripts/startup/bl_operators/anim.py @@ -56,23 +56,23 @@ class ANIM_OT_keying_set_export(Operator): scene = context.scene ks = scene.keying_sets.active - f.write("# Keying Set: %s\n" % ks.bl_idname) + f.write("# Keying Set: {!s}\n".format(ks.bl_idname)) f.write("import bpy\n\n") f.write("scene = bpy.context.scene\n\n") # Add KeyingSet and set general settings f.write("# Keying Set Level declarations\n") - f.write("ks = scene.keying_sets.new(idname=%r, name=%r)\n" % (ks.bl_idname, ks.bl_label)) - f.write("ks.bl_description = %r\n" % ks.bl_description) + f.write("ks = scene.keying_sets.new(idname={!r}, name={!r})\n".format(ks.bl_idname, ks.bl_label)) + f.write("ks.bl_description = {!r}\n".format(ks.bl_description)) # TODO: this isn't editable, it should be possible to set this flag for `scene.keying_sets.new`. # if not ks.is_path_absolute: # f.write("ks.is_path_absolute = False\n") f.write("\n") - f.write("ks.use_insertkey_needed = %r\n" % ks.use_insertkey_needed) - f.write("ks.use_insertkey_visual = %r\n" % ks.use_insertkey_visual) + f.write("ks.use_insertkey_needed = {!r}\n".format(ks.use_insertkey_needed)) + f.write("ks.use_insertkey_visual = {!r}\n".format(ks.use_insertkey_visual)) f.write("\n") # -------------------------------------------------------- @@ -96,51 +96,54 @@ class ANIM_OT_keying_set_export(Operator): # (e.g. node-tree in Material). if ksp.id.bl_rna.identifier.startswith("ShaderNodeTree"): # Find material or light using this node tree... - id_bpy_path = "bpy.data.nodes[\"%s\"]" + id_bpy_path = "bpy.data.nodes[\"{!s}\"]" found = False for mat in bpy.data.materials: if mat.node_tree == ksp.id: - id_bpy_path = "bpy.data.materials[\"%s\"].node_tree" % escape_identifier(mat.name) + id_bpy_path = "bpy.data.materials[\"{!s}\"].node_tree".format(escape_identifier(mat.name)) found = True break if not found: for light in bpy.data.lights: if light.node_tree == ksp.id: - id_bpy_path = "bpy.data.lights[\"%s\"].node_tree" % escape_identifier(light.name) + id_bpy_path = "bpy.data.lights[\"{!s}\"].node_tree".format(escape_identifier(light.name)) found = True break if not found: self.report( {'WARN'}, - rpt_("Could not find material or light using Shader Node Tree - %s") % - (ksp.id)) + rpt_("Could not find material or light using Shader Node Tree - {!s}").format(str(ksp.id)) + ) elif ksp.id.bl_rna.identifier.startswith("CompositorNodeTree"): # Find compositor node-tree using this node tree. for scene in bpy.data.scenes: if scene.node_tree == ksp.id: - id_bpy_path = "bpy.data.scenes[\"%s\"].node_tree" % escape_identifier(scene.name) + id_bpy_path = "bpy.data.scenes[\"{!s}\"].node_tree".format(escape_identifier(scene.name)) break else: - self.report({'WARN'}, rpt_("Could not find scene using Compositor Node Tree - %s") % (ksp.id)) + self.report( + {'WARN'}, + rpt_("Could not find scene using Compositor Node Tree - {!s}").format(str(ksp.id)) + ) elif ksp.id.bl_rna.name == "Key": # "keys" conflicts with a Python keyword, hence the simple solution won't work - id_bpy_path = "bpy.data.shape_keys[\"%s\"]" % escape_identifier(ksp.id.name) + id_bpy_path = "bpy.data.shape_keys[\"{!s}\"]".format(escape_identifier(ksp.id.name)) else: idtype_list = ksp.id.bl_rna.name.lower() + "s" - id_bpy_path = "bpy.data.%s[\"%s\"]" % (idtype_list, escape_identifier(ksp.id.name)) + id_bpy_path = "bpy.data.{!s}[\"{!s}\"]".format(idtype_list, escape_identifier(ksp.id.name)) # shorthand ID for the ID-block (as used in the script) - short_id = "id_%d" % len(id_to_paths_cache) + short_id = "id_{:d}".format(len(id_to_paths_cache)) # store this in the cache now id_to_paths_cache[ksp.id] = [short_id, id_bpy_path] f.write("# ID's that are commonly used\n") for id_pair in id_to_paths_cache.values(): - f.write("%s = %s\n" % (id_pair[0], id_pair[1])) + f.write("{!s} = {!s}\n".format(id_pair[0], id_pair[1])) f.write("\n") # write paths @@ -154,22 +157,21 @@ class ANIM_OT_keying_set_export(Operator): id_bpy_path = id_to_paths_cache[ksp.id][0] else: id_bpy_path = "None" # XXX... - f.write("%s, %r" % (id_bpy_path, ksp.data_path)) + f.write("{!s}, {!r}".format(id_bpy_path, ksp.data_path)) # array index settings (if applicable) if ksp.use_entire_array: f.write(", index=-1") else: - f.write(", index=%d" % ksp.array_index) + f.write(", index={:d}".format(ksp.array_index)) # grouping settings (if applicable) # NOTE: the current default is KEYINGSET, but if this changes, # change this code too if ksp.group_method == 'NAMED': - f.write(", group_method=%r, group_name=%r" % - (ksp.group_method, ksp.group)) + f.write(", group_method={!r}, group_name={!r}".format(ksp.group_method, ksp.group)) elif ksp.group_method != 'KEYINGSET': - f.write(", group_method=%r" % ksp.group_method) + f.write(", group_method={!r}".format(ksp.group_method)) # finish off f.write(")\n") @@ -364,8 +366,7 @@ class ClearUselessActions(Operator): action.user_clear() removed += 1 - self.report({'INFO'}, rpt_("Removed %d empty and/or fake-user only Actions") - % removed) + self.report({'INFO'}, rpt_("Removed {:d} empty and/or fake-user only Actions").format(removed)) return {'FINISHED'} @@ -449,7 +450,7 @@ class UpdateAnimatedTransformConstraint(Operator): print(log) text = bpy.data.texts.new("UpdateAnimatedTransformConstraint Report") text.from_string(log) - self.report({'INFO'}, rpt_("Complete report available on '%s' text datablock") % text.name) + self.report({'INFO'}, rpt_("Complete report available on '{!s}' text datablock").format(text.name)) return {'FINISHED'} @@ -495,7 +496,7 @@ class ARMATURE_OT_copy_bone_color_to_selected(Operator): # Anything else: case _: - self.report({'ERROR'}, "Cannot do anything in mode %r" % context.mode) + self.report({'ERROR'}, "Cannot do anything in mode {!r}".format(context.mode)) return {'CANCELLED'} if not bone_source: @@ -524,8 +525,10 @@ class ARMATURE_OT_copy_bone_color_to_selected(Operator): if num_pose_color_overrides: self.report( {'INFO'}, - "Bone colors were synced; for %d bones this will not be visible due to pose bone color overrides" % - num_pose_color_overrides) + "Bone colors were synced; " + "for {:d} bones this will not be visible due to pose bone color overrides".format( + num_pose_color_overrides, + )) return {'FINISHED'} @@ -660,8 +663,9 @@ class ARMATURE_OT_collection_remove_unused(Operator): for bcoll in reversed(list(bcolls_to_remove)): armature.collections.remove(bcoll) - self.report({'INFO'}, "Removed %d of %d bone collections" % - (num_bcolls_to_remove, num_bcolls_before_removal)) + self.report( + {'INFO'}, "Removed {:d} of {:d} bone collections".format(num_bcolls_to_remove, num_bcolls_before_removal), + ) classes = ( diff --git a/scripts/startup/bl_operators/assets.py b/scripts/startup/bl_operators/assets.py index d0b0c898d5e..bd84d4c7eea 100644 --- a/scripts/startup/bl_operators/assets.py +++ b/scripts/startup/bl_operators/assets.py @@ -125,7 +125,7 @@ class ASSET_OT_open_containing_blend_file(Operator): return {'RUNNING_MODAL'} if returncode: - self.report({'WARNING'}, rpt_("Blender sub-process exited with error code %d") % returncode) + self.report({'WARNING'}, rpt_("Blender sub-process exited with error code {:d}").format(returncode)) if bpy.ops.asset.library_refresh.poll(): bpy.ops.asset.library_refresh() diff --git a/scripts/startup/bl_operators/clip.py b/scripts/startup/bl_operators/clip.py index 374fb92e23a..4e4c6528bf5 100644 --- a/scripts/startup/bl_operators/clip.py +++ b/scripts/startup/bl_operators/clip.py @@ -197,7 +197,7 @@ class CLIP_OT_filter_tracks(Operator): def execute(self, context): num_tracks = self._filter_values(context, self.track_threshold) - self.report({'INFO'}, rpt_("Identified %d problematic tracks") % num_tracks) + self.report({'INFO'}, rpt_("Identified {:d} problematic tracks").format(num_tracks)) return {'FINISHED'} @@ -364,11 +364,11 @@ class CLIP_OT_delete_proxy(Operator): # proxy_[_undistorted] for x in (25, 50, 75, 100): - d = os.path.join(absproxy, "proxy_%d" % x) + d = os.path.join(absproxy, "proxy_{:d}".format(x)) self._rmproxy(d) self._rmproxy(d + "_undistorted") - self._rmproxy(os.path.join(absproxy, "proxy_%d.avi" % x)) + self._rmproxy(os.path.join(absproxy, "proxy_{:d}.avi".format(x))) tc = ( "free_run.blen_tc", diff --git a/scripts/startup/bl_operators/console.py b/scripts/startup/bl_operators/console.py index a15831b7cd0..bffc56ab7fe 100644 --- a/scripts/startup/bl_operators/console.py +++ b/scripts/startup/bl_operators/console.py @@ -42,7 +42,7 @@ class ConsoleExec(Operator): if execute is not None: return execute(context, self.interactive) else: - print("Error: bpy.ops.console.execute_%s - not found" % sc.language) + print("Error: bpy.ops.console.execute_{!s} - not found".format(sc.language)) return {'FINISHED'} @@ -64,7 +64,7 @@ class ConsoleAutocomplete(Operator): if autocomplete: return autocomplete(context) else: - print("Error: bpy.ops.console.autocomplete_%s - not found" % sc.language) + print("Error: bpy.ops.console.autocomplete_{!s} - not found".format(sc.language)) return {'FINISHED'} @@ -86,7 +86,7 @@ class ConsoleCopyAsScript(Operator): if copy_as_script: return copy_as_script(context) else: - print("Error: copy_as_script - not found for %r" % sc.language) + print("Error: copy_as_script - not found for {!r}".format(sc.language)) return {'FINISHED'} @@ -112,7 +112,7 @@ class ConsoleBanner(Operator): if banner: return banner(context) else: - print("Error: bpy.ops.console.banner_%s - not found" % sc.language) + print("Error: bpy.ops.console.banner_{!s} - not found".format(sc.language)) return {'FINISHED'} diff --git a/scripts/startup/bl_operators/file.py b/scripts/startup/bl_operators/file.py index dea250fa319..e1bc0430a55 100644 --- a/scripts/startup/bl_operators/file.py +++ b/scripts/startup/bl_operators/file.py @@ -125,7 +125,7 @@ class WM_OT_previews_batch_generate(Operator): if not self.use_backups: cmd.append("--no_backups") if subprocess.call(cmd): - self.report({'ERROR'}, rpt_("Previews generation process failed for file '%s'!") % blen_path) + self.report({'ERROR'}, rpt_("Previews generation process failed for file '{!s}'!").format(blen_path)) context.window_manager.progress_end() return {'CANCELLED'} context.window_manager.progress_update(i + 1) @@ -235,7 +235,7 @@ class WM_OT_previews_batch_clear(Operator): if not self.use_backups: cmd.append("--no_backups") if subprocess.call(cmd): - self.report({'ERROR'}, rpt_("Previews clear process failed for file '%s'!") % blen_path) + self.report({'ERROR'}, rpt_("Previews clear process failed for file '{!s}'!").format(blen_path)) context.window_manager.progress_end() return {'CANCELLED'} context.window_manager.progress_update(i + 1) @@ -273,8 +273,9 @@ class WM_OT_blend_strings_utf8_validate(Operator): val_utf8 = val_bytes.decode("utf-8", "replace") val_bytes_valid = val_utf8.encode("utf-8") if val_bytes_valid != val_bytes: - print("found bad utf8 encoded string %r, fixing to %r (%r)..." - "" % (val_bytes, val_bytes_valid, val_utf8)) + print("found bad utf8 encoded string {!r}, fixing to {!r} ({!r})...".format( + val_bytes, val_bytes_valid, val_utf8, + )) setattr(item, prop.identifier, val_utf8) changed = True elif prop.type == 'POINTER': diff --git a/scripts/startup/bl_operators/freestyle.py b/scripts/startup/bl_operators/freestyle.py index 30929e27d85..9cc4d713a1e 100644 --- a/scripts/startup/bl_operators/freestyle.py +++ b/scripts/startup/bl_operators/freestyle.py @@ -147,7 +147,7 @@ class SCENE_OT_freestyle_add_edge_marks_to_keying_set(Operator): bpy.ops.object.mode_set(mode='OBJECT', toggle=False) for i, edge in enumerate(mesh.edges): if not edge.hide and edge.select: - path = "edges[%d].use_freestyle_mark" % i + path = "edges[{:d}].use_freestyle_mark".format(i) ks.paths.add(mesh, path, index=0) bpy.ops.object.mode_set(mode=ob_mode, toggle=False) return {'FINISHED'} @@ -178,7 +178,7 @@ class SCENE_OT_freestyle_add_face_marks_to_keying_set(Operator): bpy.ops.object.mode_set(mode='OBJECT', toggle=False) for i, polygon in enumerate(mesh.polygons): if not polygon.hide and polygon.select: - path = "polygons[%d].use_freestyle_mark" % i + path = "polygons[{:d}].use_freestyle_mark".format(i) ks.paths.add(mesh, path, index=0) bpy.ops.object.mode_set(mode=ob_mode, toggle=False) return {'FINISHED'} diff --git a/scripts/startup/bl_operators/image.py b/scripts/startup/bl_operators/image.py index dffa6858202..75c1039a988 100644 --- a/scripts/startup/bl_operators/image.py +++ b/scripts/startup/bl_operators/image.py @@ -62,9 +62,10 @@ class EditExternally(Operator): return {'CANCELLED'} if not os.path.exists(filepath) or not os.path.isfile(filepath): - self.report({'ERROR'}, - rpt_("Image path %r not found, image may be packed or " - "unsaved") % filepath) + self.report( + {'ERROR'}, + rpt_("Image path {!r} not found, image may be packed or unsaved").format(filepath), + ) return {'CANCELLED'} cmd = self._editor_guess(context) + [filepath] @@ -160,7 +161,7 @@ class ProjectEdit(Operator): i = 0 while os.path.exists(bpy.path.abspath(filepath_final)): - filepath_final = filepath + ("%.3d.%s" % (i, EXT)) + filepath_final = filepath + "{:03d}.{!s}".format(i, EXT) i += 1 image_new.name = bpy.path.basename(filepath_final) @@ -190,7 +191,7 @@ class ProjectApply(Operator): image_name = ProjectEdit._proj_hack[0] # TODO, deal with this nicer image = bpy.data.images.get((image_name, None)) if image is None: - self.report({'ERROR'}, rpt_("Could not find image '%s'") % image_name) + self.report({'ERROR'}, rpt_("Could not find image '{!s}'").format(image_name)) return {'CANCELLED'} image.reload() @@ -289,7 +290,7 @@ class IMAGE_OT_open_images(Operator): ) is_tiled = context.edit_image.source == 'TILED' if len(files) > 1 and self.use_sequence_detection and not is_tiled: - context.edit_image.name = "%s%s%s" % (seq["prefix"], ("#" * seq["frame_size"]), seq["ext"]) + context.edit_image.name = "{!s}{!s}{!s}".format(seq["prefix"], ("#" * seq["frame_size"]), seq["ext"]) return {'FINISHED'} diff --git a/scripts/startup/bl_operators/mesh.py b/scripts/startup/bl_operators/mesh.py index 5058b91ad3e..75317cb9aa5 100644 --- a/scripts/startup/bl_operators/mesh.py +++ b/scripts/startup/bl_operators/mesh.py @@ -168,18 +168,25 @@ class MeshMirrorUV(Operator): bpy.ops.object.mode_set(mode='EDIT', toggle=False) if total_duplicates and total_no_active_UV: - self.report({'WARNING'}, - rpt_("%d mesh(es) with no active UV layer, " - "%d duplicates found in %d mesh(es), mirror may be incomplete") - % (total_no_active_UV, total_duplicates, meshes_with_duplicates)) + self.report( + {'WARNING'}, + rpt_( + "{:d} mesh(es) with no active UV layer, " + "{:d} duplicates found in {:d} mesh(es), mirror may be incomplete" + ).format(total_no_active_UV, total_duplicates, meshes_with_duplicates), + ) elif total_no_active_UV: - self.report({'WARNING'}, - rpt_("%d mesh(es) with no active UV layer") - % (total_no_active_UV,)) + self.report( + {'WARNING'}, + rpt_("{:d} mesh(es) with no active UV layer").format(total_no_active_UV), + ) elif total_duplicates: - self.report({'WARNING'}, - rpt_("%d duplicates found in %d mesh(es), mirror may be incomplete") - % (total_duplicates, meshes_with_duplicates)) + self.report( + {'WARNING'}, + rpt_( + "{:d} duplicates found in {:d} mesh(es), mirror may be incomplete" + ).format(total_duplicates, meshes_with_duplicates), + ) return {'FINISHED'} diff --git a/scripts/startup/bl_operators/node.py b/scripts/startup/bl_operators/node.py index ce8d5576e28..22bc86575b8 100644 --- a/scripts/startup/bl_operators/node.py +++ b/scripts/startup/bl_operators/node.py @@ -98,7 +98,7 @@ class NodeAddOperator: except AttributeError as ex: self.report( {'ERROR_INVALID_INPUT'}, - rpt_("Node has no attribute %s") % setting.name) + rpt_("Node has no attribute {!s}").format(setting.name)) print(str(ex)) # Continue despite invalid attribute diff --git a/scripts/startup/bl_operators/object.py b/scripts/startup/bl_operators/object.py index b3f2e162295..0a78eec23af 100644 --- a/scripts/startup/bl_operators/object.py +++ b/scripts/startup/bl_operators/object.py @@ -364,12 +364,12 @@ class ShapeTransfer(Operator): for ob_other in objects: if ob_other.type != 'MESH': self.report({'WARNING'}, - rpt_("Skipping '%s', not a mesh") % ob_other.name) + rpt_("Skipping '{!s}', not a mesh").format(ob_other.name)) continue me_other = ob_other.data if len(me_other.vertices) != len(me.vertices): self.report({'WARNING'}, - rpt_("Skipping '%s', vertex count differs") % ob_other.name) + rpt_("Skipping '{!s}', vertex count differs").format(ob_other.name)) continue target_normals = me_nos(me_other.vertices) @@ -506,9 +506,10 @@ class JoinUVs(Operator): bpy.ops.object.mode_set(mode='OBJECT', toggle=False) if not mesh.uv_layers: - self.report({'WARNING'}, - rpt_("Object: %s, Mesh: '%s' has no UVs") - % (obj.name, mesh.name)) + self.report( + {'WARNING'}, + rpt_("Object: {!s}, Mesh: '{!s}' has no UVs").format(obj.name, mesh.name), + ) else: nbr_loops = len(mesh.loops) @@ -530,31 +531,33 @@ class JoinUVs(Operator): mesh_other.tag = True if len(mesh_other.loops) != nbr_loops: - self.report({'WARNING'}, - rpt_("Object: %s, Mesh: " - "'%s' has %d loops (for %d faces)," - " expected %d\n") - % (obj_other.name, - mesh_other.name, - len(mesh_other.loops), - len(mesh_other.polygons), - nbr_loops, - ), - ) + self.report( + {'WARNING'}, + rpt_( + "Object: {!s}, Mesh: '{!s}' has {:d} loops (for {:d} faces), expected {:d}\n" + ).format( + obj_other.name, + mesh_other.name, + len(mesh_other.loops), + len(mesh_other.polygons), + nbr_loops, + ), + ) else: uv_other = mesh_other.uv_layers.active if not uv_other: mesh_other.uv_layers.new() uv_other = mesh_other.uv_layers.active if not uv_other: - self.report({'ERROR'}, - rpt_("Could not add " - "a new UV map to object " - "'%s' (Mesh '%s')\n") - % (obj_other.name, - mesh_other.name, - ), - ) + self.report( + {'ERROR'}, + rpt_( + "Could not add a new UV map to object '{!s}' (Mesh '{!s}')\n" + ).format( + obj_other.name, + mesh_other.name, + ), + ) # finally do the copy uv_other.data.foreach_set("uv", uv_array) @@ -790,9 +793,10 @@ class TransformsToDeltasAnim(Operator): for obj in context.selected_editable_objects: adt = obj.animation_data if (adt is None) or (adt.action is None): - self.report({'WARNING'}, - rpt_("No animation data to convert on object: %r") - % obj.name) + self.report( + {'WARNING'}, + rpt_("No animation data to convert on object: {!r}").format(obj.name), + ) continue # first pass over F-Curves: ensure that we don't have conflicting @@ -818,9 +822,8 @@ class TransformsToDeltasAnim(Operator): if fcu.array_index in existingFCurves[dpath]: # conflict self.report({'ERROR'}, - rpt_("Object %r already has %r F-Curve(s). " - "Remove these before trying again") % - (obj.name, dpath)) + rpt_("Object {!r} already has {!r} F-Curve(s). " + "Remove these before trying again").format(obj.name, dpath)) return {'CANCELLED'} else: # no conflict here diff --git a/scripts/startup/bl_operators/object_quick_effects.py b/scripts/startup/bl_operators/object_quick_effects.py index 51d0f651a5e..ac99e6265b8 100644 --- a/scripts/startup/bl_operators/object_quick_effects.py +++ b/scripts/startup/bl_operators/object_quick_effects.py @@ -277,7 +277,7 @@ class QuickExplode(ObjectModeOperator, Operator): for obj in mesh_objects: if obj.particle_systems: - self.report({'ERROR'}, rpt_("Object %r already has a " "particle system") % obj.name) + self.report({'ERROR'}, rpt_("Object {!r} already has a particle system").format(obj.name)) return {'CANCELLED'} diff --git a/scripts/startup/bl_operators/presets.py b/scripts/startup/bl_operators/presets.py index d70f547bee0..c6e6167d737 100644 --- a/scripts/startup/bl_operators/presets.py +++ b/scripts/startup/bl_operators/presets.py @@ -137,7 +137,7 @@ class AddPresetBase: if hasattr(self, "add"): self.add(context, filepath) else: - print("Writing Preset: %r" % filepath) + print("Writing Preset: {!r}".format(filepath)) if is_xml: import rna_xml @@ -150,12 +150,16 @@ class AddPresetBase: if sub_value_attr == "rna_type": continue sub_value = getattr(value, sub_value_attr) - rna_recursive_attr_expand(sub_value, "%s.%s" % (rna_path_step, sub_value_attr), level) + rna_recursive_attr_expand( + sub_value, + "{!s}.{!s}".format(rna_path_step, sub_value_attr), + level, + ) elif type(value).__name__ == "bpy_prop_collection_idprop": # could use nicer method - file_preset.write("%s.clear()\n" % rna_path_step) + file_preset.write("{!s}.clear()\n".format(rna_path_step)) for sub_value in value: - file_preset.write("item_sub_%d = %s.add()\n" % (level, rna_path_step)) - rna_recursive_attr_expand(sub_value, "item_sub_%d" % level, level + 1) + file_preset.write("item_sub_{:d} = {!s}.add()\n".format(level, rna_path_step)) + rna_recursive_attr_expand(sub_value, "item_sub_{:d}".format(level), level + 1) else: # convert thin wrapped sequences # to simple lists to repr() @@ -164,7 +168,7 @@ class AddPresetBase: except BaseException: pass - file_preset.write("%s = %r\n" % (rna_path_step, value)) + file_preset.write("{!s} = {!r}\n".format(rna_path_step, value)) file_preset = open(filepath, "w", encoding="utf-8") file_preset.write("import bpy\n") @@ -172,7 +176,7 @@ class AddPresetBase: if hasattr(self, "preset_defines"): for rna_path in self.preset_defines: exec(rna_path) - file_preset.write("%s\n" % rna_path) + file_preset.write("{!s}\n".format(rna_path)) file_preset.write("\n") for rna_path in self.preset_values: @@ -207,7 +211,7 @@ class AddPresetBase: else: os.remove(filepath) except BaseException as ex: - self.report({'ERROR'}, rpt_("Unable to remove preset: %r") % ex) + self.report({'ERROR'}, rpt_("Unable to remove preset: {!r}").format(ex)) import traceback traceback.print_exc() return {'CANCELLED'} @@ -257,7 +261,7 @@ class ExecutePreset(Operator): ext = splitext(filepath)[1].lower() if ext not in {".py", ".xml"}: - self.report({'ERROR'}, rpt_("Unknown file type: %r") % ext) + self.report({'ERROR'}, rpt_("Unknown file type: {!r}").format(ext)) return {'CANCELLED'} _call_preset_cb(getattr(preset_class, "reset_cb", None), context, filepath) @@ -648,7 +652,7 @@ class SavePresetInterfaceTheme(AddPresetBase, Operator): try: rna_xml.xml_file_write(context, filepath, preset_menu_class.preset_xml_map) except BaseException as ex: - self.report({'ERROR'}, "Unable to overwrite preset: %s" % str(ex)) + self.report({'ERROR'}, "Unable to overwrite preset: {!s}".format(str(ex))) import traceback traceback.print_exc() return {'CANCELLED'} @@ -744,7 +748,7 @@ class AddPresetOperator(AddPresetBase, Operator): for prop_id, prop in operator_rna.properties.items(): if not prop.is_skip_preset: if prop_id not in properties_blacklist: - ret.append("op.%s" % prop_id) + ret.append("op.{!s}".format(prop_id)) return ret @@ -752,7 +756,7 @@ class AddPresetOperator(AddPresetBase, Operator): def operator_path(operator): import os prefix, suffix = operator.split("_OT_", 1) - return os.path.join("operator", "%s.%s" % (prefix.lower(), suffix)) + return os.path.join("operator", "{!s}.{!s}".format(prefix.lower(), suffix)) class WM_MT_operator_presets(Menu): diff --git a/scripts/startup/bl_operators/screen_play_rendered_anim.py b/scripts/startup/bl_operators/screen_play_rendered_anim.py index c81ce02a12d..057ab4af7f0 100644 --- a/scripts/startup/bl_operators/screen_play_rendered_anim.py +++ b/scripts/startup/bl_operators/screen_play_rendered_anim.py @@ -119,7 +119,7 @@ class PlayRenderedAnim(Operator): file = rd.frame_path(frame=scene.frame_start, preview=scene.use_preview_range, view=view_suffix) file = bpy.path.abspath(file) # expand '//' if not os.path.exists(file): - err_msg = rpt_("File %r not found") % file + err_msg = rpt_("File {!r} not found").format(file) self.report({'WARNING'}, err_msg) path_valid = False @@ -127,7 +127,7 @@ class PlayRenderedAnim(Operator): if scene.use_preview_range and not path_valid: file = rd.frame_path(frame=scene.frame_start, preview=False, view=view_suffix) file = bpy.path.abspath(file) # expand '//' - err_msg = rpt_("File %r not found") % file + err_msg = rpt_("File {!r} not found").format(file) if not os.path.exists(file): self.report({'WARNING'}, err_msg) @@ -160,14 +160,14 @@ class PlayRenderedAnim(Operator): ] cmd.extend(opts) elif preset == 'FRAMECYCLER': - opts = [file, "%d-%d" % (scene.frame_start, scene.frame_end)] + opts = [file, "{:d}-{:d}".format(scene.frame_start, scene.frame_end)] cmd.extend(opts) elif preset == 'RV': opts = ["-fps", str(rd.fps), "-play"] if scene.use_preview_range: opts += [ file.replace("#", "", file.count('#') - 1), - "%d-%d" % (frame_start, frame_end), + "{:d}-{:d}".format(frame_start, frame_end), ] else: opts.append(file) @@ -181,7 +181,7 @@ class PlayRenderedAnim(Operator): opts += [ ("mf://" + file.replace("#", "?")), "-mf", - "fps=%.4f" % fps_final, + "fps={:.4f}".format(fps_final), ] opts += ["-loop", "0", "-really-quiet", "-fs"] @@ -195,7 +195,7 @@ class PlayRenderedAnim(Operator): try: subprocess.Popen(cmd) except BaseException as ex: - err_msg = rpt_("Couldn't run external animation player with command %r\n%s") % (cmd, ex) + err_msg = rpt_("Couldn't run external animation player with command {!r}\n{!s}").format(cmd, str(ex)) self.report( {'ERROR'}, err_msg, diff --git a/scripts/startup/bl_operators/sequencer.py b/scripts/startup/bl_operators/sequencer.py index 63c7f943457..a45fa61c432 100644 --- a/scripts/startup/bl_operators/sequencer.py +++ b/scripts/startup/bl_operators/sequencer.py @@ -236,7 +236,7 @@ class SequencerFadesAdd(Operator): sequence.invalidate_cache('COMPOSITE') sequence_string = "sequence" if len(faded_sequences) == 1 else "sequences" - self.report({'INFO'}, rpt_("Added fade animation to %d %s") % (len(faded_sequences), sequence_string)) + self.report({'INFO'}, rpt_("Added fade animation to {:d} {!s}").format(len(faded_sequences), sequence_string)) return {'FINISHED'} def calculate_fade_duration(self, context, sequence): @@ -366,7 +366,7 @@ class Fade: return max_value if max_value > 0.0 else 1.0 def __repr__(self): - return "Fade %r: %r to %r" % (self.type, self.start, self.end) + return "Fade {!r}: {!r} to {!r}".format(self.type, self.start, self.end) def calculate_duration_frames(scene, duration_seconds): diff --git a/scripts/startup/bl_operators/userpref.py b/scripts/startup/bl_operators/userpref.py index 89ac410b0f7..3962810a4ec 100644 --- a/scripts/startup/bl_operators/userpref.py +++ b/scripts/startup/bl_operators/userpref.py @@ -231,7 +231,7 @@ class PREFERENCES_OT_keyconfig_import(Operator): else: shutil.move(self.filepath, path) except BaseException as ex: - self.report({'ERROR'}, rpt_("Installing keymap failed: %s") % ex) + self.report({'ERROR'}, rpt_("Installing keymap failed: {!s}").format(str(ex))) return {'CANCELLED'} # sneaky way to check we're actually running the code. @@ -461,11 +461,12 @@ class PREFERENCES_OT_addon_enable(Operator): if info_ver > bpy.app.version: self.report( {'WARNING'}, - rpt_("This script was written Blender " - "version %d.%d.%d and might not " - "function (correctly), " - "though it is enabled") - % info_ver + rpt_( + "This script was written Blender " + "version {:d}.{:d}.{:d} and might not " + "function (correctly), " + "though it is enabled" + ).format(info_ver) ) return {'FINISHED'} else: @@ -549,7 +550,7 @@ class PREFERENCES_OT_theme_install(Operator): if not self.overwrite: if os.path.exists(path_dest): - self.report({'WARNING'}, rpt_("File already installed to %r\n") % path_dest) + self.report({'WARNING'}, rpt_("File already installed to {!r}\n").format(path_dest)) return {'CANCELLED'} try: @@ -669,7 +670,7 @@ class PREFERENCES_OT_addon_install(Operator): pyfile_dir = os.path.dirname(pyfile) for addon_path in addon_utils.paths(): if os.path.samefile(pyfile_dir, addon_path): - self.report({'ERROR'}, rpt_("Source file is in the add-on search path: %r") % addon_path) + self.report({'ERROR'}, rpt_("Source file is in the add-on search path: {!r}").format(addon_path)) return {'CANCELLED'} del addon_path del pyfile_dir @@ -700,7 +701,7 @@ class PREFERENCES_OT_addon_install(Operator): for f in file_to_extract_root: path_dest = os.path.join(path_addons, os.path.basename(f)) if os.path.exists(path_dest): - self.report({'WARNING'}, rpt_("File already installed to %r\n") % path_dest) + self.report({'WARNING'}, rpt_("File already installed to {!r}\n").format(path_dest)) return {'CANCELLED'} try: # extract the file to "addons" @@ -715,7 +716,7 @@ class PREFERENCES_OT_addon_install(Operator): if self.overwrite: _module_filesystem_remove(path_addons, os.path.basename(pyfile)) elif os.path.exists(path_dest): - self.report({'WARNING'}, rpt_("File already installed to %r\n") % path_dest) + self.report({'WARNING'}, rpt_("File already installed to {!r}\n").format(path_dest)) return {'CANCELLED'} # if not compressed file just copy into the addon path @@ -749,10 +750,10 @@ class PREFERENCES_OT_addon_install(Operator): bpy.utils.refresh_script_paths() # print message - msg = ( - rpt_("Modules Installed (%s) from %r into %r") % - (", ".join(sorted(addons_new)), pyfile, path_addons) + msg = rpt_("Modules Installed ({!s}) from {!r} into {!r}").format( + ", ".join(sorted(addons_new)), pyfile, path_addons, ) + print(msg) self.report({'INFO'}, msg) @@ -795,7 +796,7 @@ class PREFERENCES_OT_addon_remove(Operator): path, isdir = PREFERENCES_OT_addon_remove.path_from_addon(self.module) if path is None: - self.report({'WARNING'}, rpt_("Add-on path %r could not be found") % path) + self.report({'WARNING'}, rpt_("Add-on path {!r} could not be found").format(path)) return {'CANCELLED'} # in case its enabled @@ -814,9 +815,9 @@ class PREFERENCES_OT_addon_remove(Operator): # lame confirmation check def draw(self, _context): - self.layout.label(text=iface_("Remove Add-on: %r?") % self.module, translate=False) + self.layout.label(text=iface_("Remove Add-on: {!r}?").format(self.module), translate=False) path, _isdir = PREFERENCES_OT_addon_remove.path_from_addon(self.module) - self.layout.label(text=iface_("Path: %r") % path, translate=False) + self.layout.label(text=iface_("Path: {!r}").format(path), translate=False) def invoke(self, context, _event): wm = context.window_manager @@ -945,7 +946,7 @@ class PREFERENCES_OT_app_template_install(Operator): for f in file_to_extract_root: path_dest = os.path.join(path_app_templates, os.path.basename(f)) if os.path.exists(path_dest): - self.report({'WARNING'}, rpt_("File already installed to %r\n") % path_dest) + self.report({'WARNING'}, rpt_("File already installed to {!r}\n").format(path_dest)) return {'CANCELLED'} try: # extract the file to "bl_app_templates_user" @@ -956,7 +957,7 @@ class PREFERENCES_OT_app_template_install(Operator): else: # Only support installing zip-files. - self.report({'WARNING'}, rpt_("Expected a zip-file %r\n") % filepath) + self.report({'WARNING'}, rpt_("Expected a zip-file {!r}\n").format(filepath)) return {'CANCELLED'} app_templates_new = set(os.listdir(path_app_templates)) - app_templates_old @@ -965,10 +966,12 @@ class PREFERENCES_OT_app_template_install(Operator): bpy.utils.refresh_script_paths() # print message - msg = ( - rpt_("Template Installed (%s) from %r into %r") % - (", ".join(sorted(app_templates_new)), filepath, path_app_templates) + msg = rpt_("Template Installed ({!s}) from {!r} into {!r}").format( + ", ".join(sorted(app_templates_new)), + filepath, + path_app_templates, ) + print(msg) self.report({'INFO'}, msg) @@ -1029,9 +1032,9 @@ class PREFERENCES_OT_studiolight_install(Operator): prefs.studio_lights.load(os.path.join(path_studiolights, e.name), self.type) # print message - msg = ( - rpt_("StudioLight Installed %r into %r") % - (", ".join(e.name for e in self.files), path_studiolights) + msg = rpt_("StudioLight Installed {!r} into {!r}").format( + ", ".join(e.name for e in self.files), + path_studiolights ) print(msg) self.report({'INFO'}, msg) @@ -1087,10 +1090,7 @@ class PREFERENCES_OT_studiolight_new(Operator): prefs.studio_lights.new(path=filepath_final) # print message - msg = ( - rpt_("StudioLight Installed %r into %r") % - (self.filename, str(path_studiolights)) - ) + msg = rpt_("StudioLight Installed {!r} into {!r}").format(self.filename, str(path_studiolights)) print(msg) self.report({'INFO'}, msg) return {'FINISHED'} diff --git a/scripts/startup/bl_operators/uvcalc_lightmap.py b/scripts/startup/bl_operators/uvcalc_lightmap.py index 7d49e2408d8..56be0a1e640 100644 --- a/scripts/startup/bl_operators/uvcalc_lightmap.py +++ b/scripts/startup/bl_operators/uvcalc_lightmap.py @@ -551,7 +551,7 @@ def lightmap_uvpack( for me in meshes: me.update() - print("finished all %.2f " % (time.time() - t)) + print("finished all {:.2f} ".format(time.time() - t)) def unwrap(operator, context, **kwargs): diff --git a/scripts/startup/bl_operators/wm.py b/scripts/startup/bl_operators/wm.py index 96c461229a1..baf64055190 100644 --- a/scripts/startup/bl_operators/wm.py +++ b/scripts/startup/bl_operators/wm.py @@ -131,7 +131,7 @@ rna_module_prop = StringProperty( def context_path_validate(context, data_path): try: - value = eval("context.%s" % data_path) if data_path else Ellipsis + value = eval("context.{!s}".format(data_path)) if data_path else Ellipsis except AttributeError as ex: if str(ex).startswith("'NoneType'"): # One of the items in the rna path is None, just ignore this @@ -139,7 +139,7 @@ def context_path_validate(context, data_path): else: # Print invalid path, but don't show error to the users and fully # break the UI if the operator is bound to an event like left click. - print("context_path_validate error: context.%s not found (invalid keymap entry?)" % data_path) + print("context_path_validate error: context.{!s} not found (invalid keymap entry?)".format(data_path)) value = Ellipsis return value @@ -208,9 +208,9 @@ def description_from_data_path(base, data_path, *, prefix, value=Ellipsis): (rna_prop := context_path_to_rna_property(base, data_path)) and (description := iface_(rna_prop.description)) ): - description = iface_("%s: %s") % (prefix, description) + description = iface_("{!s}: {!s}").format(prefix, description) if value != Ellipsis: - description = "%s\n%s: %s" % (description, iface_("Value"), str(value)) + description = "{!s}\n{!s}: {!s}".format(description, iface_("Value"), str(value)) return description return None @@ -265,9 +265,9 @@ def execute_context_assign(self, context): return {'PASS_THROUGH'} if getattr(self, "relative", False): - exec("context.%s += self.value" % data_path) + exec("context.{!s} += self.value".format(data_path)) else: - exec("context.%s = self.value" % data_path) + exec("context.{!s} = self.value".format(data_path)) return operator_path_undo_return(context, data_path) @@ -340,7 +340,7 @@ class WM_OT_context_scale_float(Operator): if value == 1.0: # nothing to do return {'CANCELLED'} - exec("context.%s *= value" % data_path) + exec("context.{!s} *= value".format(data_path)) return operator_path_undo_return(context, data_path) @@ -385,10 +385,11 @@ class WM_OT_context_scale_int(Operator): else: add = "-1" func = "min" - exec("context.%s = %s(round(context.%s * value), context.%s + %s)" % - (data_path, func, data_path, data_path, add)) + exec("context.{!s} = {!s}(round(context.{!s} * value), context.{!s} + {!s})".format( + data_path, func, data_path, data_path, add, + )) else: - exec("context.%s *= value" % data_path) + exec("context.{!s} *= value".format(data_path)) return operator_path_undo_return(context, data_path) @@ -475,7 +476,7 @@ class WM_OT_context_set_value(Operator): data_path = self.data_path if context_path_validate(context, data_path) is Ellipsis: return {'PASS_THROUGH'} - exec("context.%s = %s" % (data_path, self.value)) + exec("context.{!s} = {!s}".format(data_path, self.value)) return operator_path_undo_return(context, data_path) @@ -508,7 +509,7 @@ class WM_OT_context_toggle(Operator): if context_path_validate(base, data_path) is Ellipsis: return {'PASS_THROUGH'} - exec("base.%s = not (base.%s)" % (data_path, data_path)) + exec("base.{!s} = not (base.{!s})".format(data_path, data_path)) return operator_path_undo_return(base, data_path) @@ -533,7 +534,7 @@ class WM_OT_context_toggle_enum(Operator): @classmethod def description(cls, context, props): - value = "(%r, %r)" % (props.value_1, props.value_2) + value = "({!r}, {!r})".format(props.value_1, props.value_2) return description_from_data_path(context, props.data_path, prefix=iface_("Toggle"), value=value) def execute(self, context): @@ -546,7 +547,7 @@ class WM_OT_context_toggle_enum(Operator): # keys that some values that are only available in a particular context try: exec( - "context.%s = %r if (context.%s != %r) else %r" % ( + "context.{!s} = {!r} if (context.{!s} != {!r}) else {!r}".format( data_path, self.value_2, data_path, @@ -586,17 +587,17 @@ class WM_OT_context_cycle_int(Operator): else: value += 1 - exec("context.%s = value" % data_path) + exec("context.{!s} = value".format(data_path)) if self.wrap: - if value != eval("context.%s" % data_path): + if value != eval("context.{!s}".format(data_path)): # relies on rna clamping integers out of the range if self.reverse: value = (1 << 31) - 1 else: value = -1 << 31 - exec("context.%s = value" % data_path) + exec("context.{!s} = value".format(data_path)) return operator_path_undo_return(context, data_path) @@ -646,7 +647,7 @@ class WM_OT_context_cycle_enum(Operator): advance_enum = enums[orig_index + 1] # set the new value - exec("context.%s = advance_enum" % data_path) + exec("context.{!s} = advance_enum".format(data_path)) return operator_path_undo_return(context, data_path) @@ -677,7 +678,7 @@ class WM_OT_context_cycle_array(Operator): array.append(array.pop(0)) return array - exec("context.%s = cycle(context.%s[:])" % (data_path, data_path)) + exec("context.{!s} = cycle(context.{!s}[:])".format(data_path, data_path)) return operator_path_undo_return(context, data_path) @@ -779,7 +780,7 @@ class WM_OT_operator_pie_enum(Operator): try: op_rna = op.get_rna_type() except KeyError: - self.report({'ERROR'}, rpt_("Operator not found: bpy.ops.%s") % data_path) + self.report({'ERROR'}, rpt_("Operator not found: bpy.ops.{!s}").format(data_path)) return {'CANCELLED'} def draw_cb(self, context): @@ -825,7 +826,7 @@ class WM_OT_context_set_id(Operator): if id_iter: value_id = getattr(bpy.data, id_iter).get(value) - exec("context.%s = value_id" % data_path) + exec("context.{!s} = value_id".format(data_path)) return operator_path_undo_return(context, data_path) @@ -879,8 +880,10 @@ class WM_OT_context_collection_boolean_set(Operator): elif value_orig is False: pass else: - self.report({'WARNING'}, rpt_("Non boolean value found: %s[ ].%s") % - (data_path_iter, data_path_item)) + self.report( + {'WARNING'}, + rpt_("Non boolean value found: {!s}[ ].{!s}").format(data_path_iter, data_path_item), + ) return {'CANCELLED'} items_ok.append(item) @@ -896,7 +899,7 @@ class WM_OT_context_collection_boolean_set(Operator): else: is_set = not is_set - exec_str = "item.%s = %s" % (data_path_item, is_set) + exec_str = "item.{!s} = {!s}".format(data_path_item, is_set) for item in items_ok: exec(exec_str) @@ -942,7 +945,7 @@ class WM_OT_context_modal_mouse(Operator): # check this can be set, maybe this is library data. try: - exec("item.%s = %s" % (data_path_item, value_orig)) + exec("item.{!s} = {!s}".format(data_path_item, value_orig)) except BaseException: continue @@ -956,14 +959,14 @@ class WM_OT_context_modal_mouse(Operator): data_path_item = self.data_path_item for item, value_orig in self._values.items(): if type(value_orig) == int: - exec("item.%s = int(%d)" % (data_path_item, round(value_orig + delta))) + exec("item.{!s} = int({:d})".format(data_path_item, round(value_orig + delta))) else: - exec("item.%s = %f" % (data_path_item, value_orig + delta)) + exec("item.{!s} = {:f}".format(data_path_item, value_orig + delta)) def _values_restore(self): data_path_item = self.data_path_item for item, value_orig in self._values.items(): - exec("item.%s = %s" % (data_path_item, value_orig)) + exec("item.{!s} = {!s}".format(data_path_item, value_orig)) self._values.clear() @@ -980,7 +983,7 @@ class WM_OT_context_modal_mouse(Operator): if header_text: if len(self._values) == 1: (item, ) = self._values.keys() - header_text = header_text % eval("item.%s" % self.data_path_item) + header_text = header_text % eval("item.{!s}".format(self.data_path_item)) else: header_text = (self.header_text % delta) + rpt_(" (delta)") context.area.header_text_set(header_text) @@ -1002,9 +1005,12 @@ class WM_OT_context_modal_mouse(Operator): self._values_store(context) if not self._values: - self.report({'WARNING'}, rpt_("Nothing to operate on: %s[ ].%s") % - (self.data_path_iter, self.data_path_item)) - + self.report( + {'WARNING'}, + rpt_("Nothing to operate on: {!s}[ ].{!s}").format( + self.data_path_iter, self.data_path_item, + ), + ) return {'CANCELLED'} else: self.initial_x = event.mouse_x @@ -1091,13 +1097,15 @@ class WM_OT_url_open_preset(Operator): return url_prefill_from_blender(addon_info=self.id) def _url_from_release_notes(self, _context): - return "https://www.blender.org/download/releases/%d-%d/" % bpy.app.version[:2] + return "https://www.blender.org/download/releases/{:d}-{:d}/".format(*bpy.app.version[:2]) def _url_from_manual(self, _context): - return "https://docs.blender.org/manual/%s/%d.%d/" % (bpy.utils.manual_language_code(), *bpy.app.version[:2]) + return "https://docs.blender.org/manual/{!s}/{:d}.{:d}/".format( + bpy.utils.manual_language_code(), *bpy.app.version[:2], + ) def _url_from_api(self, _context): - return "https://docs.blender.org/api/%d.%d/" % bpy.app.version[:2] + return "https://docs.blender.org/api/{:d}.{:d}/".format(*bpy.app.version[:2]) # This list is: (enum_item, url) pairs. # Allow dynamically extending. @@ -1169,7 +1177,7 @@ class WM_OT_path_open(Operator): filepath = os.path.normpath(filepath) if not os.path.exists(filepath): - self.report({'ERROR'}, rpt_("File '%s' not found") % filepath) + self.report({'ERROR'}, rpt_("File '{!s}' not found").format(filepath)) return {'CANCELLED'} if sys.platform[:3] == "win": @@ -1202,9 +1210,9 @@ def _wm_doc_get_id(doc_id, *, do_url=True, url_prefix="", report=None): if len(id_split) == 1: # rna, class if do_url: - url = "%s/bpy.types.%s.html" % (url_prefix, id_split[0]) + url = "{!s}/bpy.types.{!s}.html".format(url_prefix, id_split[0]) else: - rna = "bpy.types.%s" % id_split[0] + rna = "bpy.types.{!s}".format(id_split[0]) elif len(id_split) == 2: # rna, class.prop class_name, class_prop = id_split @@ -1212,23 +1220,17 @@ def _wm_doc_get_id(doc_id, *, do_url=True, url_prefix="", report=None): # an operator (common case - just button referencing an op) if operator_exists_pair(class_name, class_prop): if do_url: - url = ( - "%s/bpy.ops.%s.html#bpy.ops.%s.%s" % - (url_prefix, class_name, class_name, class_prop) - ) + url = "{!s}/bpy.ops.{!s}.html#bpy.ops.{!s}.{!s}".format(url_prefix, class_name, class_name, class_prop) else: - rna = "bpy.ops.%s.%s" % (class_name, class_prop) + rna = "bpy.ops.{!s}.{!s}".format(class_name, class_prop) elif operator_exists_single(class_name): # note: ignore the prop name since we don't have a way to link into it class_name, class_prop = class_name.split("_OT_", 1) class_name = class_name.lower() if do_url: - url = ( - "%s/bpy.ops.%s.html#bpy.ops.%s.%s" % - (url_prefix, class_name, class_name, class_prop) - ) + url = "{!s}/bpy.ops.{!s}.html#bpy.ops.{!s}.{!s}".format(url_prefix, class_name, class_name, class_prop) else: - rna = "bpy.ops.%s.%s" % (class_name, class_prop) + rna = "bpy.ops.{!s}.{!s}".format(class_name, class_prop) else: # An RNA setting, common case. @@ -1240,7 +1242,7 @@ def _wm_doc_get_id(doc_id, *, do_url=True, url_prefix="", report=None): if rna_class is None: if report is not None: - report({'ERROR'}, rpt_("Type \"%s\" cannot be found") % class_name) + report({'ERROR'}, rpt_("Type \"{!s}\" cannot be found").format(class_name)) return None # Detect if this is a inherited member and use that name instead. @@ -1253,16 +1255,15 @@ def _wm_doc_get_id(doc_id, *, do_url=True, url_prefix="", report=None): rna_parent = rna_parent.base if do_url: - url = ( - "%s/bpy.types.%s.html#bpy.types.%s.%s" % - (url_prefix, class_name, class_name, class_prop) + url = "{!s}/bpy.types.{!s}.html#bpy.types.{!s}.{!s}".format( + url_prefix, class_name, class_name, class_prop, ) else: - rna = "bpy.types.%s.%s" % (class_name, class_prop) + rna = "bpy.types.{!s}.{!s}".format(class_name, class_prop) else: # We assume this is custom property, only try to generate generic url/rna_id... if do_url: - url = ("%s/bpy.types.bpy_struct.html#bpy.types.bpy_struct.items" % (url_prefix,)) + url = ("{!s}/bpy.types.bpy_struct.html#bpy.types.bpy_struct.items".format(url_prefix)) else: rna = "bpy.types.bpy_struct" @@ -1279,7 +1280,7 @@ class WM_OT_doc_view_manual(Operator): @staticmethod def _find_reference(rna_id, url_mapping, *, verbose=True): if verbose: - print("online manual check for: '%s'... " % rna_id) + print("online manual check for: '{!s}'... ".format(rna_id)) from fnmatch import fnmatchcase # XXX, for some reason all RNA ID's are stored lowercase # Adding case into all ID's isn't worth the hassle so force lowercase. @@ -1311,7 +1312,7 @@ class WM_OT_doc_view_manual(Operator): if fnmatchcase(rna_id, pattern): if verbose: - print(" match found: '%s' --> '%s'" % (pattern, url_suffix)) + print(" match found: '{!s}' --> '{!s}'".format(pattern, url_suffix)) return url_suffix if verbose: print("match not found") @@ -1335,10 +1336,9 @@ class WM_OT_doc_view_manual(Operator): if url is None: self.report( {'WARNING'}, - rpt_("No reference available %r, " + rpt_("No reference available {!r}, " "Update info in 'rna_manual_reference.py' " - "or callback to bpy.utils.manual_map()") % - self.doc_id + "or callback to bpy.utils.manual_map()").format(self.doc_id) ) return {'CANCELLED'} else: @@ -1351,7 +1351,7 @@ class WM_OT_doc_view(Operator): bl_label = "View Documentation" doc_id: doc_id - _prefix = "https://docs.blender.org/api/%d.%d" % bpy.app.version[:2] + _prefix = "https://docs.blender.org/api/{:d}.{:d}".format(*bpy.app.version[:2]) def execute(self, _context): url = _wm_doc_get_id(self.doc_id, do_url=True, url_prefix=self._prefix, report=self.report) @@ -1703,7 +1703,7 @@ class WM_OT_properties_edit(Operator): self._init_subtype(self.subtype) escaped_name = bpy.utils.escape_identifier(name) - self.is_overridable_library = bool(item.is_property_overridable_library('["%s"]' % escaped_name)) + self.is_overridable_library = bool(item.is_property_overridable_library('["{!s}"]'.format(escaped_name))) # When the operator chooses a different type than the original property, # attempt to convert the old value to the new type for continuity and speed. @@ -1807,7 +1807,7 @@ class WM_OT_properties_edit(Operator): ) escaped_name = bpy.utils.escape_identifier(name) - item.property_overridable_library_set('["%s"]' % escaped_name, self.is_overridable_library) + item.property_overridable_library_set('["{!s}"]'.format(escaped_name), self.is_overridable_library) def _update_blender_for_prop_change(self, context, item, name, prop_type_old, prop_type_new): from rna_prop_ui import ( @@ -1819,7 +1819,7 @@ class WM_OT_properties_edit(Operator): # If we have changed the type of the property, update its potential anim curves! if prop_type_old != prop_type_new: escaped_name = bpy.utils.escape_identifier(name) - data_path = '["%s"]' % escaped_name + data_path = '["{!s}"]'.format(escaped_name) done = set() def _update(fcurves): @@ -1859,7 +1859,7 @@ class WM_OT_properties_edit(Operator): data_path = self.data_path name = self.property_name - item = eval("context.%s" % data_path) + item = eval("context.{!s}".format(data_path)) if (item.id_data and item.id_data.override_library and item.id_data.override_library.reference): self.report({'ERROR'}, "Cannot edit properties from override data") return {'CANCELLED'} @@ -1905,7 +1905,7 @@ class WM_OT_properties_edit(Operator): self._old_prop_name = [name] - item = eval("context.%s" % data_path) + item = eval("context.{!s}".format(data_path)) if (item.id_data and item.id_data.override_library and item.id_data.override_library.reference): self.report({'ERROR'}, "Properties from override data cannot be edited") return {'CANCELLED'} @@ -2071,7 +2071,7 @@ class WM_OT_properties_edit_value(Operator): def execute(self, context): if self.eval_string: - rna_item = eval("context.%s" % self.data_path) + rna_item = eval("context.{!s}".format(self.data_path)) try: new_value = eval(self.eval_string) except BaseException as ex: @@ -2081,7 +2081,7 @@ class WM_OT_properties_edit_value(Operator): return {'FINISHED'} def invoke(self, context, _event): - rna_item = eval("context.%s" % self.data_path) + rna_item = eval("context.{!s}".format(self.data_path)) if WM_OT_properties_edit.get_property_type(rna_item, self.property_name) == 'PYTHON': self.eval_string = WM_OT_properties_edit.convert_custom_property_to_string(rna_item, self.property_name) @@ -2094,14 +2094,14 @@ class WM_OT_properties_edit_value(Operator): def draw(self, context): from bpy.utils import escape_identifier - rna_item = eval("context.%s" % self.data_path) + rna_item = eval("context.{!s}".format(self.data_path)) layout = self.layout if WM_OT_properties_edit.get_property_type(rna_item, self.property_name) == 'PYTHON': layout.prop(self, "eval_string") else: col = layout.column(align=True) - col.prop(rna_item, '["%s"]' % escape_identifier(self.property_name), text="") + col.prop(rna_item, '["{!s}"]'.format(escape_identifier(self.property_name)), text="") class WM_OT_properties_add(Operator): @@ -2118,7 +2118,7 @@ class WM_OT_properties_add(Operator): ) data_path = self.data_path - item = eval("context.%s" % data_path) + item = eval("context.{!s}".format(data_path)) if (item.id_data and item.id_data.override_library and item.id_data.override_library.reference): self.report({'ERROR'}, "Cannot add properties to override data") @@ -2174,7 +2174,7 @@ class WM_OT_properties_remove(Operator): rna_idprop_ui_prop_update, ) data_path = self.data_path - item = eval("context.%s" % data_path) + item = eval("context.{!s}".format(data_path)) if (item.id_data and item.id_data.override_library and item.id_data.override_library.reference): self.report({'ERROR'}, "Cannot remove properties from override data") @@ -2235,8 +2235,8 @@ class WM_OT_operator_cheat_sheet(Operator): op_strings.append('') textblock = bpy.data.texts.new("OperatorList.txt") - textblock.write('# %d Operators\n\n' % tot) - textblock.write('\n'.join(op_strings)) + textblock.write("# {:d} Operators\n\n".format(tot)) + textblock.write("\n".join(op_strings)) self.report({'INFO'}, "See OperatorList.txt text block") return {'FINISHED'} @@ -2317,7 +2317,7 @@ class WM_OT_tool_set_by_id(Operator): tool_settings.workspace_tool_type = 'FALLBACK' return {'FINISHED'} else: - self.report({'WARNING'}, rpt_("Tool %r not found for space %r") % (self.name, space_type)) + self.report({'WARNING'}, rpt_("Tool {!r} not found for space {!r}").format(self.name, space_type)) return {'CANCELLED'} @@ -2964,8 +2964,8 @@ class WM_OT_batch_rename(Operator): elif ty == 'STRIP': chars = action.strip_chars chars_strip = ( - "%s%s%s" - ) % ( + "{!s}{!s}{!s}" + ).format( string.punctuation if 'PUNCT' in chars else "", string.digits if 'DIGIT' in chars else "", " " if 'SPACE' in chars else "", @@ -3142,7 +3142,7 @@ class WM_OT_batch_rename(Operator): row.prop(action, "op_remove", text="", icon='REMOVE') row.prop(action, "op_add", text="", icon='ADD') - layout.label(text=iface_("Rename %d %s") % (len(self._data[0]), self._data[2]), translate=False) + layout.label(text=iface_("Rename {:d} {!s}").format(len(self._data[0]), self._data[2]), translate=False) def check(self, context): changed = False @@ -3203,7 +3203,7 @@ class WM_OT_batch_rename(Operator): change_len += 1 total_len += 1 - self.report({'INFO'}, rpt_("Renamed %d of %d %s") % (change_len, total_len, descr)) + self.report({'INFO'}, rpt_("Renamed {:d} of {:d} {!s}").format(change_len, total_len, descr)) return {'FINISHED'} @@ -3236,7 +3236,7 @@ class WM_MT_splash_quick_setup(Menu): col = split.column() col.operator( "preferences.copy_prev", - text=iface_("Import Blender %d.%d Preferences", "Operator") % old_version, + text=iface_("Import Blender {:d}.{:d} Preferences", "Operator").format(old_version), icon='NONE', translate=False, ) @@ -3365,22 +3365,22 @@ class WM_MT_splash_about(Menu): col = split.column(align=True) col.scale_y = 0.8 - col.label(text=iface_("Version: %s") % bpy.app.version_string, translate=False) + col.label(text=iface_("Version: {!s}").format(bpy.app.version_string), translate=False) col.separator(factor=2.5) - col.label(text=iface_("Date: %s %s") % ( + col.label(text=iface_("Date: {!s} {!s}").format( bpy.app.build_commit_date.decode("utf-8", "replace"), bpy.app.build_commit_time.decode("utf-8", "replace")), translate=False ) - col.label(text=iface_("Hash: %s") % bpy.app.build_hash.decode("ascii"), translate=False) - col.label(text=iface_("Branch: %s") % bpy.app.build_branch.decode("utf-8", "replace"), translate=False) + col.label(text=iface_("Hash: {!s}").format(bpy.app.build_hash.decode("ascii")), translate=False) + col.label(text=iface_("Branch: {!s}").format(bpy.app.build_branch.decode("utf-8", "replace")), translate=False) # This isn't useful information on MS-Windows or Apple systems as dynamically switching # between windowing systems is only supported between X11/WAYLAND. from _bpy import _ghost_backend ghost_backend = _ghost_backend() if ghost_backend not in {'NONE', 'DEFAULT'}: - col.label(text=iface_("Windowing Environment: %s") % _ghost_backend(), translate=False) + col.label(text=iface_("Windowing Environment: {!s}").format(_ghost_backend()), translate=False) del _ghost_backend, ghost_backend col.separator(factor=2.0) @@ -3450,7 +3450,7 @@ class WM_MT_region_toggle_pie(Menu): assert hasattr(space_data, attr) # Technically possible these double-up, in practice this should never happen. if region_type in region_by_type: - print("%s: Unexpected double-up of region types %r" % (cls.__name__, region_type)) + print("{!s}: Unexpected double-up of region types {!r}".format(cls.__name__, region_type)) region_by_type[region_type] = region # Axis aligned pie menu items to populate. diff --git a/scripts/startup/bl_ui/node_add_menu.py b/scripts/startup/bl_ui/node_add_menu.py index 1003eb9eff2..192d16a730d 100644 --- a/scripts/startup/bl_ui/node_add_menu.py +++ b/scripts/startup/bl_ui/node_add_menu.py @@ -51,7 +51,7 @@ def draw_node_group_add_menu(context, layout): props = add_node_type(layout, node_tree_group_type[group.bl_idname], label=group.name) ops = props.settings.add() ops.name = "node_tree" - ops.value = "bpy.data.node_groups[%r]" % group.name + ops.value = "bpy.data.node_groups[{!r}]".format(group.name) def draw_assets_for_catalog(layout, catalog_path): diff --git a/scripts/startup/bl_ui/properties_data_mesh.py b/scripts/startup/bl_ui/properties_data_mesh.py index 596d09f512b..d97a07d8368 100644 --- a/scripts/startup/bl_ui/properties_data_mesh.py +++ b/scripts/startup/bl_ui/properties_data_mesh.py @@ -516,8 +516,10 @@ class MESH_UL_attributes(UIList): sub = split.row() sub.alignment = 'RIGHT' sub.active = False - sub.label(text="%s ▶ %s" % (iface_(domain_name), iface_(data_type.name)), - translate=False) + sub.label( + text="{!s} ▶ {!s}".format(iface_(domain_name), iface_(data_type.name)), + translate=False, + ) class DATA_PT_mesh_attributes(MeshButtonsPanel, Panel): @@ -637,7 +639,7 @@ class MESH_UL_color_attributes(UIList, ColorAttributesListBase): sub = split.row() sub.alignment = 'RIGHT' sub.active = False - sub.label(text="%s ▶ %s" % (iface_(domain_name), iface_(data_type.name)), translate=False) + sub.label(text="{!s} ▶ {!s}".format(iface_(domain_name), iface_(data_type.name)), translate=False) active_render = _index == data.color_attributes.render_color_index diff --git a/scripts/startup/bl_ui/properties_grease_pencil_common.py b/scripts/startup/bl_ui/properties_grease_pencil_common.py index 28c60d52ac5..05739778b0f 100644 --- a/scripts/startup/bl_ui/properties_grease_pencil_common.py +++ b/scripts/startup/bl_ui/properties_grease_pencil_common.py @@ -500,7 +500,7 @@ class AnnotationDataPanel: if gpl.active_frame: lock_status = iface_("Locked") if gpl.lock_frame else iface_("Unlocked") - lock_label = iface_("Frame: %d (%s)") % (gpl.active_frame.frame_number, lock_status) + lock_label = iface_("Frame: {:d} ({!s})").format(gpl.active_frame.frame_number, lock_status) else: lock_label = iface_("Lock Frame") row.prop(gpl, "lock_frame", text=lock_label, icon='UNLOCKED') diff --git a/scripts/startup/bl_ui/properties_output.py b/scripts/startup/bl_ui/properties_output.py index 21891585f03..590ed4b7d50 100644 --- a/scripts/startup/bl_ui/properties_output.py +++ b/scripts/startup/bl_ui/properties_output.py @@ -75,10 +75,10 @@ class RENDER_PT_format(RenderOutputButtonsPanel, Panel): custom_framerate = (fps_rate not in {23.98, 24, 25, 29.97, 30, 50, 59.94, 60, 120, 240}) if custom_framerate is True: - fps_label_text = iface_("Custom (%.4g fps)") % fps_rate + fps_label_text = iface_("Custom ({:.4g} fps)").format(fps_rate) show_framerate = True else: - fps_label_text = iface_("%.4g fps") % fps_rate + fps_label_text = iface_("{:.4g} fps").format(fps_rate) show_framerate = (preset_label == "Custom") RENDER_PT_format._frame_rate_args_prev = args diff --git a/scripts/startup/bl_ui/properties_particle.py b/scripts/startup/bl_ui/properties_particle.py index 6e06c935c0e..757007be94c 100644 --- a/scripts/startup/bl_ui/properties_particle.py +++ b/scripts/startup/bl_ui/properties_particle.py @@ -224,7 +224,7 @@ class PARTICLE_PT_context_particles(ParticleButtonsPanel, Panel): row.template_ID(psys, "settings", new="particle.new") if part.is_fluid: - layout.label(text=rpt_("%d fluid particles for this frame") % part.count, translate=False) + layout.label(text=rpt_("{:d} fluid particles for this frame").format(part.count), translate=False) return row = layout.row() @@ -435,12 +435,18 @@ class PARTICLE_PT_hair_dynamics(ParticleButtonsPanel, Panel): label = "ERROR" icon = 'ERROR' box.label(text=label, icon=icon) - box.label(text=rpt_("Iterations: %d .. %d (avg. %d)") % - (result.min_iterations, result.max_iterations, result.avg_iterations), - translate=False) - box.label(text=rpt_("Error: %.5f .. %.5f (avg. %.5f)") - % (result.min_error, result.max_error, result.avg_error), - translate=False) + box.label( + text=rpt_("Iterations: {:d} .. {:d} (avg. {:d})").format( + result.min_iterations, result.max_iterations, result.avg_iterations, + ), + translate=False, + ) + box.label( + text=rpt_("Error: {:.5f} .. {:.5f} (avg. {:.5f})").format( + result.min_error, result.max_error, result.avg_error, + ), + translate=False, + ) class PARTICLE_PT_hair_dynamics_collision(ParticleButtonsPanel, Panel): @@ -839,7 +845,7 @@ class PARTICLE_PT_physics_fluid_advanced(ParticleButtonsPanel, Panel): particle_volume = part.mass / fluid.rest_density spacing = pow(particle_volume, 1.0 / 3.0) - sub.label(text=iface_("Spacing: %g") % spacing, translate=False) + sub.label(text=iface_("Spacing: {:g}").format(spacing), translate=False) class PARTICLE_PT_physics_fluid_springs(ParticleButtonsPanel, Panel): diff --git a/scripts/startup/bl_ui/properties_workspace.py b/scripts/startup/bl_ui/properties_workspace.py index c9d76f75866..e70fb1f1165 100644 --- a/scripts/startup/bl_ui/properties_workspace.py +++ b/scripts/startup/bl_ui/properties_workspace.py @@ -96,7 +96,7 @@ class WORKSPACE_UL_addons_items(UIList): if not module: return addon.module bl_info = addon_utils.module_bl_info(module) - return "%s: %s" % (iface_(bl_info["category"]), iface_(bl_info["name"])) + return "{!s}: {!s}".format(iface_(bl_info["category"]), iface_(bl_info["name"])) @staticmethod def _filter_addons_by_category_name(pattern, bitflag, addons, reverse=False): diff --git a/scripts/startup/bl_ui/space_clip.py b/scripts/startup/bl_ui/space_clip.py index b2b49e24edf..39acfeebf22 100644 --- a/scripts/startup/bl_ui/space_clip.py +++ b/scripts/startup/bl_ui/space_clip.py @@ -169,7 +169,7 @@ class CLIP_HT_header(Header): r = active_object.reconstruction if r.is_valid and sc.view == 'CLIP': - layout.label(text=rpt_("Solve error: %.2f px") % (r.average_error), translate=False) + layout.label(text=rpt_("Solve error: {.2f} px").format(r.average_error), translate=False) row = layout.row() row.prop(sc, "pivot_point", text="", icon_only=True) @@ -761,7 +761,7 @@ class CLIP_PT_track(CLIP_PT_tracking_panel, Panel): layout.prop(act_track, "weight_stab") if act_track.has_bundle: - label_text = rpt_("Average Error: %.2f px") % (act_track.average_error) + label_text = rpt_("Average Error: {:.2f} px").format(act_track.average_error) layout.label(text=label_text, translate=False) layout.use_property_split = False @@ -1301,7 +1301,7 @@ class CLIP_MT_view_zoom(Menu): percent = ratio * 100.0 layout.operator( "clip.view_zoom_ratio", - text="%g%% (%d:%d)" % (percent, a, b), + text="{:g}% ({:d}:{:d})".format(percent, a, b), translate=False, icon='LAYER_ACTIVE' if isclose(percent, current_zoom, abs_tol=0.5) else 'NONE', ).ratio = ratio diff --git a/scripts/startup/bl_ui/space_image.py b/scripts/startup/bl_ui/space_image.py index 90048822853..adc754bcf79 100644 --- a/scripts/startup/bl_ui/space_image.py +++ b/scripts/startup/bl_ui/space_image.py @@ -127,7 +127,7 @@ class IMAGE_MT_view_zoom(Menu): percent = ratio * 100.0 layout.operator( "image.view_zoom_ratio", - text="%g%% (%d:%d)" % (percent, a, b), + text="{:g}% ({:d}:{:d})".format(percent, a, b), translate=False, icon='LAYER_ACTIVE' if isclose(percent, current_zoom, abs_tol=0.5) else 'NONE', ).ratio = ratio diff --git a/scripts/startup/bl_ui/space_node.py b/scripts/startup/bl_ui/space_node.py index 666c8b7bd1b..57f65c3d5f9 100644 --- a/scripts/startup/bl_ui/space_node.py +++ b/scripts/startup/bl_ui/space_node.py @@ -404,7 +404,7 @@ class NODE_PT_material_slots(Panel): def draw_header(self, context): ob = context.object self.bl_label = ( - iface_("Slot %d") % (ob.active_material_index + 1) if ob.material_slots else + iface_("Slot {:d}").format(ob.active_material_index + 1) if ob.material_slots else iface_("Slot") ) diff --git a/scripts/startup/bl_ui/space_sequencer.py b/scripts/startup/bl_ui/space_sequencer.py index 1b7a5fbcd3a..d39437708d6 100644 --- a/scripts/startup/bl_ui/space_sequencer.py +++ b/scripts/startup/bl_ui/space_sequencer.py @@ -382,7 +382,7 @@ class SEQUENCER_MT_preview_zoom(Menu): layout.operator( "sequencer.view_zoom_ratio", - text="%g%% (%d:%d)" % (percent, a, b), + text="{:g}% ({:d}:{:d})".format(percent, a, b), translate=False, icon='LAYER_ACTIVE' if isclose(percent, current_zoom, abs_tol=0.5) else 'NONE', ).ratio = ratio @@ -1334,8 +1334,8 @@ class SEQUENCER_PT_color_tag_picker(SequencerColorTagPicker, Panel): row = layout.row(align=True) row.operator("sequencer.strip_color_tag_set", icon='X').color = 'NONE' for i in range(1, 10): - icon = 'SEQUENCE_COLOR_%02d' % i - row.operator("sequencer.strip_color_tag_set", icon=icon).color = 'COLOR_%02d' % i + icon = 'SEQUENCE_COLOR_{:02d}'.format(i) + row.operator("sequencer.strip_color_tag_set", icon=icon).color = 'COLOR_{:02d}'.format(i) class SEQUENCER_MT_color_tag_picker(SequencerColorTagPicker, Menu): @@ -1561,11 +1561,11 @@ class SEQUENCER_PT_effect(SequencerButtonsPanel, Panel): if i == strip.multicam_source: sub = row.row(align=True) sub.enabled = False - sub.operator("sequencer.split_multicam", text="%d" % i).camera = i + sub.operator("sequencer.split_multicam", text="{:d}".format(i)).camera = i else: sub_1 = row.row(align=True) sub_1.enabled = True - sub_1.operator("sequencer.split_multicam", text="%d" % i).camera = i + sub_1.operator("sequencer.split_multicam", text="{:d}".format(i)).camera = i if strip.channel > BT_ROW and (strip_channel - 1) % BT_ROW: for i in range(strip.channel, strip_channel + ((BT_ROW + 1 - strip_channel) % BT_ROW)): @@ -1726,7 +1726,7 @@ class SEQUENCER_PT_source(SequencerButtonsPanel, Panel): if sound.samplerate <= 0: split.label(text="Unknown") else: - split.label(text="%d Hz" % sound.samplerate, translate=False) + split.label(text="{:d} Hz".format(sound.samplerate), translate=False) split = col.split(factor=0.5, align=False) split.alignment = 'RIGHT' @@ -1782,7 +1782,7 @@ class SEQUENCER_PT_source(SequencerButtonsPanel, Panel): size = (elem.orig_width, elem.orig_height) if elem else (0, 0) if size[0] and size[1]: split.alignment = 'LEFT' - split.label(text="%dx%d" % size, translate=False) + split.label(text="{:d}x{:d}".format(*size), translate=False) else: split.label(text="None") # FPS @@ -1791,7 +1791,7 @@ class SEQUENCER_PT_source(SequencerButtonsPanel, Panel): split.alignment = 'RIGHT' split.label(text="FPS") split.alignment = 'LEFT' - split.label(text="%.2f" % elem.orig_fps, translate=False) + split.label(text="{:.2f}".format(elem.orig_fps), translate=False) class SEQUENCER_PT_scene(SequencerButtonsPanel, Panel): @@ -1896,7 +1896,10 @@ class SEQUENCER_PT_mask(SequencerButtonsPanel, Panel): if mask: sta = mask.frame_start end = mask.frame_end - layout.label(text=rpt_("Original frame range: %d-%d (%d)") % (sta, end, end - sta + 1), translate=False) + layout.label( + text=rpt_("Original frame range: {:d}-{:d} ({:d})").format(sta, end, end - sta + 1), + translate=False, + ) class SEQUENCER_PT_time(SequencerButtonsPanel, Panel): @@ -1993,7 +1996,7 @@ class SEQUENCER_PT_time(SequencerButtonsPanel, Panel): split.alignment = 'RIGHT' split.label(text="End") split = split.split(factor=factor + 0.3 + max_factor, align=True) - split.label(text="%14s" % smpte_from_frame(frame_final_end)) + split.label(text="{:>14s}".format(smpte_from_frame(frame_final_end))) split.alignment = 'RIGHT' split.label(text=str(frame_final_end) + " ") @@ -2037,7 +2040,7 @@ class SEQUENCER_PT_time(SequencerButtonsPanel, Panel): split.label(text="Current Frame") split = split.split(factor=factor + 0.3 + max_factor, align=True) frame_display = frame_current - frame_final_start - split.label(text="%14s" % smpte_from_frame(frame_display)) + split.label(text="{:>14s}".format(smpte_from_frame(frame_display))) split.alignment = 'RIGHT' split.label(text=str(frame_display) + " ") @@ -2051,7 +2054,7 @@ class SEQUENCER_PT_time(SequencerButtonsPanel, Panel): split.alignment = 'RIGHT' split.label(text="Original Frame Range") split.alignment = 'LEFT' - split.label(text="%d-%d (%d)" % (sta, end, end - sta + 1), translate=False) + split.label(text="{:d}-{:d} ({:d})".format(sta, end, end - sta + 1), translate=False) class SEQUENCER_PT_adjust_sound(SequencerButtonsPanel, Panel): @@ -2090,7 +2093,7 @@ class SEQUENCER_PT_adjust_sound(SequencerButtonsPanel, Panel): audio_channels = context.scene.render.ffmpeg.audio_channels pan_enabled = sound.use_mono and audio_channels != 'MONO' - pan_text = "%.2f°" % (strip.pan * 90) + pan_text = "{:.2f}°".format(strip.pan * 90.0) split = col.split(factor=0.4) split.alignment = 'RIGHT' @@ -2683,10 +2686,10 @@ class SEQUENCER_PT_modifiers(SequencerButtonsPanel, Panel): col = flow.column() box = col.box() split = box.split(factor=0.4) - split.label(text="%.2f" % sound_eq.curve_mapping.clip_min_x) + split.label(text="{.2f}".format(sound_eq.curve_mapping.clip_min_x)) split.label(text="Hz") split.alignment = "RIGHT" - split.label(text="%.2f" % sound_eq.curve_mapping.clip_max_x) + split.label(text="{.2f}".format(sound_eq.curve_mapping.clip_max_x)) box.template_curve_mapping( sound_eq, "curve_mapping", diff --git a/scripts/startup/bl_ui/space_text.py b/scripts/startup/bl_ui/space_text.py index f4017ac54aa..55af5315145 100644 --- a/scripts/startup/bl_ui/space_text.py +++ b/scripts/startup/bl_ui/space_text.py @@ -67,12 +67,12 @@ class TEXT_HT_footer(Header): if text.filepath: if text.is_dirty: row.label( - text=iface_("File: *%s (unsaved)") % text.filepath, + text=iface_("File: *{!s} (unsaved)").format(text.filepath), translate=False, ) else: row.label( - text=iface_("File: %s") % text.filepath, + text=iface_("File: {!s}").format(text.filepath), translate=False, ) else: diff --git a/scripts/startup/bl_ui/space_toolsystem_common.py b/scripts/startup/bl_ui/space_toolsystem_common.py index 5cde9f1a06b..485e01500f2 100644 --- a/scripts/startup/bl_ui/space_toolsystem_common.py +++ b/scripts/startup/bl_ui/space_toolsystem_common.py @@ -213,7 +213,7 @@ class ToolSelectPanelHelper: The value is must be a sequence of (mode, tool_list) pairs, where mode may be object-mode edit-mode etc. The mode may be None for tool-bars that don't make use of sub-modes. """ - raise Exception("Sub-class %r must implement this method!" % cls) + raise Exception("Sub-class {!r} must implement this method!".format(cls)) @classmethod def tools_from_context(cls, context, mode=None): @@ -221,7 +221,7 @@ class ToolSelectPanelHelper: Return all tools for the current context, this result is used at run-time and may filter out tools to display. """ - raise Exception("Sub-class %r must implement this method!" % cls) + raise Exception("Sub-class {!r} must implement this method!".format(cls)) @staticmethod def _tool_class_from_space_type(space_type): @@ -486,7 +486,7 @@ class ToolSelectPanelHelper: @classmethod def _km_action_simple(cls, kc_default, kc, context_descr, label, keymap_fn): - km_idname = "%s %s, %s" % (cls.keymap_prefix, context_descr, label) + km_idname = "{!s} {!s}, {!s}".format(cls.keymap_prefix, context_descr, label) km = kc.keymaps.get(km_idname) km_kwargs = dict(space_type=cls.bl_space_type, region_type='WINDOW', tool=True) if km is None: @@ -1053,7 +1053,7 @@ def _activate_by_item(context, space_type, item, index, *, as_fallback=False): gizmo_properties = item.widget_properties if gizmo_properties is not None: if not isinstance(gizmo_properties, list): - raise Exception("expected a list, not a %r" % type(gizmo_properties)) + raise Exception("expected a list, not a {!r}".format(type(gizmo_properties))) from bl_keymap_utils.io import _init_properties_from_data _init_properties_from_data(props, gizmo_properties) diff --git a/scripts/startup/bl_ui/space_toolsystem_toolbar.py b/scripts/startup/bl_ui/space_toolsystem_toolbar.py index 21bfc08e071..9ccf284dc60 100644 --- a/scripts/startup/bl_ui/space_toolsystem_toolbar.py +++ b/scripts/startup/bl_ui/space_toolsystem_toolbar.py @@ -135,12 +135,12 @@ class _defs_view3d_generic: kmi_remove = None return tip_( "Measure distance and angles.\n" - "\u2022 %s anywhere for new measurement.\n" + "\u2022 {!s} anywhere for new measurement.\n" "\u2022 Drag ruler segment to measure an angle.\n" - "\u2022 %s to remove the active ruler.\n" + "\u2022 {!s} to remove the active ruler.\n" "\u2022 Ctrl while dragging to snap.\n" "\u2022 Shift while dragging to measure surface thickness" - ) % ( + ).format( kmi_to_string_or_none(kmi_add), kmi_to_string_or_none(kmi_remove), ) @@ -506,11 +506,11 @@ class _defs_view3d_add: kmi_center = None kmi_fixed_aspect = None return tip_( - "%s\n" - "\u2022 %s toggles snap while dragging.\n" - "\u2022 %s toggles dragging from the center.\n" - "\u2022 %s toggles fixed aspect" - ) % ( + "{!s}\n" + "\u2022 {!s} toggles snap while dragging.\n" + "\u2022 {!s} toggles dragging from the center.\n" + "\u2022 {!s} toggles fixed aspect" + ).format( prefix, kmi_to_string_or_none(kmi_snap), kmi_to_string_or_none(kmi_center), @@ -779,10 +779,10 @@ class _defs_edit_mesh: kmi_delete = None return tip_( "Use multiple operators in an interactive way to add, delete, or move geometry.\n" - "\u2022 %s - Add geometry by moving the cursor close to an element.\n" - "\u2022 %s - Extrude edges by moving the cursor.\n" - "\u2022 %s - Delete mesh element" - ) % ( + "\u2022 {!s} - Add geometry by moving the cursor close to an element.\n" + "\u2022 {!s} - Extrude edges by moving the cursor.\n" + "\u2022 {!s} - Delete mesh element" + ).format( kmi_to_string_or_none(kmi_add), kmi_to_string_or_none(kmi_extrude), kmi_to_string_or_none(kmi_delete), @@ -1759,7 +1759,7 @@ class _defs_weight_paint: weight = context.tool_settings.weight_paint.brush.weight else: return - layout.label(text="Weight: %.3f" % weight) + layout.label(text="Weight: {:.3f}".format(weight)) return dict( idname="builtin.sample_weight", label="Sample Weight", diff --git a/scripts/startup/bl_ui/space_topbar.py b/scripts/startup/bl_ui/space_topbar.py index 7b6ee9b2f8b..01fa8f9f6eb 100644 --- a/scripts/startup/bl_ui/space_topbar.py +++ b/scripts/startup/bl_ui/space_topbar.py @@ -378,8 +378,8 @@ class TOPBAR_MT_file_defaults(Menu): props = layout.operator("wm.read_factory_settings", text="Load Factory Blender Settings") props.app_template = app_template props = layout.operator("wm.read_factory_settings", - text=iface_("Load Factory %s Settings", - i18n_contexts.operator_default) % display_name, + text=iface_("Load Factory {!s} Settings", + i18n_contexts.operator_default).format(display_name), translate=False) props.app_template = app_template props.use_factory_startup_app_template_only = True diff --git a/scripts/startup/bl_ui/space_userpref.py b/scripts/startup/bl_ui/space_userpref.py index 5f561bc00e2..fd89207049d 100644 --- a/scripts/startup/bl_ui/space_userpref.py +++ b/scripts/startup/bl_ui/space_userpref.py @@ -123,7 +123,7 @@ class USERPREF_MT_save_load(Menu): display_name = bpy.path.display_name(iface_(app_template)) layout.operator("wm.read_factory_userpref", text="Load Factory Blender Preferences") props = layout.operator("wm.read_factory_userpref", - text=iface_("Load Factory %s Preferences") % display_name, + text=iface_("Load Factory {!s} Preferences").format(display_name), translate=False) props.use_factory_startup_app_template_only = True del display_name @@ -1161,7 +1161,7 @@ class USERPREF_PT_theme_bone_color_sets(ThemePanel, CenterAlignMixIn, Panel): layout.use_property_split = True for i, ui in enumerate(theme.bone_color_sets, 1): - layout.label(text=iface_("Color Set %d") % i, translate=False) + layout.label(text=iface_("Color Set {:d}").format(i), translate=False) flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=True) @@ -1187,7 +1187,7 @@ class USERPREF_PT_theme_collection_colors(ThemePanel, CenterAlignMixIn, Panel): flow = layout.grid_flow(row_major=False, columns=2, even_columns=True, even_rows=False, align=False) for i, ui in enumerate(theme.collection_color, 1): - flow.prop(ui, "color", text=iface_("Color %d") % i, translate=False) + flow.prop(ui, "color", text=iface_("Color {:d}").format(i), translate=False) class USERPREF_PT_theme_strip_colors(ThemePanel, CenterAlignMixIn, Panel): @@ -1206,7 +1206,7 @@ class USERPREF_PT_theme_strip_colors(ThemePanel, CenterAlignMixIn, Panel): flow = layout.grid_flow(row_major=False, columns=2, even_columns=True, even_rows=False, align=False) for i, ui in enumerate(theme.strip_color, 1): - flow.prop(ui, "color", text=iface_("Color %d") % i, translate=False) + flow.prop(ui, "color", text=iface_("Color {:d}").format(i), translate=False) # Base class for dynamically defined theme-space panels. @@ -2367,7 +2367,7 @@ class USERPREF_PT_addons(AddOnPanel, Panel): sub = row.row() sub.active = is_enabled - sub.label(text="%s: %s" % (iface_(bl_info["category"]), iface_(bl_info["name"]))) + sub.label(text="{!s}: {!s}".format(iface_(bl_info["category"]), iface_(bl_info["name"]))) if bl_info["warning"]: sub.label(icon='ERROR') @@ -2424,9 +2424,9 @@ class USERPREF_PT_addons(AddOnPanel, Panel): ).url = bl_info["tracker_url"] elif not user_addon: addon_info = ( - "Name: %s %s\n" - "Author: %s\n" - ) % (bl_info["name"], str(bl_info["version"]), bl_info["author"]) + "Name: {!s} {!s}\n" + "Author: {!s}\n" + ).format(bl_info["name"], str(bl_info["version"]), bl_info["author"]) props = sub.operator( "wm.url_open_preset", text="Report a Bug", icon='URL', ) @@ -2506,7 +2506,7 @@ class StudioLightPanelMixin: layout.label(text=self.get_error_message()) def get_error_message(self): - return rpt_("No custom %s configured") % self.bl_label + return rpt_("No custom {!s} configured").format(self.bl_label) def draw_studio_light(self, layout, studio_light): box = layout.box() diff --git a/scripts/startup/bl_ui/space_view3d.py b/scripts/startup/bl_ui/space_view3d.py index e7d7609a52d..0f14de499d1 100644 --- a/scripts/startup/bl_ui/space_view3d.py +++ b/scripts/startup/bl_ui/space_view3d.py @@ -1252,7 +1252,7 @@ class VIEW3D_MT_editor_menus(Menu): elif mesh.use_paint_mask_vertex and mode_string in {'PAINT_WEIGHT', 'PAINT_VERTEX'}: layout.menu("VIEW3D_MT_select_paint_mask_vertex") elif mode_string not in {'SCULPT', 'SCULPT_CURVES', 'PAINT_GREASE_PENCIL', 'SCULPT_GREASE_PENCIL'}: - layout.menu("VIEW3D_MT_select_%s" % mode_string.lower()) + layout.menu("VIEW3D_MT_select_{!s}".format(mode_string.lower())) if gp_edit: pass @@ -1284,7 +1284,7 @@ class VIEW3D_MT_editor_menus(Menu): layout.menu("VIEW3D_MT_paint_gpencil") elif edit_object: - layout.menu("VIEW3D_MT_edit_%s" % edit_object.type.lower()) + layout.menu("VIEW3D_MT_edit_{!s}".format(edit_object.type.lower())) if mode_string == 'EDIT_MESH': layout.menu("VIEW3D_MT_edit_mesh_vertices") @@ -1305,7 +1305,7 @@ class VIEW3D_MT_editor_menus(Menu): elif obj: if mode_string not in {'PAINT_TEXTURE', 'SCULPT_CURVES', 'SCULPT_GREASE_PENCIL'}: - layout.menu("VIEW3D_MT_%s" % mode_string.lower()) + layout.menu("VIEW3D_MT_{!s}".format(mode_string.lower())) if mode_string == 'SCULPT': layout.menu("VIEW3D_MT_mask") layout.menu("VIEW3D_MT_face_sets") @@ -1335,9 +1335,9 @@ class ShowHideMenu: def draw(self, _context): layout = self.layout - layout.operator("%s.reveal" % self._operator_name) - layout.operator("%s.hide" % self._operator_name, text="Hide Selected").unselected = False - layout.operator("%s.hide" % self._operator_name, text="Hide Unselected").unselected = True + layout.operator("{!s}.reveal".format(self._operator_name)) + layout.operator("{!s}.hide".format(self._operator_name), text="Hide Selected").unselected = False + layout.operator("{!s}.hide".format(self._operator_name), text="Hide Unselected").unselected = True # Standard transforms which apply to all cases (mix-in class, not used directly). @@ -1465,7 +1465,7 @@ class VIEW3D_MT_mirror(Menu): for (space_name, space_id) in (("Global", 'GLOBAL'), ("Local", 'LOCAL')): for axis_index, axis_name in enumerate("XYZ"): props = layout.operator("transform.mirror", - text="%s %s" % (axis_name, iface_(space_name)), + text="{!s} {!s}".format(axis_name, iface_(space_name)), translate=False) props.constraint_axis[axis_index] = True props.orient_type = space_id diff --git a/scripts/startup/bl_ui/temp_anim_layers.py b/scripts/startup/bl_ui/temp_anim_layers.py index 7d494743e6e..19912cb8feb 100644 --- a/scripts/startup/bl_ui/temp_anim_layers.py +++ b/scripts/startup/bl_ui/temp_anim_layers.py @@ -69,7 +69,7 @@ class VIEW3D_PT_animation_layers(Panel): for layer_idx, layer in reversed(list(enumerate(anim.layers))): layerbox = layout.box() col = layerbox.column(align=True) - col.prop(layer, "name", text="Layer %d:" % (layer_idx + 1)) + col.prop(layer, "name", text="Layer {:d}:".format(layer_idx + 1)) col.prop(layer, "influence") col.prop(layer, "mix_mode") diff --git a/scripts/startup/keyingsets_builtins.py b/scripts/startup/keyingsets_builtins.py index 79e4eda1aed..1ffd75a6d4d 100644 --- a/scripts/startup/keyingsets_builtins.py +++ b/scripts/startup/keyingsets_builtins.py @@ -512,7 +512,7 @@ class WholeCharacterMixin: # for now, just add all of 'em prop_rna = type(bone).bl_rna.properties.get(prop, None) if prop_rna is None: - prop_path = '["%s"]' % bpy.utils.escape_identifier(prop) + prop_path = '["{!s}"]'.format(bpy.utils.escape_identifier(prop)) try: rna_property = bone.path_resolve(prop_path, False) except ValueError: diff --git a/scripts/startup/nodeitems_builtins.py b/scripts/startup/nodeitems_builtins.py index ecfdf8fc656..6b802e123f0 100644 --- a/scripts/startup/nodeitems_builtins.py +++ b/scripts/startup/nodeitems_builtins.py @@ -82,7 +82,7 @@ def node_group_items(context): continue yield NodeItem(node_tree_group_type[group.bl_idname], label=group.name, - settings={"node_tree": "bpy.data.node_groups[%r]" % group.name}) + settings={"node_tree": "bpy.data.node_groups[{!r}]".format(group.name)}) # only show input/output nodes inside node groups