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

Pydantic v2 support #2972

Merged
merged 34 commits into from
Aug 7, 2023
Merged

Conversation

thejaminator
Copy link
Contributor

@thejaminator thejaminator commented Jul 22, 2023

Description

Types of Changes

Adds initial support for pydantic V2.

This is extremely experimental for wider initial testing.

We do not encourage using this in production systems yet.

  • Core
  • Bugfix
  • New feature
  • Enhancement/optimization
  • Documentation

Issues Fixed or Closed by This PR

Checklist

  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have read the CONTRIBUTING document.
  • I have added tests to cover my changes.
  • I have tested the changes and verified that they work and don't break anything (as well as I can manage).

@thejaminator thejaminator mentioned this pull request Jul 22, 2023
11 tasks
@botberry
Copy link
Member

botberry commented Jul 22, 2023

Thanks for adding the RELEASE.md file!

Here's a preview of the changelog:


Adds initial support for pydantic V2.

This is extremely experimental for wider initial testing.

We do not encourage using this in production systems yet.


Here's the preview release card for twitter:

Here's the tweet text:

🆕 Release (next) is out! Thanks to James Chua for the PR 👏

Get it here 👉 https://github.com/strawberry-graphql/strawberry/releases/tag/(next)

This reverts commit dc0b9dd.
@codecov
Copy link

codecov bot commented Jul 22, 2023

Codecov Report

Merging #2972 (d78d907) into main (1cb0edb) will decrease coverage by 0.03%.
The diff coverage is 96.18%.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2972      +/-   ##
==========================================
- Coverage   96.50%   96.47%   -0.03%     
==========================================
  Files         467      469       +2     
  Lines       29050    29144      +94     
  Branches     3570     3587      +17     
==========================================
+ Hits        28035    28117      +82     
- Misses        829      840      +11     
- Partials      186      187       +1     

@codspeed-hq
Copy link

codspeed-hq bot commented Jul 22, 2023

CodSpeed Performance Report

Merging #2972 will not alter performance

Comparing thejaminator:compat_folder (d78d907) with main (1cb0edb)

Summary

✅ 12 untouched benchmarks

],
]
if IS_PYDANTIC_V1
else [],
Copy link
Contributor Author

Choose a reason for hiding this comment

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

need to do this trick otherwise it will still getattr on the pydantic namespace and explode

allow_none: bool
has_alias: bool
description: Optional[str]

Copy link
Contributor Author

Choose a reason for hiding this comment

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

we have a compat file (inspired by how fastapi does it) to work with both versions

@thejaminator thejaminator changed the title WIP: Pydantic v2 Pydantic v2 support Jul 22, 2023
else:
field = PydanticModelField.deserialize(
info=ctx.cls.info, data=data, api=ctx.api
)
pydantic_fields.add(field)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

they also change their plugin

@@ -112,7 +112,7 @@ channels = "^3.0.5"
Django = ">=3.2"
fastapi = {version = ">=0.65.0", optional = false}
flask = ">=1.1"
pydantic = {version = "<2", optional = false}
pydantic = {version = ">1.6.1", optional = false}
pytest-aiohttp = "^1.0.3"
Copy link
Contributor Author

@thejaminator thejaminator Jul 23, 2023

Choose a reason for hiding this comment

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

set this back to >1.6.1 and update lock file (am I doing this right?)

@@ -159,6 +159,9 @@ jobs:

- run: poetry install --with integrations
if: steps.setup-python.outputs.cache-hit != 'true'
# Since we are running all the integrations at once, we can't use
# pydantic v2. It is not compatible with starlette yet
- run: poetry run pip install pydantic==1.10

Copy link
Contributor Author

Choose a reason for hiding this comment

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

errr otherwise starlette goes boom

@thejaminator
Copy link
Contributor Author

/pre-release

Copy link
Member

@patrick91 patrick91 left a comment

Choose a reason for hiding this comment

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

this looks awesome so far! I've left some minor nitpicks

I'm sure @Kludex will be proud 😉

noxfile.py Outdated Show resolved Hide resolved
strawberry/experimental/pydantic/error_type.py Outdated Show resolved Hide resolved
Comment on lines +15 to +17
get_args,
get_origin,
is_new_type,
Copy link
Member

Choose a reason for hiding this comment

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

I wonder if we should have these on our typing module?

