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:
MappingThe 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_beforeandinject_afterallow 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
Configurationfor all mappings.Otherwise, they will be treated as a normal value and not merged.
Injection occurs before
base_pathis applied.I.e. You must include the
base_pathin the injectedConfiguration.
Using injections disables “identical immutable configurations” caching.
This is only available for
LazyLoadConfigurationAs
MutableLazyLoadConfigurationdoesn’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
dictdoes not act asConfiguration.dictinstances 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
Trueis only required if you don’t changeenv_location_var_namefrom 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_locationlist.Setting the Environment Variable is always optional.
Default:
G_CONFIG_LOCATIONSetting
use_env_location=Trueis required to use the default value.
inject_before (Configuration, optional) – Inject a runtime
Configurationinstance, as if it were the first loaded file.inject_after (Configuration, optional) – Inject a runtime
Configurationinstance, 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
Configurationsubclass 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 aSafeConfigurationProxyof this instance as the requestedConfigurationsubclass.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
Configurationto assume- Returns:
SafeConfigurationProxyinstance 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 anawaitparadigm 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
Configurationto assume- Returns:
EagerIOConfigurationProxyinstance 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
Mappingof configuration.You can create type annotated subclasses of
Configurationto enable type checking and code completion, as if your subclass was adataclass[1].With you typed class, you can cast a general
Configurationto 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
Configurationby shallow copying initiating mapping.iterable (Iterable[tuple[KT, VT]]) – Constructs a
Configurationfrom an iterable of key-value pairs.**kwargs (VT) – Constructs a
Configurationvia keyword arguments. (Due to a limitation of defaults,KTis 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
strThrows
AttributeErrorinstead 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
Configurationas standard Pythondict. NestedConfigurationobjects will also be converted.Evaluation Notice
This will evaluate all lazy tag functions and throw an exception on
Placeholderobjects.
- as_json_string( ) str[source]
Returns this
Configurationas a JSON string, using standardjsonlibrary 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
Placeholderobjects.- Parameters:
default (Callable[[Any], Any], optional) – Replacement
defaultfactory. Defaults tojson_default().**kwds (Any) – Arguments to be passed into
json.dumps()
- Returns:
JSON-format string
- Return type:
- as_typed( ) C[source]
Cast this
Configurationinstance into subclass ofConfigurationwith 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 requestedConfigurationsubclass. 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
Configurationto assume- Returns:
This instance
- Return type:
- copy() Configuration[KT, VT]
Returns a shallow copy of this instance. (Matches
dict.copy()interface.)Caution
LazyEvaldo not make copies. If you have not evaluated all tags, you should calledevaluate_all()before calling this method.Tip
Configurationis 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
Placeholderinstances
- exists(key: Any) bool[source]
Checks that a key exists and is not a
Placeholder- Parameters:
key (Any) – key to be checked
- Returns:
Returns
Trueif 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.
keyis 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,MutableMappingUsed 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
LazyLoadConfigurationin you code to reduce unexpected side-effects.Classes used for mutability
MutableConfigurationfor mappingslistfor 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
Trueis only required if you don’t changeenv_location_var_namefrom 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_locationlist.Setting the Environment Variable is always optional.
Default:
G_CONFIG_LOCATIONSetting
use_env_location=Trueis 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
MutableMappingof the configuration. Inherits fromConfigurationTip
Consider using
Configurationin you code to reduce unexpected side-effects.- Parameters:
mapping (Mapping[KT, VT]) – Constructs a
MutableConfigurationby shallow copying initiating mapping.iterable (Iterable[tuple[KT, VT]]) – Constructs a
MutableConfigurationfrom an iterable of key-value pairs.**kwargs (VT) – Constructs a
MutableConfigurationvia keyword arguments. (Due to a limitation of defaults,KTis 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
strThrows
AttributeErrorinstead 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
Configurationas standard Pythondict. NestedConfigurationobjects will also be converted.Evaluation Notice
This will evaluate all lazy tag functions and throw an exception on
Placeholderobjects.
- as_json_string( ) str
Returns this
Configurationas a JSON string, using standardjsonlibrary 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
Placeholderobjects.- Parameters:
default (Callable[[Any], Any], optional) – Replacement
defaultfactory. Defaults tojson_default().**kwds (Any) – Arguments to be passed into
json.dumps()
- Returns:
JSON-format string
- Return type:
- as_typed( ) C
Cast this
Configurationinstance into subclass ofConfigurationwith 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 requestedConfigurationsubclass. 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
Configurationto 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
LazyEvaldo 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
Placeholderinstances
- exists(key: Any) bool
Checks that a key exists and is not a
Placeholder- Parameters:
key (Any) – key to be checked
- Returns:
Returns
Trueif 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.
keyis 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.UUIDas hyphenated hex string!Date/datetime.dateasisoformat()!DateTime/datetime.datetimeasisoformat()!Func/Callableasf"<{func.__module__}.{func.__name__}>"!Class/typeasf"<{class.__module__}.{class.__name__}>"For niceness,
Mappingand non-strSequenceinstances are converted todictandtuple
- 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-
Configurationobjects.Extracts
ConfigurationfromLazyEvalandLazyLoadConfiguration.Any
os.PathLikeobjects are loaded via individualLazyLoadConfigurationinstances.
Why does this exist?
To enable merging a framework configuration with a library-specific configuration.
The explicit case was for a
pytestsub-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_pathis 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
dictdoes not act asConfiguration.dictinstances are values that do not merge.
- Parameters:
configs (Iterable[Configuration | LazyLoadConfiguration | LazyEval | PathLike | Any]) – Configurations to be merged
mutable (bool, optional) – If
True,MutableConfigurationis used, elseConfigurationis 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:
strUsed to keep secrets from printing to screen when running tests.
Inherits from
str.Replaces the standard
__repr__()result with the constant literal'<****>'.Used by
!Masktag (ref).
Note
Does not alter text or prevent
print()from display the string value.