Coverage for pyTooling / Configuration / __init__.py: 94%
54 statements
« prev ^ index » next coverage.py v7.13.4, created at 2026-02-13 22:36 +0000
« prev ^ index » next coverage.py v7.13.4, created at 2026-02-13 22:36 +0000
1# ==================================================================================================================== #
2# _____ _ _ ____ __ _ _ _ #
3# _ __ _ |_ _|__ ___ | (_)_ __ __ _ / ___|___ _ __ / _(_) __ _ _ _ _ __ __ _| |_(_) ___ _ __ #
4# | '_ \| | | || |/ _ \ / _ \| | | '_ \ / _` || | / _ \| '_ \| |_| |/ _` | | | | '__/ _` | __| |/ _ \| '_ \ #
5# | |_) | |_| || | (_) | (_) | | | | | | (_| || |__| (_) | | | | _| | (_| | |_| | | | (_| | |_| | (_) | | | | #
6# | .__/ \__, ||_|\___/ \___/|_|_|_| |_|\__, (_)____\___/|_| |_|_| |_|\__, |\__,_|_| \__,_|\__|_|\___/|_| |_| #
7# |_| |___/ |___/ |___/ #
8# ==================================================================================================================== #
9# Authors: #
10# Patrick Lehmann #
11# #
12# License: #
13# ==================================================================================================================== #
14# Copyright 2021-2026 Patrick Lehmann - Bötzingen, Germany #
15# #
16# Licensed under the Apache License, Version 2.0 (the "License"); #
17# you may not use this file except in compliance with the License. #
18# You may obtain a copy of the License at #
19# #
20# http://www.apache.org/licenses/LICENSE-2.0 #
21# #
22# Unless required by applicable law or agreed to in writing, software #
23# distributed under the License is distributed on an "AS IS" BASIS, #
24# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
25# See the License for the specific language governing permissions and #
26# limitations under the License. #
27# #
28# SPDX-License-Identifier: Apache-2.0 #
29# ==================================================================================================================== #
30#
31"""
32Abstract configuration reader.
34.. hint::
36 See :ref:`high-level help <CONFIG>` for explanations and usage examples.
37"""
38from pathlib import Path
39from typing import Union, ClassVar, Iterator, Type, Optional as Nullable
41from pyTooling.Decorators import export, readonly
42from pyTooling.MetaClasses import ExtendedType, mixin
43from pyTooling.Exceptions import ToolingException
46__all__ = ["KeyT", "NodeT", "ValueT"]
49KeyT = Union[str, int] #: Type variable for keys.
50NodeT = Union["Dictionary", "Sequence"] #: Type variable for nodes.
51ValueT = Union[NodeT, str, int, float] #: Type variable for values.
54@export
55class ConfigurationException(ToolingException):
56 """Base-exception of all exceptions raised by :mod:`pyTooling.Configuration`."""
59@export
60class Node(metaclass=ExtendedType, slots=True):
61 """Abstract node in a configuration data structure."""
63 DICT_TYPE: ClassVar[Type["Dictionary"]] #: Type reference used when instantiating new dictionaries
64 SEQ_TYPE: ClassVar[Type["Sequence"]] #: Type reference used when instantiating new sequences
65 _root: "Configuration" #: Reference to the root node.
66 _parent: "Dictionary" #: Reference to a parent node.
68 def __init__(self, root: "Configuration" = None, parent: Nullable[NodeT] = None) -> None:
69 """
70 Initializes a node.
72 :param root: Reference to the root node.
73 :param parent: Reference to the parent node.
74 """
75 self._root = root
76 self._parent = parent
78 def __len__(self) -> int: # type: ignore[empty-body]
79 """
80 Returns the number of sub-elements.
82 :returns: Number of sub-elements.
83 """
85 def __getitem__(self, key: KeyT) -> ValueT: # type: ignore[empty-body]
86 """
87 Access an element in the node by index or key.
89 :param key: Index or key of the element.
90 :returns: A node (sequence or dictionary) or scalar value (int, float, str).
91 """
92 raise NotImplementedError()
94 def __setitem__(self, key: KeyT, value: ValueT) -> None: # type: ignore[empty-body]
95 """
96 Set an element in the node by index or key.
98 :param key: Index or key of the element.
99 :param value: Value to set
100 """
101 raise NotImplementedError()
103 def __iter__(self) -> Iterator[ValueT]: # type: ignore[empty-body]
104 """
105 Returns an iterator to iterate a node.
107 :returns: Node iterator.
108 """
109 raise NotImplementedError()
111 @property
112 def Key(self) -> KeyT:
113 raise NotImplementedError()
115 @Key.setter
116 def Key(self, value: KeyT) -> None:
117 raise NotImplementedError()
119 def QueryPath(self, query: str) -> ValueT: # type: ignore[empty-body]
120 """
121 Return a node or value based on a path description to that node or value.
123 :param query: String describing the path to the node or value.
124 :returns: A node (sequence or dictionary) or scalar value (int, float, str).
125 """
126 raise NotImplementedError()
129@export
130@mixin
131class Dictionary(Node):
132 """Abstract dictionary node in a configuration."""
134 def __init__(self, root: "Configuration" = None, parent: Nullable[NodeT] = None) -> None:
135 """
136 Initializes a dictionary.
138 :param root: Reference to the root node.
139 :param parent: Reference to the parent node.
140 """
141 Node.__init__(self, root, parent)
143 def __contains__(self, key: KeyT) -> bool: # type: ignore[empty-body]
144 raise NotImplementedError()
147@export
148@mixin
149class Sequence(Node):
150 """Abstract sequence node in a configuration."""
152 def __init__(self, root: "Configuration" = None, parent: Nullable[NodeT] = None) -> None:
153 """
154 Initializes a sequence.
156 :param root: Reference to the root node.
157 :param parent: Reference to the parent node.
158 """
159 Node.__init__(self, root, parent)
161 def __getitem__(self, index: int) -> ValueT: # type: ignore[empty-body]
162 raise NotImplementedError()
164 def __setitem__(self, index: int, value: ValueT) -> None: # type: ignore[empty-body]
165 raise NotImplementedError()
168setattr(Node, "DICT_TYPE", Dictionary)
169setattr(Node, "SEQ_TYPE", Sequence)
172@export
173@mixin
174class Configuration(Node):
175 """Abstract root node in a configuration."""
177 _configFile: Path #: Path to the configuration file.
179 def __init__(self, configFile: Path, root: "Configuration" = None, parent: Nullable[NodeT] = None) -> None:
180 """
181 Initializes a configuration.
183 :param configFile: Configuration file.
184 :param root: Reference to the root node.
185 :param parent: Reference to the parent node.
186 """
187 Node.__init__(self, root, parent)
188 self._configFile = configFile
190 @readonly
191 def ConfigFile(self) -> Path:
192 """
193 Read-only property to access the configuration file's path.
195 :returns: Path to the configuration file.
196 """
197 return self._configFile