Coverage for pyVHDLModel/Namespace.py: 23%

87 statements  

« 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. 

34 

35A helper class to implement namespaces and scopes. 

36""" 

37from typing import TypeVar, Generic, Dict, Optional as Nullable, Any, Tuple 

38 

39from pyTooling.Decorators import readonly 

40 

41from pyVHDLModel.Object import Obj, Signal, Constant, Variable 

42from pyVHDLModel.Symbol import ComponentInstantiationSymbol, Symbol, PossibleReference 

43from pyVHDLModel.Type import Subtype, FullType, BaseType 

44 

45K = TypeVar("K") 

46O = TypeVar("O") 

47 

48 

49class ExtendedKeyError(KeyError): 

50 key: str 

51 searchedNamespaces: Tuple["Namespace", ...] 

52 

53 def __init__(self, key: str, searchedNamespaces: Tuple["Namespace", ...], message: str) -> None: 

54 super().__init__(message) 

55 

56 self.key = key 

57 self.searchedNamespaces = searchedNamespaces 

58 

59 

60class Namespace(Generic[K, O]): 

61 _name: str 

62 _parentNamespace: "Namespace" 

63 _subNamespaces: Dict[str, "Namespace"] 

64 _elements: Dict[K, O] 

65 

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 = {} 

71 

72 @readonly 

73 def Name(self) -> str: 

74 return self._name 

75 

76 @readonly 

77 def ParentNamespace(self) -> 'Namespace': 

78 return self._parentNamespace 

79 

80 @ParentNamespace.setter 

81 def ParentNamespace(self, value: 'Namespace'): 

82 self._parentNamespace = value 

83 value._subNamespaces[self._name] = self 

84 

85 @readonly 

86 def SubNamespaces(self) -> Dict[str, 'Namespace']: 

87 return self._subNamespaces 

88 

89 def Elements(self) -> Dict[K, O]: 

90 return self._elements 

91 

92 def FindComponent(self, componentSymbol: ComponentInstantiationSymbol) -> 'Component': 

93 from pyVHDLModel.DesignUnit import Component 

94 

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 

103 

104 if (parentNamespace := self._parentNamespace) is None: 

105 raise ExtendedKeyError(key, (self, ), f"Component '{key}' not found in '{self._name}'.") 

106 

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 

112 

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}'.") 

131 

132 return parentNamespace.FindSubtype(subtypeSymbol) 

133 

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}'.") 

159 

160 return parentNamespace.FindObject(objectSymbol)