-
-
Notifications
You must be signed in to change notification settings - Fork 3k
[mypyc] Add a str.format specializer which only supports empty brackets #10697
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
[mypyc] Add a str.format specializer which only supports empty brackets #10697
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm glad to see the performance improvement! Left some mostly minor comments. Once you handle {{
and }}
this seems enough features for a first iteration.
Add several optimization:
running str_format_format_method compiled is 2.057x faster |
The build is failing. Can you have a look? |
@JukkaL I fixed it by replacing "{{" with "{" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the updates! Left various suggestions about more test coverage. Right now test coverage is still a bit limited, and there may be some bugs still lurking in the code.
mypyc/test-data/run-strings.test
Outdated
assert "{{}}{}".format(name) == "{}Eric" | ||
assert "Hi! {{{}}}".format(name) == "Hi! {Eric}" | ||
assert "Hi! {{ {}".format(name) == "Hi! { Eric" | ||
assert "Hi! {{ {} }}}}".format(name) == "Hi! { Eric }}" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add more tests. We want fairly complete test coverage to make sure nothing has regressed. It's important both valid and error cases produce the same output when optimized. For example, any exceptions should be identical.
Examples (but there are probably more):
- Simplest possible case:
''.format()
- Plain text only:
'xyz'.format()
- Extra positional arguments:
'a{}b'.format(1, 2, 3)
- Too few arguments
- Various format specifiers that are supported within
{...}
(these should still work, even if they aren't optimized) - Keyword arguments to
format
*args
toformat
- Invalid format string
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extra positional arguments case this compile error: error: Not all arguments converted during string formatting
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These test cases could still be useful. Can you double check if they aren't covered:
'{}{}'.format(1, 2)
(empty literals)'x{}y{}'.format(*args)
(*args
)
return None | ||
|
||
|
||
def can_optimize_format(format_str: str) -> bool: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add unit tests for this, since it has pretty tricky logic. Also consider various error cases and edge cases.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the updates! This is almost ready to merge. Just a few remaining comments.
@@ -159,3 +159,20 @@ L2: | |||
L3: | |||
unreachable | |||
|
|||
[case testStringFormatMethod] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a few more IR build test cases, such as these:
- an empty literal
{{
and}}
in the format string
mypyc/test-data/run-strings.test
Outdated
assert "{{}}{}".format(name) == "{}Eric" | ||
assert "Hi! {{{}}}".format(name) == "Hi! {Eric}" | ||
assert "Hi! {{ {}".format(name) == "Hi! { Eric" | ||
assert "Hi! {{ {} }}}}".format(name) == "Hi! { Eric }}" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These test cases could still be useful. Can you double check if they aren't covered:
'{}{}'.format(1, 2)
(empty literals)'x{}y{}'.format(*args)
(*args
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
Description
This PR adds a str.format specializer which only supports empty brackets. Also, the detection code can deal with the bracket literals, for example, "{{}}".
The specializer first split the formatting string by "{}". Then it replaces the brackets by
PyObject_Str
. Finally, all these separated substrings would be sent to a C helper function to generate a joint one.Test Plan
mypyc_benchmark: