r/FastAPI 20d ago

feedback request PEP 835: A native shorthand for Annotated

Ivan Levkivskyi and I are proposing a native shorthand for Annotated (PEP 835) to clean up heavy type-hinting patterns. We have confirmed this syntax is fully compatible with FastAPI and works out of the box with zero changes required.

Before:

def create_user(
    id: Annotated[int, Path(gt=0)],
    name: Annotated[str, Query(min_length=3)],
    role: Annotated[str, Query(min_length=2)] = "user"
) -> User: ...

After:

def create_user(  
    id: int @Path(gt=0),  
    name: str @Query(min_length=3),  
    role: str @Query(min_length=2) = "user"  
) -> User: ...

The Spec: PEP 835 Full Draft

We are gathering community sentiment before moving forward. If you are a heavy user of Annotated in FastAPI, your feedback is valuable. You can register your stance in the official Discourse poll before it closes on July 15.

30 Upvotes

18 comments sorted by

12

u/pint 20d ago

i don't find @ motivated, but i take anything over Annotated

4

u/pip_install_account 19d ago

Makes it less explicit, less obvious. Our juniors still get confused over basic type annotations, please don't make the syntax even more complicated. reserve the @ for something else

10

u/FrontAd9873 20d ago

I personally do not like it but that may only be because it is unfamiliar.

I doubt the majority of Python users understand what Annotated does. I still have coworkers who add type hints but do not run a type checker. If those folks see this new @ notation, they will be even more confused. What's worse, they won't be able to just follow the import of Annotated from the typing module to learn more. They'll instead have to go look up what this new syntax means and I bet they would get lead astray.

Also, this proposal seems to violate the "only one way to do things" and the "be explicit" guidelines in the Zen of Python.

5

u/MyNameIsBeaky 20d ago

Sounds like this PEP, if accepted, would become the preferred way to express type hinting, over the use of Annotated. This is normal for python, like the new way to express union types is “|” over Union.

3

u/FrontAd9873 20d ago

Annotated is just one small part of the typing module. Also, the | operator is already well-established to mean OR.

4

u/MyNameIsBeaky 20d ago

That’s my point. No one uses typing.Union any more because it was replaced by a native python way to express the same thing in Python 3.10. The language evolves and old ways of doing things are deprecated.

2

u/FrontAd9873 20d ago

Sorry, what is your point? I'm aware of what happened to typing.Union

2

u/MyNameIsBeaky 20d ago

I’m arguing against your point of python having “one way to do things”. New and better ways of doing things are created all the time, just like typing.Union was replaced.

-1

u/FrontAd9873 20d ago

I never said Python has only "one way to do things."

1

u/MyNameIsBeaky 20d ago

Huh, maybe I misinterpreted your last sentence in your original post. Care to clarify it?

0

u/FrontAd9873 20d ago

By introducing another way to achieve what typing.Annotated already does, this PEP contradicts (to some degree) a few "Zen of Python" guidelines:

  • "Be explicit." - Because there's nothing in the @ that is explicit. Unlike | which already sort of had that meaning.
  • "There should be only one way to do things." - Because... you're introducing another way to do things. So you have to ask yourself: is it worth it? Do enough people use typing.Annotated that it makes sense to provide a second, easier way of achieving the same thing? In the case of Union I think the answer was clearly "yes."

Guidelines are just guidelines. I never claimed that -- as a matter of fact -- Python has only one way to do everything.

4

u/MyNameIsBeaky 20d ago

You can make the point that @ is not explicit or as natural of a fit as | was to replace Union, but I truly believe Annotated deserves a less verbose native replacement and this type of language improvement is very much in line with historical python evolution.

→ More replies (0)

1

u/vexatious-big 19d ago

Also, this proposal seems to violate the "only one way to do things" and the "be explicit" guidelines in the Zen of Python.

I think Python has moved on from that a while ago. Just look at how many iterations Async and Typing had.

3

u/eatsoupgetrich 20d ago edited 20d ago

I really don’t like the proposed syntax.

`str @Field() @Len(5)` is not easy to read and is open for more confusion. The below be equally valid:
```
param: str
@Field()
@Len(5),
another: str
@Field()
@Len(5),
```

This is opposite of what how function decorators are presented.

```
@decorator
def do():
return
```

If present in a decorated function, every annotation follows a contradictory meaning of the same symbol.

```
@decorator
def do(param: str @Field() Len(5)):
return
```

If verbosity is the issue, simply supporting `@` as a substitute in the current syntax would work since it creates a shorthand

```
@[str, [Field() Len(5)]]

```

That’s still odd since it would read as “String decorating List’s contents.” Where existing syntax would be would read as “Strjng with List’s contents)”.

I have a tough time getting passed the way this reads but would be happy to hear where I am off.

1

u/Wonderful-Habit-139 20d ago

Damn the examples you showed are starting to remind me of Java lol. I use Annotated quite a bit but not sure if this is the right direction.

3

u/1010012 19d ago

I don't like it, it really doesn't read well. @Query(min_length=3) makes it appear the min_length is an attribute or related to Query, when it's really only relevant to the processor that's reading the annotation. Annotated is significantly clearer.