API

This part of the documentation briefly covers the interfaces of Concrete Settings.

Settings

class concrete_settings.setting.Setting(value=<class 'concrete_settings.types.Undefined'>, *, doc='', validators=(), type_hint=<class 'concrete_settings.types.GuessSettingType'>, override=False)[source]

A setting is a named object for storing, documenting and validating a certain value.

Parameters
  • value (Any) – the initial value of a setting with the default Undefined.

  • doc (str) – an end-user -friendly setting documentation.

  • validators (tuple) – setting validators, a tuple of Validator callables.

  • type_hint (Any) – setting type, something one would use as type annotation. The default value (GuessSettingType) would invoke type guessing mechanism.

  • override (bool) – a indicates that settings definiton is explicitly overriden.

The corresponding implicit definition of a setting in Settings class is written as following:

class MySettings(Settings):
    default_validators = (...)
    mandatory_validators = (...)

    #: Documentation is written
    #: in Sphinx-style comments above
    #: the setting definition
    SETTING_NAME: type_hint = value @behavior1 @behavior2 @...
name

Setting attribute name (read-only).

_behaviors

Internal attribute for storing behaviors attached to the setting

class concrete_settings.settings.Settings(**kwargs)[source]

Settings is a container for one or more Setting objects. Settings classes can be mixed and nested.

default_validators

Validators applied to each Setting that have no defined validators.

Type

tuple[Validator]

Value

()

mandatory_validators

Validators applied to every Setting in the class.

Type

tuple[Validator]

Value

(ValueTypeValidator(), )

is_valid(raise_exception=False)bool[source]

Validate settings and return True if settings are valid.

If raise_exception is False, validation errors are stored in self.errors. Otherwise a ValidationError is raised when the first invalid setting is encountered.

validate()[source]

Validate settings altogether.

This is a stub method intended to be overriden when needed. It is called after individual settings have been validated without any errors.

Raise ValidationError to indicate errors.

property errors

errors property contains validation errors from the last settings.is_valid(raise_exception=False) call. The errors are packed in recursive ValidationErrorDetail structure.

property is_being_validated

Indicates that settings are being validated.

The property is intended to be used by behaviors to distinguish between Setting reads during validation and normal usage.

update(source[, strategies])[source]

Update settings from the given source.

The update process consist of two stages:

  1. Intializing an access and/or reading a source object - Python, YAML or JSON file, environmental variables, a dict, locals() etc.

  2. Update the settings by the values read from the sources.

Parameters
  • source – can either be a dict, an instance of Source or a path to the source file.

  • strategies – a dictionary of { setting_name: Strategy} which affect how settings’ values are updated.

extract_to(destination[, prefix])[source]
class concrete_settings.settings.setting
class concrete_settings.settings.PropertySetting[source]

@setting (an alias to PropertySetting decorator-class) is used to mark class methods as settings. The property-settings are read-only and used to compute a value, usually based on other settings. For example:

class AppSettings(Settings):
    ADMIN_NAME: str = 'Alex'
    ADMIN_EMAIL: str = 'alex@example.com'

    @setting
    def ADMIN_FULL_EMAIL(self) -> str:
        """Full admin email in `name <email>` format"""
        return f'{self.ADMIN_NAME} <{self.ADMIN_EMAIL}>'

Note that methods written in UPPER_CASE are converted to PropertySetting automatically and do not require decoration by @setting.

Types

class concrete_settings.types.Undefined(*args, **kwargs)[source]

A special Setting value which indicates that a value should be set by other means, e.g. by updating the settings object. Often used in conjuction with RequiredValidator and required behavior.

class AppSettings(Settings):
   SPEED: int = Undefined
class concrete_settings.types.GuessSettingType[source]

A special value for Setting.type_hint, which indicates that a Setting type should be guessed from the default value.

For an Undefined or an unknown type, the guessed type hint is typing.Any.

KNOWN_TYPES = [<class 'bool'>, <class 'int'>, <class 'float'>, <class 'complex'>, <class 'list'>, <class 'tuple'>, <class 'range'>, <class 'bytes'>, <class 'str'>, <class 'frozenset'>, <class 'set'>, <class 'dict'>]

Recognized Setting value types

Validators

class concrete_settings.validators.Validator(Protocol)[source]

A validator is a callable that raises an exception if a value is wrong.

A validator accepts a value as a mandatory argument, and keyword-only arguments referring to settings, setting and setting’s name.

__call__(value, *, name=None, owner=None, setting=None)[source]

Validate a value. Raise ValidationError if value is wrong.

class concrete_settings.exceptions.ValidationError(details='')[source]

Raised by a setting validator when a setting value is invalid.

concrete_settings.exceptions.ValidationErrorDetails = typing.Union[str, typing.List[ForwardRef('ValidationErrorDetails')], typing.Dict[str, ForwardRef('ValidationErrorDetails')]]

A recursive union type which describes validation errors.

ValidationErrorDetails is defined as

SettingName = str

ValidationErrorDetails = Union[
    str,
    List[ValidationErrorDetails],
    Dict[SettingName, ValidationErrorDetails]
]

ValueTypeValidator

class concrete_settings.validators.ValueTypeValidator(*args, **kwds)[source]

Matches setting value type and its type hint.

Setting value type should match setting.type_hint. Undefined value is considered valid for any type hint.

ValueTypeValidator is the default validator in Settings.mandatory_validators.

Parameters

type_hint – If setting.type_hint is None, then type match is performed against the given type_hint.

RequiredValidator

class concrete_settings.validators.RequiredValidator(message=None)[source]

Validates that setting value is not Undefined For convenient usage, see required behavior.

Parameters

message – Custom validation error message template.

Value message

“Setting {name} is required to have a value. Current value is `Undefined`”

DeprecatedValidator

class concrete_settings.contrib.validators.DeprecatedValidator(msg, raise_exception=False)[source]

Emits a warning or raises ValidationError <concrete_settings.exceptions.ValidationError> indicating that setting is deprecated.

This is a helper validator added to a Setting attribute validators by @deprecated behavior.

Behaviors

class concrete_settings.behaviors.Behavior(*args, init_with_arguments=False, **kwargs)[source]

Base class for Setting attributes behaviors.

decorate(setting: concrete_settings.setting.Setting)[source]

Decorate setting attribute.

If your custom behavior adds a validator to the Setting, override this method as follows:

def decorate(self, setting):
   setting.validators = (
       MyValidator()
   ) + setting.validators

   super().attach_to(setting)
Parameters

setting – Setting to which the behavior is attached.

Returns

Passed setting object.

class concrete_settings.behaviors.GetterSetterBehavior(*args, init_with_arguments=False, **kwargs)[source]

A base class for behaviors which provide custom get / set behavior. The super class methods have to be invoked to invoke behaviors get / set chain down to the decorated original setting.

get_value(setting, owner)[source]
Return type

Any

Parameters
  • setting (Setting) – Setting to which behavior is attached.

  • owner (Settings) – Settings object - setting attribute’s owner.

Invoked when the decorated Setting is being read.

When overriding this method remember to call the base class method super().get_value(setting, owner) to invoke the chained behaviors down to the setting’s original value getter. For example:

def get_value(self, setting: 'Setting', owner: 'Settings') -> Any:
    val =  super().get_value(setting, owner)
    print(f"Setting {setting.name} has been accessed, its value was {val}")
    return val
set_value(setting, owner, value)[source]
Parameters
  • setting (Setting) – Setting to which behavior is attached.

  • owner (Settings) – Settings object - setting attribute’s owner.

  • value – Value being written to the setting.

Invoked when the decorated Setting is being written.

When overriding this method, remember to call the base class method super().set_value(setting, owner, value) to invoke the chained behaviors down to the setting’s original value setter.

override

class concrete_settings.behaviors.override(*args, init_with_arguments=False, **kwargs)[source]

Sets Setting.override = True.

Usage:

from concrete_settings import Settings, override

class BaseSettings(Settings):
    SECRET: int = 100200300400500
    ...

