Coverage for pyEDAA/IPXACT/__init__.py: 69%

142 statements  

« prev     ^ index     » next       coverage.py v7.6.7, created at 2024-11-17 01:13 +0000

1# ==================================================================================================================== # 

2# _____ ____ _ _ ___ ______ __ _ ____ _____ # 

3# _ __ _ _| ____| _ \ / \ / \ |_ _| _ \ \/ / / \ / ___|_ _| # 

4# | '_ \| | | | _| | | | |/ _ \ / _ \ | || |_) \ / / _ \| | | | # 

5# | |_) | |_| | |___| |_| / ___ \ / ___ \ _ | || __// \ / ___ \ |___ | | # 

6# | .__/ \__, |_____|____/_/ \_\/_/ \_(_)___|_| /_/\_\/_/ \_\____| |_| # 

7# |_| |___/ # 

8# ==================================================================================================================== # 

9# Authors: # 

10# Patrick Lehmann # 

11# # 

12# License: # 

13# ==================================================================================================================== # 

14# Copyright 2017-2024 Patrick Lehmann - Bötzingen, Germany # 

15# Copyright 2016-2016 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"""A DOM based IP-XACT implementation for Python.""" 

33from pathlib import Path 

34from sys import version_info 

35from textwrap import dedent 

36from typing import Union, Dict 

37 

38from pyTooling.Decorators import export, readonly 

39from pyTooling.Common import getResourceFile, getFullyQualifiedName 

40from pyTooling.Versioning import SemanticVersion, CalendarVersion 

41 

42from . import Schema 

43 

44 

45__author__ = "Patrick Lehmann" 

46__email__ = "Paebbels@gmail.com" 

47__copyright__ = "2016-2024, Patrick Lehmann" 

48__license__ = "Apache License, Version 2.0" 

49__version__ = "0.4.0" 

50 

51 

52@export 

53class IpxactSchema: 

54 """Schema descriptor made of version, namespace prefix, URI, URL and local path.""" 

55 

56 _version: Union[SemanticVersion, CalendarVersion] #: Schema version 

57 _namespacePrefix: str #: XML namespace prefix 

58 _schemaUri: str #: Schema URI 

59 _schemaUrl: str #: Schema URL 

60 _localPath: Path #: Local path 

61 

62 def __init__( 

63 self, 

64 version: Union[str, SemanticVersion, CalendarVersion], 

65 xmlNamespacePrefix: str, 

66 schemaUri: str, 

67 schemaUrl: str, 

68 localPath: Path 

69 ) -> None: 

70 """ 

71 Initializes an IP-XACT Schema description. 

72 

73 :param version: Version of the IP-XACT Schema. 

74 :param xmlNamespacePrefix: XML namespace prefix (``<prefix:element>``) 

75 :param schemaUri: IP-XACT schema URI 

76 :param schemaUrl: URL the IP-XACT schema definition file (XSD). 

77 :param localPath: Path to the local XSD file. 

78 """ 

79 

80 if version is None: 80 ↛ 81line 80 didn't jump to line 81 because the condition on line 80 was never true

81 raise ValueError(f"Parameter 'version' is None.") 

82 elif isinstance(version, str): 82 ↛ 87line 82 didn't jump to line 87 because the condition on line 82 was always true

83 if version.startswith("20"): 

84 self._version = CalendarVersion.Parse(version) 

85 else: 

86 self._version = SemanticVersion.Parse(version) 

87 elif isinstance(version, (SemanticVersion, CalendarVersion)): 

88 self._version = version 

89 else: 

90 ex = TypeError(f"Parameter 'version' is neither a 'SemanticVersion', a 'CalendarVersion' nor a string.") 

91 if version_info >= (3, 11): # pragma: no cover 

92 ex.add_note(f"Got type '{getFullyQualifiedName(version)}'.") 

93 raise ex 

94 

95 if xmlNamespacePrefix is None: 95 ↛ 96line 95 didn't jump to line 96 because the condition on line 95 was never true

96 raise ValueError(f"Parameter 'namespacePrefix' is None.") 

97 elif not isinstance(xmlNamespacePrefix, str): 97 ↛ 98line 97 didn't jump to line 98 because the condition on line 97 was never true

98 ex = TypeError(f"Parameter 'namespacePrefix' is not a string.") 

99 if version_info >= (3, 11): # pragma: no cover 

100 ex.add_note(f"Got type '{getFullyQualifiedName(version)}'.") 

101 raise ex 

102 

103 if schemaUri is None: 103 ↛ 104line 103 didn't jump to line 104 because the condition on line 103 was never true

104 raise ValueError(f"Parameter 'schemaUri' is None.") 

105 elif not isinstance(schemaUri, str): 105 ↛ 106line 105 didn't jump to line 106 because the condition on line 105 was never true

106 ex = TypeError(f"Parameter 'schemaUri' is not a string.") 

107 if version_info >= (3, 11): # pragma: no cover 

108 ex.add_note(f"Got type '{getFullyQualifiedName(schemaUri)}'.") 

109 raise ex 

110 

