etherlab/etherlab.py
changeset 2355 fec77f2b9e07
parent 2165 02a2b5dee5e3
child 2356 c26e0c66d8d5
equal deleted inserted replaced
2354:9460872f1440 2355:fec77f2b9e07
    28 
    28 
    29 #--------------------------------------------------
    29 #--------------------------------------------------
    30 #                 Ethercat ConfNode
    30 #                 Ethercat ConfNode
    31 #--------------------------------------------------
    31 #--------------------------------------------------
    32 
    32 
    33 EtherCATInfoParser = GenerateParserFromXSD(os.path.join(os.path.dirname(__file__), "EtherCATInfo.xsd")) 
    33 EtherCATInfoParser = GenerateParserFromXSD(os.path.join(os.path.dirname(__file__), "EtherCATInfo.xsd"))
    34 EtherCATInfo_XPath = lambda xpath: etree.XPath(xpath)
    34 EtherCATInfo_XPath = lambda xpath: etree.XPath(xpath)
    35 
    35 
    36 def HexDecValue(context, *args):
    36 def HexDecValue(context, *args):
    37     return str(ExtractHexDecValue(args[0][0]))
    37     return str(ExtractHexDecValue(args[0][0]))
    38 
    38 
    39 def EntryName(context, *args):
    39 def EntryName(context, *args):
    40     return ExtractName(args[0], 
    40     return ExtractName(args[0],
    41         args[1][0] if len(args) > 1 else None)
    41         args[1][0] if len(args) > 1 else None)
    42 
    42 
    43 ENTRY_INFOS_KEYS = [
    43 ENTRY_INFOS_KEYS = [
    44     ("Index", lambda x: "#x%4.4X" % int(x), "#x0000"),
    44     ("Index", lambda x: "#x%4.4X" % int(x), "#x0000"),
    45     ("SubIndex", str, "0"),
    45     ("SubIndex", str, "0"),
    54 
    54 
    55 class EntryListFactory:
    55 class EntryListFactory:
    56 
    56 
    57     def __init__(self, entries):
    57     def __init__(self, entries):
    58         self.Entries = entries
    58         self.Entries = entries
    59     
    59 
    60     def AddEntry(self, context, *args):
    60     def AddEntry(self, context, *args):
    61         index, subindex = map(lambda x: int(x[0]), args[:2])
    61         index, subindex = map(lambda x: int(x[0]), args[:2])
    62         new_entry_infos = {
    62         new_entry_infos = {
    63             key: translate(arg[0]) if len(arg) > 0 else default
    63             key: translate(arg[0]) if len(arg) > 0 else default
    64             for (key, translate, default), arg
    64             for (key, translate, default), arg
    65             in zip(ENTRY_INFOS_KEYS, args)}
    65             in zip(ENTRY_INFOS_KEYS, args)}
    66         
    66 
    67         if (index, subindex) != (0, 0):
    67         if (index, subindex) != (0, 0):
    68             entry_infos = self.Entries.get((index, subindex))
    68             entry_infos = self.Entries.get((index, subindex))
    69             if entry_infos is not None:
    69             if entry_infos is not None:
    70                 for param in ["PDO index", "PDO name", "PDO type"]:
    70                 for param in ["PDO index", "PDO name", "PDO type"]:
    71                     value = new_entry_infos.get(param)
    71                     value = new_entry_infos.get(param)
    77 entries_list_xslt = etree.parse(
    77 entries_list_xslt = etree.parse(
    78     os.path.join(ScriptDirectory, "entries_list.xslt"))
    78     os.path.join(ScriptDirectory, "entries_list.xslt"))
    79 
    79 
    80 cls = EtherCATInfoParser.GetElementClass("DeviceType")
    80 cls = EtherCATInfoParser.GetElementClass("DeviceType")
    81 if cls:
    81 if cls:
    82     
    82 
    83     profile_numbers_xpath = EtherCATInfo_XPath("Profile/ProfileNo")
    83     profile_numbers_xpath = EtherCATInfo_XPath("Profile/ProfileNo")
    84     def GetProfileNumbers(self):
    84     def GetProfileNumbers(self):
    85         return [number.text for number in profile_numbers_xpath(self)]
    85         return [number.text for number in profile_numbers_xpath(self)]
    86     setattr(cls, "GetProfileNumbers", GetProfileNumbers)
    86     setattr(cls, "GetProfileNumbers", GetProfileNumbers)
    87     
    87 
    88     def getCoE(self):
    88     def getCoE(self):
    89         mailbox = self.getMailbox()
    89         mailbox = self.getMailbox()
    90         if mailbox is not None:
    90         if mailbox is not None:
    91             return mailbox.getCoE()
    91             return mailbox.getCoE()
    92         return None
    92         return None
    93     setattr(cls, "getCoE", getCoE)
    93     setattr(cls, "getCoE", getCoE)
    94 
    94 
    95     def GetEntriesList(self, limits=None):
    95     def GetEntriesList(self, limits=None):
    96         entries = {}
    96         entries = {}
    97         
    97 
    98         factory = EntryListFactory(entries)
    98         factory = EntryListFactory(entries)
    99         
    99 
   100         entries_list_xslt_tree = etree.XSLT(
   100         entries_list_xslt_tree = etree.XSLT(
   101             entries_list_xslt, extensions = {
   101             entries_list_xslt, extensions = {
   102                 ("entries_list_ns", "AddEntry"): factory.AddEntry,
   102                 ("entries_list_ns", "AddEntry"): factory.AddEntry,
   103                 ("entries_list_ns", "HexDecValue"): HexDecValue,
   103                 ("entries_list_ns", "HexDecValue"): HexDecValue,
   104                 ("entries_list_ns", "EntryName"): EntryName})
   104                 ("entries_list_ns", "EntryName"): EntryName})
   105         entries_list_xslt_tree(self, **dict(zip(
   105         entries_list_xslt_tree(self, **dict(zip(
   106             ["min_index", "max_index"], 
   106             ["min_index", "max_index"],
   107             map(lambda x: etree.XSLT.strparam(str(x)),
   107             map(lambda x: etree.XSLT.strparam(str(x)),
   108                 limits if limits is not None else [0x0000, 0xFFFF])
   108                 limits if limits is not None else [0x0000, 0xFFFF])
   109             )))
   109             )))
   110         
   110 
   111         return entries
   111         return entries
   112     setattr(cls, "GetEntriesList", GetEntriesList)
   112     setattr(cls, "GetEntriesList", GetEntriesList)
   113 
   113 
   114     def GetSyncManagers(self):
   114     def GetSyncManagers(self):
   115         sync_managers = []
   115         sync_managers = []
   145 
   145 
   146 class ModulesLibrary:
   146 class ModulesLibrary:
   147 
   147 
   148     MODULES_EXTRA_PARAMS = [
   148     MODULES_EXTRA_PARAMS = [
   149         ("pdo_alignment", {
   149         ("pdo_alignment", {
   150             "column_label": _("PDO alignment"), 
   150             "column_label": _("PDO alignment"),
   151             "column_size": 150,
   151             "column_size": 150,
   152             "default": 8,
   152             "default": 8,
   153             "description": _(
   153             "description": _(
   154 "Minimal size in bits between 2 pdo entries")}),
   154 "Minimal size in bits between 2 pdo entries")}),
   155         ("max_pdo_size", {
   155         ("max_pdo_size", {
   158             "default": 255,
   158             "default": 255,
   159             "description": _(
   159             "description": _(
   160 """Maximal number of entries mapped in a PDO
   160 """Maximal number of entries mapped in a PDO
   161 including empty entries used for PDO alignment""")}),
   161 including empty entries used for PDO alignment""")}),
   162         ("add_pdo", {
   162         ("add_pdo", {
   163             "column_label": _("Creating new PDO"), 
   163             "column_label": _("Creating new PDO"),
   164             "column_size": 150,
   164             "column_size": 150,
   165             "default": 0,
   165             "default": 0,
   166             "description": _(
   166             "description": _(
   167 """Adding a PDO not defined in default configuration
   167 """Adding a PDO not defined in default configuration
   168 for mapping needed location variables
   168 for mapping needed location variables
   169 (1 if possible)""")})
   169 (1 if possible)""")})
   170     ]
   170     ]
   171     
   171 
   172     def __init__(self, path, parent_library=None):
   172     def __init__(self, path, parent_library=None):
   173         self.Path = path
   173         self.Path = path
   174         if not os.path.exists(self.Path):
   174         if not os.path.exists(self.Path):
   175             os.makedirs(self.Path)
   175             os.makedirs(self.Path)
   176         self.ParentLibrary = parent_library
   176         self.ParentLibrary = parent_library
   177         
   177 
   178         if parent_library is not None:
   178         if parent_library is not None:
   179             self.LoadModules()
   179             self.LoadModules()
   180         else:
   180         else:
   181             self.Library = None
   181             self.Library = None
   182         self.LoadModulesExtraParams()
   182         self.LoadModulesExtraParams()
   183     
   183 
   184     def GetPath(self):
   184     def GetPath(self):
   185         return self.Path
   185         return self.Path
   186     
   186 
   187     def GetModulesExtraParamsFilePath(self):
   187     def GetModulesExtraParamsFilePath(self):
   188         return os.path.join(self.Path, "modules_extra_params.cfg")
   188         return os.path.join(self.Path, "modules_extra_params.cfg")
   189     
   189 
   190     groups_xpath = EtherCATInfo_XPath("Descriptions/Groups/Group")
   190     groups_xpath = EtherCATInfo_XPath("Descriptions/Groups/Group")
   191     devices_xpath = EtherCATInfo_XPath("Descriptions/Devices/Device")
   191     devices_xpath = EtherCATInfo_XPath("Descriptions/Devices/Device")
   192     def LoadModules(self):
   192     def LoadModules(self):
   193         self.Library = {}
   193         self.Library = {}
   194         
   194 
   195         files = os.listdir(self.Path)
   195         files = os.listdir(self.Path)
   196         for file in files:
   196         for file in files:
   197             filepath = os.path.join(self.Path, file)
   197             filepath = os.path.join(self.Path, file)
   198             if os.path.isfile(filepath) and os.path.splitext(filepath)[-1] == ".xml":
   198             if os.path.isfile(filepath) and os.path.splitext(filepath)[-1] == ".xml":
   199                 self.modules_infos = None
   199                 self.modules_infos = None
   200                 
   200 
   201                 xmlfile = open(filepath, 'r')
   201                 xmlfile = open(filepath, 'r')
   202                 try:
   202                 try:
   203                     self.modules_infos, error = EtherCATInfoParser.LoadXMLString(xmlfile.read())
   203                     self.modules_infos, error = EtherCATInfoParser.LoadXMLString(xmlfile.read())
   204                     if error is not None:
   204                     if error is not None:
   205                         self.GetCTRoot().logger.write_warning(
   205                         self.GetCTRoot().logger.write_warning(
   206                             XSDSchemaErrorMessage % (filepath + error))
   206                             XSDSchemaErrorMessage % (filepath + error))
   207                 except Exception, exc:
   207                 except Exception, exc:
   208                     self.modules_infos, error = None, unicode(exc)
   208                     self.modules_infos, error = None, unicode(exc)
   209                 xmlfile.close()
   209                 xmlfile.close()
   210                 
   210 
   211                 if self.modules_infos is not None:
   211                 if self.modules_infos is not None:
   212                     vendor = self.modules_infos.getVendor()
   212                     vendor = self.modules_infos.getVendor()
   213                     
   213 
   214                     vendor_category = self.Library.setdefault(
   214                     vendor_category = self.Library.setdefault(
   215                         ExtractHexDecValue(vendor.getId()), 
   215                         ExtractHexDecValue(vendor.getId()),
   216                         {"name": ExtractName(vendor.getName(), _("Miscellaneous")), 
   216                         {"name": ExtractName(vendor.getName(), _("Miscellaneous")),
   217                          "groups": {}})
   217                          "groups": {}})
   218                     
   218 
   219                     for group in self.groups_xpath(self.modules_infos):
   219                     for group in self.groups_xpath(self.modules_infos):
   220                         group_type = group.getType()
   220                         group_type = group.getType()
   221                         
   221 
   222                         vendor_category["groups"].setdefault(group_type, 
   222                         vendor_category["groups"].setdefault(group_type,
   223                             {"name": ExtractName(group.getName(), group_type), 
   223                             {"name": ExtractName(group.getName(), group_type),
   224                              "parent": group.getParentGroup(),
   224                              "parent": group.getParentGroup(),
   225                              "order": group.getSortOrder(), 
   225                              "order": group.getSortOrder(),
   226                              #"value": group.getcontent()["value"],
   226                              #"value": group.getcontent()["value"],
   227                              "devices": []})
   227                              "devices": []})
   228                     
   228 
   229                     for device in self.devices_xpath(self.modules_infos):
   229                     for device in self.devices_xpath(self.modules_infos):
   230                         device_group = device.getGroupType()
   230                         device_group = device.getGroupType()
   231                         if not vendor_category["groups"].has_key(device_group):
   231                         if not vendor_category["groups"].has_key(device_group):
   232                             raise ValueError, "Not such group \"%\"" % device_group
   232                             raise ValueError, "Not such group \"%\"" % device_group
   233                         vendor_category["groups"][device_group]["devices"].append(
   233                         vendor_category["groups"][device_group]["devices"].append(
   234                             (device.getType().getcontent(), device))
   234                             (device.getType().getcontent(), device))
   235                 
   235 
   236                 else:
   236                 else:
   237                         
   237 
   238                     self.GetCTRoot().logger.write_error(
   238                     self.GetCTRoot().logger.write_error(
   239                         _("Couldn't load %s XML file:\n%s") % (filepath, error))
   239                         _("Couldn't load %s XML file:\n%s") % (filepath, error))
   240                 
   240 
   241         return self.Library
   241         return self.Library
   242 
   242 
   243     def GetModulesLibrary(self, profile_filter=None):
   243     def GetModulesLibrary(self, profile_filter=None):
   244         if self.Library is None:
   244         if self.Library is None:
   245             self.LoadModules()
   245             self.LoadModules()
   288         library.sort(lambda x, y: cmp(x["name"], y["name"]))
   288         library.sort(lambda x, y: cmp(x["name"], y["name"]))
   289         return library
   289         return library
   290 
   290 
   291     def GetVendors(self):
   291     def GetVendors(self):
   292         return [(vendor_id, vendor["name"]) for vendor_id, vendor in self.Library.items()]
   292         return [(vendor_id, vendor["name"]) for vendor_id, vendor in self.Library.items()]
   293     
   293 
   294     def GetModuleInfos(self, module_infos):
   294     def GetModuleInfos(self, module_infos):
   295         vendor = ExtractHexDecValue(module_infos["vendor"])
   295         vendor = ExtractHexDecValue(module_infos["vendor"])
   296         vendor_infos = self.Library.get(vendor)
   296         vendor_infos = self.Library.get(vendor)
   297         if vendor_infos is not None:
   297         if vendor_infos is not None:
   298             for group_name, group_infos in vendor_infos["groups"].iteritems():
   298             for group_name, group_infos in vendor_infos["groups"].iteritems():
   299                 for device_type, device_infos in group_infos["devices"]:
   299                 for device_type, device_infos in group_infos["devices"]:
   300                     product_code = ExtractHexDecValue(device_infos.getType().getProductCode())
   300                     product_code = ExtractHexDecValue(device_infos.getType().getProductCode())
   301                     revision_number = ExtractHexDecValue(device_infos.getType().getRevisionNo())
   301                     revision_number = ExtractHexDecValue(device_infos.getType().getRevisionNo())
   302                     if (product_code == ExtractHexDecValue(module_infos["product_code"]) and
   302                     if (product_code == ExtractHexDecValue(module_infos["product_code"]) and
   303                         revision_number == ExtractHexDecValue(module_infos["revision_number"])):
   303                         revision_number == ExtractHexDecValue(module_infos["revision_number"])):
   304                         self.cntdevice = device_infos 
   304                         self.cntdevice = device_infos
   305                         self.cntdeviceType = device_type  
   305                         self.cntdeviceType = device_type
   306                         return device_infos, self.GetModuleExtraParams(vendor, product_code, revision_number)
   306                         return device_infos, self.GetModuleExtraParams(vendor, product_code, revision_number)
   307         return None, None
   307         return None, None
   308     
   308 
   309     def ImportModuleLibrary(self, filepath):
   309     def ImportModuleLibrary(self, filepath):
   310         if os.path.isfile(filepath):
   310         if os.path.isfile(filepath):
   311             shutil.copy(filepath, self.Path)
   311             shutil.copy(filepath, self.Path)
   312             self.LoadModules()
   312             self.LoadModules()
   313             return True
   313             return True
   314         return False
   314         return False
   315     
   315 
   316     def LoadModulesExtraParams(self):
   316     def LoadModulesExtraParams(self):
   317         self.ModulesExtraParams = {}
   317         self.ModulesExtraParams = {}
   318         
   318 
   319         csvfile_path = self.GetModulesExtraParamsFilePath()
   319         csvfile_path = self.GetModulesExtraParamsFilePath()
   320         if os.path.exists(csvfile_path):
   320         if os.path.exists(csvfile_path):
   321             csvfile = open(csvfile_path, "rb")
   321             csvfile = open(csvfile_path, "rb")
   322             sample = csvfile.read(1024)
   322             sample = csvfile.read(1024)
   323             csvfile.seek(0)
   323             csvfile.seek(0)
   334                         if value != "":
   334                         if value != "":
   335                             params_values[param] = int(value)
   335                             params_values[param] = int(value)
   336                     self.ModulesExtraParams[
   336                     self.ModulesExtraParams[
   337                         tuple(map(int, row[:3]))] = params_values
   337                         tuple(map(int, row[:3]))] = params_values
   338             csvfile.close()
   338             csvfile.close()
   339     
   339 
   340     def SaveModulesExtraParams(self):
   340     def SaveModulesExtraParams(self):
   341         csvfile = open(self.GetModulesExtraParamsFilePath(), "wb")
   341         csvfile = open(self.GetModulesExtraParamsFilePath(), "wb")
   342         extra_params = [param for param, params_infos in self.MODULES_EXTRA_PARAMS]
   342         extra_params = [param for param, params_infos in self.MODULES_EXTRA_PARAMS]
   343         writer = csv.writer(csvfile, delimiter=';')
   343         writer = csv.writer(csvfile, delimiter=';')
   344         writer.writerow(['Vendor', 'product_code', 'revision_number'] + extra_params)
   344         writer.writerow(['Vendor', 'product_code', 'revision_number'] + extra_params)
   345         for (vendor, product_code, revision_number), module_extra_params in self.ModulesExtraParams.iteritems():
   345         for (vendor, product_code, revision_number), module_extra_params in self.ModulesExtraParams.iteritems():
   346             writer.writerow([vendor, product_code, revision_number] + 
   346             writer.writerow([vendor, product_code, revision_number] +
   347                             [module_extra_params.get(param, '') 
   347                             [module_extra_params.get(param, '')
   348                              for param in extra_params])
   348                              for param in extra_params])
   349         csvfile.close()
   349         csvfile.close()
   350     
   350 
   351     def SetModuleExtraParam(self, vendor, product_code, revision_number, param, value):
   351     def SetModuleExtraParam(self, vendor, product_code, revision_number, param, value):
   352         vendor = ExtractHexDecValue(vendor)
   352         vendor = ExtractHexDecValue(vendor)
   353         product_code = ExtractHexDecValue(product_code)
   353         product_code = ExtractHexDecValue(product_code)
   354         revision_number = ExtractHexDecValue(revision_number)
   354         revision_number = ExtractHexDecValue(revision_number)
   355         
   355 
   356         module_infos = (vendor, product_code, revision_number)
   356         module_infos = (vendor, product_code, revision_number)
   357         self.ModulesExtraParams.setdefault(module_infos, {})
   357         self.ModulesExtraParams.setdefault(module_infos, {})
   358         self.ModulesExtraParams[module_infos][param] = value
   358         self.ModulesExtraParams[module_infos][param] = value
   359         
   359 
   360         self.SaveModulesExtraParams()
   360         self.SaveModulesExtraParams()
   361     
   361 
   362     def GetModuleExtraParams(self, vendor, product_code, revision_number):
   362     def GetModuleExtraParams(self, vendor, product_code, revision_number):
   363         vendor = ExtractHexDecValue(vendor)
   363         vendor = ExtractHexDecValue(vendor)
   364         product_code = ExtractHexDecValue(product_code)
   364         product_code = ExtractHexDecValue(product_code)
   365         revision_number = ExtractHexDecValue(revision_number)
   365         revision_number = ExtractHexDecValue(revision_number)
   366         
   366 
   367         if self.ParentLibrary is not None:
   367         if self.ParentLibrary is not None:
   368             extra_params = self.ParentLibrary.GetModuleExtraParams(vendor, product_code, revision_number)
   368             extra_params = self.ParentLibrary.GetModuleExtraParams(vendor, product_code, revision_number)
   369         else:
   369         else:
   370             extra_params = {}
   370             extra_params = {}
   371         
   371 
   372         extra_params.update(self.ModulesExtraParams.get((vendor, product_code, revision_number), {}))
   372         extra_params.update(self.ModulesExtraParams.get((vendor, product_code, revision_number), {}))
   373         
   373 
   374         for param, param_infos in self.MODULES_EXTRA_PARAMS:
   374         for param, param_infos in self.MODULES_EXTRA_PARAMS:
   375             extra_params.setdefault(param, param_infos["default"])
   375             extra_params.setdefault(param, param_infos["default"])
   376         
   376 
   377         return extra_params
   377         return extra_params
   378 
   378 
   379 USERDATA_DIR = wx.StandardPaths.Get().GetUserDataDir()
   379 USERDATA_DIR = wx.StandardPaths.Get().GetUserDataDir()
   380 if wx.Platform != '__WXMSW__':
   380 if wx.Platform != '__WXMSW__':
   381     USERDATA_DIR += '_files'
   381     USERDATA_DIR += '_files'
   382 
   382 
   383 ModulesDatabase = ModulesLibrary(
   383 ModulesDatabase = ModulesLibrary(
   384     os.path.join(USERDATA_DIR, "ethercat_modules"))
   384     os.path.join(USERDATA_DIR, "ethercat_modules"))
   385 
   385 
   386 class RootClass:
   386 class RootClass:
   387     
   387 
   388     CTNChildrenTypes = [("EthercatNode",_EthercatCTN,"Ethercat Master")]
   388     CTNChildrenTypes = [("EthercatNode",_EthercatCTN,"Ethercat Master")]
   389     EditorType = LibraryEditor
   389     EditorType = LibraryEditor
   390        
   390 
   391     
   391 
   392     def __init__(self):
   392     def __init__(self):
   393         self.ModulesLibrary = None
   393         self.ModulesLibrary = None
   394         self.LoadModulesLibrary()
   394         self.LoadModulesLibrary()
   395     
   395 
   396     def GetIconName(self):
   396     def GetIconName(self):
   397         return "Ethercat"
   397         return "Ethercat"
   398     
   398 
   399     def GetModulesLibraryPath(self, project_path=None):
   399     def GetModulesLibraryPath(self, project_path=None):
   400         if project_path is None:
   400         if project_path is None:
   401             project_path = self.CTNPath()
   401             project_path = self.CTNPath()
   402         return os.path.join(project_path, "modules") 
   402         return os.path.join(project_path, "modules")
   403     
   403 
   404     def OnCTNSave(self, from_project_path=None):
   404     def OnCTNSave(self, from_project_path=None):
   405         if from_project_path is not None:
   405         if from_project_path is not None:
   406             shutil.copytree(self.GetModulesLibraryPath(from_project_path),
   406             shutil.copytree(self.GetModulesLibraryPath(from_project_path),
   407                             self.GetModulesLibraryPath())
   407                             self.GetModulesLibraryPath())
   408         return True
   408         return True
   409     
   409 
   410     def CTNGenerate_C(self, buildpath, locations):
   410     def CTNGenerate_C(self, buildpath, locations):
   411         return [],"",False
   411         return [],"",False
   412     
   412 
   413     def LoadModulesLibrary(self):
   413     def LoadModulesLibrary(self):
   414         if self.ModulesLibrary is None:
   414         if self.ModulesLibrary is None:
   415             self.ModulesLibrary = ModulesLibrary(self.GetModulesLibraryPath(), ModulesDatabase)
   415             self.ModulesLibrary = ModulesLibrary(self.GetModulesLibraryPath(), ModulesDatabase)
   416         else:
   416         else:
   417             self.ModulesLibrary.LoadModulesLibrary()
   417             self.ModulesLibrary.LoadModulesLibrary()
   418     
   418 
   419     def GetModulesDatabaseInstance(self):
   419     def GetModulesDatabaseInstance(self):
   420         return ModulesDatabase
   420         return ModulesDatabase
   421     
   421 
   422     def GetModulesLibraryInstance(self):
   422     def GetModulesLibraryInstance(self):
   423         return self.ModulesLibrary
   423         return self.ModulesLibrary
   424     
   424 
   425     def GetModulesLibrary(self, profile_filter=None):
   425     def GetModulesLibrary(self, profile_filter=None):
   426         return self.ModulesLibrary.GetModulesLibrary(profile_filter)
   426         return self.ModulesLibrary.GetModulesLibrary(profile_filter)
   427     
   427 
   428     def GetVendors(self):
   428     def GetVendors(self):
   429         return self.ModulesLibrary.GetVendors()
   429         return self.ModulesLibrary.GetVendors()
   430     
   430 
   431     def GetModuleInfos(self, module_infos):
   431     def GetModuleInfos(self, module_infos):
   432         return self.ModulesLibrary.GetModuleInfos(module_infos)
   432         return self.ModulesLibrary.GetModuleInfos(module_infos)
   433