-
-
Notifications
You must be signed in to change notification settings - Fork 3k
Type checking of string interpolation using % #472
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
Conversation
Turns out a placeholder like |
…fier formats, except for mapping keys
Errors like this are not caught: def f(a, b):
return '%d' % (a, b) because the type of |
… str to make sure that str is of length 1. Made checker aware of mapping keys: errors are reported when specifiers with mapping keys are mixed with those without. Error is reported when mapping keys and stars (in precision of minimum field width) are mixed. When mapping keys are present, the replacement expression is not yet checked.
Travis reports two error:
Both look like mypy bugs to me. I'll work around the second one (the current implementation with two optional keywords violates SRP anyway). But I don't know what to do with the first. Any suggestions? |
rhs_type = self.accept(replacements) | ||
rep_types = [] # type: List[Type] | ||
if isinstance(rhs_type, TupleType): | ||
rep_types = cast(TupleType, rhs_type).items |
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 think this cast is redundant, since mypy does some type inference of isinstance
checks
Looks good! It's okay not to check for these kinds of errors in dynamically typed functions. It may make sense to perform some level of type checking in dynamically typed functions as well, but let's leave that for the future. The first Travis error is due to a mypy bug (#259). You can work it around by using The second one is not a bug but a limitation of function types. Function types can't currently have default argument values or keyword arguments. You can work it around by either using The latter is a long-standing known issue and it's been brought up every now and then. We currently don't have any syntax for more general function types, but it would be pretty easy to implement then if we can agree on a syntax, as most of the type checking machinery is already there. |
Thanks for the review. I'll replace the check functions with a tuple of I should be able to fix your other remarks within a few days (or evenings rather :-) ). |
I fixed all remarks that you made. Also, in 9add187, I've moved all code for checking string formatter code into a new
|
Right now, in case like I'm not sure whether this is worth the effort at the moment, so maybe it can be made into an issue. |
Looks good! It's a good idea to move the code to a separate module. Based on a quick corpus analysis, dictionaries are used pretty rarely with |
Type checking of string interpolation using %
This PR adds type checking of printf-style string formatting and fixes #469.
Simple examples
For each conversion specifier present in the formatting string, the replacement tuple must contain a replacement of the right type.
Variable minimum field width and precision
A conversion specifier may contain a minimum field width (
%3d
) and a precision (%.3f
). Both may be a*
. When a*
is specified, the width or precision is taken from the replacement tuple and must be and integer. Both the presence and type of these are checked:(The behaviour of the last example depends on the version of Python. On my Mac, Python 3.4 just prints a
%
, while Python 2.7 prints ' %'. However, both expect anint
in the replacement tuple, so type checking is identical.)Key mapping
A conversion specifier may contain a key mapping, like the
foo
in%(foo)s
. Specifiers with key mappings may not be mixed with specifiers without mappings. In addition, when key mappings are used, the minimum field with and precision components must not be a star. These errors are checked for:When key mappings are used, the replacement must be a dictionary. When a dictionary expression is supplied and all keys are string literals, then also the presence and type of the mapping is checked: