-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
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: add support for NamedTuple
and TypedDict
types
#2216
feat: add support for NamedTuple
and TypedDict
types
#2216
Conversation
Codecov Report
@@ Coverage Diff @@
## master #2216 +/- ##
===========================================
- Coverage 100.00% 99.88% -0.12%
===========================================
Files 21 23 +2
Lines 4199 4405 +206
Branches 854 886 +32
===========================================
+ Hits 4199 4400 +201
- Misses 0 5 +5
Continue to review full report at Codecov.
|
16d53eb
to
da3d88f
Compare
namedtuple
typeNamedTuple
and TypedDict
types
da3d88f
to
0cbe31f
Compare
d472bf0
to
9a2dba9
Compare
9a2dba9
to
de54b65
Compare
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.
This looks awesome, would be great if we could have a proper example in the docs.
`typing.Dict` | ||
: see [Typing Iterables](#typing-iterables) below for more detail on parsing and validation | ||
|
||
`subclass of typing.TypedDict` |
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.
`subclass of typing.TypedDict` | |
`typing.TypedDict` |
I think the subclass is implicit
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.
It used to be the case for me too but I now tend to disagree since we added the support of enum.Enum
to have a valid enum instance. We could someday add typing.TypedDict
just to have a valid TypedDict
instance for example. WDYT?
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 would still prefer to remove subclass of
and instead be explicity when we mean the actual type, like Enum
.
docs/usage/types.md
Outdated
@@ -85,9 +85,17 @@ with custom properties and validation. | |||
`typing.Tuple` | |||
: see [Typing Iterables](#typing-iterables) below for more detail on parsing and validation | |||
|
|||
`subclass of typing.NamedTuple (or collections.namedtuple)` |
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.
`subclass of typing.NamedTuple (or collections.namedtuple)` | |
`typing.NamedTuple` (or `collections.namedtuple`) |
again I think the "subclass of..." is implicit
pydantic/typing.py
Outdated
def is_typed_dict_type(type_: Type[Any]) -> bool: | ||
from .utils import lenient_issubclass | ||
|
||
return lenient_issubclass(type_, dict) and getattr(type_, '__annotations__', None) |
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.
Humm, I wonder if this is a water tight check. I can't think of a better solution though.
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.
Currently there is no easier way afaik. There will be a public method in 3.10 though
tests/test_main.py
Outdated
@@ -1425,3 +1434,90 @@ class M(BaseModel): | |||
a: int | |||
|
|||
get_type_hints(M.__config__) | |||
|
|||
|
|||
def test_named_tuple(): |
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 know test files are a mess, but please can you move this to somewhere else. I try to keep test_main.py
for the most vanilla cases.
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.
Sure thing! TBH I didn't know it was for vanilla cases. Maybe a module docstring on top of the module could help. I'll try to find a better place for these bad boys
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 created a new dedicated file test_annotated_types
. Suggestions welcome if you don't like it
Ok I added a dedicated section in the doc for both annotated types and took your remarks into account except the |
This looks great, I'll be putting it to good use, thanks! However there is an issue that this does not respect subclassing, for example, the following will raise a class OptionalUser(TypedDict, total=False):
name: str
class User(OptionalUser):
id: int
class Model(BaseModel):
user: User
Model(user={'id': 1}) I had a quick look to try and fix this issue but couldn't find a complete solution. There are If there is no universal solution for this issue then |
Hi @RobertCraigie EDIT: I added a commit. Feedback welcome :) |
Glad I could help! I would also like to be able to explicitly forbid passing extra keys, is this feasible? |
d3477f1
to
63f4a1e
Compare
@RobertCraigie Sure easy peasy ! :) Just needed to pass down the |
9376bb5
to
ebfd440
Compare
c68515d
to
8221ce2
Compare
10941ab
to
d737f07
Compare
ae66729
to
ee7033a
Compare
|
||
if TYPE_CHECKING: | ||
|
||
class TypedDict(Dict[str, Any]): |
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.
We could use typing_extensions.TypedDict
for python < 3.9 or typing.TypedDict
for 3.9+ but we would need to add typing_extensions
in linting requirements.
@@ -4,5 +4,5 @@ Cython==0.29.21;sys_platform!='win32' | |||
devtools==0.6.1 | |||
email-validator==1.1.2 | |||
dataclasses==0.6; python_version < '3.7' | |||
typing-extensions==3.7.4.1; python_version < '3.8' | |||
typing-extensions==3.7.4.3; python_version < '3.9' |
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.
Had to bump this to have the good version of TypedDict
for python < 3.9
ee7033a
to
9481776
Compare
Is there any timeframe for when we can expect this to get released? :) |
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.
this is going to be f***ing awesome. Can't wait for it.
Just a few small things.
`typing.Dict` | ||
: see [Typing Iterables](#typing-iterables) below for more detail on parsing and validation | ||
|
||
`subclass of typing.TypedDict` |
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 would still prefer to remove subclass of
and instead be explicity when we mean the actual type, like Enum
.
@@ -16,6 +17,9 @@ | |||
# WARNING __all__ from .errors is not included here, it will be removed as an export here in v2 | |||
# please use "from pydantic.errors import ..." instead | |||
__all__ = [ | |||
# annotated types utils | |||
'create_model_from_namedtuple', |
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.
yes agree, perhaps we might want create_model_from
which takes any of the three types, but we definitely want these standalone methods for performance.
Or we could go even further and extend create_model
to take a single dataclass, named tuple or typed dict instead of fields?
@samuelcolvin Feedback taken except for the rewording on |
Don't worry about it, the whole file needs rethinking, what's there is fine. I'll merge tomorrow. |
🎉 this is great, thank you so much. |
Change Summary
Also expose two utils
create_model_from_namedtuple
create_model_from_typeddict
Related issue number
fix #760
fix #1324
fix #1430
Checklist
changes/<pull request or issue id>-<github username>.md
file added describing change(see changes/README.md for details)