Skip to content
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

feat: support generic types and | operator #2609

Closed
wants to merge 6 commits into from

Conversation

PrettyWood
Copy link
Member

@PrettyWood PrettyWood commented Mar 30, 2021

Change Summary

Now this is possible with python 3.7+

from __future__ import annotations

from pydantic import BaseModel, Field

class User(BaseModel, validate_assignment=True):
    first_name: int | str
    last_name: str | None = None
    friends: list[User] = Field(default_factory=list)
    metadata: dict[str, int] | None = None

user = User(first_name='pika', last_name=666)

assert user.last_name == '666'
assert user.friends == []
user.metadata = {b'1': b'1'}
assert m.user.metadata == {'1': 1}

Related issue number

Checklist

  • Unit tests for the changes exist
  • Tests pass on CI and coverage remains at 100%
  • Documentation reflects the changes where applicable
  • changes/<pull request or issue id>-<github username>.md file added describing change
    (see changes/README.md for details)

@samuelcolvin
Copy link
Member

I'm assuming this is still a work in progress? let me know when you want me to review it.

(please update (just for the bot to assign you 😄))

Copy link
Member

@samuelcolvin samuelcolvin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've just had a quick read of this, it looks great to me.

setup.py Outdated
@@ -133,6 +133,7 @@ def extra(self):
extras_require={
'email': ['email-validator>=1.0.3'],
'dotenv': ['python-dotenv>=0.10.4'],
'future': ['future-typing>=0.4.0'],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we go with this, I think we'll need a more clear name for this extra.

@PrettyWood PrettyWood marked this pull request as ready for review May 14, 2021 13:08
else:
# We need a merged version of typing (with typing_extensions) to
# ensure we can resolve things like `Literal` or `Annotated` with older versions
from . import typing_merge
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At first I did something like

all_typing_mod_name = 'pydantic_all_typing___'
all_typing_mod = types.ModuleType(all_typing_mod_name)
exec("from typing import *\nfrom typing_extensions import *", all_typing_mod.__dict__)

But since using eval() is problematic with cython, I went with this approach.

@PrettyWood
Copy link
Member Author

I wrote some documentation. Feedback welcome! Please review

br3ndonland added a commit to br3ndonland/inboard that referenced this pull request Jul 5, 2021
pydantic models aren't yet compatible with Python 3.10 type annotations.
See pydantic/pydantic#2597 and pydantic/pydantic#2609.
@PrettyWood PrettyWood added deferred deferred until future release or until something else gets done and removed ready for review labels Sep 4, 2021
@PrettyWood
Copy link
Member Author

Let's focus on 3.10 and see if people actually want this.
With the switch from PEP 563 to 649, I don't know how it will affect the future.annotations.
And supporting only generics and unions but not some types or forwardrefs may create more support.
I tag this PR as deferred in the meantime

@elyase
Copy link

elyase commented Oct 19, 2021

I was surprised to see that pydantic doesnt support the | operator. Would love to have this merged.

@tuchandra
Copy link

tuchandra commented Mar 30, 2022

Let's focus on 3.10 and see if people actually want this. With the switch from PEP 563 to 649, I don't know how it will affect the future.annotations. And supporting only generics and unions but not some types or forwardrefs may create more support. I tag this PR as deferred in the meantime

Hi @PrettyWood - I'd like to give a +1 in support of landing this if still possible. I think the support for unions & generics will cover 80+% of cases; it'd be nice to write x: str | None, and I suspect that the majority of the utility comes from simple stuff like this.

Forward refs in particular have always been a little bit of a thorn (even with the stdlib), and so I don't think it needs to block something like this that supports the simpler cases.

@PrettyWood
Copy link
Member Author

@tuchandra If you use 3.10, it's already supported. This PR is to have a workaround for python 3.7+ using from __future__ import annotations but I don't think it's worth merging it.

@tuchandra
Copy link

@PrettyWood sorry, I wasn't clear - yeah, I'm on 3.8/3.9 but I understand not merging it. Thanks for the reply!

br3ndonland added a commit to br3ndonland/inboard that referenced this pull request Apr 2, 2022
This commit will update type annotation syntax for Python 3.10. The
project currently also supports Python 3.8 and 3.9, so the annotations
are imported with `from __future__ import annotations`.

The Python 3.10 union operator (the pipe, like `str | None`) will not be
used on pydantic models. If running Python 3.9 or below, pydantic is not
compatible with the union operator, even if annotations are imported
with `from __future__ import annotations`.

https://peps.python.org/pep-0604/
https://docs.python.org/3/whatsnew/3.10.html
pydantic/pydantic#2597 (comment)
pydantic/pydantic#2609 (comment)
pydantic/pydantic#3300 (comment)
@samuelcolvin
Copy link
Member

@tuchandra If you use 3.10, it's already supported. This PR is to have a workaround for python 3.7+ using from __future__ import annotations but I don't think it's worth merging it.

agreed

@eseglem
Copy link

eseglem commented Aug 7, 2022

I understand not merging as well but I would certainly love to see something like this actually get merged. Its not great but unfortunately I have systems stuck with 3.8 for the foreseeable future and it would be nice to use the newer syntax.

It could also be useful for packages that use Pydantic which still support older versions of python as well.

But honestly, it probably better to focus on the future.

@samuelcolvin
Copy link
Member

I really think this would have been too confusing for users, we were right to drop it.

On a related note, see #4339.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
deferred deferred until future release or until something else gets done
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants