Coverage for pyVHDLModel/Namespace.py: 23%
87 statements
« prev ^ index » next coverage.py v7.15.1, created at 2026-07-13 17:58 +0000
« prev ^ index » next coverage.py v7.15.1, created at 2026-07-13 17:58 +0000
1# ==================================================================================================================== #
2# __ ___ _ ____ _ __ __ _ _ #
3# _ __ _ \ \ / / | | | _ \| | | \/ | ___ __| | ___| | #
4# | '_ \| | | \ \ / /| |_| | | | | | | |\/| |/ _ \ / _` |/ _ \ | #
5# | |_) | |_| |\ V / | _ | |_| | |___| | | | (_) | (_| | __/ | #
6# | .__/ \__, | \_/ |_| |_|____/|_____|_| |_|\___/ \__,_|\___|_| #
7# |_| |___/ #
8# ==================================================================================================================== #
9# Authors: #
10# Patrick Lehmann #
11# #
12# License: #
13# ==================================================================================================================== #
14# Copyright 2017-2026 Patrick Lehmann - Boetzingen, Germany #
15# Copyright 2016-2017 Patrick Lehmann - Dresden, Germany #
16# #
17# Licensed under the Apache License, Version 2.0 (the "License"); #
18# you may not use this file except in compliance with the License. #
19# You may obtain a copy of the License at #
20# #
21# http://www.apache.org/licenses/LICENSE-2.0 #
22# #
23# Unless required by applicable law or agreed to in writing, software #
24# distributed under the License is distributed on an "AS IS" BASIS, #
25# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
26# See the License for the specific language governing permissions and #
27# limitations under the License. #
28# #
29# SPDX-License-Identifier: Apache-2.0 #
30# ==================================================================================================================== #
31#
32"""
33This module contains parts of an abstract document language model for VHDL.
35A helper class to implement namespaces and scopes.
36"""
37from typing import TypeVar, Generic, Dict, Optional as Nullable, Any, Tuple
39from pyTooling.Decorators import readonly
41from pyVHDLModel.Object import Obj, Signal, Constant, Variable
42from pyVHDLModel.Symbol import ComponentInstantiationSymbol, Symbol, PossibleReference
43from pyVHDLModel.Type import Subtype, FullType, BaseType
45K = TypeVar("K")
46O = TypeVar("O")
49class ExtendedKeyError(KeyError):
50 key: str
51 searchedNamespaces: Tuple["Namespace", ...]
53 def __init__(self, key: str, searchedNamespaces: Tuple["Namespace", ...], message: str) -> None:
54 super().__init__(message)
56 self.key = key
57 self.searchedNamespaces = searchedNamespaces
60class Namespace(Generic[K, O]):
61 _name: str
62 _parentNamespace: "Namespace"
63 _subNamespaces: Dict[str, "Namespace"]
64 _elements: Dict[K, O]
66 def __init__(self, name: str, parentNamespace: Nullable["Namespace"] = None) -> None:
67 self._name = name
68 self._parentNamespace = parentNamespace
69 self._subNamespaces = {}
70 self._elements = {}
72 @readonly
73 def Name(self) -> str:
74 return self._name
76 @readonly
77 def ParentNamespace(self) -> 'Namespace':
78 return self._parentNamespace
80 @ParentNamespace.setter
81 def ParentNamespace(self, value: 'Namespace'):
82 self._parentNamespace = value
83 value._subNamespaces[self._name] = self
85 @readonly
86 def SubNamespaces(self) -> Dict[str, 'Namespace']:
87 return self._subNamespaces
89 def Elements(self) -> Dict[K, O]:
90 return self._elements
92 def FindComponent(self, componentSymbol: ComponentInstantiationSymbol) -> 'Component':
93 from pyVHDLModel.DesignUnit import Component
95 try:
96 element = self._elements[componentSymbol._name._normalizedIdentifier]
97 if isinstance(element, Component):
98 return element
99 else:
100 raise TypeError(f"Found element '{componentSymbol._name._identifier}', but it is not a component.")
101 except KeyError:
102 key = componentSymbol._name._identifier
104 if (parentNamespace := self._parentNamespace) is None:
105 raise ExtendedKeyError(key, (self, ), f"Component '{key}' not found in '{self._name}'.")
107 try:
108 return parentNamespace.FindComponent(componentSymbol)
109 except ExtendedKeyError as ex:
110 searchedNamespaces = (self, *ex.searchedNamespaces)
111 raise ExtendedKeyError(key, searchedNamespaces, f"Component '{key}' not found in: {', '.join(ns._name for ns in searchedNamespaces)}.") from ex
113 def FindSubtype(self, subtypeSymbol: Symbol) -> BaseType:
114 try:
115 element = self._elements[subtypeSymbol._name._normalizedIdentifier]
116 if isinstance(element, Subtype):
117 if PossibleReference.Subtype in subtypeSymbol._possibleReferences:
118 return element
119 else:
120 raise TypeError(f"Found subtype '{subtypeSymbol._name._identifier}', but it was not expected.")
121 elif isinstance(element, FullType):
122 if PossibleReference.Type in subtypeSymbol._possibleReferences:
123 return element
124 else:
125 raise TypeError(f"Found type '{subtypeSymbol._name._identifier}', but it was not expected.")
126 else:
127 raise TypeError(f"Found element '{subtypeSymbol._name._identifier}', but it is not a type or subtype.")
128 except KeyError:
129 if (parentNamespace := self._parentNamespace) is None:
130 raise KeyError(f"Subtype '{subtypeSymbol._name._identifier}' not found in '{self._name}'.")
132 return parentNamespace.FindSubtype(subtypeSymbol)
134 def FindObject(self, objectSymbol: Symbol) -> Obj:
135 try:
136 element = self._elements[objectSymbol._name._normalizedIdentifier]
137 if isinstance(element, Signal):
138 if PossibleReference.Signal in objectSymbol._possibleReferences:
139 return element
140 elif PossibleReference.SignalAttribute in objectSymbol._possibleReferences:
141 return element
142 else:
143 raise TypeError(f"Found signal '{objectSymbol._name._identifier}', but it was not expected.")
144 elif isinstance(element, Constant):
145 if PossibleReference.Constant in objectSymbol._possibleReferences:
146 return element
147 else:
148 raise TypeError(f"Found constant '{objectSymbol._name._identifier}', but it was not expected.")
149 elif isinstance(element, Variable):
150 if PossibleReference.Variable in objectSymbol._possibleReferences:
151 return element
152 else:
153 raise TypeError(f"Found variable '{objectSymbol._name._identifier}', but it was not expected.")
154 else:
155 raise TypeError(f"Found element '{objectSymbol._name._identifier}', but it is not a type or subtype.")
156 except KeyError:
157 if (parentNamespace := self._parentNamespace) is None:
158 raise KeyError(f"Subtype '{objectSymbol._name._identifier}' not found in '{self._name}'.")
160 return parentNamespace.FindObject(objectSymbol)