Coverage for pyTooling/GenericPath/__init__.py: 97%
56 statements
« prev ^ index » next coverage.py v7.8.0, created at 2025-04-25 22:22 +0000
« prev ^ index » next coverage.py v7.8.0, created at 2025-04-25 22:22 +0000
1# ==================================================================================================================== #
2# _____ _ _ ____ _ ____ _ _ #
3# _ __ _ |_ _|__ ___ | (_)_ __ __ _ / ___| ___ _ __ ___ _ __(_) ___| _ \ __ _| |_| |__ #
4# | '_ \| | | || |/ _ \ / _ \| | | '_ \ / _` || | _ / _ \ '_ \ / _ \ '__| |/ __| |_) / _` | __| '_ \ #
5# | |_) | |_| || | (_) | (_) | | | | | | (_| || |_| | __/ | | | __/ | | | (__| __/ (_| | |_| | | | #
6# | .__/ \__, ||_|\___/ \___/|_|_|_| |_|\__, (_)____|\___|_| |_|\___|_| |_|\___|_| \__,_|\__|_| |_| #
7# |_| |___/ |___/ #
8# ==================================================================================================================== #
9# Authors: #
10# Patrick Lehmann #
11# #
12# License: #
13# ==================================================================================================================== #
14# Copyright 2017-2025 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"""A generic path to derive domain specific path libraries."""
32from typing import List, Optional as Nullable
34try:
35 from pyTooling.Decorators import export
36 from pyTooling.MetaClasses import ExtendedType
37except (ImportError, ModuleNotFoundError): # pragma: no cover
38 print("[pyTooling.GenericPath] Could not import from 'pyTooling.*'!")
40 try:
41 from Decorators import export
42 from MetaClasses import ExtendedType
43 except (ImportError, ModuleNotFoundError) as ex: # pragma: no cover
44 print("[pyTooling.GenericPath] Could not import directly!")
45 raise ex
48@export
49class Base(metaclass=ExtendedType, mixin=True):
50 """Base-class for all pyTooling.GenericPath path elements."""
52 DELIMITER = "/"
54 _parent: Nullable["Base"]
56 def __init__(self, parent: Nullable["Base"]) -> None:
57 self._parent = parent
60@export
61class RootMixIn(Base, mixin=True):
62 """Mixin-class for root elements in a path system."""
64 def __init__(self) -> None:
65 super().__init__(None)
68@export
69class ElementMixIn(Base, mixin=True):
70 """Mixin-class for elements in a path system."""
72 _elementName: str
74 def __init__(self, parent: Base, elementName: str) -> None:
75 super().__init__(parent)
76 self._elementName = elementName
78 def __str__(self) -> str:
79 return self._elementName
82@export
83class PathMixIn(metaclass=ExtendedType, mixin=True):
84 """Mixin-class for a path."""
86 ELEMENT_DELIMITER = "/"
87 ROOT_DELIMITER = "/"
89 _isAbsolute: bool
90 _elements: List[ElementMixIn]
92 def __init__(self, elements: List[ElementMixIn], isAbsolute: bool) -> None:
93 self._isAbsolute = isAbsolute
94 self._elements = elements
96 def __len__(self) -> int:
97 """
98 Returns the number of path elements.
100 :returns: Number of path elements.
101 """
102 return len(self._elements)
104 def __str__(self) -> str:
105 result = self.ROOT_DELIMITER if self._isAbsolute else ""
107 if len(self._elements) > 0: 107 ↛ 113line 107 didn't jump to line 113 because the condition on line 107 was always true
108 result = result + str(self._elements[0])
110 for element in self._elements[1:]:
111 result = result + self.ELEMENT_DELIMITER + str(element)
113 return result
115 @classmethod
116 def Parse(cls, path: str, root, pathCls, elementCls):
117 """Parses a string representation of a path and returns a path instance."""
119 parent = root
121 if path.startswith(cls.ROOT_DELIMITER):
122 isAbsolute = True
123 path = path[len(cls.ELEMENT_DELIMITER):]
124 else:
125 isAbsolute = False
127 parts = path.split(cls.ELEMENT_DELIMITER)
128 elements = []
129 for part in parts:
130 element = elementCls(parent, part)
131 parent = element
132 elements.append(element)
134 return pathCls(elements, isAbsolute)
137@export
138class SystemMixIn(metaclass=ExtendedType, mixin=True):
139 """Mixin-class for a path system."""