111 if schemaUrl is None: 111 ↛ 112line 111 didn't jump to line 112 because the condition on line 111 was never true

112 raise ValueError(f"Parameter 'schemaUrl' is None.") 

113 elif not isinstance(schemaUrl, str): 113 ↛ 114line 113 didn't jump to line 114 because the condition on line 113 was never true

114 ex = TypeError(f"Parameter 'schemaUrl' is not a string.") 

115 if version_info >= (3, 11): # pragma: no cover 

116 ex.add_note(f"Got type '{getFullyQualifiedName(schemaUrl)}'.") 

117 raise ex 

118 

119 if localPath is None: 119 ↛ 120line 119 didn't jump to line 120 because the condition on line 119 was never true

120 raise ValueError(f"Parameter 'localPath' is None.") 

121 elif not isinstance(localPath, Path): 121 ↛ 122line 121 didn't jump to line 122 because the condition on line 121 was never true

122 ex = TypeError(f"Parameter 'localPath' is not a Path.") 

123 if version_info >= (3, 11): # pragma: no cover 

124 ex.add_note(f"Got type '{getFullyQualifiedName(localPath)}'.") 

125 raise ex 

126 

127 self._namespacePrefix = xmlNamespacePrefix 

128 self._schemaUri = schemaUri 

129 self._schemaUrl = schemaUrl 

130 self._localPath = localPath 

131 

132 @readonly 

133 def Version(self) -> Union[SemanticVersion, CalendarVersion]: 

134 return self._version 

135 

136 @readonly 

137 def NamespacePrefix(self) -> str: 

138 return self._namespacePrefix 

139 

140 @readonly 

141 def SchemaUri(self) -> str: 

142 return self._schemaUri 

143 

144 @readonly 

145 def SchemaUrl(self) -> str: 

146 return self._schemaUrl 

147 

148 @readonly 

149 def LocalPath(self) -> Path: 

150 return self._localPath 

151 

152 

153# version, xmlns, URI URL, Local Path 

154_IPXACT_10 = IpxactSchema("1.0", "spirit", "http://www.spiritconsortium.org/XMLSchema/SPIRIT/1.0", "", getResourceFile(Schema, "ipxact-1.0/index.xsd")) 

155_IPXACT_11 = IpxactSchema("1.1", "spirit", "http://www.spiritconsortium.org/XMLSchema/SPIRIT/1.1", "", getResourceFile(Schema, "ipxact-1.1/index.xsd")) 

156_IPXACT_12 = IpxactSchema("1.2", "spirit", "http://www.spiritconsortium.org/XMLSchema/SPIRIT/1.2", "", getResourceFile(Schema, "ipxact-1.2/index.xsd")) 

157_IPXACT_14 = IpxactSchema("1.4", "spirit", "http://www.spiritconsortium.org/XMLSchema/SPIRIT/1.4", "", getResourceFile(Schema, "ipxact-1.4/index.xsd")) 

158_IPXACT_15 = IpxactSchema("1.5", "spirit", "http://www.spiritconsortium.org/XMLSchema/SPIRIT/1.5", "", getResourceFile(Schema, "ipxact-1.5/index.xsd")) 

159_IPXACT_2009 = IpxactSchema("2009", "spirit", "http://www.spiritconsortium.org/XMLSchema/SPIRIT/1685-2009", "", getResourceFile(Schema, "ieee-1685-2009/index.xsd")) 

160_IPXACT_2014 = IpxactSchema("2014", "ipxact", "http://www.accellera.org/XMLSchema/IPXACT/1685-2014", "http://www.accellera.org/XMLSchema/IPXACT/1685-2014/index.xsd", getResourceFile(Schema, "ieee-1685-2014/index.xsd")) 

161_IPXACT_2022 = IpxactSchema("2022", "ipxact", "http://www.accellera.org/XMLSchema/IPXACT/1685-2022", "http://www.accellera.org/XMLSchema/IPXACT/1685-2022/index.xsd", getResourceFile(Schema, "ieee-1685-2022/index.xsd")) 

162 

163__VERSION_TABLE__: Dict[str, IpxactSchema] = { 

164 '1.0': _IPXACT_10, 

165 '1.1': _IPXACT_11, 

166 '1.4': _IPXACT_14, 

167 '1.5': _IPXACT_15, 

168 '2009': _IPXACT_2009, 

169 '2014': _IPXACT_2014, 

170 '2022': _IPXACT_2022 

171} #: Dictionary of all IP-XACT versions mapping to :class:`IpxactSchema` instances. 

172 

173__URI_MAP__: Dict[str, IpxactSchema] = {value.SchemaUri: value for key, value in __VERSION_TABLE__.items()} #: Mapping from schema URIs to :class:`IpxactSchema` instances. 

174 

175__DEFAULT_VERSION__ = "2022" #: IP-XACT default version 

176__DEFAULT_SCHEMA__ = __VERSION_TABLE__[__DEFAULT_VERSION__] #: IP-XACT default Schema 

177 

178 

179@export 

180class Vlnv: 

181 """VLNV data structure (Vendor, Library, Name, Version) as a unique identifier in IP-XACT.""" 

