Check out the Issue Explorer
Looking to fund some work? You can submit a new Funded Issue here.
### What is the problem
RLP objects are not very good at inheritance.
fields = (
fields = (
('field_a', sedes.Binary), # not DRY, repeated from base class
There is no good *pythonic* way to extend a base class's fields.
### How can we fix it.
Much the same way that django models perform magical metaclass voodoo, we can do the same. Implement a metaclass for use that finds all attributes which are valid `sedes` types and does all the fancy stuff that happens within the `__init__` method of `Serializable`. In general, doing away with `Serializable.fields` seems like a nice cleanup.
The example above would look something like:
field_a = sedes.Binary()
field_a = sedes.Binary() # required to maintain explicit field ordering.
another_field = sedes.Binary()
### Implementation specifics.
#### Field class
We need a `Field` class which we can use to define RLP fields. This should be a thin wrapper of sorts around a `rlp.sedes` object. Ideally, we can have some sort of thin shortcut for converting a `sedes` object to a `Field` object using something like a classmethod `Field.from_sedes(...)`
Unless an alternate solution is presented, the `rlp.Serializable` class needs to be converted to use a metaclass. This metaclass will need to introspect the current fields as well as all of the fields for the base class to construct the class.
I suggest this part be done in two steps.
- **Step 1**
The first step would be to have the metaclass construct an `rlp.Serializable` instance with the proper `fields` property, and to allow the existing internals of `rlp.Serializable` to populate the actual attribute setters and getters. Under this approach accessing the field properties from the class would likely result in an `AttributeError` as they would not be constructed until class instantiation.
- **Step 2**
The second step is to invert this, and have the metaclass (or the underlying `Field` class) create these attributes at the class level, likely using descriptors (which the `Field` class could implement). Then, the `fields` property on the class would only be present for backwards compatibility.
#### Field ordering
The field ordering for RLP objects is important. Luckily, this is easy to do using metaclasses.
However, this gets complicated in cases of inheritance. From the discussion on this issue, we've decided that the best solution to fixing this is to required that either **all** fields or **zero** field be overridden when a class is sub classed.
The documentation will need to be updated to reflect this new API.