MDANSE icon indicating copy to clipboard operation
MDANSE copied to clipboard

[RFC] Use descriptors as `Configurator`s

Open oerc0122 opened this issue 1 year ago • 1 comments

Is your feature request related to a problem? Please describe. Currently, there are multiple stages to a Configurator:

  • Building the settings dict
  • Accessing the (_)configuration dict
  • Building GUI widgets from configurators

Configurators also manage various limitations on assigning variables implemented through custom routines on setting.

Describe the solution you'd like Descriptors provide a Python-level unified interface for these types of deferred or restricted variables. They intercept the assignment of attributes (generally at a class level) and allow custom implementation of how they are assigned. It may be possible to implement the majority of Configurators as descriptors.

An example might be (without too much thought or detail):

class IntegerConfigurator:
    class_name = "IntegerConfigurator"  # Available on all IntegerConfigurators
 
    def __init__(
        self, name, mini=None, maxi=None, choices=None, exclude=None, **kwargs
    ):
        """
        ...
        """

        # The base class constructor.
        super().__init__(self, **kwargs)
        self._mini = int(mini) if mini is not None else None
        self._maxi = int(maxi) if maxi is not None else None
        self._choices = choices if choices is not None else []
        self._exclude = exclude if exclude is not None else ()

   def __set_name__(self, owner, name):
       if not hasattr(owner, "settings"):
           owner.settings = {}
       owner.settings[name] = self.value
       self.ref = name

   def __set__(self, owner, value):
       try:
           value = int(value)
       except (ValueError, TypeError) as err:
            ...
      if self._choices and value not in _choices:
           return "..."
      ...

      owner.settings[self.ref] = value

   def __get__(self, owner, objType = None):
       return owner.settings[self.ref]

This could subsequently be used as:

class MyJob(job):
    my_int = IntegerConfigurator(mini=0, maxi=3)

    def __init__(self, val):
         self.settings["my_int"] = 0
         print(self.settings["my_int"])  # 0
         print(self.my_int)  # 0 
         self.my_int = 4  # Raise 

oerc0122 avatar Feb 20 '25 14:02 oerc0122

To replace all of them would be a significant amount of work, but also a big improvement for long-term maintainability of the code. But you are right that many of them should be easy.

We should definitely keep this idea in mind.

MBartkowiakSTFC avatar Feb 20 '25 15:02 MBartkowiakSTFC