-
Notifications
You must be signed in to change notification settings - Fork 21
[Messages] Pydantic schema for message validation #272
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
[Messages] Pydantic schema for message validation #272
Conversation
|
Depends on #271. |
23520c3 to
c8cddfe
Compare
0aebd56 to
e536c4b
Compare
e536c4b to
fd488ae
Compare
| message["item_type"] = item_type_from_hash(message["item_hash"]).value | ||
| except ValueError as error: | ||
| LOGGER.warning(error) | ||
| _ = parse_message(message) |
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.
Not a fan of _ =
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.
Me neither, but it's to show that I'm not ignoring the return value until this line goes away in #277.
|
|
||
| return values | ||
|
|
||
| @root_validator() |
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.
Does this need to be a root validator instead of a simple validator ?
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, if only because we're accessing other fields. The main problem is that check_item_hash uses item_type and check_item_type uses item_hash, so at least one of the functions has to be a root validator.
| @validator("item_hash") | ||
| def check_item_hash(cls, v, values): | ||
| """ | ||
| For inline item types, check that the item hash is equal to | ||
| the hash of the item content. | ||
| """ | ||
|
|
||
| item_type = values["item_type"] | ||
| if item_type == ItemType.inline: | ||
| item_content: str = values["item_content"] | ||
|
|
||
| computed_hash: str = sha256(item_content.encode()).hexdigest() | ||
| if v != computed_hash: | ||
| raise ValueError( | ||
| "'item_hash' do not match 'sha256(item_content)'" | ||
| f", expecting {computed_hash}" | ||
| ) | ||
| elif item_type == ItemType.ipfs: | ||
| # TODO: CHeck that the hash looks like an IPFS multihash | ||
| pass | ||
| else: | ||
| assert item_type == ItemType.storage | ||
| return v |
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.
This code is identical to the one in aleph-message. Can we do something like this, or do the decorators get in the way ?
| @validator("item_hash") | |
| def check_item_hash(cls, v, values): | |
| """ | |
| For inline item types, check that the item hash is equal to | |
| the hash of the item content. | |
| """ | |
| item_type = values["item_type"] | |
| if item_type == ItemType.inline: | |
| item_content: str = values["item_content"] | |
| computed_hash: str = sha256(item_content.encode()).hexdigest() | |
| if v != computed_hash: | |
| raise ValueError( | |
| "'item_hash' do not match 'sha256(item_content)'" | |
| f", expecting {computed_hash}" | |
| ) | |
| elif item_type == ItemType.ipfs: | |
| # TODO: CHeck that the hash looks like an IPFS multihash | |
| pass | |
| else: | |
| assert item_type == ItemType.storage | |
| return v | |
| check_item_hash = aleph_message.models.BaseMessage.check_item_hash |
| @validator("item_hash") | |
| def check_item_hash(cls, v, values): | |
| """ | |
| For inline item types, check that the item hash is equal to | |
| the hash of the item content. | |
| """ | |
| item_type = values["item_type"] | |
| if item_type == ItemType.inline: | |
| item_content: str = values["item_content"] | |
| computed_hash: str = sha256(item_content.encode()).hexdigest() | |
| if v != computed_hash: | |
| raise ValueError( | |
| "'item_hash' do not match 'sha256(item_content)'" | |
| f", expecting {computed_hash}" | |
| ) | |
| elif item_type == ItemType.ipfs: | |
| # TODO: CHeck that the hash looks like an IPFS multihash | |
| pass | |
| else: | |
| assert item_type == ItemType.storage | |
| return v | |
| @validator("item_hash") | |
| def check_item_hash(cls, v, values): | |
| return aleph_message.models.BaseMessage.check_item_hash(v, values) |
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.
Just tried it, the validator does not get in the way but I removed the hash_type member of the message model, if only because we will probably never use it (better to use multihash/multicodec instead). If that's okay for you, I think I'll leave it like that for the moment, and we'll do a large update of aleph_message once we're fixed on the models.
I basically want to have a class tree like this:
PendingMessage: base class, = the data sent by aleph-client or similarDbMessage: inherits PendingMessage (or a common base class), = the schema of the data stored in MongoDB.ApiMessage: inherits DbMessage (or a common base class), = the schema of the API response. Similar to the current aleph_message Message.
Added new Pydantic models/schemas to validate Aleph messages coming from the network. These models are similar to the ones implemented in aleph-message, but focus on validating messages before processing them. This validation replaces the validation in check_message and will later be used to use objects as early as possible in the processing of messages. Added tests for the major types of messages.
1a85141 to
d29670f
Compare
Added new Pydantic models/schemas to validate Aleph messages
coming from the network. These models are similar to the ones
implemented in aleph-message, but focus on validating messages
before processing them.
This validation replaces the validation in check_message
and will later be used to use objects as early as possible
in the processing of messages.
Added tests for the major types of messages.
Breaking changes (to validate):
item_typefield is now mandatory for all message typesaddressandtimefields are now mandatory for the content of all messages.