base.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. import functools
  2. from .grammar import (
  3. BasicType,
  4. TupleType,
  5. normalize,
  6. parse,
  7. )
  8. def parse_type_str(expected_base=None, with_arrlist=False):
  9. """
  10. Used by BaseCoder subclasses as a convenience for implementing the
  11. ``from_type_str`` method required by ``ABIRegistry``. Useful if normalizing
  12. then parsing a type string with an (optional) expected base is required in
  13. that method.
  14. """
  15. def decorator(old_from_type_str):
  16. @functools.wraps(old_from_type_str)
  17. def new_from_type_str(cls, type_str, registry):
  18. normalized_type_str = normalize(type_str)
  19. abi_type = parse(normalized_type_str)
  20. type_str_repr = repr(type_str)
  21. if type_str != normalized_type_str:
  22. type_str_repr = "{} (normalized to {})".format(
  23. type_str_repr,
  24. repr(normalized_type_str),
  25. )
  26. if expected_base is not None:
  27. if not isinstance(abi_type, BasicType):
  28. raise ValueError(
  29. "Cannot create {} for non-basic type {}".format(
  30. cls.__name__,
  31. type_str_repr,
  32. )
  33. )
  34. if abi_type.base != expected_base:
  35. raise ValueError(
  36. "Cannot create {} for type {}: expected type with "
  37. "base '{}'".format(
  38. cls.__name__,
  39. type_str_repr,
  40. expected_base,
  41. )
  42. )
  43. if not with_arrlist and abi_type.arrlist is not None:
  44. raise ValueError(
  45. "Cannot create {} for type {}: expected type with "
  46. "no array dimension list".format(
  47. cls.__name__,
  48. type_str_repr,
  49. )
  50. )
  51. if with_arrlist and abi_type.arrlist is None:
  52. raise ValueError(
  53. "Cannot create {} for type {}: expected type with "
  54. "array dimension list".format(
  55. cls.__name__,
  56. type_str_repr,
  57. )
  58. )
  59. # Perform general validation of default solidity types
  60. abi_type.validate()
  61. return old_from_type_str(cls, abi_type, registry)
  62. return classmethod(new_from_type_str)
  63. return decorator
  64. def parse_tuple_type_str(old_from_type_str):
  65. """
  66. Used by BaseCoder subclasses as a convenience for implementing the
  67. ``from_type_str`` method required by ``ABIRegistry``. Useful if normalizing
  68. then parsing a tuple type string is required in that method.
  69. """
  70. @functools.wraps(old_from_type_str)
  71. def new_from_type_str(cls, type_str, registry):
  72. normalized_type_str = normalize(type_str)
  73. abi_type = parse(normalized_type_str)
  74. type_str_repr = repr(type_str)
  75. if type_str != normalized_type_str:
  76. type_str_repr = "{} (normalized to {})".format(
  77. type_str_repr,
  78. repr(normalized_type_str),
  79. )
  80. if not isinstance(abi_type, TupleType):
  81. raise ValueError(
  82. "Cannot create {} for non-tuple type {}".format(
  83. cls.__name__,
  84. type_str_repr,
  85. )
  86. )
  87. abi_type.validate()
  88. return old_from_type_str(cls, abi_type, registry)
  89. return classmethod(new_from_type_str)
  90. class BaseCoder:
  91. """
  92. Base class for all encoder and decoder classes.
  93. """
  94. is_dynamic = False
  95. def __init__(self, **kwargs):
  96. cls = type(self)
  97. # Ensure no unrecognized kwargs were given
  98. for key, value in kwargs.items():
  99. if not hasattr(cls, key):
  100. raise AttributeError(
  101. "Property {key} not found on {cls_name} class. "
  102. "`{cls_name}.__init__` only accepts keyword arguments which are "
  103. "present on the {cls_name} class.".format(
  104. key=key,
  105. cls_name=cls.__name__,
  106. )
  107. )
  108. setattr(self, key, value)
  109. # Validate given combination of kwargs
  110. self.validate()
  111. def validate(self):
  112. pass
  113. @classmethod
  114. def from_type_str(cls, type_str, registry): # pragma: no cover
  115. """
  116. Used by :any:`ABIRegistry` to get an appropriate encoder or decoder
  117. instance for the given type string and type registry.
  118. """
  119. raise NotImplementedError("Must implement `from_type_str`")