-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
[3/n][pythonic config] Layer in Pydantic compat abstractions #16436
[3/n][pythonic config] Layer in Pydantic compat abstractions #16436
Conversation
Current dependencies on/for this PR:
This comment was auto-generated by Graphite. |
ee5378b
to
70a48e7
Compare
Deploy preview for dagster-docs ready! Preview available at https://dagster-docs-1mvswt01j-elementl.vercel.app Direct link to changed pages: |
if "Instance is frozen" in str( # Pydantic 2.x error | ||
e | ||
) or "is immutable and does not support item assignment" in str( # Pydantic 1.x error | ||
e | ||
): |
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.
is there any less fragile way of doing this?
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.
Still relevant comment
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.
Sadly no, not that I can tell. These values aren't set or exported as constants anywhere, just passed directly to the error constructor.
I've pulled this out into a separate fn for the moment. Our tests should at least catch if this changes.
def ensure_env_vars_set_post_init(set_value: T, input_value: Any) -> T: | ||
"""Pydantic 2.x utility. Ensures that Pydantic field values are set to the appropriate | ||
EnvVar or IntEnvVar objects post-model-instantiation, since Pydantic 2.x will cast | ||
EnvVar or IntEnvVar values to raw strings or ints as part of the model instantiation process. | ||
""" | ||
if isinstance(set_value, dict) and isinstance(input_value, dict): |
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.
do we have any context as to why Pydantic 2 does this? Are we going to break anything by doing this?
invalid_type=e.current_value, | ||
is_resource=model_cls is not None | ||
and safe_is_subclass(model_cls, ConfigurableResourceFactory), | ||
) | ||
|
||
shape_cls = Permissive if model_cls.__config__.extra == Extra.allow else Shape | ||
shape_cls = Permissive if model_config(model_cls).get("extra") == "allow" else Shape |
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.
is there a first-class way of doing this in pydantic 2?
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 can be extracted directly (outside of the compat layer), but still relies on a .get
call (it's an unstructured dictionary):
>>> MyModel2(a_str='foo').model_config
{'extra': 'allow'}
python_modules/dagster/dagster/_config/pythonic_config/pydantic_compat_layer.py
Outdated
Show resolved
Hide resolved
# Pydantic 1.x | ||
field_info = getattr(self.field, "field_info", None) | ||
if field_info: | ||
return field_info.description | ||
|
||
# Pydantic 2.x | ||
return getattr(self.field, "description", None) | ||
|
||
def is_required(self): | ||
# Pydantic 2.x | ||
if hasattr(self.field, "is_required"): | ||
return self.field.is_required() | ||
|
||
# Pydantic 1.x | ||
return self.field.required | ||
|
||
@property | ||
def discriminator(self): | ||
# Pydantic 2.x | ||
if hasattr(self.field, "discriminator"): | ||
return self.field.discriminator | ||
|
||
# Pydantic 1.x | ||
return getattr(self.field, "discriminator_key", 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.
should we just explicitly have different codepaths for each version here? I think that will be more bulletproof
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, that's a better approach I think. Reworked.
python_modules/dagster/dagster/_config/pythonic_config/pydantic_compat_layer.py
Outdated
Show resolved
Hide resolved
python_modules/dagster/dagster/_config/pythonic_config/pydantic_compat_layer.py
Outdated
Show resolved
Hide resolved
from pydantic import BaseModel | ||
|
||
from .attach_other_object_to_context import ( | ||
IAttachDifferentObjectToOpContext as IAttachDifferentObjectToOpContext, |
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.
sidenote: should we just kill this feature?
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 still use it in a few places, unfortunately. I think it would be a bit of work to strip it out, but can look into it once this lands.
203badb
to
6c0fe9b
Compare
49b59df
to
73e9411
Compare
b6e711d
to
039c24b
Compare
73e9411
to
8924ae9
Compare
if "Instance is frozen" in str( # Pydantic 2.x error | ||
e | ||
) or "is immutable and does not support item assignment" in str( # Pydantic 1.x error | ||
e | ||
): |
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.
Still relevant comment
python_modules/dagster/dagster/_config/pythonic_config/config.py
Outdated
Show resolved
Hide resolved
python_modules/dagster/dagster/_config/pythonic_config/config.py
Outdated
Show resolved
Hide resolved
python_modules/dagster/dagster/_config/pythonic_config/config.py
Outdated
Show resolved
Hide resolved
python_modules/dagster/dagster/_config/pythonic_config/conversion_utils.py
Outdated
Show resolved
Hide resolved
python_modules/dagster/dagster/_config/pythonic_config/conversion_utils.py
Outdated
Show resolved
Hide resolved
python_modules/dagster/dagster/_config/pythonic_config/config.py
Outdated
Show resolved
Hide resolved
039c24b
to
a627a90
Compare
8924ae9
to
4d29663
Compare
python_modules/dagster/dagster/_config/pythonic_config/pydantic_compat_layer.py
Show resolved
Hide resolved
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.
e9127ce
to
2c5ee94
Compare
35f9b86
to
4c102b0
Compare
28fc043
to
a6aba5f
Compare
4c102b0
to
afebf53
Compare
Merge activity
|
afebf53
to
b7beca2
Compare
Summary
PR stack which re-implements #16257, in hopes of making it easier to review.
This PR builds out a Pydantic 2 compat layer, which abstracts away some of the model accesses. The next PR in the stack will actually enable Pydantic 2 tests + turn on compatibility.
Test Plan
Existing unit tests.