granular_configuration_language
- class granular_configuration_language.LazyLoadConfiguration(
- *load_order_location: Path | str | PathLike,
- base_path: str | Sequence[str] | None = None,
- use_env_location: bool = False,
- env_location_var_name: str = 'G_CONFIG_LOCATION',
- inject_before: Configuration | None = None,
- inject_after: Configuration | None = None,
- disable_caching: bool = False,
- **kwargs: Any,
Bases:
Mapping
The entry point for defining an immutable Configuration from file paths that lazily loads on first access.
- Options:
Using
env_location_var_name
, you can enable pulling locations from an environment variable.See
LazyLoadConfiguration.as_typed()
for type annotated usage.inject_before
andinject_after
allow you to inject Python-created settings into you configuration without use a file.
as_typed()
Exampleclass SubConfig(Configuration): c: str class Config(Configuration): a: int b: SubConfig typed = LazyLoadConfiguration("config.yaml").as_typed(Config) assert typed.a == 101 assert typed.b.c == "test me" assert typed["a"] == 101
Injection Rules and Example
Injections must use
Configuration
for all mappings.Otherwise, they will be treated as a normal value and not merged.
Injection occurs before
base_path
is applied.I.e. You must include the
base_path
in the injectedConfiguration
.
Using injections disables “identical immutable configurations” caching.
This is only available for
LazyLoadConfiguration
As
MutableLazyLoadConfiguration
doesn’t required this.
Examples:
You might want to have a setting the is the current date.
You want to provide substitution options via
!Sub
.
# "config.yaml" app: data: key1: !Sub ${$.LOOKUP_KEY} key2: !Sub ${$.LOOKUP_KEY}
CONFIG = LazyLoadConfiguration( "config.yaml", base_path="app", inject_after=Configuration( app=Configuration( today=date.today().isoformat(), ), LOOKUP_KEY="value made available to `!Sub`", ), ) CONFIG.today # Today's date as a constant string. CONFIG.data.as_dict() # Data defined with a reusable library defined value.
Attention
dict
does not act asConfiguration
.dict
instances are values that do not merge.
- Parameters:
*load_order_location (Path | str | os.PathLike) – File path to configuration file
base_path (str | Sequence[str], optional) – Defines the subsection of the configuration file to use. See Examples for usage options.
use_env_location (bool, optional) –
Enabled to use the default environment variable location.
Setting to
True
is only required if you don’t changeenv_location_var_name
from its default value.
env_location_var_name (str, optional) –
Specify what environment variable to check for additional file paths.
The Environment Variable is read as a comma-delimited list of configuration path that will be appended to
load_order_location
list.Setting the Environment Variable is always optional.
Default:
G_CONFIG_LOCATION
Setting
use_env_location=True
is required to use the default value.
inject_before (Configuration, optional) – Inject a runtime
Configuration
instance, as if it were the first loaded file.inject_after (Configuration, optional) – Inject a runtime
Configuration
instance, as if it were the last loaded file.disable_caching (bool, optional) – When
True
, this instance will not participate in the caching of “identical immutable configurations”.**kwargs (Any) – There are no public-facing supported extra parameters.
- Examples:
# Base Path - Single Key LazyLoadConfiguration(..., base_path="base_path") # Base Path - JSON Pointer (strings only) LazyLoadConfiguration(..., base_path="/base/path") # Base Path - List of keys LazyLoadConfiguration(..., base_path=("base", "path")) # Use Environment Variable: "CONFIG_LOC" LazyLoadConfiguration(..., env_location_var_name="CONFIG_LOC") # Use default Environment Variable: "G_CONFIG_LOCATION" LazyLoadConfiguration(..., use_env_location=True) # With a typed `Configuration` LazyLoadConfiguration(...).as_typed(TypedConfig)
- __getattr__(
- name: str,
Loads (if not loaded) and fetches from the underlying Configuration object
This also exposes the methods of
Configuration
(except dunders).
- as_typed( ) C [source]
Create a proxy that is cast to provide
Configuration
subclass with typed annotated attributes.This proxy ensures laziness is preserved and is fully compatible with
Configuration
.Example
class SubConfig(Configuration): c: str class Config(Configuration): a: int b: SubConfig typed = LazyLoadConfiguration("config.yaml").as_typed(Config) assert typed.a == 101 assert typed.b.c == "test me" assert typed["a"] == 101
No runtime type checking
This method uses
typing.cast()
to return aSafeConfigurationProxy
of this instance as the requestedConfiguration
subclass.This enables typing checking and typed attributes with minimal runtime cost, but it is limited to just improving developer experience.
Use
Pydantic
, or some like it, if you require runtime type checking.- Parameters:
typed_base (type[C]) – Subclass of
Configuration
to assume- Returns:
SafeConfigurationProxy
instance that has been cast to the provided type.- Return type:
- eager_load( ) C [source]
Added in version 2.3.0.
This will eagerly load this instance, so that there is minimum IO load on future.
This is intended to play well with
asyncio
, by avoiding blocking the main thread/event loop on IO calls, without introducing anawait
paradigm just for a few one-time calls.Part of the EagerIO feature set
Using
eager_load()
causes immediate loading of this instance in a background thread, so that future calls are non-/minimally blocking.Behaves like
as_typed()
otherwise.- Parameters:
typed_base (type[C]) – Subclass of
Configuration
to assume- Returns:
EagerIOConfigurationProxy
instance that has been cast to the provided type.- Return type:
- get(
- k[,
- d,]
- items() a set-like object providing a view on D's items
- keys() a set-like object providing a view on D's keys
- values() an object providing a view on D's values
- property config: Configuration
Load and fetch the configuration. Configuration is cached for subsequent calls.
Thread-safe
Loading the configuration is thread-safe and locks while the configuration is loaded to prevent duplicative processing and data
- class granular_configuration_language.Configuration[source]
- class granular_configuration_language.Configuration( )
- class granular_configuration_language.Configuration( )
- class granular_configuration_language.Configuration(
- **kwargs: VT,
Bases:
Generic
[KT
,VT
],Mapping
[KT
,VT
]This class represents an immutable
Mapping
of configuration.You can create type annotated subclasses of
Configuration
to enable type checking and code completion, as if your subclass was adataclass
[1].With you typed class, you can cast a general
Configuration
to your subclass viaConfiguration.as_typed()
.as_typed()
Exampleclass SubConfig(Configuration): c: str class Config(Configuration): a: int b: SubConfig config = ... # A Configuration instance typed = config.as_typed(Config) assert typed.a == 101 assert typed.b.c == "test me" assert typed["a"] == 101 # Or loading with LazyLoadConfiguration typed = LazyLoadConfiguration("config.yaml").as_typed(Config)
Advisement
Consider using
LazyLoadConfiguration.as_typed()
to load your entire configuration as a typedConfiguration
.Footnotes
Changes
Changed in version 2.3.0: Added Generic Type Parameters, which default to
Any
.- Parameters:
mapping (Mapping[KT, VT]) – Constructs a
Configuration
by shallow copying initiating mapping.iterable (Iterable[tuple[KT, VT]]) – Constructs a
Configuration
from an iterable of key-value pairs.**kwargs (VT) – Constructs a
Configuration
via keyword arguments. (Due to a limitation of defaults,KT
is inferred to beAny
, instead ofstr
.)
- __getattr__(
- name: str,
Provides a potentially cleaner path as an alternative to
__getitem__()
.Comparing to
__getitem__()
Three less characters
Only accepts
str
Throws
AttributeError
instead ofKeyError
- Example:
config.a.b.c # Using `__getattr__` config["a"]["b"]["c"] # Using `__getitem__`
- Parameters:
name (str) – Attribute name
- Returns:
Fetched value
- Return type:
- Raises:
AttributeError – When an attribute is not present.
- as_dict() dict[KT, VT] [source]
Returns this
Configuration
as standard Pythondict
. NestedConfiguration
objects will also be converted.Evaluation Notice
This will evaluate all lazy tag functions and throw an exception on
Placeholder
objects.
- as_json_string( ) str [source]
Returns this
Configuration
as a JSON string, using standardjson
library and (as default) the default factory provided by this library (granular_configuration_language.json_default()
).Evaluation Notice
This will evaluate all lazy tag functions and throw an exception on
Placeholder
objects.- Parameters:
default (Callable[[Any], Any], optional) – Replacement
default
factory. Defaults tojson_default()
.**kwds (Any) – Arguments to be passed into
json.dumps()
- Returns:
JSON-format string
- Return type:
- as_typed( ) C [source]
Cast this
Configuration
instance into subclass ofConfiguration
with typed annotated attributesAdvisement
Consider using
LazyLoadConfiguration.as_typed()
to load your entire configuration as a typedConfiguration
, instead of just a section with this version.No runtime type checking
This method uses
typing.cast()
to return this instance, unmodified, as the requestedConfiguration
subclass. This enables typing checking and typed attributes with minimal a runtime cost. It is limited to just improving developer experience.Use
Pydantic
, or some like it, if you require runtime type checking.- Parameters:
typed_base (type[C]) – Subclass of
Configuration
to assume- Returns:
This instance
- Return type:
- copy() Configuration[KT, VT]
Returns a shallow copy of this instance. (Matches
dict.copy()
interface.)Caution
LazyEval
do not make copies. If you have not evaluated all tags, you should calledevaluate_all()
before calling this method.Tip
Configuration
is immutable, so you do not need to make a copy to protect it.
- evaluate_all() None [source]
Evaluates all lazy tag functions and throws an exception on
Placeholder
instances
- exists(key: Any) bool [source]
Checks that a key exists and is not a
Placeholder
- Parameters:
key (Any) – key to be checked
- Returns:
Returns
True
if the key exists and is not aPlaceholder
- Return type:
- get(
- key: KT,
- /,
- get( ) VT | T
Return the value for key if key is in the
Configuration
, else default.Changed in version 2.3.0: Added typing overload.
key
is typed as positional.
- items() a set-like object providing a view on D's items
- keys() a set-like object providing a view on D's keys
- typed_get( ) T [source]
- typed_get( ) T
- typed_get( ) T
- typed_get( ) T
Provides a typed-checked
get()
option- Parameters:
- Returns:
Value stored under the key
- Return type:
- Raises:
TypeError – If the real type is not an instance of the expected type
- values() an object providing a view on D's values
- class granular_configuration_language.MutableLazyLoadConfiguration(
- *load_order_location: Path | str | PathLike,
- base_path: str | Sequence[str] | None = None,
- use_env_location: bool = False,
- env_location_var_name: str = 'G_CONFIG_LOCATION',
Bases:
LazyLoadConfiguration
,MutableMapping
Used to define a mutable Configuration from file paths that lazily loads on first access.
- Options:
Using
env_location_var_name
, you can enable pulling locations from an environment variable.
Tip
Consider using an immutable configuration with
LazyLoadConfiguration
in you code to reduce unexpected side-effects.Classes used for mutability
MutableConfiguration
for mappingslist
for sequences
- Parameters:
*load_order_location (Path | str | os.PathLike) – File path to configuration file
base_path (str | Sequence[str], optional) – Defines the subsection of the configuration file to use. See Examples for usage options.
use_env_location (bool, optional) –
Enabled to use the default environment variable location.
Setting to
True
is only required if you don’t changeenv_location_var_name
from its default value.
env_location_var_name (str, optional) –
Specify what environment variable to check for additional file paths.
The Environment Variable is read as a comma-delimited list of configuration path that will be appended to
load_order_location
list.Setting the Environment Variable is always optional.
Default:
G_CONFIG_LOCATION
Setting
use_env_location=True
is required to use the default value.
- Examples:
# Base Path - Single Key MutableLazyLoadConfiguration(..., base_path="base_path") # Base Path - JSON Pointer (strings only) MutableLazyLoadConfiguration(..., base_path="/base/path") # Base Path - List of keys MutableLazyLoadConfiguration(..., base_path=("base", "path")) # Use Environment Variable: "CONFIG_LOC" MutableLazyLoadConfiguration(..., env_location_var_name="CONFIG_LOC") # Use default Environment Variable: "G_CONFIG_LOCATION" MutableLazyLoadConfiguration(..., use_env_location=True)
- __getattr__(
- name: str,
Loads (if not loaded) and fetches from the underlying Configuration object
This also exposes the methods of
Configuration
(except dunders).
- as_typed( ) NoReturn [source]
Not supported for
MutableLazyLoadConfiguration
. UseLazyLoadConfiguration
.
- clear() None. Remove all items from D.
- eager_load( ) NoReturn [source]
Not supported for
MutableLazyLoadConfiguration
. UseLazyLoadConfiguration
.
- get(
- k[,
- d,]
- items() a set-like object providing a view on D's items
- keys() a set-like object providing a view on D's keys
- pop(
- k[,
- d,]
If key is not found, d is returned if given, otherwise KeyError is raised.
- popitem() (k, v), remove and return some (key, value) pair
as a 2-tuple; but raise KeyError if D is empty.
- setdefault(
- k[,
- d,]
- update(
- [E,]
- **F,
If E present and has a .keys() method, does: for k in E.keys(): D[k] = E[k] If E present and lacks .keys() method, does: for (k, v) in E: D[k] = v In either case, this is followed by: for k, v in F.items(): D[k] = v
- values() an object providing a view on D's values
- property config: MutableConfiguration
Load and fetch the configuration. Configuration is cached for subsequent calls.
Thread-safe
Loading the configuration is thread-safe and locks while the configuration is loaded to prevent duplicative processing and data
- class granular_configuration_language.MutableConfiguration[source]
- class granular_configuration_language.MutableConfiguration( )
- class granular_configuration_language.MutableConfiguration( )
- class granular_configuration_language.MutableConfiguration(
- **kwargs: VT,
Bases:
Generic
[KT
,VT
],MutableMapping
[KT
,VT
],Configuration
[KT
,VT
]This class represents an
MutableMapping
of the configuration. Inherits fromConfiguration
Tip
Consider using
Configuration
in you code to reduce unexpected side-effects.- Parameters:
mapping (Mapping[KT, VT]) – Constructs a
MutableConfiguration
by shallow copying initiating mapping.iterable (Iterable[tuple[KT, VT]]) – Constructs a
MutableConfiguration
from an iterable of key-value pairs.**kwargs (VT) – Constructs a
MutableConfiguration
via keyword arguments. (Due to a limitation of defaults,KT
is inferred to beAny
, instead ofstr
.)
- __getattr__(
- name: str,
Provides a potentially cleaner path as an alternative to
__getitem__()
.Comparing to
__getitem__()
Three less characters
Only accepts
str
Throws
AttributeError
instead ofKeyError
- Example:
config.a.b.c # Using `__getattr__` config["a"]["b"]["c"] # Using `__getitem__`
- Parameters:
name (str) – Attribute name
- Returns:
Fetched value
- Return type:
- Raises:
AttributeError – When an attribute is not present.
- as_dict() dict[KT, VT]
Returns this
Configuration
as standard Pythondict
. NestedConfiguration
objects will also be converted.Evaluation Notice
This will evaluate all lazy tag functions and throw an exception on
Placeholder
objects.
- as_json_string( ) str
Returns this
Configuration
as a JSON string, using standardjson
library and (as default) the default factory provided by this library (granular_configuration_language.json_default()
).Evaluation Notice
This will evaluate all lazy tag functions and throw an exception on
Placeholder
objects.- Parameters:
default (Callable[[Any], Any], optional) – Replacement
default
factory. Defaults tojson_default()
.**kwds (Any) – Arguments to be passed into
json.dumps()
- Returns:
JSON-format string
- Return type:
- as_typed( ) C
Cast this
Configuration
instance into subclass ofConfiguration
with typed annotated attributesAdvisement
Consider using
LazyLoadConfiguration.as_typed()
to load your entire configuration as a typedConfiguration
, instead of just a section with this version.No runtime type checking
This method uses
typing.cast()
to return this instance, unmodified, as the requestedConfiguration
subclass. This enables typing checking and typed attributes with minimal a runtime cost. It is limited to just improving developer experience.Use
Pydantic
, or some like it, if you require runtime type checking.- Parameters:
typed_base (type[C]) – Subclass of
Configuration
to assume- Returns:
This instance
- Return type:
- clear() None. Remove all items from D.
- copy() MutableConfiguration
Returns a shallow copy of this instance. (Matches
dict.copy()
interface.)Caution
LazyEval
do not make copies. If you have not evaluated all tags, you should calledevaluate_all()
before calling this method.
- evaluate_all() None
Evaluates all lazy tag functions and throws an exception on
Placeholder
instances
- exists(key: Any) bool
Checks that a key exists and is not a
Placeholder
- Parameters:
key (Any) – key to be checked
- Returns:
Returns
True
if the key exists and is not aPlaceholder
- Return type:
- get( ) VT | T | None
Return the value for key if key is in the
Configuration
, else default.Changed in version 2.3.0: Added typing overload.
key
is typed as positional.
- items() a set-like object providing a view on D's items
- keys() a set-like object providing a view on D's keys
- pop(
- k[,
- d,]
If key is not found, d is returned if given, otherwise KeyError is raised.
- popitem() (k, v), remove and return some (key, value) pair
as a 2-tuple; but raise KeyError if D is empty.
- setdefault(
- k[,
- d,]
- typed_get( ) T [source]
- typed_get( ) T
- typed_get( ) T
- typed_get( ) T
Provides a typed-checked
get()
option- Parameters:
- Returns:
Value stored under the key
- Return type:
- Raises:
TypeError – If the real type is not an instance of the expected type
- update(
- [E,]
- **F,
If E present and has a .keys() method, does: for k in E.keys(): D[k] = E[k] If E present and lacks .keys() method, does: for (k, v) in E: D[k] = v In either case, this is followed by: for k, v in F.items(): D[k] = v
- values() an object providing a view on D's values
- granular_configuration_language.LLC
alias of
LazyLoadConfiguration
- granular_configuration_language.json_default(value: Any) Any [source]
A factory function to be used by the
json.dump()
family of functions.Provides serialization for types produced by this library’s Tags.
Explicitly:
!UUID
/uuid.UUID
as hyphenated hex string!Date
/datetime.date
asisoformat()
!DateTime
/datetime.datetime
asisoformat()
!Func
/Callable
asf"<{func.__module__}.{func.__name__}>"
!Class
/type
asf"<{class.__module__}.{class.__name__}>"
For niceness,
Mapping
and non-str
Sequence
instances are converted todict
andtuple
- Parameters:
value (Any) – Value being converted
- Returns:
json.dump()
compatible object- Return type:
Any
- Raises:
TypeError – When an incompatible is provided, as required by
JSONEncoder
- granular_configuration_language.merge(
- configs: Iterable[Configuration | LazyLoadConfiguration | LazyEval | PathLike | Any],
- *,
- mutable: bool = False,
Merges the provided configurations into a single configuration.
Filters out non-
Configuration
objects.Extracts
Configuration
fromLazyEval
andLazyLoadConfiguration
.Any
os.PathLike
objects are loaded via individualLazyLoadConfiguration
instances.
Why does this exist?
To enable merging a framework configuration with a library-specific configuration.
The explicit case was for a
pytest
sub-plugin that was a part of a framework plugin.Using
merge()
allows users to set settings in the framework configuration without requiring the framework configuration needing to know about the sub-plugin.base_path
is required to ensure safety.
Caution
Don’t use
merge()
as a replacement forLazyLoadConfiguration
. It is less efficient and creates Load Boundaries on each configuration.Attention
dict
does not act asConfiguration
.dict
instances are values that do not merge.
- Parameters:
configs (Iterable[Configuration | LazyLoadConfiguration | LazyEval | PathLike | Any]) – Configurations to be merged
mutable (bool, optional) – If
True
,MutableConfiguration
is used, elseConfiguration
is used. Defaults toFalse
.
- Returns:
Merged configuration. Empty if nothing was mergeable.
- Return type:
Made available from .yaml.classes
- class granular_configuration_language.Masked[source]
Bases:
str
Used to keep secrets from printing to screen when running tests.
Inherits from
str
.Replaces the standard
__repr__()
result with the constant literal'<****>'
.Used by
!Mask
tag (ref).
Note
Does not alter text or prevent
print()
from display the string value.