Python: refactor scripts under scripts/startup/ to use str.format
#120552
No reviewers
Labels
No Label
Interest
Alembic
Interest
Animation & Rigging
Interest
Asset Browser
Interest
Asset Browser Project Overview
Interest
Audio
Interest
Automated Testing
Interest
Blender Asset Bundle
Interest
BlendFile
Interest
Collada
Interest
Compatibility
Interest
Compositing
Interest
Core
Interest
Cycles
Interest
Dependency Graph
Interest
Development Management
Interest
EEVEE
Interest
EEVEE & Viewport
Interest
Freestyle
Interest
Geometry Nodes
Interest
Grease Pencil
Interest
ID Management
Interest
Images & Movies
Interest
Import Export
Interest
Line Art
Interest
Masking
Interest
Metal
Interest
Modeling
Interest
Modifiers
Interest
Motion Tracking
Interest
Nodes & Physics
Interest
OpenGL
Interest
Overlay
Interest
Overrides
Interest
Performance
Interest
Physics
Interest
Pipeline, Assets & IO
Interest
Platforms, Builds & Tests
Interest
Python API
Interest
Render & Cycles
Interest
Render Pipeline
Interest
Sculpt, Paint & Texture
Interest
Text Editor
Interest
Translations
Interest
Triaging
Interest
Undo
Interest
USD
Interest
User Interface
Interest
UV Editing
Interest
VFX & Video
Interest
Video Sequencer
Interest
Virtual Reality
Interest
Vulkan
Interest
Wayland
Interest
Workbench
Interest: X11
Legacy
Blender 2.8 Project
Legacy
Milestone 1: Basic, Local Asset Browser
Legacy
OpenGL Error
Meta
Good First Issue
Meta
Papercut
Meta
Retrospective
Meta
Security
Module
Animation & Rigging
Module
Core
Module
Development Management
Module
EEVEE & Viewport
Module
Grease Pencil
Module
Modeling
Module
Nodes & Physics
Module
Pipeline, Assets & IO
Module
Platforms, Builds & Tests
Module
Python API
Module
Render & Cycles
Module
Sculpt, Paint & Texture
Module
Triaging
Module
User Interface
Module
VFX & Video
Platform
FreeBSD
Platform
Linux
Platform
macOS
Platform
Windows
Priority
High
Priority
Low
Priority
Normal
Priority
Unbreak Now!
Status
Archived
Status
Confirmed
Status
Duplicate
Status
Needs Info from Developers
Status
Needs Information from User
Status
Needs Triage
Status
Resolved
Type
Bug
Type
Design
Type
Known Issue
Type
Patch
Type
Report
Type
To Do
No Milestone
No project
No Assignees
3 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: blender/blender#120552
Loading…
Reference in New Issue
No description provided.
Delete Branch "ideasman42/blender:pr-str-format-refactor"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
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.
@blender-bot build
Obviously did not check every line, but looks in line with the design task.
f53af30ed0
to770d8e24a3
770d8e24a3
tof8448c3d31
I have a question about the replacement of
%s
with{:s}
, like here:Because
%
-formatting always needed a type indicator,%s
had to be used. In this case, however,ks.bl_idname
is already a string, and so the simpler{}
is valid here too. What's the reason to go for the more complex{:s}
? Personally I would only add extra formatting parameters when they are actually necessary, i.e. when there is the necessity to actually callstr(…)
on the formatted object. The format string language spec even mentions that:s
is the default for string types and may be ommitted.Diving into this further: when the formatted object is not a string, this format is not even valid, so it can cause errors:
As you can see, replacing
%s
with{:s}
has to be done very carefully, and doing so would count as a functional change.A similar argument can be made for replacing
%d
with{:d}
by the way, when the parameter is already an integer.:d
is the same as having no format specifier at all. And again, it is only valid onint
whereas"%d"
is also valid when formattingfloat
s:@ -71,3 +70,2 @@
f.write("ks.use_insertkey_needed = %s\n" % ks.use_insertkey_needed)
f.write("ks.use_insertkey_visual = %s\n" % ks.use_insertkey_visual)
f.write("ks.use_insertkey_needed = {!r}\n".format(ks.use_insertkey_needed))
This changes the semantics of the format string, from calling
str(…)
torepr(…)
on the formatted object. It might be more correct to use the latter when generating Python code, but for this PR I would strongly recommend restricting it strictly to non-functional changes.f8448c3d31
to1c4eec9ed6
@dr.sybren
Good points and this does come down to personal preference, there are times I read over code and it's not clear what the original developer intended, in most cases I would rather get an error message if something which is intended to be one type - (but got broken in a refactor or similar). Instead of working but producing a string which doesn't error but doesn't work as it's supposed to.
For example, reading the following formatting, I find the type specifiers help with clarity.
Callers that need to convert to
str(..)
can always use{!s}
, then it's clear when a string is passed in, or a value that needed to be converted into a string was passed in instead.On balance I'd rather always use type specifiers, but I'm not that fussed.
@mont29 what do you think about this?
I would also rather have explicit type specifiers here, it helps disambiguating the code, and catching early errors.
Indeed this does imply potential functional changes in this patch.
1c4eec9ed6
tod1224d57de
I've gone over the patch and double checked type specifiers were used correctly the vast majority are very straightforward (translated labels, files/URL's & data-paths).
ANIM_OT_keying_set_export
inmain
(2b7f46bc0b
), rebased this patch.d1224d57de
to342c2872c5
I agree that what you describe here is somewhat personal. Personally I would strongly prefer type annotations and the structural use of mypy for this. If you need string formatting arguments to check your types for you, or to clarify which variable is of which (expected) type, then I feel that the type checking is done at the wrong level, in the wrong bit of code.
What I was describing has little to do with personal preference, though. Replacing
%s
with{:s}
is objectively a functional change. The former can be applied to any Python object, whereas the latter only to strings.For sanity sake, this pull request should limit itself to a non-functional change to another formatting API. Once that change is done, the strengths of that new API can be utilised to improve the code. These two should not be intertwined into one big commit.
Proper support of mypy & it's type hints would be helpful but I don't see these as mutually exclusive, if you don't use type specifiers then the arguments to
format(..)
are effectively untyped, a change to a type for e.g. (which mypy would accept) could be result in unexpected formatting.It's disputable what is/isn't a functional change in a context when strings are clearly in use e.g.:
"A {:s} B".format(", ".join(args))
text="{:s} ▶ {:s}".format(iface_(domain_name), iface_(data_type.name))
Nevertheless, its a large patch and there is some chance converting to a string was needed, so I'll use
{!s}
for strings and switch to{:s}
in a separate commit.Note that there doesn't seem to be an equivalent
%d
, so in this cases I'll check each instance as there aren't so many.342c2872c5
tob47ff3031e
b47ff3031e
to3a3a6257ee
3a3a6257ee
to86cc3316d7
86cc3316d7
to742386f19f
Oh for sure. And I also see the advantage of more explicit type indicators in the format string, especially when translating them.
Thanks.
👍