Comment on lines 85 to 95
Most of these fields are not supported by pydantic V2
"""
FIELDS_MAP = (
{
getattr(pydantic, field_name): type
for field_name, type in ATTR_TO_TYPE_MAP.items()
if hasattr(pydantic, field_name)
}
if not IS_PYDANTIC_V2
else {}
)
Copy link
Member

Choose a reason for hiding this comment

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

I think quite a few are still supported, no?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

will investigate further in an issue / PR because i think pydantic v2's types are just normal annotated types that should work out of the box

Comment on lines 12 to 13
IS_PYDANTIC_V2: bool = PYDANTIC_VERSION.startswith("2.")
IS_PYDANTIC_V1: bool = not IS_PYDANTIC_V2
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
IS_PYDANTIC_V2: bool = PYDANTIC_VERSION.startswith("2.")
IS_PYDANTIC_V1: bool = not IS_PYDANTIC_V2
IS_PYDANTIC_V2: bool = PYDANTIC_VERSION.startswith("2.")
IS_PYDANTIC_V1: bool = PYDANTIC_VERSION.startswith("1.")

we might have this code until v3 :P

strawberry/experimental/pydantic/v2_compat.py Outdated Show resolved Hide resolved
tests/experimental/pydantic/schema/test_defaults.py Outdated Show resolved Hide resolved
tests/experimental/pydantic/test_fields.py Outdated Show resolved Hide resolved
@patrick91
Copy link
Member

/pre-release

@botberry
Copy link
Member

Pre-release

👋

Releasing commit [f17ee94] to PyPi as pre-release! 📦

@botberry
Copy link
Member

Pre-release

👋

Pre-release 0.196.0.dev.1690222024 [f17ee94] has been released on PyPi! 🚀
You can try it by doing:

poetry add strawberry-graphql==0.196.0.dev.1690222024

- run: |
poetry run pytest --cov=. --cov-append --cov-report=xml -n auto --showlocals -vv

poetry run pytest --cov=. --cov-append --cov-report=xml -n auto --showlocals --ignore tests/mypy -vv
- name: coverage xml
Copy link
Contributor Author

Choose a reason for hiding this comment

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

ignores mypy for windows

Copy link
Member

@patrick91 patrick91 left a comment

Choose a reason for hiding this comment

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

Let's get this out! Thanks @thejaminator <3

@patrick91 patrick91 merged commit 0737532 into strawberry-graphql:main Aug 7, 2023
@@ -25,6 +32,10 @@
TypingGenericAlias = ()
else:
raise
if sys.version_info < (3, 10):
Copy link

@Mark90 Mark90 Aug 9, 2023

Choose a reason for hiding this comment

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

Hi, not sure if anyone will read this comment, but it is related to this change I believe.

On Python 3.9 I'm noticing some issues here when (indirectly) importing from this module:

from strawberry.experimental.pydantic.conversion_types import StrawberryTypeFromPydantic
/usr/local/lib/python3.9/site-packages/strawberry/experimental/pydantic/__init__.py:3: in <module>
    from .object_type import input, interface, type
/usr/local/lib/python3.9/site-packages/strawberry/experimental/pydantic/object_type.py:31: in <module>
    from strawberry.experimental.pydantic.fields import replace_types_recursively
/usr/local/lib/python3.9/site-packages/strawberry/experimental/pydantic/fields.py: in <module>
    from types import UnionType as TypingUnionType
E   ImportError: cannot import name 'UnionType' from 'types' (/usr/local/lib/python3.9/types.py)

On Python 3.10 and 3.11 it works fine.

From reading the import handling here I think it makes sense because it seems that this is what happens for different python versions;

Python 3.8 -> ImportError on UnionType

  • TypingGenericAlias = ()
  • TypingUnionType = ()

Python 3.9 -> ImportError on UnionType

  • Re-raise error

Python 3.10 -> (no import error)

  • TypingGenericAlias = typing.GenericAlias
  • TypingUnionType = types.UnionType

Copy link
Member

Choose a reason for hiding this comment

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

@Mark90 this should be fixed now 😊

Copy link

Choose a reason for hiding this comment

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

Great :) Thanks for notifying me!

etripier pushed a commit to Greenbax/strawberry that referenced this pull request Oct 25, 2023
* work so far

* add modelfield

* it works kinda

* fix missing type

* fix default tesT

* skip tests for constrained types

* add tests pass?

* ruff

* Revert "ruff"

This reverts commit dc0b9dd.

* make most of mypy happy

* make linters and mypy happy

* fix pydantic v1 import

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* remove extra ruff

* fix tests for pydantic v1

* remove weird stuff ruff added

* add release file

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* bump pydantic in pyproject.toml

* upgrade pydantic lock file

* remove unused

* fix mypy

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* fix poetry

* remove implicit default test

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* force pydantic 1.10

* Update noxfile.py

Co-authored-by: Patrick Arminio <[email protected]>

* Update tests/experimental/pydantic/schema/test_defaults.py

Co-authored-by: Patrick Arminio <[email protected]>

* rename v2_compat -> _compat

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* ignore mypy windows tests

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Patrick Arminio <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants