1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
|
from typing import (
Any,
Dict,
Type,
)
from pydantic import (
BaseModel,
ConfigDict,
)
from pydantic._internal._core_utils import (
CoreSchemaField,
)
from pydantic.alias_generators import (
to_camel,
)
from pydantic.json_schema import (
DEFAULT_REF_TEMPLATE,
GenerateJsonSchema,
JsonSchemaMode,
)
class OmitJsonSchema(GenerateJsonSchema):
"""
Custom JSON schema generator that omits the schema generation for fields that are
invalid. Excluded fields (``Field(exclude=True)``) are generally useful as
properties of the model but are not meant to be serialized to JSON.
"""
def field_is_present(self, field: CoreSchemaField) -> bool:
# override ``field_is_present`` and omit excluded fields from the schema
if field.get("serialization_exclude", False):
return False
return super().field_is_present(field)
class CamelModel(BaseModel):
"""
Camel-case pydantic model. This model is used to ensure serialization in a
consistent manner, aliasing as camelCase serialization. This is useful for models
that are used in JSON-RPC requests and responses, marking useful fields for the
model, but that are not part of the JSON-RPC object, with ``Field(exclude=True)``.
To serialize a model to the expected JSON-RPC format, or camelCase, use
``model_dump(by_alias=True)``.
.. code-block:: python
>>> from eth_utils.pydantic import CamelModel
>>> from pydantic import Field
>>> class SignedSetCodeAuthorization(CamelModel):
... chain_id: int
... address: bytes
... nonce: int
...
... # useful fields for the object but excluded from serialization
... # (not part of the JSON-RPC object)
... authorization_hash: bytes = Field(exclude=True)
... signature: bytes = Field(exclude=True)
>>> auth = SignedSetCodeAuthorization(
... chain_id=1,
... address=b"0x0000000000000000000000000000000000000000",
... nonce=0,
... authorization_hash=generated_hash,
... signature=generated_signature,
... )
>>> auth.model_dump(by_alias=True)
{'chainId': 1, 'address': '0x000000000000000000000000000000000000', 'nonce': 0}
"""
model_config = ConfigDict(
arbitrary_types_allowed=True,
# populate by snake_case (python) args
populate_by_name=True,
# serialize by camelCase (json-rpc) keys
alias_generator=to_camel,
# validate default values
validate_default=True,
)
@classmethod
def model_json_schema(
cls,
by_alias: bool = True,
ref_template: str = DEFAULT_REF_TEMPLATE,
# default to ``OmitJsonSchema`` to prevent errors from excluded fields
schema_generator: Type[GenerateJsonSchema] = OmitJsonSchema,
mode: JsonSchemaMode = "validation",
) -> Dict[str, Any]:
"""
Omits excluded fields from the JSON schema, preventing errors that would
otherwise be raised by the default schema generator.
"""
return super().model_json_schema(
by_alias=by_alias,
ref_template=ref_template,
schema_generator=schema_generator,
mode=mode,
)
|