-
-
Notifications
You must be signed in to change notification settings - Fork 535
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
WIP: Pydantic v2 compat #2888
WIP: Pydantic v2 compat #2888
Conversation
Codecov Report
Additional details and impacted files@@ Coverage Diff @@
## main #2888 +/- ##
==========================================
- Coverage 96.11% 94.64% -1.48%
==========================================
Files 211 219 +8
Lines 9232 9591 +359
Branches 1489 1562 +73
==========================================
+ Hits 8873 9077 +204
- Misses 229 367 +138
- Partials 130 147 +17 |
use_pydantic_alias: bool = True, | ||
) -> Callable[..., Type[StrawberryTypeFromPydantic[PydanticModel]]]: | ||
def wrap(cls: Any) -> Type[StrawberryTypeFromPydantic[PydanticModel]]: | ||
model_fields: Dict[str, FieldInfo] = model.model_fields |
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.
in pydantic v1 this was ModelFields, but its now FieldInfo in pydantic v2. The FieldInfo
also does not contain the name of the field itself, so now its a dit.
Hi, thanks for contributing to Strawberry 🍓! We noticed that this PR is missing a So as soon as this PR is merged, a release will be made 🚀. Here's an example of Release type: patch
Description of the changes, ideally with some examples, if adding a new feature. Release type can be one of patch, minor or major. We use semver, so make sure to pick the appropriate type. If in doubt feel free to ask :) Here's the tweet text:
|
age: int | ||
password: Optional[str] | ||
|
||
@strawberry.experimental.pydantic2.type(UserModel, all_fields=True) |
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.
for now its just pydantic2
, for the lack of a better name
fee8e8d
to
f582d41
Compare
for more information, see https://pre-commit.ci
|
||
# Note that unlike pydantic v1, pydantic v2 does not add a default of None when | ||
# the field is Optional[something] | ||
# so there is no need to handle that case here |
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.
eb59415
to
c7a9b8c
Compare
for more information, see https://pre-commit.ci
CodSpeed Performance ReportMerging #2888 will not alter performanceFalling back to comparing Summary
|
"--ignore=tests/mypy", | ||
"--ignore=tests/pyright", | ||
"--ignore=tests/experimental/pydantic", | ||
"--ignore=tests/experimental/pydantic2", | ||
) |
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.
otherwise pytest on the pydantic2 folder would go boom. since it tries to import stuff directly from pydantic v2.
# We don't recommend using it yet | ||
__all__ = ["pydantic2"] | ||
except ImportError as e: | ||
pass |
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.
explicitly a separate module
for more information, see https://pre-commit.ci
@thejaminator I was just curious if we had any idea on timeline for when we would feel comfortable with someone using pydantic v2 in a production type environment? I know your comment above mentioned that this MR is just adding initial support, and we wouldn't recommend people using it. Not sure this is the right place to ask, but I was also wondering if there has been any talk of removing the experimental tag from pydantic in general? Our team has found a ton of value out of using the pydantic integration with strawberry. For better or worse we've been using the existing experimental pydantic support in our production environments for over a year without any issues. |
I’m going to chat with James next week about this :)
That’s good to know, I think we could do that, but we’d need to make sure we have enough bandwidth to fix issues once this is marked as non experimental there’s also an idea of doing first class support for pydantic in future, so maybe this integration could not be that useful anymore? Also @ppease do you think your company could be interested in sponsoring us to work a bit on this? that’d be very helpful |
Thanks for the quick response. Is this the right issue to follow to get updates on work being done with pydantic v2? Also I'd be willing to try an early version of stuff and report any bugs if that would help you all out.
I'm assuming this issue is what you mean by first class support? If so I do think first class support would help us because that is one of the pain points right now with using the experimental support is having to create duplicate types. There will probably still be cases where we end up creating duplicate classes because we want to expose different items at the graphql layer vs. our data model layer so maybe the experimental support would still be useful for those use cases? I could also see different ways of doing that with a more first class built in way as well.
We are not too big of a company so I can't make any promises, but I'll bring it up. At a minimum we might be able to commit some time from myself or another dev to try and help out as well. |
Making the MR here isntead (did a compat file instead of a different folder) |
@ppease can you try this release? |
@patrick91 I just saw this. I probably won't have time this week, and I'm OOO next week. However, when I get back, I should be able to prioritize trying this out. |
Hi there, I'm currently running @strawberry.experimental.pydantic.type(model=PydanticOne, all_fields=True)
class One:
@strawberry.field
def two(self: 'One') -> 'Two':
return Two()
@strawberry.experimental.pydantic.type(model=PydanticTwo, all_fields=True)
class Two:
@strawberry.field
def one(self: 'Two') -> 'One':
return One() Type hints work as expected, but at runtime whichever type is defined second fails to resolve the forward ref on the strawberry.field.
Side note, this error message was difficult to debug as nowhere in the stack trace does it specify the filename or class the unresolved field belongs to. I can use @strawberry.experimental.pydantic.type(model=PydanticOne, all_fields=True)
class Two:
@strawberry.field
def one(self: 'Two') -> LazyType['One', __name__]:
return One() |
@patrick91 Sorry for taking a while to respond to this. I tried the latest version of strawberry, 0.208.1, with my graphql project, and I was able to generate a schema that matched my existing schema aside from some stuff moving around which was related to alphabetical order. I did have to comment out two fields. One that was using conint, and another one that was using EmailStr. It looks like inside of strawberry/experimental/pydantic/fields.py we already have a FIELDS_MAP to map from pydantic specific types to the base type. If both of those fields are fully supported in pydantic v2, could I just add those to the pydantic v2 field map? Another data point is I ran all of our unit tests for our graphql code and those passed as well so this seems like a really promising start! I plan on doing more testing in our dev environment this week, and I'll report back any issues I find. |
@ppease feel free to open issues or send PRs 😊 |
This PR provides basic functionality for pydantic v2. I do not recommend people to actually use it, but would like to merge this in first so that others can get work started on it.
This is done by creating a new directory inside strawberry, that is a sister subdirectory to pydantic v1.
This does duplicate a lot of code, but the upside is that
if pydantic version == 1
logicif pydantic version == 1
at run time messes up your IDE and type checkers. (or at least it did for me)FastAPI did take the other approach of having a compat module, and a bunch of
if pydantic version == 1
logic scattered around tests and files. I'm not sure which of these ways are better. Having a shared module like them could have been better if we really are commiting to continue to support pydantic v1 when we introduce new fixes. But I do think that it would slow us down in the sense of developing something new on pydantic v2 (because we are scared to break pydantic v1 stuff)For tests, i've only added some of them so far. I'll add the rest of them in from pydantic v1 over the next few MRs. Not all the tests have the same behavior between pydantic v1 and v2.
Description
Types of Changes
Issues Fixed or Closed by This PR
Checklist