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 a 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
Note
Does not alter text or prevent
print()
from display the string value.
- class granular_configuration_language.Placeholder(message: str)[source]
Bases:
object
Representation of !Placeholder tag.
Holds the
!Placeholder
message.