Uh oh!
There was an error while loading. Please reload this page.
Add initial LiteralString support - #13664
Conversation
sobolevn
commented
Sep 14, 2022
Current failures show that we need to special case this: x='a'x='Value: {}'.format(x) |
This comment has been minimized.
This comment has been minimized.
| expects_literal_string('a') | ||
| expects_literal_string('a' + 'b') | ||
| expects_literal_string('a' * 2) |
There was a problem hiding this comment.
Why do we need to care about this at all? Isn't this just a question of defining these correctly in typeshed? For example:
@overloaddef__add__(self: LiteralStr, other: LiteralStr) ->LiteralStr: ...
@overloaddef__add__(self, other: str) ->str: ...It seems to be much easier to agree on this once and for all rather than special-casing all these in all type-checkers.
There was a problem hiding this comment.
Good question! I think that we should have both.
Typeshed will store the base implementation for it.
But, mypy can go further with full literal type math.
Or we can just use the typeshed if ltm is never merged / implemented.
There was a problem hiding this comment.
OK, I see, but as I said below, we need to be sure "typeshed way" will work well. Having "a" + "b" accepted where Literal["ab"] is expected is lower priority IMO.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
sobolevn
commented
Sep 14, 2022
I consider the very first version done! 🎉 |
This comment has been minimized.
This comment has been minimized.
Primer output
|
This comment has been minimized.
This comment has been minimized.
1 similar comment
This comment has been minimized.
This comment has been minimized.
hauntsaninja
commented
Sep 15, 2022
Currently we patch typeshed... Can we revert #13093 in this PR and see if everything works? |
JukkaL
left a comment
There was a problem hiding this comment.
Thanks for working on this! This is an important feature to have now that 3.11 will be soon out. Not a full review .
| T = TypeVar('T', bound=LiteralString) | ||
| def expects_literal_string(x: T): ... | ||
| expects_literal_string('a') |
There was a problem hiding this comment.
Maybe also test something like this:
ls: Literal['a'] =expects_literal_string('a')| @overload | ||
| def some(x: LiteralString, y: LiteralString) -> LiteralString: ... | ||
| @overload | ||
| def some(x: str, y: str) -> str: ... |
There was a problem hiding this comment.
Test also a str method with self annotated as self: LiteralString in one overload variant (e.g. for __add__)? This way we should be able to make 'x' + 'y' be a LiteralString without special casing?
There was a problem hiding this comment.
I actually tried this and mypy gives an error like Self type is not a supertype of class. I think this is too strict, we already check self-type at call site. I would say we can simply skip this check for overloads (maybe only keep it for overload implementation).
There was a problem hiding this comment.
Just to be clear, I think we still need this test, see also my comment above #13664 (comment)
| @@ -0,0 +1,57 @@ | |||
| # Builtins stub used in tuple-related test cases. | |||
ilevkivskyi
commented
Sep 16, 2022
+1 to this idea. |
sobolevn
commented
Sep 16, 2022
I am away for a week, I will return to this shortly after I get home! Thanks for your feedback. |
sobolevn
commented
Oct 10, 2022
Adding this back to my todo list :) |
Diff from mypy_primer, showing the effect of this PR on open source code: sphinx (https://github.com/sphinx-doc/sphinx)
+ sphinx/setup_command.py:133:43: error: Argument 1 to "join" has incompatible type "str"; expected "LiteralString" [arg-type]
psycopg (https://github.com/psycopg/psycopg)
+ psycopg/psycopg/_typeinfo.py:93: error: Argument 1 to "execute" of "Cursor" has incompatible type "str"; expected "Union[LiteralString, bytes, SQL, Composed]" [arg-type]+ psycopg/psycopg/_typeinfo.py:112: error: Argument 1 to "execute" of "AsyncCursor" has incompatible type "str"; expected "Union[LiteralString, bytes, SQL, Composed]" [arg-type]+ psycopg/psycopg/server_cursor.py:170: error: Argument 1 to "SQL" has incompatible type "str"; expected "LiteralString" [arg-type]+ psycopg/psycopg/server_cursor.py:179: error: Incompatible types in assignment (expression has type "str", variable has type "Union[LiteralString, bytes, SQL, Composed]") [assignment]+ psycopg/psycopg/server_cursor.py:181: error: Argument 1 to "SQL" has incompatible type "Union[LiteralString, bytes]"; expected "LiteralString" [arg-type]+ psycopg/psycopg/server_cursor.py:188: error: Argument 1 to "SQL" has incompatible type "str"; expected "LiteralString" [arg-type]+ psycopg/psycopg/connection.py:1024: error: Argument 1 to "execute" of "Cursor" has incompatible type "str"; expected "Union[LiteralString, bytes, SQL, Composed]" [arg-type]+ psycopg/psycopg/connection_async.py:430: error: Argument 1 to "execute" of "AsyncCursor" has incompatible type "str"; expected "Union[LiteralString, bytes, SQL, Composed]" [arg-type]+ tests/scripts/dectest.py:31: error: Argument 1 to "copy" of "Cursor" has incompatible type "str"; expected "Union[LiteralString, bytes, SQL, Composed]" [arg-type]+ tests/scripts/dectest.py:40: error: Argument 1 to "executemany" of "Cursor" has incompatible type "str"; expected "Union[LiteralString, bytes, SQL, Composed]" [arg-type]+ tests/crdb/test_copy.py:209: error: Argument 1 to "SQL" has incompatible type "str"; expected "LiteralString" [arg-type]+ tests/crdb/test_copy_async.py:215: error: Argument 1 to "SQL" has incompatible type "str"; expected "LiteralString" [arg-type]+ tests/test_sql.py:466: error: Argument 1 to "SQL" has incompatible type "str"; expected "LiteralString" [arg-type]+ tests/test_sql.py:534: error: Argument 1 to "SQL" has incompatible type "str"; expected "LiteralString" [arg-type]+ tests/types/test_numeric.py:580: error: Argument 1 to "SQL" has incompatible type "str"; expected "LiteralString" [arg-type]
spark (https://github.com/apache/spark)
+ python/pyspark/pandas/sql_formatter.py:194: error: Signature of "vformat" incompatible with supertype "Formatter" [override]+ python/pyspark/pandas/sql_formatter.py:194: note: Superclass:+ python/pyspark/pandas/sql_formatter.py:194: note: @overload+ python/pyspark/pandas/sql_formatter.py:194: note: def vformat(self, format_string: LiteralString, args: Sequence[LiteralString], kwargs: Mapping[LiteralString, LiteralString]) -> LiteralString+ python/pyspark/pandas/sql_formatter.py:194: note: @overload+ python/pyspark/pandas/sql_formatter.py:194: note: def vformat(self, format_string: str, args: Sequence[Any], kwargs: Mapping[str, Any]) -> str+ python/pyspark/pandas/sql_formatter.py:194: note: Subclass:+ python/pyspark/pandas/sql_formatter.py:194: note: def vformat(self, format_string: str, args: Sequence[Any], kwargs: Mapping[str, Any]) -> str |
sobolevn
commented
Dec 9, 2022
Working on it! |
ilevkivskyi
commented
Aug 12, 2023
@sobolevn It looks like you may have forgotten about this one :-) It would be great to finally finish this. |
sobolevn
commented
Aug 13, 2023
Yes, I am sorry :( I will try to finish this next week! |
DragonMinded
commented
Feb 17, 2026
@sobolevn I think this got lost again? I'm hoping to use |
sobolevn
commented
Feb 17, 2026
Sorry, I don't have time right now to work on this :( |
I went for the smallest possible diff in this feature.
There are couple of other options I did not want to go with:
class LiteralStringTypeand using it inlast_known_value. There are lots of places where.last_known_valueis used for literal context checking. In this case we would also need to add new visitor methods to every type visitor, which is way harderLiteralString(str)type infoLiteralStringwith_promotehackeryTODO in the next PRs:
x: LiteralString = 'a' + 'b'--enable-incomplete-featuresflag from this featureRefs #12554