pydantic.py 3.3 KB

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