Source code for pyTooling.Configuration

# ==================================================================================================================== #
#             _____           _ _               ____             __ _                       _   _                      #
#  _ __  _   |_   _|__   ___ | (_)_ __   __ _  / ___|___  _ __  / _(_) __ _ _   _ _ __ __ _| |_(_) ___  _ __           #
# | '_ \| | | || |/ _ \ / _ \| | | '_ \ / _` || |   / _ \| '_ \| |_| |/ _` | | | | '__/ _` | __| |/ _ \| '_ \          #
# | |_) | |_| || | (_) | (_) | | | | | | (_| || |__| (_) | | | |  _| | (_| | |_| | | | (_| | |_| | (_) | | | |         #
# | .__/ \__, ||_|\___/ \___/|_|_|_| |_|\__, (_)____\___/|_| |_|_| |_|\__, |\__,_|_|  \__,_|\__|_|\___/|_| |_|         #
# |_|    |___/                          |___/                         |___/                                            #
# ==================================================================================================================== #
# Authors:                                                                                                             #
#   Patrick Lehmann                                                                                                    #
#                                                                                                                      #
# License:                                                                                                             #
# ==================================================================================================================== #
# Copyright 2021-2025 Patrick Lehmann - Bötzingen, Germany                                                             #
#                                                                                                                      #
# Licensed under the Apache License, Version 2.0 (the "License");                                                      #
# you may not use this file except in compliance with the License.                                                     #
# You may obtain a copy of the License at                                                                              #
#                                                                                                                      #
#   http://www.apache.org/licenses/LICENSE-2.0                                                                         #
#                                                                                                                      #
# Unless required by applicable law or agreed to in writing, software                                                  #
# distributed under the License is distributed on an "AS IS" BASIS,                                                    #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.                                             #
# See the License for the specific language governing permissions and                                                  #
# limitations under the License.                                                                                       #
#                                                                                                                      #
# SPDX-License-Identifier: Apache-2.0                                                                                  #
# ==================================================================================================================== #
#
"""\
Abstract configuration reader.

.. hint:: See :ref:`high-level help <CONFIG>` for explanations and usage examples.
"""
from pathlib       import Path
from typing        import Union, ClassVar, Iterator, Type, Optional as Nullable

try:
	from pyTooling.Decorators  import export, readonly
	from pyTooling.MetaClasses import ExtendedType, mixin
	from pyTooling.Exceptions  import ToolingException
except (ImportError, ModuleNotFoundError):  # pragma: no cover
	print("[pyTooling.Configuration] Could not import from 'pyTooling.*'!")

	try:
		from Decorators          import export, readonly
		from MetaClasses         import ExtendedType, mixin
		from Exceptions          import ToolingException
	except (ImportError, ModuleNotFoundError) as ex:  # pragma: no cover
		print("[pyTooling.Configuration] Could not import directly!")
		raise ex


KeyT = Union[str, int]
NodeT = Union["Dictionary", "Sequence"]
ValueT = Union[NodeT, str, int, float]


[docs] @export class ConfigurationException(ToolingException): pass
[docs] @export class Node(metaclass=ExtendedType, slots=True): """Abstract node in a configuration data structure.""" DICT_TYPE: ClassVar[Type["Dictionary"]] #: Type reference used when instantiating new dictionaries SEQ_TYPE: ClassVar[Type["Sequence"]] #: Type reference used when instantiating new sequences _root: "Configuration" #: Reference to the root node. _parent: "Dictionary" #: Reference to a parent node.
[docs] def __init__(self, root: "Configuration" = None, parent: Nullable[NodeT] = None) -> None: """ Initializes a node. :param root: Reference to the root node. :param parent: Reference to the parent node. """ self._root = root self._parent = parent
[docs] def __len__(self) -> int: # type: ignore[empty-body] """ Returns the number of sub-elements. :returns: Number of sub-elements. """
def __getitem__(self, key: KeyT) -> ValueT: # type: ignore[empty-body] raise NotImplementedError() def __setitem__(self, key: KeyT, value: ValueT) -> None: # type: ignore[empty-body] raise NotImplementedError() def __iter__(self) -> Iterator[ValueT]: # type: ignore[empty-body] raise NotImplementedError() @property def Key(self) -> KeyT: raise NotImplementedError() @Key.setter def Key(self, value: KeyT): raise NotImplementedError() def QueryPath(self, query: str) -> ValueT: # type: ignore[empty-body] raise NotImplementedError()
[docs] @export @mixin class Dictionary(Node): """Abstract dictionary node in a configuration."""
[docs] def __init__(self, root: "Configuration" = None, parent: Nullable[NodeT] = None) -> None: """ Initializes a dictionary. :param root: Reference to the root node. :param parent: Reference to the parent node. """ Node.__init__(self, root, parent)
def __contains__(self, key: KeyT) -> bool: # type: ignore[empty-body] raise NotImplementedError()
[docs] @export @mixin class Sequence(Node): """Abstract sequence node in a configuration."""
[docs] def __init__(self, root: "Configuration" = None, parent: Nullable[NodeT] = None) -> None: """ Initializes a sequence. :param root: Reference to the root node. :param parent: Reference to the parent node. """ Node.__init__(self, root, parent)
def __getitem__(self, index: int) -> ValueT: # type: ignore[empty-body] raise NotImplementedError() def __setitem__(self, index: int, value: ValueT) -> None: # type: ignore[empty-body] raise NotImplementedError()
setattr(Node, "DICT_TYPE", Dictionary) setattr(Node, "SEQ_TYPE", Sequence)
[docs] @export @mixin class Configuration(Node): """Abstract root node in a configuration.""" _configFile: Path
[docs] def __init__(self, configFile: Path, root: "Configuration" = None, parent: Nullable[NodeT] = None) -> None: """ Initializes a configuration. :param configFile: Configuration file. :param root: Reference to the root node. :param parent: Reference to the parent node. """ Node.__init__(self, root, parent) self._configFile = configFile
@readonly def ConfigFile(self) -> Path: return self._configFile