182 

183 _vendor: str #: Vendor name in a VLNV unique identifier 

184 _library: str #: Library name in a VLNV unique identifier 

185 _name: str #: Component name in a VLNV unique identifier 

186 _version: SemanticVersion #: Version in a VLNV unique identifier 

187 

188 def __init__(self, vendor: str, library: str, name: str, version: Union[str, SemanticVersion]) -> None: 

189 """ 

190 Initializes the VLNV data structure. 

191 

192 :param vendor: Vendor name in a VLNV unique identifier 

193 :param library: Library name in a VLNV unique identifier 

194 :param name: Component name in a VLNV unique identifier 

195 :param version: Version in a VLNV unique identifier 

196 """ 

197 

198 if vendor is None: 198 ↛ 199line 198 didn't jump to line 199 because the condition on line 198 was never true

199 raise ValueError(f"Parameter 'vendor' is None.") 

200 elif not isinstance(vendor, str): 200 ↛ 201line 200 didn't jump to line 201 because the condition on line 200 was never true

201 ex = TypeError(f"Parameter 'vendor' is not a string.") 

202 if version_info >= (3, 11): # pragma: no cover 

203 ex.add_note(f"Got type '{getFullyQualifiedName(vendor)}'.") 

204 raise ex 

205 

206 if library is None: 206 ↛ 207line 206 didn't jump to line 207 because the condition on line 206 was never true

207 raise ValueError(f"Parameter 'library' is None.") 

208 elif not isinstance(library, str): 208 ↛ 209line 208 didn't jump to line 209 because the condition on line 208 was never true

209 ex = TypeError(f"Parameter 'library' is not a string.") 

210 if version_info >= (3, 11): # pragma: no cover 

211 ex.add_note(f"Got type '{getFullyQualifiedName(library)}'.") 

212 raise ex 

213 

214 if name is None: 214 ↛ 215line 214 didn't jump to line 215 because the condition on line 214 was never true

215 raise ValueError(f"Parameter 'name' is None.") 

216 elif not isinstance(name, str): 216 ↛ 217line 216 didn't jump to line 217 because the condition on line 216 was never true

217 ex = TypeError(f"Parameter 'name' is not a string.") 

218 if version_info >= (3, 11): # pragma: no cover 

219 ex.add_note(f"Got type '{getFullyQualifiedName(name)}'.") 

220 raise ex 

221 

222 if version is None: 222 ↛ 223line 222 didn't jump to line 223 because the condition on line 222 was never true

223 raise ValueError(f"Parameter 'version' is None.") 

224 elif isinstance(version, str): 

225 self._version = SemanticVersion.Parse(version) 

226 elif isinstance(version, SemanticVersion): 226 ↛ 229line 226 didn't jump to line 229 because the condition on line 226 was always true

227 self._version = version 

228 else: 

229 ex = TypeError(f"Parameter 'version' is neither a 'SemanticVersion' nor a string.") 

230 if version_info >= (3, 11): # pragma: no cover 

231 ex.add_note(f"Got type '{getFullyQualifiedName(version)}'.") 

232 raise ex 

233 

234 self._vendor = vendor 

235 self._library = library 

236 self._name = name 

237 

238 @readonly 

239 def Vendor(self) -> str: 

240 return self._vendor 

241 

242 @readonly 

243 def Library(self) -> str: 

244 return self._library 

245 

246 @readonly 

247 def Name(self) -> str: 

248 return self._name 

249 

250 @readonly 

251 def Version(self) -> SemanticVersion: 

252 return self._version 

253 

254 def ToXml(self, indent=1, isVersionedIdentifier=False): 

255 """Converts the object's data into XML format.""" 

256 

257 if isVersionedIdentifier: 

258 buffer = dedent("""\ 

259 {indent}<{xmlns}:vendor>{vendor}</{xmlns}:vendor> 

260 {indent}<{xmlns}:library>{library}</{xmlns}:library> 

261 {indent}<{xmlns}:name>{name}</{xmlns}:name> 

262 {indent}<{xmlns}:version>{version}</{xmlns}:version>\ 

263 """) 

264 else: 

265 buffer = """{indent}<{xmlns}:vlnv vendor="{vendor}" library="{library}" name="{name}" version="{version}"/>""" 

266 

267 return buffer.format(indent= "\t" *indent, xmlns=__DEFAULT_SCHEMA__.NamespacePrefix, vendor=self._vendor, library=self._library, name=self._name, version=self._version) 

268 

269 

270@export 

271class RootElement: 

272 """Base-class for all IP-XACT data classes.""" 

273 

274 _vlnv: Vlnv #: VLNV unique identifier. 

275 

276 def __init__(self, vlnv: Vlnv) -> None: 

277 """ 

278 Initializes the RootElement with an VLNV field for all derives classes. 

279 

280 :param vlnv: VLNV unique identifier. 

281 """ 

282 self._vlnv = vlnv 

283 

284 @classmethod 

285 def FromFile(cls, file): 

286 pass 

287 

288 

289@export 

290class PyIpxactException(Exception): 

291 """Base-exception for all exceptions in this package."""