-
-
Notifications
You must be signed in to change notification settings - Fork 32.1k
Consider making Template
and Interpolation
generic at runtime
#133970
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
Comments
One alternative is to make foo: str = ""
bar: int = 42
tmpl = t"x{foo}{bar}y"
assert_type(tmpl, Template[str, int])
assert_type(tmpl.values, tuple[str, int]) |
@srittau this would be also possible, if we just add |
Yes, I think we should do this, and it should be fine to do it during the beta phase as part of stabilizing the new feature. We'll have to decide in typeshed what the actual generic parameters are. I think it makes the most sense to use a single type parameter for both |
@JelleZijlstra ok, I will send a PR with |
cc @lysnikolaou @davepeck (edit: Lysandros was alredy tagged, sorry!) |
I think having
What do the question marks mean here? This isn't legal syntax. A |
This is how mypy pretty-prints type when |
Considering the two suggested approaches:
Walking through a simple example: def user_image(user: User, classes: Sequence[str] = None):
return t"<img src={user.image_url} alt={user.image_name} class={classes} />"
def user_details(user: User, attribs: Mapping = None, classes: Sequence[str] = None):
return t"""
<div {attribs}>
<span>{user.name} ({user.star_count})</span>
{user_image(user, classes)}
</div>
"""
# What's the type of this `Template`?
template = user_details(
some_user,
{"aria-label": user.name, "aria-hidden": False},
["rounded"]
) In this example:
In approach (1) we probably end up with In approach (2) I suppose we get something like |
I would think of this in terms of the type that you write if you accept a template. In your example, there might be a function |
Right. With approach (1) and the example above, I suppose we'd type it as (Sorry... maybe I'm just not thinking clearly about this?) |
Any big union can be just replaced with |
@davepeck If you don't want to be precise you can still write just |
Hah, yeah, sorry for my cobwebs here. 😅
Of the options, So why the cobwebs? Mostly just the realization that (a) real-world template processing code will essentially always have large unions for But both of those things are just fine! Okay, cobwebs cleared. Assuming we're all on the same page, LMK and I'll put together a PR for the PEP. PS: two minor things maybe worth mentioning:
|
The big unions might be alleviated a bit by aliases, especially if checkers can display them unexpanded. Probably they'll be necessary anyway, since you'd want to specify sub-templates recursively. For the default, |
(cherry picked from commit c3a1da5) Co-authored-by: sobolevn <mail@sobolevn.me>
I merged the runtime generics PR, but I won't close the issue, we can continue talking about semantics here :) |
I'm not sure about this. Yes, Tying ourselves to this specific design of making |
The runtime support is very simple; it just allows writing It's hard to do much with a vague "we need to think bigger", but it seems likely that any type system support for templates will involve some variation of Template + square brackets, whether those square brackets hold the types of the interpolations or something else. Having this support in CPython now means that even if we specify a type system feature later, people will be able to use it even in CPython 3.14. I'd encourage you to open a discussion in the typing section on Discuss to brainstorm what this bigger thing would look like. What would be helpful would be examples of how templates are expected to be used and what kinds of things you'd like type checkers to be able to help you catch. |
Probably any reference implementation for any of the type-checkers will also help a lot to decide what is best for the static typing. |
Okay, I misunderstood the PR then and this looks good.
I know that this is vague and I apologize for that. It's just that I can't really do better than that because I don't know what that "bigger thinking" might look like. There's ideas about combining type checking with static analysis for DSLs, but I don't think that's in scope for this thread. The recommendation to open a thread on Discuss is good. I also did a lightning talk in the language summit to get people to think about this stuff. I'll try to do it ASAP, but I'm not able to lead that discussion. |
Uh oh!
There was an error while loading. Please reload this page.
Feature or enhancement
Template
andInterpolation
will once be supported by type-checkers. And it might be worth adding generics support for these types.Example
Here we can see that
Interpolation[str]
can be useful in users' code.We can also benefit from generic
Template
, where we can make it generic based on exactTypeVarTuple
. Demo:https://mypy-play.net/?mypy=latest&python=3.13&gist=0dc13b3b926e1efb9783ab9b70d39ceb
This can potentially help type checkers to infer correct
Template
type.Current state
Current
typeshed
definitions: https://github.com/python/typeshed/blob/main/stdlib/string/templatelib.pyiHere's how
Template
is defined:Ideally, it should be generic on
TypeVarTuple
Here's how
Interpolation
is defined:Ideally, it should be generic on
value
.Interpolation[str]
means thatvalue
isstr
andInterpolation[tuple[int, int]]
means thatInterpolation
has avalue
for typetuple[int, int]
Proposal
From runtime's part with only need to add
Py_GenericAlias
, that's it.Is it too late for feature freeze? This is a minor detail, so I hope it is not :)
I have a PR ready.
CC @srittau @JelleZijlstra @lysnikolaou
Linked PRs
The text was updated successfully, but these errors were encountered: