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

pydantic2.0 #168

Merged
merged 9 commits into from
Aug 3, 2023
Merged

pydantic2.0 #168

merged 9 commits into from
Aug 3, 2023

Conversation

ruthenian8
Copy link
Member

Description

Use pydantic 2.0

Checklist

  • I have covered the code with tests
  • I have added comments to my code to help others understand it
  • I have updated the documentation to reflect the changes
  • I have performed a self-review of the changes

@ruthenian8 ruthenian8 changed the title initial commit pydantic2.0 Jul 14, 2023
@kudep kudep marked this pull request as ready for review July 25, 2023 11:27

from .database import DBContextStorage, threadsafe_method
from dff.script import Context


class SerializableStorage(BaseModel, extra=Extra.allow):
@root_validator
class SerializableStorage(BaseModel, extra="allow"):
Copy link
Member

Choose a reason for hiding this comment

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

Not directly related to pydantic 2.0, but why is this storage implemented using this class?
Seems like the only use is to cast all values in loaded json file to Context but can't we just do that inside the _load method?
If not, this class should be documented and defined inside the JSONContextStorage class.

Previously this issue wasn't that evident, but now code like len(self.storage.model_extra) looks weird.

Copy link
Member Author

Choose a reason for hiding this comment

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

No idea

Copy link
Member Author

Choose a reason for hiding this comment

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

I don't think that changes to this class are necessary, since it's going to be replaced by the new context storage implementation

dff/messengers/telegram/message.py Outdated Show resolved Hide resolved
dff/pipeline/types.py Outdated Show resolved Hide resolved
elif not issubclass(type(ctx), Context):
raise ValueError(
f"context expected as sub class of Context class or object of dict/str(json) type, but got {ctx}"
)
return ctx

@validate_arguments
Copy link
Member

Choose a reason for hiding this comment

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

What's the status on the pickling issue?
Is it going to be fixed in #93?

Copy link
Member Author

Choose a reason for hiding this comment

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

validating arguments is not needed now, we can parse the argument inside the function body

Copy link
Member

Choose a reason for hiding this comment

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

We can but that is not how we are supposed to work with pydantic.

Copy link
Member Author

Choose a reason for hiding this comment

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

In my view, this strategy is better, since it does not modify the Context model, while using validate_call decorators leads to the Message class being referenced in the Context class body which causes the pickling problems

dff/script/core/context.py Outdated Show resolved Hide resolved
dff/context_storages/json.py Show resolved Hide resolved
dff/script/core/message.py Outdated Show resolved Hide resolved
dff/script/core/script.py Outdated Show resolved Hide resolved
dff/script/core/script.py Show resolved Hide resolved
Comment on lines 16 to 20
normalize_label,
normalize_condition,
normalize_transitions,
normalize_response,
normalize_processing,
normalize_script,
)
Copy link
Member

Choose a reason for hiding this comment

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

Not related to the PR, but:

Why import these functions if they are not supposed to be used by the user?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Copy link
Member

@RLKRo RLKRo left a comment

Choose a reason for hiding this comment

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

This PR seems good but

There are still three comments left that are unrelated to this PR:

  1. pydantic2.0 #168 (comment) -- question about json storage for @pseusys
  2. pydantic2.0 #168 (comment) -- question about context pickling (why do we pickle all methods of the context class and is this behavior going to be changed) for @pseusys
  3. pydantic2.0 #168 (comment) -- question about function imports for @kudep

elif not issubclass(type(ctx), Context):
raise ValueError(
f"context expected as sub class of Context class or object of dict/str(json) type, but got {ctx}"
)
return ctx

@validate_arguments
Copy link
Member

Choose a reason for hiding this comment

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

We can but that is not how we are supposed to work with pydantic.

@RLKRo RLKRo added the dependencies Updating dependencies label Jul 26, 2023
@pseusys
Copy link
Collaborator

pseusys commented Aug 2, 2023

Speaking of the comment:

  1. Json storage is using BaseModel and to my mind not using it won't be easier for several reasons (otherwise custom json serializer functions will be required):
    • Context class includes nested timestamp objects and json module doesn't know how to serialize them.
    • There are Dicts with integer keys in Context objects that can't be serialized by json module.
  2. Pickle modlue serializes only the required fields now, it works as expected.

@RLKRo
Copy link
Member

RLKRo commented Aug 2, 2023

Pickle modlue [sic] serializes only the required fields now, it works as expected.

"now" means in #93?

I'm assuming this PR will be merged before that one, so I think we should return validate_call decorators for context methods inside the partial_context_updates branch (once this one is merged).

@pseusys
Copy link
Collaborator

pseusys commented Aug 2, 2023

Yes, "now" means in #93.
I don't really think we should wrap anything in validate_all in partial context updates branch since no untrusted data is pickled or unpickled.

@RLKRo
Copy link
Member

RLKRo commented Aug 2, 2023

validate_call validates types of arguments.

Previously it was validate_arguments, pydantic 2.0 changed it.
New version validate_call wasn't working with pickle, so we used manual validation (request = Message.model_validate(item)), which is supposed to happen inside the validate_call decorator.

Or do you mean that we shouldn't use any type validation? I don't think we should do that. Type validation would help in case a user would accidentally write a function that sets ctx.last_request to str instead of Message.

@pseusys
Copy link
Collaborator

pseusys commented Aug 2, 2023

I only meant that I don't think there should be any concerns about pickling while reasoning about validating arguments.
I don't really understand how pickling should affect argument validation.

@kudep kudep merged commit 72e167f into dev Aug 3, 2023
@kudep kudep deleted the feat/pydantic2.0 branch August 3, 2023 13:28
@RLKRo RLKRo mentioned this pull request Sep 18, 2023
6 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
dependencies Updating dependencies
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants