Handle settings inheritance statically through a metaclass
This commit is contained in:
parent
e41d12079f
commit
60470e4d7f
@ -5,7 +5,34 @@ import logging
|
|||||||
import getpass
|
import getpass
|
||||||
|
|
||||||
|
|
||||||
class SettingsBase:
|
class SettingsBaseMeta(type):
|
||||||
|
"""Add interval setting to `settings` attribute if it does not exist."""
|
||||||
|
|
||||||
|
def __init__(cls, name, bases, namespace):
|
||||||
|
super().__init__(name, bases, namespace)
|
||||||
|
|
||||||
|
cls.settings, cls.required = SettingsBaseMeta.get_merged_settings(cls)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_merged_settings(cls):
|
||||||
|
def unique(settings):
|
||||||
|
def name(s):
|
||||||
|
return s[0] if isinstance(s, tuple) else s
|
||||||
|
seen = set()
|
||||||
|
return [setting for setting in settings if not (
|
||||||
|
name(setting) in seen or seen.add(name(setting)))]
|
||||||
|
|
||||||
|
settings = tuple()
|
||||||
|
required = tuple()
|
||||||
|
# getmro returns base classes according to Method Resolution Order,
|
||||||
|
# which always includes the class itself as the first element.
|
||||||
|
for base in inspect.getmro(cls):
|
||||||
|
settings += tuple(getattr(base, "settings", []))
|
||||||
|
required += tuple(getattr(base, "required", []))
|
||||||
|
return unique(settings), required
|
||||||
|
|
||||||
|
|
||||||
|
class SettingsBase(metaclass=SettingsBaseMeta):
|
||||||
"""
|
"""
|
||||||
Support class for providing a nice and flexible settings interface
|
Support class for providing a nice and flexible settings interface
|
||||||
|
|
||||||
@ -37,24 +64,6 @@ class SettingsBase:
|
|||||||
log_level = logging.NOTSET
|
log_level = logging.NOTSET
|
||||||
logger = None
|
logger = None
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def get_merged_settings(cls):
|
|
||||||
def unique(settings):
|
|
||||||
def name(s):
|
|
||||||
return s[0] if isinstance(s, tuple) else s
|
|
||||||
seen = set()
|
|
||||||
return [setting for setting in settings if not (
|
|
||||||
name(setting) in seen or seen.add(name(setting)))]
|
|
||||||
|
|
||||||
settings = tuple()
|
|
||||||
required = tuple()
|
|
||||||
# getmro returns base classes according to Method Resolution Order,
|
|
||||||
# which always includes the class itself as the first element.
|
|
||||||
for base in inspect.getmro(cls):
|
|
||||||
settings += getattr(base, "settings", tuple())
|
|
||||||
required += getattr(base, "required", tuple())
|
|
||||||
return unique(settings), required
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
def get_argument_dict(args, kwargs):
|
def get_argument_dict(args, kwargs):
|
||||||
if len(args) == 1 and not kwargs:
|
if len(args) == 1 and not kwargs:
|
||||||
@ -65,10 +74,9 @@ class SettingsBase:
|
|||||||
|
|
||||||
self.__name__ = "{}.{}".format(self.__module__, self.__class__.__name__)
|
self.__name__ = "{}.{}".format(self.__module__, self.__class__.__name__)
|
||||||
|
|
||||||
settings, required = self.get_merged_settings()
|
settings = self.flatten_settings(self.settings)
|
||||||
settings = self.flatten_settings(settings)
|
|
||||||
|
|
||||||
sm = KeyConstraintDict(settings, required)
|
sm = KeyConstraintDict(settings, self.required)
|
||||||
settings_source = get_argument_dict(args, kwargs)
|
settings_source = get_argument_dict(args, kwargs)
|
||||||
|
|
||||||
protected = self.get_protected_settings(settings_source)
|
protected = self.get_protected_settings(settings_source)
|
||||||
|
Loading…
Reference in New Issue
Block a user