50 ("PDOMapping", str, ""), |
55 ("PDOMapping", str, ""), |
51 ("PDO index", str, ""), |
56 ("PDO index", str, ""), |
52 ("PDO name", str, ""), |
57 ("PDO name", str, ""), |
53 ("PDO type", str, "")] |
58 ("PDO type", str, "")] |
54 |
59 |
|
60 # Read DefaultValue from ESI file |
|
61 # Add by jblee 151229 |
|
62 ENTRY_INFOS_KEYS_FOR_DV = [ |
|
63 ("Index", lambda x: "#x%4.4X" % int(x), "#x0000"), |
|
64 ("SubIndex", str, "0"), |
|
65 ("Name", str, ""), |
|
66 ("Type", str, ""), |
|
67 ("BitSize", int, 0), |
|
68 ("Access", str, ""), |
|
69 ("PDOMapping", str, ""), |
|
70 ("DefaultValue", str, ""), |
|
71 ("Sub_entry_flag", str, "0")] |
|
72 |
55 class EntryListFactory: |
73 class EntryListFactory: |
56 |
74 |
57 def __init__(self, entries): |
75 def __init__(self, entries): |
58 self.Entries = entries |
76 self.Entries = entries |
59 |
77 |
60 def AddEntry(self, context, *args): |
78 def AddEntry(self, context, *args): |
61 index, subindex = map(lambda x: int(x[0]), args[:2]) |
79 index, subindex = map(lambda x: int(x[0]), args[:2]) |
62 new_entry_infos = { |
80 if len(args) > 9: |
|
81 new_entry_infos = { |
63 key: translate(arg[0]) if len(arg) > 0 else default |
82 key: translate(arg[0]) if len(arg) > 0 else default |
64 for (key, translate, default), arg |
83 for (key, translate, default), arg |
65 in zip(ENTRY_INFOS_KEYS, args)} |
84 in zip(ENTRY_INFOS_KEYS, args)} |
66 |
85 else: |
|
86 new_entry_infos = { |
|
87 key: translate(arg[0]) if len(arg) > 0 else default |
|
88 for (key, translate, default), arg |
|
89 in zip(ENTRY_INFOS_KEYS_FOR_DV, args)} |
|
90 |
67 if (index, subindex) != (0, 0): |
91 if (index, subindex) != (0, 0): |
68 entry_infos = self.Entries.get((index, subindex)) |
92 entry_infos = self.Entries.get((index, subindex)) |
69 if entry_infos is not None: |
93 if entry_infos is not None: |
70 for param in ["PDO index", "PDO name", "PDO type"]: |
94 for param in ["PDO index", "PDO name", "PDO type"]: |
71 value = new_entry_infos.get(param) |
95 value = new_entry_infos.get(param) |
90 if mailbox is not None: |
115 if mailbox is not None: |
91 return mailbox.getCoE() |
116 return mailbox.getCoE() |
92 return None |
117 return None |
93 setattr(cls, "getCoE", getCoE) |
118 setattr(cls, "getCoE", getCoE) |
94 |
119 |
|
120 # Modify by jblee |
|
121 def ExtractDataTypes(self): |
|
122 #self.DataTypes = {} |
|
123 #self.DT = {} |
|
124 DT = {} |
|
125 objects = [] |
|
126 |
|
127 # get Profile Field |
|
128 for profile in self.getProfile(): |
|
129 # get each (ProfileNo, Dictionary) Field as child |
|
130 for child in profile.getchildren(): |
|
131 # child.text is not None -> ProfileNo, is None -> Dictionary |
|
132 if child.text is None: |
|
133 # get each (DataTypes, Objects) Field |
|
134 dataTypes = child.getDataTypes() |
|
135 objects = child.getObjects() |
|
136 |
|
137 for dataType in dataTypes.getDataType(): |
|
138 #if dataType.getName() is not None: |
|
139 # print dataType.getName(), dataType |
|
140 DT[dataType.getName()] = dataType |
|
141 |
|
142 return DT, objects |
|
143 setattr(cls, "ExtractDataTypes", ExtractDataTypes) |
|
144 |
95 def GetEntriesList(self, limits=None): |
145 def GetEntriesList(self, limits=None): |
|
146 DataTypes, objects = self.ExtractDataTypes() |
|
147 |
96 entries = {} |
148 entries = {} |
97 |
149 |
98 factory = EntryListFactory(entries) |
150 # get each Object Field |
99 |
151 for object in objects: |
100 entries_list_xslt_tree = etree.XSLT( |
152 # Object Field mendatory : Index, Name, Type, BitSize |
101 entries_list_xslt, extensions = { |
153 # Frequently Use : Info, Flags |
102 ("entries_list_ns", "AddEntry"): factory.AddEntry, |
154 # Info Field -> DefaultData, SubItem |
103 ("entries_list_ns", "HexDecValue"): HexDecValue, |
155 # Flags Field -> Access, Category, PdoMapping |
104 ("entries_list_ns", "EntryName"): EntryName}) |
156 object_index = object.getIndex().getcontent() |
105 entries_list_xslt_tree(self, **dict(zip( |
157 index = ExtractHexDecValue(object_index) |
106 ["min_index", "max_index"], |
158 if limits is None or limits[0] <= index <= limits[1]: |
107 map(lambda x: etree.XSLT.strparam(str(x)), |
159 object_type = object.getType() |
108 limits if limits is not None else [0x0000, 0xFFFF]) |
160 object_name = ExtractName(object.getName()) |
109 ))) |
161 object_size = object.getBitSize() |
|
162 defaultData = "" |
|
163 object_access = "" |
|
164 object_PDOMapping_data = "" |
|
165 |
|
166 object_type_infos = DataTypes.get(object_type, None) |
|
167 subItem_infos = object_type_infos.getchildren() |
|
168 countSubIndex = 0 |
|
169 if len(subItem_infos) > 2: |
|
170 for subItem_info in subItem_infos: |
|
171 if subItem_info.tag == "SubItem" : |
|
172 subItemName = subItem_info.getName() |
|
173 subIdx = subItem_info.getSubIdx() |
|
174 if subIdx is not None: |
|
175 object_subidx = ExtractHexDecValue(subIdx) |
|
176 else: |
|
177 object_subidx = ExtractHexDecValue(countSubIndex) |
|
178 subType = subItem_info.getType() |
|
179 subBitSize = subItem_info.getBitSize() |
|
180 subFlags = subItem_info.getFlags() |
|
181 subAccess = "" |
|
182 subPDOMapping_data = "" |
|
183 if subFlags is not None: |
|
184 subAccess = subFlags.getAccess().getcontent() |
|
185 subPDOMapping = subFlags.getPdoMapping() |
|
186 if subPDOMapping is not None: |
|
187 subPDOMapping_data = subFlags.getPdoMapping().upper() |
|
188 |
|
189 entries[(index, object_subidx)] = { |
|
190 "Index": object_index, |
|
191 "SubIndex": subIdx, |
|
192 "Name": "%s - %s" % |
|
193 (object_name.decode("utf-8"), |
|
194 subItemName.decode("utf-8")), |
|
195 "Type": subType, |
|
196 "BitSize": subBitSize, |
|
197 "Access": subAccess, |
|
198 "PDOMapping": subPDOMapping_data} |
|
199 |
|
200 countSubIndex += 1 |
|
201 |
|
202 info = object.getInfo() |
|
203 # subItemTest : check subItem |
|
204 countSubIndex = 0 |
|
205 if info is not None: |
|
206 subItems = info.getchildren() |
|
207 if len(subItems) > 1: |
|
208 for subItem in subItems: |
|
209 defaultdata_subidx = ExtractHexDecValue(countSubIndex) |
|
210 defaultData = subItem.getchildren()[1].findtext("DefaultData") |
|
211 entry = entries.get((index, defaultdata_subidx), None) |
|
212 if entry is not None: |
|
213 entry["DefaultData"] = defaultData |
|
214 countSubIndex += 1 |
|
215 |
|
216 else : |
|
217 info = object.getInfo() |
|
218 if info is not None: |
|
219 subItems = info.getchildren() |
|
220 if len(subItems) <= 1: |
|
221 defaultData = subItems[0].text |
|
222 |
|
223 object_flag = object.getFlags() |
|
224 object_access = object_flag.getAccess().getcontent() |
|
225 object_PDOMapping = object_flag.getPdoMapping() |
|
226 if object_PDOMapping is not None: |
|
227 object_PDOMapping_data = object_flag.getPdoMapping().upper() |
|
228 entries[(index, 0)] = { |
|
229 "Index": object_index, |
|
230 "SubIndex": "0", |
|
231 "Name": object_name, |
|
232 "Type": object_type, |
|
233 "BitSize": object_size, |
|
234 "DefaultData" : defaultData, |
|
235 "Access": object_access, |
|
236 "PDOMapping": object_PDOMapping_data} |
|
237 |
|
238 for TxPdo in self.getTxPdo(): |
|
239 ExtractPdoInfos(TxPdo, "Transmit", entries, limits) |
|
240 for RxPdo in self.getRxPdo(): |
|
241 ExtractPdoInfos(RxPdo, "Receive", entries, limits) |
110 |
242 |
111 return entries |
243 return entries |
112 setattr(cls, "GetEntriesList", GetEntriesList) |
244 setattr(cls, "GetEntriesList", GetEntriesList) |
|
245 |
|
246 # def GetEntriesList(self, limits=None): |
|
247 # entries = {} |
|
248 |
|
249 # factory = EntryListFactory(entries) |
|
250 |
|
251 # entries_list_xslt_tree = etree.XSLT( |
|
252 # entries_list_xslt, extensions = { |
|
253 # ("entries_list_ns", "AddEntry"): factory.AddEntry, |
|
254 # ("entries_list_ns", "HexDecValue"): HexDecValue, |
|
255 # ("entries_list_ns", "EntryName"): EntryName}) |
|
256 # entries_list_xslt_tree(self, **dict(zip( |
|
257 # ["min_index", "max_index"], |
|
258 # map(lambda x: etree.XSLT.strparam(str(x)), |
|
259 # limits if limits is not None else [0x0000, 0xFFFF]) |
|
260 # ))) |
|
261 # |
|
262 # return entries |
|
263 # setattr(cls, "GetEntriesList", GetEntriesList) |
113 |
264 |
114 def GetSyncManagers(self): |
265 def GetSyncManagers(self): |
115 sync_managers = [] |
266 sync_managers = [] |
116 for sync_manager in self.getSm(): |
267 for sync_manager in self.getSm(): |
117 sync_manager_infos = {} |
268 sync_manager_infos = {} |
140 def SortGroupItems(group): |
293 def SortGroupItems(group): |
141 for item in group["children"]: |
294 for item in group["children"]: |
142 if item["type"] == ETHERCAT_GROUP: |
295 if item["type"] == ETHERCAT_GROUP: |
143 SortGroupItems(item) |
296 SortGroupItems(item) |
144 group["children"].sort(GroupItemCompare) |
297 group["children"].sort(GroupItemCompare) |
|
298 |
|
299 def ExtractPdoInfos(pdo, pdo_type, entries, limits=None): |
|
300 pdo_index = pdo.getIndex().getcontent() |
|
301 pdo_name = ExtractName(pdo.getName()) |
|
302 exclude = pdo.getExclude() |
|
303 for pdo_entry in pdo.getEntry(): |
|
304 entry_index = pdo_entry.getIndex().getcontent() |
|
305 entry_subindex = pdo_entry.getSubIndex() |
|
306 index = ExtractHexDecValue(entry_index) |
|
307 subindex = ExtractHexDecValue(entry_subindex) |
|
308 object_size = pdo_entry.getBitLen() |
|
309 |
|
310 if limits is None or limits[0] <= index <= limits[1]: |
|
311 entry = entries.get((index, subindex), None) |
|
312 if entry is not None: |
|
313 entry["PDO index"] = pdo_index |
|
314 entry["PDO name"] = pdo_name |
|
315 entry["PDO type"] = pdo_type |
|
316 else: |
|
317 entry_type = pdo_entry.getDataType() |
|
318 if entry_type is not None: |
|
319 if pdo_type == "Transmit": |
|
320 access = "ro" |
|
321 pdomapping = "T" |
|
322 else: |
|
323 access = "wo" |
|
324 pdomapping = "R" |
|
325 entries[(index, subindex)] = { |
|
326 "Index": entry_index, |
|
327 "SubIndex": entry_subindex, |
|
328 "Name": ExtractName(pdo_entry.getName()), |
|
329 "Type": entry_type.getcontent(), |
|
330 "BitSize": object_size, |
|
331 "Access": access, |
|
332 "PDOMapping": pdomapping} |
|
333 |
|
334 #cls3 = EtherCATBaseParser.GetElementClass("ModuleType") |
|
335 #if cls3: |
|
336 # module_xpath = EtherCATBase_XPath("Descriptions/Modules/Module") |
|
337 # def test(self): |
|
338 # print module_xpath |
|
339 |
|
340 # setattr(cls, "test", test) |
|
341 |
145 |
342 |
146 class ModulesLibrary: |
343 class ModulesLibrary: |
147 |
344 |
148 MODULES_EXTRA_PARAMS = [ |
345 MODULES_EXTRA_PARAMS = [ |
149 ("pdo_alignment", { |
346 ("pdo_alignment", { |
178 if parent_library is not None: |
375 if parent_library is not None: |
179 self.LoadModules() |
376 self.LoadModules() |
180 else: |
377 else: |
181 self.Library = None |
378 self.Library = None |
182 self.LoadModulesExtraParams() |
379 self.LoadModulesExtraParams() |
183 |
380 |
184 def GetPath(self): |
381 def GetPath(self): |
185 return self.Path |
382 return self.Path |
186 |
383 |
187 def GetModulesExtraParamsFilePath(self): |
384 def GetModulesExtraParamsFilePath(self): |
188 return os.path.join(self.Path, "modules_extra_params.cfg") |
385 return os.path.join(self.Path, "modules_extra_params.cfg") |
189 |
386 |
190 groups_xpath = EtherCATInfo_XPath("Descriptions/Groups/Group") |
387 groups_xpath = EtherCATInfo_XPath("Descriptions/Groups/Group") |
191 devices_xpath = EtherCATInfo_XPath("Descriptions/Devices/Device") |
388 devices_xpath = EtherCATInfo_XPath("Descriptions/Devices/Device") |
|
389 module_xpath = EtherCATBase_XPath("Descriptions/Modules/Module") |
|
390 |
192 def LoadModules(self): |
391 def LoadModules(self): |
193 self.Library = {} |
392 self.Library = {} |
|
393 # add by jblee for Modular Device Profile |
|
394 self.MDPList = [] |
|
395 self.ModuleList = [] |
|
396 self.MDPEntryList = {} |
|
397 dtDic = {} |
|
398 self.idxIncrement = 0 |
|
399 self.slotIncrement = 0 |
|
400 # add by jblee for PDO Mapping |
|
401 self.DataTypes = {} |
|
402 self.ObjectDictionary = {} |
194 |
403 |
195 files = os.listdir(self.Path) |
404 files = os.listdir(self.Path) |
196 for file in files: |
405 for file in files: |
197 filepath = os.path.join(self.Path, file) |
406 filepath = os.path.join(self.Path, file) |
198 if os.path.isfile(filepath) and os.path.splitext(filepath)[-1] == ".xml": |
407 if os.path.isfile(filepath) and os.path.splitext(filepath)[-1] == ".xml": |
199 self.modules_infos = None |
408 self.modules_infos = None |
200 |
409 |
201 xmlfile = open(filepath, 'r') |
410 xmlfile = open(filepath, 'r') |
202 try: |
411 try: |
203 self.modules_infos, error = EtherCATInfoParser.LoadXMLString(xmlfile.read()) |
412 self.modules_infos, error = EtherCATInfoParser.LoadXMLString(xmlfile.read()) |
204 if error is not None: |
413 #if error is not None: |
205 self.GetCTRoot().logger.write_warning( |
414 # self.GetCTRoot().logger.write_warning( |
206 XSDSchemaErrorMessage % (filepath + error)) |
415 # XSDSchemaErrorMessage % (filepath + error)) |
207 except Exception, exc: |
416 except Exception, exc: |
208 self.modules_infos, error = None, unicode(exc) |
417 self.modules_infos, error = None, unicode(exc) |
209 xmlfile.close() |
418 xmlfile.close() |
210 |
419 |
211 if self.modules_infos is not None: |
420 if self.modules_infos is not None: |
212 vendor = self.modules_infos.getVendor() |
421 vendor = self.modules_infos.getVendor() |
213 |
422 |
214 vendor_category = self.Library.setdefault( |
423 vendor_category = self.Library.setdefault( |
215 ExtractHexDecValue(vendor.getId()), |
424 ExtractHexDecValue(vendor.getId()), |
216 {"name": ExtractName(vendor.getName(), _("Miscellaneous")), |
425 {"name": ExtractName(vendor.getName(), _("Miscellaneous")), |
217 "groups": {}}) |
426 "groups": {}}) |
218 |
427 |
219 for group in self.groups_xpath(self.modules_infos): |
428 for group in self.groups_xpath(self.modules_infos): |
220 group_type = group.getType() |
429 group_type = group.getType() |
|
430 # add for XmlToEeprom Func by jblee. |
|
431 self.LcId_data = group.getchildren()[1] |
|
432 self.Image16x14_data = group.getchildren()[2] |
221 |
433 |
222 vendor_category["groups"].setdefault(group_type, |
434 vendor_category["groups"].setdefault(group_type, |
223 {"name": ExtractName(group.getName(), group_type), |
435 {"name": ExtractName(group.getName(), group_type), |
224 "parent": group.getParentGroup(), |
436 "parent": group.getParentGroup(), |
225 "order": group.getSortOrder(), |
437 "order": group.getSortOrder(), |
226 #"value": group.getcontent()["value"], |
438 "devices": [], |
227 "devices": []}) |
439 # add jblee for support Moduler Device Profile (MDP) |
|
440 "modules": []}) |
228 |
441 |
229 for device in self.devices_xpath(self.modules_infos): |
442 for device in self.devices_xpath(self.modules_infos): |
230 device_group = device.getGroupType() |
443 device_group = device.getGroupType() |
231 if not vendor_category["groups"].has_key(device_group): |
444 if not vendor_category["groups"].has_key(device_group): |
232 raise ValueError, "Not such group \"%\"" % device_group |
445 raise ValueError, "Not such group \"%\"" % device_group |
233 vendor_category["groups"][device_group]["devices"].append( |
446 vendor_category["groups"][device_group]["devices"].append( |
234 (device.getType().getcontent(), device)) |
447 (device.getType().getcontent(), device)) |
235 |
448 |
|
449 # ------------------ Test Section --------------------# |
|
450 slots = device.getSlots() |
|
451 if slots is not None: |
|
452 for slot in slots.getSlot(): |
|
453 self.idxIncrement = slot.getSlotIndexIncrement() |
|
454 self.slotIncrement = slot.getSlotPdoIncrement() |
|
455 for child in slot.getchildren(): |
|
456 if child.tag == "ModuleClass": |
|
457 child_class = child.getClass() |
|
458 child_name = child.getName() |
|
459 |
|
460 # -------------------- Test Section ----------------------------------# |
|
461 LocalMDPList = [] |
|
462 for module in self.module_xpath(self.modules_infos): |
|
463 module_type = module.getType().getModuleClass() |
|
464 module_name = module.getName() |
|
465 LocalMDPData = ExtractName(module_name) + " (" + module_type + ")" |
|
466 |
|
467 self.ModuleList.append(module) |
|
468 try : |
|
469 module_pdos = module.getTxPdo() |
|
470 module_pdos += module.getRxPdo() |
|
471 for module_pdo in module_pdos: |
|
472 device_name = ExtractName(module_name) |
|
473 pdo_index = module_pdo.getIndex().getcontent() |
|
474 pdo_name = ExtractName(module_pdo.getName()) |
|
475 pdo_entry = module_pdo.getEntry() |
|
476 if module_pdo.tag == "TxPdo": |
|
477 mapping_type = "T" |
|
478 else : |
|
479 mapping_type = "R" |
|
480 |
|
481 LocalMDPEntry = [] |
|
482 for entry in pdo_entry: |
|
483 entry_index = entry.getIndex().getcontent() |
|
484 entry_subidx = entry.getSubIndex() |
|
485 entry_name = ExtractName(entry.getName()) |
|
486 entry_bitsize = entry.getBitLen() |
|
487 try : |
|
488 entry_type = entry.getDataType().getcontent() |
|
489 except : |
|
490 entry_type = "" |
|
491 |
|
492 LocalMDPEntry.append({ |
|
493 "Index": entry_index, |
|
494 "SubIndex": entry_subidx, |
|
495 "Name": "%s - %s" % (pdo_name, entry_name), |
|
496 "Type": entry_type, |
|
497 "BitSize": entry_bitsize, |
|
498 "Access": "", |
|
499 "PDOMapping": mapping_type}) |
|
500 |
|
501 self.MDPEntryList[device_name] = LocalMDPEntry |
|
502 |
|
503 LocalMDPList.append([LocalMDPData, module, LocalMDPEntry]) |
|
504 except : |
|
505 LocalMDPList.append([LocalMDPData, module, []]) |
|
506 |
|
507 if LocalMDPList: |
|
508 vendor_category["groups"][device_group]["modules"].append( |
|
509 (device.getType().getcontent(), LocalMDPList, self.idxIncrement, self.slotIncrement)) |
|
510 #self.MDPList.append([device.getType().getcontent(), LocalMDPList, |
|
511 # self.idxIncrement, self.slotIncrement]) |
|
512 |
|
513 # --------------------------------------------------------------------- # |
|
514 |
236 else: |
515 else: |
237 |
516 pass |
238 self.GetCTRoot().logger.write_error( |
517 #self.GetCTRoot().logger.write_error( |
239 _("Couldn't load %s XML file:\n%s") % (filepath, error)) |
518 # _("Couldn't load %s XML file:\n%s") % (filepath, error)) |
240 |
519 |
241 return self.Library |
520 #print self.ObjectDictionary |
242 |
521 return self.Library ## add jblee |
|
522 |
|
523 # add jblee |
|
524 def GetMDPList(self): |
|
525 return self.MDPList |
|
526 |
|
527 # add jblee |
|
528 def GetSelectModule(self, idx): |
|
529 return self.ModuleList[idx] |
|
530 |
|
531 # add jblee |
|
532 def GetModuleEntryList(self): |
|
533 return self.MDPEntryList |
|
534 |
|
535 # add jblee |
|
536 def GetModuleIncrement(self): |
|
537 return (self.idxIncrement, self.slotIncrement) |
|
538 |
|
539 # add jblee |
|
540 #def GetEntriesList(self): |
|
541 # return self.ObjectDictionary |
|
542 |
243 def GetModulesLibrary(self, profile_filter=None): |
543 def GetModulesLibrary(self, profile_filter=None): |
244 if self.Library is None: |
544 if self.Library is None: |
245 self.LoadModules() |
545 self.LoadModules() |
246 library = [] |
546 library = [] |
247 for vendor_id, vendor in self.Library.iteritems(): |
547 for vendor_id, vendor in self.Library.iteritems(): |
299 for device_type, device_infos in group_infos["devices"]: |
599 for device_type, device_infos in group_infos["devices"]: |
300 product_code = ExtractHexDecValue(device_infos.getType().getProductCode()) |
600 product_code = ExtractHexDecValue(device_infos.getType().getProductCode()) |
301 revision_number = ExtractHexDecValue(device_infos.getType().getRevisionNo()) |
601 revision_number = ExtractHexDecValue(device_infos.getType().getRevisionNo()) |
302 if (product_code == ExtractHexDecValue(module_infos["product_code"]) and |
602 if (product_code == ExtractHexDecValue(module_infos["product_code"]) and |
303 revision_number == ExtractHexDecValue(module_infos["revision_number"])): |
603 revision_number == ExtractHexDecValue(module_infos["revision_number"])): |
304 self.cntdevice = device_infos |
604 self.cntdevice = device_infos ## add by hwang 13.05.01. |
305 self.cntdeviceType = device_type |
605 self.cntdeviceType = device_type ## add by hwang 13.05.01. |
306 return device_infos, self.GetModuleExtraParams(vendor, product_code, revision_number) |
606 return device_infos, self.GetModuleExtraParams(vendor, product_code, revision_number) |
307 return None, None |
607 return None, None |
|
608 |
|
609 # add jblee for MDP |
|
610 def GetMDPInfos(self, module_infos): |
|
611 vendor = ExtractHexDecValue(module_infos["vendor"]) |
|
612 vendor_infos = self.Library.get(vendor) |
|
613 if vendor_infos is not None: |
|
614 for group_name, group_infos in vendor_infos["groups"].iteritems(): |
|
615 return group_infos["modules"] |
|
616 #for device_type, module_list, idx_inc, slot_inc in group_infos["modules"]: |
|
617 # return module_list, idx_inc, slot_inc |
|
618 |
|
619 #return None, None, None |
308 |
620 |
309 def ImportModuleLibrary(self, filepath): |
621 def ImportModuleLibrary(self, filepath): |
310 if os.path.isfile(filepath): |
622 if os.path.isfile(filepath): |
311 shutil.copy(filepath, self.Path) |
623 shutil.copy(filepath, self.Path) |
312 self.LoadModules() |
624 self.LoadModules() |