class DevSettings(BaseSettings):
    SECRET: str = 'abcdef12345' @override

validate

class concrete_settings.validate(*validators)[source]

Provides behavior-style way of attaching validators to a setting.

from concrete_settings import Settings, validate, ValidationError

def is_positive(value, **kwargs):
    if value <= 0:
        raise ValidationError(f'must be a positive integer')

class AppSettings(Settings):
    SPEED: int = 20 @ validate(is_positive)

app_settings = AppSettings()
app_settings.SPEED = -10

print(app_settings.is_valid())
print(app_settings.errors)
False
{'SPEED': ['must be a positive integer']}

required

class concrete_settings.contrib.behaviors.required(message=None)[source]

Attaches RequiredValidator to the setting which validates that setting value is not Undefined.

Usage:

from concrete_settings import Settings, Undefined, required

class AppSettings(Settings):
    SECRET_STRING: str = Undefined @required

deprecated

class concrete_settings.contrib.behaviors.deprecated(deprecation_message='Setting `{name}` in class `{owner}` is deprecated.', *, warn_on_validation=True, error_on_validation=False, warn_on_get=False, warn_on_set=False)[source]

Emit warnings when Setting is read, written or being validated.

Parameters
  • deprecation_message

    Warning message template. Placeholders:

    • {name} - setting name.

    • {owner} - owner Settings object.

  • warn_on_validation (bool) – Add warning-raising DeprecatedValidator to the setting’s validators list.

  • error_on_validation (bool) – Add exception-raising DeprecatedValidator to the setting’s validators list. When this parameter is set to True, warn_on_validation is ignored.

  • warn_on_get (bool) – Emit warning when reading the setting.

  • warn_on_set (bool) – Emit warning when writing the setting.

Sources

concrete_settings.sources.AnySource

AnySource = Union[Dict[str, Any], str, 'Source', Path]

Valid settings sources types union. A valid source is either a dict, an instance of Source or a path (str or Path)

class concrete_settings.sources.Source[source]

The base class of all Concrete Settings sources.

static get_source(src)[source]
Return type

Optional[Source]

Parameters

src (AnySource) – some source representation

A static method which returns a Source instance or None if src is not suitable. For example, DictSource implements it as follows:

@staticmethod
def get_source(src: AnySource) -> Optional['DictSource']:
    if isinstance(src, dict):
        return DictSource(src)
    elif isinstance(src, DictSource):
        return src
    else:
        return None
read(setting, parents=())[source]
Return type

Union[Type[NotFound], Any]

Parameters
  • setting (Setting) – Setting attribute instance being processed. Usually setting.name is of interest.

  • parents (tuple[str]) – A chain of parent Settings classes names (i.e. in case of nested settings). This is used to map source setting keys like DB_HOST_PORT to AppSettings.DB.HOST.PORT. In this case parents=('DB', 'HOST').

Called for each setting from settings beign read. A source should return the corresponding value.

read() should return NotFound if setting value was not provided by the source.

class concrete_settings.sources.NotFound[source]

Returned by Source.read when setting value is not provided by the source.

class concrete_settings.sources.DictSource(s)[source]

Python dict -parsing source.

Update strategies

class concrete_settings.sources.strategies.Strategy(Protocol)[source]

A strategy decides how a setting value will be updated.

abstract __call__(current_value, new_value)[source]

Call self as a function.

The signature of Strategy callables

Parameters
  • current_value – is the current value of a setting

  • new_value – is the new_value from a source.

Usually a strategy is a simple and small function. For example if a setting is a tuple, the following strategy would append values, instead of overwriting the tuple:

# the required strategy
def append(new_val, old_val):
    return new_val + old_val

class AppSettings(Settings):
    ADMIN_EMAILS: Tuple[str] = ('cto@example.com', )

app_settings = AppSettings()
app_settings.update(
    source={
        'ADMIN_EMAILS': ('alex@example.com', )
    },
    strategies={
        'ADMIN_EMAILS': append
    }
)

print(app_settings.ADMIN_EMAILS)

Output:

('cto@example.com', 'alex@example.com')