Using descriptors with sequnce-like types?

Hello. I’m implementing a Settings class. This class represents a collection of individual Setting values. The code below is adapted from Raymond Hettinger’s Descriptor HowTo Guide.

class Setting(ABC):
    def __set_name__(self, owner, name): ...
    def __get__(self, instance, owner=None):
    def __set__(self, instance, value: T): ...
    def __delete__(self, instance): ...

    @abstractmethod
    def validate(self, value: T):
        pass

This class is inherited by BoolSetting, IntSetting, StringSetting, etc.

This solution is very elegant. Every derived class provides its own validator. The values are validated upon every assignment. The settings can print their names (using the well-known if instance is None trick in __get__).

However, all these perks are lost when a sequence-like setting is needed. The ListSetting validator is able to validate that it is assigned a list, but it cannot validate the elements added to the list. Assigning elements to the list is completely out of control.

Now, I believe this problem has a few solutions, but is there a recommended (and equally elegant) one? For example, can I define descriptors on classes derived from mutable classes like list, set, etc.?

Store a copy of the mutable and not a reference maybe?
Also returning a copy not a reference.
This would avoids the stored copy from being update outside your control.

1 Like

Just by way of FYI there is alot of prior art in this area (some going back 15+ years) that you can refer to for ideas:

And at least a few others I’m forgetting. For the specific question you have, I can point to Bokeh’s solution, which is to wrap the container values with instrumented adapters that mimic the relevant container API but also hook into the validation and notification system:

https://github.com/bokeh/bokeh/blob/branch-3.3/src/bokeh/core/property/wrappers.py

1 Like

Guys, thank you for the ideas and references!