BaseTool: Error handling for PCD datumtype.
[mirror_edk2.git] / BaseTools / Source / Python / Workspace / DecBuildData.py
CommitLineData
ae7b6df8
LG
1## @file\r
2# This file is used to create a database used by build tool\r
3#\r
e0db09cd 4# Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>\r
ae7b6df8
LG
5# (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>\r
6# This program and the accompanying materials\r
7# are licensed and made available under the terms and conditions of the BSD License\r
8# which accompanies this distribution. The full text of the license may be found at\r
9# http://opensource.org/licenses/bsd-license.php\r
10#\r
11# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13#\r
14from Common.String import *\r
15from Common.DataType import *\r
16from Common.Misc import *\r
17from types import *\r
79820e32 18from collections import OrderedDict\r
ae7b6df8
LG
19\r
20from Workspace.BuildClassObject import PackageBuildClassObject, StructurePcd, PcdClassObject\r
21\r
22## Platform build information from DEC file\r
23#\r
24# This class is used to retrieve information stored in database and convert them\r
25# into PackageBuildClassObject form for easier use for AutoGen.\r
26#\r
27class DecBuildData(PackageBuildClassObject):\r
28 # dict used to convert PCD type in database to string used by build tool\r
29 _PCD_TYPE_STRING_ = {\r
30 MODEL_PCD_FIXED_AT_BUILD : "FixedAtBuild",\r
31 MODEL_PCD_PATCHABLE_IN_MODULE : "PatchableInModule",\r
32 MODEL_PCD_FEATURE_FLAG : "FeatureFlag",\r
33 MODEL_PCD_DYNAMIC : "Dynamic",\r
34 MODEL_PCD_DYNAMIC_DEFAULT : "Dynamic",\r
35 MODEL_PCD_DYNAMIC_HII : "DynamicHii",\r
36 MODEL_PCD_DYNAMIC_VPD : "DynamicVpd",\r
37 MODEL_PCD_DYNAMIC_EX : "DynamicEx",\r
38 MODEL_PCD_DYNAMIC_EX_DEFAULT : "DynamicEx",\r
39 MODEL_PCD_DYNAMIC_EX_HII : "DynamicExHii",\r
40 MODEL_PCD_DYNAMIC_EX_VPD : "DynamicExVpd",\r
41 }\r
42\r
43 # dict used to convert part of [Defines] to members of DecBuildData directly\r
44 _PROPERTY_ = {\r
45 #\r
46 # Required Fields\r
47 #\r
48 TAB_DEC_DEFINES_PACKAGE_NAME : "_PackageName",\r
49 TAB_DEC_DEFINES_PACKAGE_GUID : "_Guid",\r
50 TAB_DEC_DEFINES_PACKAGE_VERSION : "_Version",\r
51 TAB_DEC_DEFINES_PKG_UNI_FILE : "_PkgUniFile",\r
52 }\r
53\r
54\r
55 ## Constructor of DecBuildData\r
56 #\r
57 # Initialize object of DecBuildData\r
58 #\r
59 # @param FilePath The path of package description file\r
60 # @param RawData The raw data of DEC file\r
61 # @param BuildDataBase Database used to retrieve module information\r
62 # @param Arch The target architecture\r
63 # @param Platform (not used for DecBuildData)\r
64 # @param Macros Macros used for replacement in DSC file\r
65 #\r
66 def __init__(self, File, RawData, BuildDataBase, Arch='COMMON', Target=None, Toolchain=None):\r
67 self.MetaFile = File\r
68 self._PackageDir = File.Dir\r
69 self._RawData = RawData\r
70 self._Bdb = BuildDataBase\r
71 self._Arch = Arch\r
72 self._Target = Target\r
73 self._Toolchain = Toolchain\r
74 self._Clear()\r
75\r
76 ## XXX[key] = value\r
77 def __setitem__(self, key, value):\r
78 self.__dict__[self._PROPERTY_[key]] = value\r
79\r
80 ## value = XXX[key]\r
81 def __getitem__(self, key):\r
82 return self.__dict__[self._PROPERTY_[key]]\r
83\r
84 ## "in" test support\r
85 def __contains__(self, key):\r
86 return key in self._PROPERTY_\r
87\r
88 ## Set all internal used members of DecBuildData to None\r
89 def _Clear(self):\r
90 self._Header = None\r
91 self._PackageName = None\r
92 self._Guid = None\r
93 self._Version = None\r
94 self._PkgUniFile = None\r
95 self._Protocols = None\r
96 self._Ppis = None\r
97 self._Guids = None\r
98 self._Includes = None\r
0a57a978 99 self._CommonIncludes = None\r
ae7b6df8
LG
100 self._LibraryClasses = None\r
101 self._Pcds = None\r
102 self.__Macros = None\r
103 self._PrivateProtocols = None\r
104 self._PrivatePpis = None\r
105 self._PrivateGuids = None\r
106 self._PrivateIncludes = None\r
107\r
108 ## Get current effective macros\r
109 def _GetMacros(self):\r
110 if self.__Macros == None:\r
111 self.__Macros = {}\r
112 self.__Macros.update(GlobalData.gGlobalDefines)\r
113 return self.__Macros\r
114\r
115 ## Get architecture\r
116 def _GetArch(self):\r
117 return self._Arch\r
118\r
119 ## Set architecture\r
120 #\r
121 # Changing the default ARCH to another may affect all other information\r
122 # because all information in a platform may be ARCH-related. That's\r
123 # why we need to clear all internal used members, in order to cause all\r
124 # information to be re-retrieved.\r
125 #\r
126 # @param Value The value of ARCH\r
127 #\r
128 def _SetArch(self, Value):\r
129 if self._Arch == Value:\r
130 return\r
131 self._Arch = Value\r
132 self._Clear()\r
133\r
134 ## Retrieve all information in [Defines] section\r
135 #\r
136 # (Retriving all [Defines] information in one-shot is just to save time.)\r
137 #\r
138 def _GetHeaderInfo(self):\r
139 RecordList = self._RawData[MODEL_META_DATA_HEADER, self._Arch]\r
140 for Record in RecordList:\r
141 Name = Record[1]\r
142 if Name in self:\r
143 self[Name] = Record[2]\r
144 self._Header = 'DUMMY'\r
145\r
146 ## Retrieve package name\r
147 def _GetPackageName(self):\r
148 if self._PackageName == None:\r
149 if self._Header == None:\r
150 self._GetHeaderInfo()\r
151 if self._PackageName == None:\r
152 EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE, "No PACKAGE_NAME", File=self.MetaFile)\r
153 return self._PackageName\r
154\r
155 ## Retrieve file guid\r
156 def _GetFileGuid(self):\r
157 if self._Guid == None:\r
158 if self._Header == None:\r
159 self._GetHeaderInfo()\r
160 if self._Guid == None:\r
161 EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE, "No PACKAGE_GUID", File=self.MetaFile)\r
162 return self._Guid\r
163\r
164 ## Retrieve package version\r
165 def _GetVersion(self):\r
166 if self._Version == None:\r
167 if self._Header == None:\r
168 self._GetHeaderInfo()\r
169 if self._Version == None:\r
170 self._Version = ''\r
171 return self._Version\r
172\r
173 ## Retrieve protocol definitions (name/value pairs)\r
174 def _GetProtocol(self):\r
175 if self._Protocols == None:\r
176 #\r
177 # tdict is a special kind of dict, used for selecting correct\r
178 # protocol defition for given ARCH\r
179 #\r
180 ProtocolDict = tdict(True)\r
181 PrivateProtocolDict = tdict(True)\r
182 NameList = []\r
183 PrivateNameList = []\r
184 PublicNameList = []\r
185 # find out all protocol definitions for specific and 'common' arch\r
186 RecordList = self._RawData[MODEL_EFI_PROTOCOL, self._Arch]\r
187 for Name, Guid, Dummy, Arch, PrivateFlag, ID, LineNo in RecordList:\r
188 if PrivateFlag == 'PRIVATE':\r
189 if Name not in PrivateNameList:\r
190 PrivateNameList.append(Name)\r
191 PrivateProtocolDict[Arch, Name] = Guid\r
192 if Name in PublicNameList:\r
193 EdkLogger.error('build', OPTION_CONFLICT, "Can't determine %s's attribute, it is both defined as Private and non-Private attribute in DEC file." % Name, File=self.MetaFile, Line=LineNo)\r
194 else:\r
195 if Name not in PublicNameList:\r
196 PublicNameList.append(Name)\r
197 if Name in PrivateNameList:\r
198 EdkLogger.error('build', OPTION_CONFLICT, "Can't determine %s's attribute, it is both defined as Private and non-Private attribute in DEC file." % Name, File=self.MetaFile, Line=LineNo)\r
199 if Name not in NameList:\r
200 NameList.append(Name)\r
201 ProtocolDict[Arch, Name] = Guid\r
202 # use sdict to keep the order\r
203 self._Protocols = sdict()\r
204 self._PrivateProtocols = sdict()\r
205 for Name in NameList:\r
206 #\r
207 # limit the ARCH to self._Arch, if no self._Arch found, tdict\r
208 # will automatically turn to 'common' ARCH for trying\r
209 #\r
210 self._Protocols[Name] = ProtocolDict[self._Arch, Name]\r
211 for Name in PrivateNameList:\r
212 self._PrivateProtocols[Name] = PrivateProtocolDict[self._Arch, Name]\r
213 return self._Protocols\r
214\r
215 ## Retrieve PPI definitions (name/value pairs)\r
216 def _GetPpi(self):\r
217 if self._Ppis == None:\r
218 #\r
219 # tdict is a special kind of dict, used for selecting correct\r
220 # PPI defition for given ARCH\r
221 #\r
222 PpiDict = tdict(True)\r
223 PrivatePpiDict = tdict(True)\r
224 NameList = []\r
225 PrivateNameList = []\r
226 PublicNameList = []\r
227 # find out all PPI definitions for specific arch and 'common' arch\r
228 RecordList = self._RawData[MODEL_EFI_PPI, self._Arch]\r
229 for Name, Guid, Dummy, Arch, PrivateFlag, ID, LineNo in RecordList:\r
230 if PrivateFlag == 'PRIVATE':\r
231 if Name not in PrivateNameList:\r
232 PrivateNameList.append(Name)\r
233 PrivatePpiDict[Arch, Name] = Guid\r
234 if Name in PublicNameList:\r
235 EdkLogger.error('build', OPTION_CONFLICT, "Can't determine %s's attribute, it is both defined as Private and non-Private attribute in DEC file." % Name, File=self.MetaFile, Line=LineNo)\r
236 else:\r
237 if Name not in PublicNameList:\r
238 PublicNameList.append(Name)\r
239 if Name in PrivateNameList:\r
240 EdkLogger.error('build', OPTION_CONFLICT, "Can't determine %s's attribute, it is both defined as Private and non-Private attribute in DEC file." % Name, File=self.MetaFile, Line=LineNo)\r
241 if Name not in NameList:\r
242 NameList.append(Name)\r
243 PpiDict[Arch, Name] = Guid\r
244 # use sdict to keep the order\r
245 self._Ppis = sdict()\r
246 self._PrivatePpis = sdict()\r
247 for Name in NameList:\r
248 #\r
249 # limit the ARCH to self._Arch, if no self._Arch found, tdict\r
250 # will automatically turn to 'common' ARCH for trying\r
251 #\r
252 self._Ppis[Name] = PpiDict[self._Arch, Name]\r
253 for Name in PrivateNameList:\r
254 self._PrivatePpis[Name] = PrivatePpiDict[self._Arch, Name]\r
255 return self._Ppis\r
256\r
257 ## Retrieve GUID definitions (name/value pairs)\r
258 def _GetGuid(self):\r
259 if self._Guids == None:\r
260 #\r
261 # tdict is a special kind of dict, used for selecting correct\r
262 # GUID defition for given ARCH\r
263 #\r
264 GuidDict = tdict(True)\r
265 PrivateGuidDict = tdict(True)\r
266 NameList = []\r
267 PrivateNameList = []\r
268 PublicNameList = []\r
269 # find out all protocol definitions for specific and 'common' arch\r
270 RecordList = self._RawData[MODEL_EFI_GUID, self._Arch]\r
271 for Name, Guid, Dummy, Arch, PrivateFlag, ID, LineNo in RecordList:\r
272 if PrivateFlag == 'PRIVATE':\r
273 if Name not in PrivateNameList:\r
274 PrivateNameList.append(Name)\r
275 PrivateGuidDict[Arch, Name] = Guid\r
276 if Name in PublicNameList:\r
277 EdkLogger.error('build', OPTION_CONFLICT, "Can't determine %s's attribute, it is both defined as Private and non-Private attribute in DEC file." % Name, File=self.MetaFile, Line=LineNo)\r
278 else:\r
279 if Name not in PublicNameList:\r
280 PublicNameList.append(Name)\r
281 if Name in PrivateNameList:\r
282 EdkLogger.error('build', OPTION_CONFLICT, "Can't determine %s's attribute, it is both defined as Private and non-Private attribute in DEC file." % Name, File=self.MetaFile, Line=LineNo)\r
283 if Name not in NameList:\r
284 NameList.append(Name)\r
285 GuidDict[Arch, Name] = Guid\r
286 # use sdict to keep the order\r
287 self._Guids = sdict()\r
288 self._PrivateGuids = sdict()\r
289 for Name in NameList:\r
290 #\r
291 # limit the ARCH to self._Arch, if no self._Arch found, tdict\r
292 # will automatically turn to 'common' ARCH for trying\r
293 #\r
294 self._Guids[Name] = GuidDict[self._Arch, Name]\r
295 for Name in PrivateNameList:\r
296 self._PrivateGuids[Name] = PrivateGuidDict[self._Arch, Name]\r
297 return self._Guids\r
298\r
299 ## Retrieve public include paths declared in this package\r
300 def _GetInclude(self):\r
0a57a978
FB
301 if self._Includes == None or self._CommonIncludes is None:\r
302 self._CommonIncludes = []\r
ae7b6df8
LG
303 self._Includes = []\r
304 self._PrivateIncludes = []\r
305 PublicInclues = []\r
306 RecordList = self._RawData[MODEL_EFI_INCLUDE, self._Arch]\r
307 Macros = self._Macros\r
308 Macros["EDK_SOURCE"] = GlobalData.gEcpSource\r
309 for Record in RecordList:\r
310 File = PathClass(NormPath(Record[0], Macros), self._PackageDir, Arch=self._Arch)\r
311 LineNo = Record[-1]\r
312 # validate the path\r
313 ErrorCode, ErrorInfo = File.Validate()\r
314 if ErrorCode != 0:\r
315 EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo, File=self.MetaFile, Line=LineNo)\r
316\r
317 # avoid duplicate include path\r
318 if File not in self._Includes:\r
319 self._Includes.append(File)\r
320 if Record[4] == 'PRIVATE':\r
321 if File not in self._PrivateIncludes:\r
322 self._PrivateIncludes.append(File)\r
323 if File in PublicInclues:\r
324 EdkLogger.error('build', OPTION_CONFLICT, "Can't determine %s's attribute, it is both defined as Private and non-Private attribute in DEC file." % File, File=self.MetaFile, Line=LineNo)\r
325 else:\r
326 if File not in PublicInclues:\r
327 PublicInclues.append(File)\r
328 if File in self._PrivateIncludes:\r
329 EdkLogger.error('build', OPTION_CONFLICT, "Can't determine %s's attribute, it is both defined as Private and non-Private attribute in DEC file." % File, File=self.MetaFile, Line=LineNo)\r
0a57a978
FB
330 if Record[3] == "COMMON":\r
331 self._CommonIncludes.append(File)\r
ae7b6df8
LG
332 return self._Includes\r
333\r
334 ## Retrieve library class declarations (not used in build at present)\r
335 def _GetLibraryClass(self):\r
336 if self._LibraryClasses == None:\r
337 #\r
338 # tdict is a special kind of dict, used for selecting correct\r
339 # library class declaration for given ARCH\r
340 #\r
341 LibraryClassDict = tdict(True)\r
342 LibraryClassSet = set()\r
343 RecordList = self._RawData[MODEL_EFI_LIBRARY_CLASS, self._Arch]\r
344 Macros = self._Macros\r
345 for LibraryClass, File, Dummy, Arch, PrivateFlag, ID, LineNo in RecordList:\r
346 File = PathClass(NormPath(File, Macros), self._PackageDir, Arch=self._Arch)\r
347 # check the file validation\r
348 ErrorCode, ErrorInfo = File.Validate()\r
349 if ErrorCode != 0:\r
350 EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo, File=self.MetaFile, Line=LineNo)\r
351 LibraryClassSet.add(LibraryClass)\r
352 LibraryClassDict[Arch, LibraryClass] = File\r
353 self._LibraryClasses = sdict()\r
354 for LibraryClass in LibraryClassSet:\r
355 self._LibraryClasses[LibraryClass] = LibraryClassDict[self._Arch, LibraryClass]\r
356 return self._LibraryClasses\r
357\r
358 ## Retrieve PCD declarations\r
359 def _GetPcds(self):\r
360 if self._Pcds == None:\r
361 self._Pcds = sdict()\r
362 self._Pcds.update(self._GetPcd(MODEL_PCD_FIXED_AT_BUILD))\r
363 self._Pcds.update(self._GetPcd(MODEL_PCD_PATCHABLE_IN_MODULE))\r
364 self._Pcds.update(self._GetPcd(MODEL_PCD_FEATURE_FLAG))\r
365 self._Pcds.update(self._GetPcd(MODEL_PCD_DYNAMIC))\r
366 self._Pcds.update(self._GetPcd(MODEL_PCD_DYNAMIC_EX))\r
367 return self._Pcds\r
368\r
369\r
370 def ProcessStructurePcd(self, StructurePcdRawDataSet):\r
79820e32 371 s_pcd_set = OrderedDict()\r
ae7b6df8
LG
372 for s_pcd,LineNo in StructurePcdRawDataSet:\r
373 if s_pcd.TokenSpaceGuidCName not in s_pcd_set:\r
374 s_pcd_set[s_pcd.TokenSpaceGuidCName] = []\r
375 s_pcd_set[s_pcd.TokenSpaceGuidCName].append((s_pcd,LineNo))\r
376\r
377 str_pcd_set = []\r
378 for pcdname in s_pcd_set:\r
379 dep_pkgs = []\r
380 struct_pcd = StructurePcd()\r
381 for item,LineNo in s_pcd_set[pcdname]:\r
382 if "<HeaderFiles>" in item.TokenCName:\r
81add864 383 struct_pcd.StructuredPcdIncludeFile.append(item.DefaultValue)\r
ae7b6df8
LG
384 elif "<Packages>" in item.TokenCName:\r
385 dep_pkgs.append(item.DefaultValue)\r
386 elif item.DatumType == item.TokenCName:\r
387 struct_pcd.copy(item)\r
388 struct_pcd.TokenValue = struct_pcd.TokenValue.strip("{").strip()\r
389 struct_pcd.TokenSpaceGuidCName, struct_pcd.TokenCName = pcdname.split(".")\r
6a103440
FB
390 struct_pcd.PcdDefineLineNo = LineNo\r
391 struct_pcd.PkgPath = self.MetaFile.File\r
06140766 392 struct_pcd.SetDecDefaultValue(item.DefaultValue)\r
ae7b6df8
LG
393 else:\r
394 struct_pcd.AddDefaultValue(item.TokenCName, item.DefaultValue,self.MetaFile.File,LineNo)\r
395\r
396 struct_pcd.PackageDecs = dep_pkgs\r
ae7b6df8 397 str_pcd_set.append(struct_pcd)\r
ae7b6df8
LG
398 return str_pcd_set\r
399\r
400 ## Retrieve PCD declarations for given type\r
401 def _GetPcd(self, Type):\r
402 Pcds = sdict()\r
403 #\r
404 # tdict is a special kind of dict, used for selecting correct\r
405 # PCD declaration for given ARCH\r
406 #\r
407 PcdDict = tdict(True, 3)\r
408 # for summarizing PCD\r
e651d06c 409 PcdSet = []\r
ae7b6df8
LG
410 # find out all PCDs of the 'type'\r
411\r
412 StrPcdSet = []\r
413 RecordList = self._RawData[Type, self._Arch]\r
414 for TokenSpaceGuid, PcdCName, Setting, Arch, PrivateFlag, Dummy1, Dummy2 in RecordList:\r
415 PcdDict[Arch, PcdCName, TokenSpaceGuid] = (Setting,Dummy2)\r
e651d06c
LG
416 if not (PcdCName, TokenSpaceGuid) in PcdSet:\r
417 PcdSet.append((PcdCName, TokenSpaceGuid))\r
ae7b6df8
LG
418\r
419 for PcdCName, TokenSpaceGuid in PcdSet:\r
420 #\r
421 # limit the ARCH to self._Arch, if no self._Arch found, tdict\r
422 # will automatically turn to 'common' ARCH and try again\r
423 #\r
424 Setting,LineNo = PcdDict[self._Arch, PcdCName, TokenSpaceGuid]\r
425 if Setting == None:\r
426 continue\r
427\r
428 DefaultValue, DatumType, TokenNumber = AnalyzePcdData(Setting)\r
429 validateranges, validlists, expressions = self._RawData.GetValidExpression(TokenSpaceGuid, PcdCName)\r
430 PcdObj = PcdClassObject(\r
431 PcdCName,\r
432 TokenSpaceGuid,\r
433 self._PCD_TYPE_STRING_[Type],\r
434 DatumType,\r
435 DefaultValue,\r
436 TokenNumber,\r
437 '',\r
438 {},\r
439 False,\r
440 None,\r
441 list(validateranges),\r
442 list(validlists),\r
443 list(expressions)\r
444 )\r
065a7d40 445 PcdObj.DefinitionPosition = (self.MetaFile.File,LineNo)\r
ae7b6df8
LG
446 if "." in TokenSpaceGuid:\r
447 StrPcdSet.append((PcdObj,LineNo))\r
448 else:\r
449 Pcds[PcdCName, TokenSpaceGuid, self._PCD_TYPE_STRING_[Type]] = PcdObj\r
450\r
451 StructurePcds = self.ProcessStructurePcd(StrPcdSet)\r
452 for pcd in StructurePcds:\r
453 Pcds[pcd.TokenCName, pcd.TokenSpaceGuidCName, self._PCD_TYPE_STRING_[Type]] = pcd\r
065a7d40
FB
454 StructPattern = re.compile(r'[_a-zA-Z][0-9A-Za-z_]*$')\r
455 for pcd in Pcds.values():\r
456 if pcd.DatumType not in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64, TAB_VOID, "BOOLEAN"]:\r
457 if StructPattern.match(pcd.DatumType) == None:\r
458 EdkLogger.error('build', FORMAT_INVALID, "DatumType only support BOOLEAN, UINT8, UINT16, UINT32, UINT64, VOID* or a valid struct name.", pcd.DefinitionPosition[0],pcd.DefinitionPosition[1])\r
459 for struct_pcd in Pcds.values():\r
460 if isinstance(struct_pcd,StructurePcd) and not struct_pcd.StructuredPcdIncludeFile:\r
461 EdkLogger.error("build", PCD_STRUCTURE_PCD_ERROR, "The structure Pcd %s.%s header file is not found in %s line %s \n" % (struct_pcd.TokenSpaceGuidCName, struct_pcd.TokenCName,struct_pcd.DefinitionPosition[0],struct_pcd.DefinitionPosition[1] ))\r
ae7b6df8
LG
462\r
463 return Pcds\r
0a57a978
FB
464 @property\r
465 def CommonIncludes(self):\r
466 if self._CommonIncludes is None:\r
467 self.Includes\r
468 return self._CommonIncludes\r
ae7b6df8
LG
469\r
470\r
471 _Macros = property(_GetMacros)\r
472 Arch = property(_GetArch, _SetArch)\r
473 PackageName = property(_GetPackageName)\r
474 Guid = property(_GetFileGuid)\r
475 Version = property(_GetVersion)\r
476\r
477 Protocols = property(_GetProtocol)\r
478 Ppis = property(_GetPpi)\r
479 Guids = property(_GetGuid)\r
480 Includes = property(_GetInclude)\r
481 LibraryClasses = property(_GetLibraryClass)\r
482 Pcds = property(_GetPcds)\r