Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle %s strings with length and alignment #194

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

Lalufu
Copy link

@Lalufu Lalufu commented Nov 16, 2023

%s format strings allow for padding and alignment, but their behaviour is very different from fstrings.

%20s will pad a string to 20 characters, and right align %-20s will pad a string to 20 characters, and left align

This behaviour is carried over from the C *printf() functions.

This patch adds the ability to properly convert these to fstrings, using the correct alignment markers.

The feature is gated behind aggressive mode for now.

The earlier code did already convert %20s, but changed the alignment (the resulting fstring would be left aligned instead of right), and did not understand %-20s at all.

%s format strings allow for padding and alignment, but their behaviour
is very different from fstrings.

%20s will pad a string to 20 characters, and right align
%-20s will pad a string to 20 characters, and left align

This behaviour is carried over from the C *printf() functions.

This patch adds the ability to properly convert these to fstrings, using
the correct alignment markers.

The feature is gated behind aggressive mode for now.

The earlier code did already convert %20s, but changed the alignment
(the resulting fstring would be left aligned instead of right), and did
not understand %-20s at all.
Copy link
Owner

@ikamensh ikamensh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for your contribution @Lalufu and sorry for super late review. There are few minor improvements to be made, otherwise looking good.

Comment on lines 41 to +56
def test_string_specific_len(state: State):
s_in = """'%5s' % CLASS_NAMES[labels[j]]"""
s_expected = """f'{CLASS_NAMES[labels[j]]:>5}'"""

state.aggressive = True
s_out, count = code_editor.fstringify_code_by_line(s_in, state)
assert s_out == s_expected


def test_string_specific_len_right_aligned(state: State):
s_in = """'%5s' % CLASS_NAMES[labels[j]]"""
s_expected = """f'{CLASS_NAMES[labels[j]]:>5}'"""

state.aggressive = True
s_out, count = code_editor.fstringify_code_by_line(s_in, state)
assert s_out == s_expected
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These two tests are exactly the same? lets delete one.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, test_string_specific_len can go?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes.

# In order to not have to figure out what sort of number we are
# dealing with, just look at the leading - sign (if there is one)
# and remove it for the conversion
if aggressive and fmt_prefix.startswith("-"):
Copy link
Owner

@ikamensh ikamensh Aug 21, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if aggressive and fmt_prefix.startswith("-"):
if fmt_prefix.startswith("-"):

It seems that we have handled all possible cases within this branch (fmt_spec == "s" and fmt_prefix), so there is no room for error anymore; therefore we don't need aggressive flag? aggressive means "risky", some changes that are not guaranteed to be correct.

Is there any known/suspected case where outputs might differ for original and new f-string? to me it sounds exhaustive what you've suggested.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason I "locked" this behind the aggressive flag is that it changes the current behaviour. Arguably the current behaviour is wrong (a right aligned percentage string would become a left aligned fstring), but still.
If you feel that's not critical I'm fine with dropping the flag requirement.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my logic aggressive is not for compatibility with old version, people can freeze flynt version for this. Its to use some logic that might change how strings come out of formatting. Seems all cases are handled here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants