1

I want to create a settings registry. I also want to be able to group settings in macro-categories.

The following simplified example works with a single registry:

class RegistryHolder:
    registry = {}

    def __init_subclass__(cls, setting_name=None, **kwargs):
        super().__init_subclass__(**kwargs)
        cls.registry[setting_name] = cls

class SettingOne(RegistryHolder, setting_name='SettingOne'):
    pass

class SettingTwo(RegistryHolder, setting_name='SettingTwo'):
    pass

And the result is:

print(RegistryHolder.registry)

{'SettingOne': <class '__main__.SettingOne'>,
 'SettingTwo': <class '__main__.SettingTwo'>}

I would like to group the settings by macro categories without rewriting the __init_subclass__() each time. Something like:

class UserRegistryHolder(RegistryHolder):
    pass

class SettingOne(UserRegistryHolder, setting_name='SettingOne'):
    pass

class SettingTwo(UserRegistryHolder, setting_name='SettingOne'):
    pass
class SystemRegistryHolder(RegistryHolder):
    pass

class SettingA(SystemRegistryHolder, setting_name='SettingA'):
    pass

class SettingB(SystemRegistryHolder, setting_name='SettingB'):
    pass

This obviously does not work because when I subclass the RegistryHolder, I am 'registering' the User/System classes as part of the registry, e.g. for UserRegistryHolder.registry I get:

{'SettingOne': <class '__main__.SettingTwo'>, 
 'SettingTwo': <class '__main__.SettingTwo'>, 
 None: <class '__main__.UserRegistryHolder'>}

So a few questions:

  • Am I aksing the wrong question?
  • Am I overthinking it?
  • How would you go about creating such an interface cleanly (alternatives are welcome)?
Oleg
  • 10,406
  • 3
  • 29
  • 57
  • 2
    let's elaborate: `RegistryHolder` is only a base class and should not accumulate all settings, while its sub-holders `User/System` should do that, right? – RomanPerekhrest Aug 23 '19 at 13:24
  • It seems like you aren't differentiating between registries and registry holders. `SettingA` is a registry, not a registry holder. (Or possibly, you want to distinguish between registry holders and registry-holder holders.) – chepner Aug 23 '19 at 13:36
  • What would you like this settings registry with grouped settings in macro-categories to look like? – martineau Aug 23 '19 at 14:19

1 Answers1

2

Assuming that RegistryHolder is only a base class (template) and should not accumulate all settings, while its sub-holders UserRegistryHolder/SystemRegistryHolder are expected do keep the "respective" settings:

class RegistryHolder:
    registry = {}

    def __init_subclass__(cls, setting_name=None, **kwargs):
        super().__init_subclass__(**kwargs)
        parent = cls.__bases__[0]
        if setting_name:
            parent.registry[setting_name] = cls  # add setting to parent sub-holder
        else:
            cls.registry = {}   # init registry for sub-holder


class UserRegistryHolder(RegistryHolder):
    pass

class SettingOne(UserRegistryHolder, setting_name='SettingOne'):
    pass

class SettingTwo(UserRegistryHolder, setting_name='SettingTwo'):
    pass

class SystemRegistryHolder(RegistryHolder):
    pass

class SettingA(SystemRegistryHolder, setting_name='SettingA'):
    pass

class SettingB(SystemRegistryHolder, setting_name='SettingB'):
    pass


print(RegistryHolder.registry)
print(UserRegistryHolder.registry)
print(SystemRegistryHolder.registry)

The output (consecutively):

{}
{'SettingOne': <class '__main__.SettingOne'>, 'SettingTwo': <class '__main__.SettingTwo'>}
{'SettingA': <class '__main__.SettingA'>, 'SettingB': <class '__main__.SettingB'>}
RomanPerekhrest
  • 88,541
  • 4
  • 65
  • 105