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

[1.10.x] Properly encode model and dataclass default for schema #4781

Merged

Conversation

Bobronium
Copy link
Contributor

Closes #4774

Fix was pretty straightforward, I guess we can have this in 1.10.x.

@Bobronium
Copy link
Contributor Author

CI seems to be failing with installation error unrelated to the changes.

@hramezani
Copy link
Member

I created #4782 to fix the CI problem.
I am not sure about the solution

@Bobronium
Copy link
Contributor Author

Bobronium commented Nov 25, 2022

Perhaps, I can rebase Bobronium:1.10.X-fix-schema-model-default on hramezani:setuptools?

@samuelcolvin samuelcolvin mentioned this pull request Nov 25, 2022
8 tasks
@hramezani
Copy link
Member

FYI, I closed #4782 because it was on main and seems not a proper fix

@hramezani
Copy link
Member

As the problem got fixed in 78ca710, you can rebase your patch now!

@Bobronium Bobronium force-pushed the 1.10.X-fix-schema-model-default branch from 3097b85 to 74ceaaf Compare November 25, 2022 15:14
@Bobronium
Copy link
Contributor Author

Please review :)

tests/test_schema.py Outdated Show resolved Hide resolved
return dft.value
elif isinstance(dft, (int, float, str)):
return dft
elif isinstance(dft, (list, tuple)):
t = dft.__class__
seq_args = (encode_default(v) for v in dft)
return t(*seq_args) if is_namedtuple(t) else t(seq_args)
elif isinstance(dft, dict):

if isinstance(dft, dict):
Copy link
Member

Choose a reason for hiding this comment

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

Do we need this change here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes. Notice the change above: we transform models and dataclasses to dict in first if and need this to be a separate one to work.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Any ideas how to make this more explicit and obvious, btw?

Copy link
Member

Choose a reason for hiding this comment

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

maybe just a comment with the above explanation.

Copy link
Member

Choose a reason for hiding this comment

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

I would add the first if as a separate if and move the isinstance(dft, dict) check to the top.

Here is my suggestion(I haven't tested it locally):

def encode_default(dft: Any) -> Any:
    from .main import BaseModel

    if isinstance(dft, BaseModel) or is_dataclass(dft):
        dft = cast('dict[str, Any]', pydantic_encoder(dft))

    if isinstance(dft, dict):
        return {encode_default(k): encode_default(v) for k, v in dft.items()}
    elif isinstance(dft, Enum):
        return dft.value
    elif isinstance(dft, (int, float, str)):
        return dft
    elif isinstance(dft, (list, tuple)):
        t = dft.__class__
        seq_args = (encode_default(v) for v in dft)
        return t(*seq_args) if is_namedtuple(t) else t(seq_args)
    elif dft is None:
        return None
    else:
        return pydantic_encoder(dft)

Copy link
Contributor Author

@Bobronium Bobronium Nov 29, 2022

Choose a reason for hiding this comment

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

Happy to accept suggestions on phrasing as well :)

Previous suggestion
Suggested change
if isinstance(dft, dict):
# we can end up here either from first condition or if none of above conditions were met
if isinstance(dft, dict):

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for suggestion, @hramezani, I like your approach! I think I was hesitant on reordering at first, but it seems like the best move here, indeed.

@hramezani
Copy link
Member

@Bobronium I left a suggestion and asked a question.

Please update

Bobronium and others added 2 commits November 29, 2022 16:21
Co-authored-by: Hasan Ramezani <hasan.r67@gmail.com>
@Bobronium
Copy link
Contributor Author

Nice catch with suggestion, @hramezani! I answered the question as well.

Please review.

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.

Otherwise LGTM.

return dft.value
elif isinstance(dft, (int, float, str)):
return dft
elif isinstance(dft, (list, tuple)):
t = dft.__class__
seq_args = (encode_default(v) for v in dft)
return t(*seq_args) if is_namedtuple(t) else t(seq_args)
elif isinstance(dft, dict):

if isinstance(dft, dict):
Copy link
Member

Choose a reason for hiding this comment

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

maybe just a comment with the above explanation.

Copy link
Member

@hramezani hramezani left a comment

Choose a reason for hiding this comment

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

LGTM 👍
Thanks @Bobronium

@samuelcolvin samuelcolvin merged commit 18359d7 into pydantic:1.10.X-fixes Nov 29, 2022
samuelcolvin pushed a commit that referenced this pull request Nov 29, 2022
* Properly encode model and dataclass default for schema

* Wrap type annotation in quotes

* Fix compatibility

* Add changes file

* Remove unnecessary import

Co-authored-by: Hasan Ramezani <hasan.r67@gmail.com>

* Add a blank line back

* Reorder conditions

As per suggestion in #4781 (comment).

Co-authored-by: Hasan Ramezani <hasan.r67@gmail.com>
@samuelcolvin
Copy link
Member

Thanks so much.

I've also cherry-picked this into main, mostly so we don't forget this edge case when working on JSONSchema for V2.

@Bobronium Bobronium deleted the 1.10.X-fix-schema-model-default branch November 29, 2022 13:17
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.

None yet

4 participants