Best Python code snippet using SeleniumBase
node.py
Source:node.py
1from __future__ import print_function2from __future__ import unicode_literals3import sys4if sys.version_info[0] > 2:5 basestring = unicode = str6try:7 import cdecimal as decimal8except ImportError:9 import decimal10from django.utils.translation import ugettext as _11#bots-modules12from . import botslib13from . import botsglobal14from .botsconfig import *15class Node(object):16 ''' Node class for building trees in inmessage and outmessage17 '''18 #slots: python optimalisation to preserve memory. Disadv.: no dynamic attr in this class19 #in tests: for normal translations less memory and faster; no effect fo one-on-one translations.20 __slots__ = ('record','children','_queries','linpos_info','structure')21 def __init__(self,record=None,linpos_info=None):22 if record and 'BOTSIDnr' not in record:23 record['BOTSIDnr'] = '1'24 self.record = record #record is a dict with fields25 self.children = []26 self.linpos_info = linpos_info27 self._queries = None28 self.structure = None29 def linpos(self):30 if self.linpos_info:31 return ' line %(lin)s pos %(pos)s'%{'lin':self.linpos_info[0],'pos':self.linpos_info[1]}32 else:33 return ''34 def append(self,childnode):35 '''append child to node'''36 self.children.append(childnode)37 #********************************************************38 #*** queries ********************************************39 #********************************************************40 def _getquerie(self):41 ''' getter for queries: get queries of a node '''42 if self._queries:43 return self._queries44 else:45 return {}46 def _updatequerie(self,updatequeries):47 ''' setter for queries: set/update queries of a node with dict queries.48 '''49 if updatequeries:50 if self._queries is None:51 self._queries = updatequeries.copy()52 else:53 botslib.updateunlessset(self._queries,updatequeries)54 queries = property(_getquerie,_updatequerie)55 def processqueries(self,queries,maxlevel):56 ''' copies values for queries 'down the tree' untill right level.57 So when edi file is split up in messages,58 querie-info from higher levels is copied to message.'''59 self.queries = queries60 if self.record and not maxlevel:61 return62 for childnode in self.children:63 childnode.processqueries(self.queries,maxlevel-1)64 def displayqueries(self,level=0):65 '''for debugging66 usage: in mappingscript: inn.root.displayqueries()67 '''68 if level == 0:69 print('displaying queries for nodes in tree')70 print(' '*level,'node:',end='')71 if self.record:72 print(self.record['BOTSID'],end='')73 else:74 print('None',end='')75 print('',end='')76 print(self.queries)77 for childnode in self.children:78 childnode.displayqueries(level+1)79 #********************************************************80 #*** handling of QUERIES and SUBTRANSLATION *************81 #********************************************************82 def enhancedget(self,mpaths):83 ''' to get QUERIES, SUBTRANSLATION or nextmessageblock.84 mpaths can be85 - dict: do one get(mpaths); can not be a mpath quering one level deeper->in that case use a tuple: ({'BOTSID':'ISA'},{'BOTSID':'GS','GS02':None})86 - tuple: do one get(mpaths); can be multiple dicts in mpaths87 - list: for each list member do a get(); append the results88 - function: user exit that returns a value (or None, if not found)89 - string: return that string90 '''91 if isinstance(mpaths,dict):92 return self.get(mpaths)93 elif isinstance(mpaths,tuple):94 return self.get(*mpaths)95 elif isinstance(mpaths,list):96 lijst = [self.enhancedget(mpath) for mpath in mpaths] #go recursive97 return ''.join(part.strip() for part in lijst if part is not None)98 elif callable(mpaths):99 return mpaths(thisnode=self)100 elif isinstance(mpaths,basestring):101 return mpaths102 else:103 raise botslib.MappingFormatError(_('Errors in mpath for QUERIES, SUBTRANSLATION or nextmessageblock; you used %(mpath)s.'),{'mpath':mpaths})104 def get_queries_from_edi(self,record_definition):105 ''' extract information from edifile using QUERIES in grammar.structure; information will be placed in ta_info and in db-ta106 '''107 tmpdict = {}108 for key,value in record_definition[QUERIES].items():109 found = self.enhancedget(value) #search in last added node110 if found is not None:111 found = found.strip() #needed to get correct ISA-fields112 if found:113 tmpdict[key] = found114 self.queries = tmpdict115 #********************************************************116 #*** manipulate node.tree: get, put, change, delete etc *117 #********************************************************118 def getrecord(self,*mpaths):119 ''' get whole node record120 '''121 self._mpath_sanity_check(mpaths)122 for part in mpaths:123 if 'BOTSIDnr' not in part:124 part['BOTSIDnr'] = '1'125 terug = self._getrecordcore(mpaths)126 botsglobal.logmap.debug('"%(terug)s" for getrecord%(mpaths)s',{'terug':unicode(terug),'mpaths':unicode(mpaths)})127 return terug128 def _getrecordcore(self,mpaths):129 for key,value in mpaths[0].items(): #check all key, value for first part of where;130 if key not in self.record or value != self.record[key]:131 return None #no match:132 else: #all key,value are matched.133 if len(mpaths) == 1: #mpath is exhausted; so we are there!!! #replace values with values in 'change'; delete if None134 return self.record135 else: #go recursive136 for childnode in self.children:137 terug = childnode._getrecordcore(mpaths[1:])138 if terug:139 return terug140 else: #no child has given a valid return141 return None142 def change(self,where,change):143 ''' where: node to find.144 change is applied to found node145 uses first matching node for 'where'.146 '''147 self._mpath_sanity_check(where)148 for part in where:149 if 'BOTSIDnr' not in part:150 part['BOTSIDnr'] = '1'151 #sanity check 'change' parameter152 if not isinstance(change,dict):153 raise botslib.MappingFormatError(_('Parameter "change" must be dict: change(where=%(where)s,change=%(change)s)'),154 {'where':where,'change':change})155 change.pop('BOTSID','nep') #remove 'BOTSID' from change. BOTSID can not be changed156 change.pop('BOTSIDnr','nep') #remove 'BOTSIDnr' from change. BOTSIDnr can not be changed157 for key,value in change.items():158 if not isinstance(key,basestring):159 raise botslib.MappingFormatError(_('Keys in "change" must be strings: change(where=%(where)s,change=%(change)s)'),160 {'where':where,'change':change})161 if value is None: #if None, item is deleted162 pass163 elif isinstance(value,list): #for now, just pass lists164 pass165 else:166 change[key] = unicode(value).strip() #leading and trailing spaces are stripped from the values167 terug = self._changecore(where,change)168 botsglobal.logmap.debug('"%(terug)s" for change(where=%(where)s,change=%(change)s)',{'terug':terug,'where':unicode(where),'change':unicode(change)})169 return terug170 def _changecore(self,where,change):171 for key,value in where[0].items(): #check all key, value for first part of where;172 if key not in self.record or value != self.record[key]:173 return False #no match:174 else: #all key,value are matched.175 if len(where) == 1: #mpath is exhausted; so we are there!!! #replace values with values in 'change'; delete if None176 for key,value in change.items():177 if value is None:178 self.record.pop(key,'nep')179 else:180 self.record[key] = value181 return True182 else: #go recursive183 for childnode in self.children:184 if childnode._changecore(where[1:],change):185 return True186 else: #no child has given a valid return187 return False188 def delete(self,*mpaths):189 ''' delete the last record of mpath if found (first: find/identify record, than delete).'''190 self._mpath_sanity_check(mpaths)191 if len(mpaths) == 1:192 raise botslib.MappingFormatError(_('Only one dict: not allowed. Use different solution: delete(%(mpath)s)'),{'mpath':mpaths})193 for part in mpaths:194 if 'BOTSIDnr' not in part:195 part['BOTSIDnr'] = '1'196 terug = bool(self._deletecore(mpaths))197 botsglobal.logmap.debug('"%(terug)s" for delete%(mpaths)s',{'terug':terug,'mpaths':unicode(mpaths)})198 return terug #return False if not removed, return True if removed199 def _deletecore(self,mpaths):200 for key,value in mpaths[0].items(): #check all items in first part of mpaths201 if key not in self.record or value != self.record[key]:202 return 0203 else: #all items are matched204 if len(mpaths) == 1: #mpath is exhausted; so we are there!!!205 return 2 #indicates node should be removed206 else:207 for i, childnode in enumerate(self.children):208 terug = childnode._deletecore(mpaths[1:]) #search recursive for rest of mpaths209 if terug == 2: #indicates node should be removed210 del self.children[i] #remove node211 return 1 #this indicates: deleted successfull, do not remove anymore (no removal of parents)212 if terug:213 return terug214 else: #no child has given a valid return215 return 0216 def get(self,*mpaths):217 ''' get value of a field in a record from a edi-message218 mpath is xpath-alike query to identify the record/field219 function returns 1 value; return None if nothing found.220 if more than one value can be found: first one is returned221 starts searching in current node, then deeper222 '''223 if Node.checklevel:224 self._mpath_sanity_check(mpaths[:-1])225 #sanity check of last part of mpaths: None only allowed in last section of Mpath; check last part226 if not isinstance(mpaths[-1],dict):227 raise botslib.MappingFormatError(_('Must be dicts in tuple: get(%(mpath)s)'),{'mpath':mpaths})228 if 'BOTSID' not in mpaths[-1]:229 raise botslib.MappingFormatError(_('Last section without "BOTSID": get(%(mpath)s)'),{'mpath':mpaths})230 count = 0231 for key,value in mpaths[-1].items():232 if not isinstance(key,basestring):233 raise botslib.MappingFormatError(_('Keys must be strings in last section: get(%(mpath)s)'),{'mpath':mpaths})234 if value is None:235 count += 1236 elif not isinstance(value,basestring):237 raise botslib.MappingFormatError(_('Values must be strings (or none) in last section: get(%(mpath)s)'),{'mpath':mpaths})238 if count > 1:239 raise botslib.MappingFormatError(_('Max one "None" in last section: get(%(mpath)s)'),{'mpath':mpaths})240 for part in mpaths:241 if 'BOTSIDnr' not in part:242 part['BOTSIDnr'] = '1'243 if Node.checklevel == 2:244 self._mpath_grammar_check(mpaths)245 terug = self._getcore(mpaths)246 botsglobal.logmap.debug('"%(terug)s" for get%(mpaths)s',{'terug':terug,'mpaths':unicode(mpaths)})247 return terug248 def _getcore(self,mpaths):249 if len(mpaths) != 1: #node is not end-node250 for key,value in mpaths[0].items(): #check all items in mpath;251 if key not in self.record or value != self.record[key]: #does not match/is not right node252 return None253 else: #all items in mpath are matched and OK; recursuve search254 for childnode in self.children:255 terug = childnode._getcore(mpaths[1:]) #recursive search for rest of mpaths256 if terug is not None:257 return terug258 else: #nothing found in children259 return None260 else: #node is end-node261 terug = 1 #default return value: if there is no 'None' in the mpath, but everything is matched, 1 is returned (like True)262 for key,value in mpaths[0].items(): #check all items in mpath;263 if key not in self.record: #does not match/is not right node264 return None265 elif value is None: #item has None-value; remember this value because this might be the right node266 terug = self.record[key][:] #copy to avoid memory problems267 elif value != self.record[key]: #compare values268 return None #does not match/is not right node269 else: #all keys/values in this mpathr are matched and OK.270 return terug #either the remembered value is returned or 1 (as a boolean, indicated 'found)271 def getcount(self):272 '''count the number of nodes/records under the node/in whole tree'''273 count = 0274 if self.record:275 count += 1 #count itself276 for childnode in self.children:277 count += childnode.getcount()278 return count279 def getcountoccurrences(self,*mpaths):280 ''' count number of occurences of mpath. Eg count nr of LIN's'''281 return len(list(self.getloop(*mpaths)))282 def getcountsum(self,*mpaths):283 ''' return the sum for all values found in mpath. Eg total number of ordered quantities.'''284 mpath_for_found_node = mpaths[-1].copy()285 for key,value in list(mpaths[-1].items()):286 if value is None:287 del mpaths[-1][key]288 count = decimal.Decimal(0)289 for i in self.getloop(*mpaths):290 count += i.getdecimal(mpath_for_found_node)291 return unicode(count)292 def getloop(self,*mpaths):293 ''' generator. Returns one by one the nodes as indicated in mpath294 '''295 if Node.checklevel:296 self._mpath_sanity_check(mpaths)297 for part in mpaths:298 if 'BOTSIDnr' not in part:299 part['BOTSIDnr'] = '1'300 if Node.checklevel == 2:301 self._mpath_grammar_check(mpaths)302 for terug in self._getloopcore(mpaths):303 botsglobal.logmap.debug('getloop %(mpaths)s returns "%(record)s".',{'mpaths':mpaths,'record':terug.record})304 yield terug305 def _getloopcore(self,mpaths):306 ''' recursive part of getloop()307 '''308 for key,value in mpaths[0].items():309 if key not in self.record or value != self.record[key]:310 return311 else: #all items are checked and OK.312 if len(mpaths) == 1:313 yield self #found!314 else:315 for childnode in self.children:316 for terug in childnode._getloopcore(mpaths[1:]): #search recursive for rest of mpaths317 yield terug318 def getloop_including_mpath(self,*mpaths):319 ''' generator. Returns one by one the nodes as indicated in mpath320 like getloop(), but returns a list: [mpath,mpath,etc,,node] ->node is same as returned by getloop()321 '''322 if Node.checklevel:323 self._mpath_sanity_check(mpaths)324 for part in mpaths:325 if 'BOTSIDnr' not in part:326 part['BOTSIDnr'] = '1'327 if Node.checklevel == 2:328 self._mpath_grammar_check(mpaths)329 for terug in self._getloopcore_including_mpath(mpaths):330 botsglobal.logmap.debug('getloop %(mpaths)s returns "%(terug)s".',{'mpaths':mpaths,'terug':terug})331 yield terug332 def _getloopcore_including_mpath(self,mpaths):333 ''' recursive part of getloop()334 '''335 for key,value in mpaths[0].items():336 if key not in self.record or value != self.record[key]:337 return338 else: #all items are checked and OK.339 if len(mpaths) == 1:340 yield [self] #found!341 else:342 for childnode in self.children:343 for terug in childnode._getloopcore_including_mpath(mpaths[1:]): #search recursive for rest of mpaths344 yield [self.record] + terug if terug is not None else None345 #~ def get_for_sort(self,*mpaths):346 #~ ''' like get, but either returns a value or '' (empty string). If get() delivers None, return as ''.347 #~ used by sort()348 #~ '''349 #~ terug = self.get(*mpaths)350 #~ if not terug:351 #~ return ''352 #~ return terug353 def getnozero(self,*mpaths):354 ''' like get, but either return a numerical value (as string) or None. If value to return is equal to zero, None is returned.355 useful eg for fixed records, where num fields are initialised with zeroes.356 '''357 terug = self.get(*mpaths)358 try:359 value = float(terug)360 except (TypeError,ValueError):361 return None362 if value == 0:363 return None364 return terug365 def getdecimal(self,*mpaths):366 ''' like get, but return a decimal value. If value to return is None or not numeric, zero is returned.367 warning: this function might 'mask' errors, because when input is not-valid, it aalwyas return a decimal 0. 368 useful eg for when math calculations are needed in mapping.369 '''370 terug = self.get(*mpaths)371 if terug and terug[-1] == '-': #if minus-sign at the end, put it in front. This is useful for idocs, where fields are never defined as numeric.372 terug = terug[-1] + terug[:-1]373 try:374 return decimal.Decimal(terug)375 except (TypeError,ValueError):376 return decimal.Decimal('0')377 def put(self,*mpaths,**kwargs):378 #sanity check of mpaths379 if not mpaths or not isinstance(mpaths,tuple):380 raise botslib.MappingFormatError(_('Must be dicts in tuple: put(%(mpath)s)'),{'mpath':mpaths})381 for part in mpaths:382 if not isinstance(part,dict):383 raise botslib.MappingFormatError(_('Must be dicts in tuple: put(%(mpath)s)'),{'mpath':mpaths})384 if 'BOTSID' not in part:385 raise botslib.MappingFormatError(_('Section without "BOTSID": put(%(mpath)s)'),{'mpath':mpaths})386 for key,value in part.items():387 if value is None:388 botsglobal.logmap.debug('"None" in put %(mpaths)s.',{'mpaths':unicode(mpaths)})389 return False390 if not isinstance(key,basestring):391 raise botslib.MappingFormatError(_('Keys must be strings: put(%(mpath)s)'),{'mpath':mpaths})392 if isinstance(value,list):393 #empty is not useful, drop it (like None)394 if not value:395 botsglobal.logmap.debug('Empty list in put %(mpaths)s.',{'mpaths':unicode(mpaths)})396 return False397 else:398 if kwargs.get('strip',True):399 part[key] = unicode(value).strip() #leading and trailing spaces are stripped from the values400 else:401 part[key] = unicode(value) #used for fixed ISA header of x12402 if 'BOTSIDnr' not in part:403 part['BOTSIDnr'] = '1'404 if self._sameoccurence(mpaths[0]):405 self._putcore(mpaths[1:])406 else:407 raise botslib.MappingRootError(_('Error in root put "%(mpath)s".'),{'mpath':mpaths[0]})408 botsglobal.logmap.debug('"True" for put %(mpaths)s',{'mpaths':unicode(mpaths)})409 return True410 def _putcore(self,mpaths):411 if not mpaths: #newmpath is exhausted, stop searching.412 return413 for childnode in self.children:414 if childnode.record['BOTSID'] == mpaths[0]['BOTSID'] and childnode._sameoccurence(mpaths[0]): #checking of BOTSID is also done in sameoccurance!->performance!415 childnode._putcore(mpaths[1:])416 return417 else: #is not present in children, so append mpath as a new node418 self.append(Node(mpaths[0]))419 self.children[-1]._putcore(mpaths[1:])420 def putloop(self,*mpaths):421 #sanity check of mpaths422 if not mpaths or not isinstance(mpaths,tuple):423 raise botslib.MappingFormatError(_('Must be dicts in tuple: putloop(%(mpath)s)'),{'mpath':mpaths})424 for part in mpaths:425 if not isinstance(part,dict):426 raise botslib.MappingFormatError(_('Must be dicts in tuple: putloop(%(mpath)s)'),{'mpath':mpaths})427 if 'BOTSID' not in part:428 raise botslib.MappingFormatError(_('Section without "BOTSID": putloop(%(mpath)s)'),{'mpath':mpaths})429 for key,value in part.items():430 if not isinstance(key,basestring):431 raise botslib.MappingFormatError(_('Keys must be strings: putloop(%(mpath)s)'),{'mpath':mpaths})432 if value is None:433 return False434 part[key] = unicode(value).strip()435 if 'BOTSIDnr' not in part:436 part['BOTSIDnr'] = '1'437 if self._sameoccurence(mpaths[0]):438 if len(mpaths)==1:439 return self440 return self._putloopcore(mpaths[1:])441 else:442 raise botslib.MappingRootError(_('Error in root putloop "%(mpath)s".'),{'mpath':mpaths[0]})443 def _putloopcore(self,mpaths):444 if len(mpaths) ==1: #end of mpath reached; always make new child-node445 self.append(Node(mpaths[0]))446 return self.children[-1]447 for childnode in self.children: #if first part of mpaths exists already in children go recursive448 if childnode.record['BOTSID'] == mpaths[0]['BOTSID'] and childnode._sameoccurence(mpaths[0]): #checking of BOTSID is also done in sameoccurance!->performance!449 return childnode._putloopcore(mpaths[1:])450 else: #is not present in children, so append a child, and go recursive451 self.append(Node(mpaths[0]))452 return self.children[-1]._putloopcore(mpaths[1:])453 def _sameoccurence(self, mpath):454 ''' checks if all items that appear in both node and mpath have the same value. If so, all new items in mpath are added to node455 '''456 for key,value in self.record.items():457 if key in mpath and mpath[key] != value:458 return False459 else: #all equal keys have same values, thus both are 'equal'.460 self.record.update(mpath) #add items to self.record that are new461 return True462 def sort(self,*mpaths):463 ''' sort nodes. eg in mappingscript: 464 1a. inn.sort({'BOTSID':'UNH'},{'BOTSID':'LIN','C212.7140':None}) -> sorts the LIN segments by article number.465 1b. inn.sort(sortfrom=({'BOTSID':'UNH'},),compare=({'BOTSID':'LIN','C212.7140':None},)) -> sorts the LIN segments by article number.466 2a. inn.sort({'BOTSID':'envelope'},{'BOTSID':'message'},{'BOTSID':'lines'},{'BOTSID':'line','gtin':None}) -> sorts lines by GTIN467 2b. inn.sort({'BOTSID':'envelope'},{'BOTSID':'message'},{'BOTSID':'lines'},{'BOTSID':'line','gtin':None}) -> sorts lines by GTIN468 3a. inn.sort({'BOTSID':'UNH'},{'BOTSID':'LIN'},{'BOTSID':'QTY','C186.6063':'12','C186.6060':None}) -> sorts the LIN segments according to quantityby article number.469 3b. inn.sort({'BOTSID':'UNH'},{'BOTSID':'LIN'},{'BOTSID':'QTY','C186.6063':'12','C186.6060':None}) -> sorts the LIN segments according to quantityby article number.470 version <= 3.2 only had mpaths as parameters; extended this in order to be upward compatible. mpath was split in sort_from_node and comparekey471 Case 3 can not be done with old parameter.472 new parameters (in **kwargs)473 - sort_from_node474 - comparekey475 - reverse - as reverse in python's sort476 - sort_if_none: if comparekey not there; should these be sorted as last or first. None is lowest, none is highest477 - sort_decimal: numerical sort478 '''479 if Node.checklevel:480 self._mpath_sanity_check(mpaths[:-1])481 #sanity check of last part of mpaths: None only allowed in last section of Mpath; check last part482 if not isinstance(mpaths[-1],dict):483 raise botslib.MappingFormatError(_('Must be dicts in tuple: get(%(mpath)s)'),{'mpath':mpaths})484 if 'BOTSID' not in mpaths[-1]:485 raise botslib.MappingFormatError(_('Last section without "BOTSID": get(%(mpath)s)'),{'mpath':mpaths})486 count = 0487 for key,value in mpaths[-1].items():488 if not isinstance(key,basestring):489 raise botslib.MappingFormatError(_('Keys must be strings in last section: get(%(mpath)s)'),{'mpath':mpaths})490 if value is None:491 count += 1492 elif not isinstance(value,basestring):493 raise botslib.MappingFormatError(_('Values must be strings (or none) in last section: get(%(mpath)s)'),{'mpath':mpaths})494 if count > 1:495 raise botslib.MappingFormatError(_('Max one "None" in last section: get(%(mpath)s)'),{'mpath':mpaths})496 for part in mpaths:497 if 'BOTSIDnr' not in part:498 part['BOTSIDnr'] = '1'499 if Node.checklevel == 2:500 self._mpath_grammar_check(mpaths)501 remember = Node.checklevel502 Node.checklevel = 0503 comparekey = mpaths[-1:]504 sort_from_node = mpaths[:-1]505 try:506 for n in self.getloop(*sort_from_node):507 n.children.sort(key=lambda s: s.get(*comparekey))508 finally:509 Node.checklevel = remember510 511 #~ comparekey = mpaths[1:]512 #~ #does not work with checklevel == 2, so temporary set checklevel to 0 513 #~ remember = Node.checklevel514 #~ Node.checklevel = 0515 #~ try:516 #~ self.children.sort(key=lambda s: s.get_for_sort(*comparekey))517 #~ finally:518 #~ Node.checklevel = remember519 #********************************************************520 #*** utility functions **********************************521 #********************************************************522 @staticmethod523 def _mpath_sanity_check(mpaths):524 ''' sanity check of mpaths. '''525 if not isinstance(mpaths,tuple):526 raise botslib.MappingFormatError(_('Parameter mpath must be tuple: %(mpaths)s'),{'mpaths':mpaths})527 for part in mpaths:528 if not isinstance(part,dict):529 raise botslib.MappingFormatError(_('Parameter mpath must be dicts in a tuple: %(mpaths)s'),{'mpaths':mpaths})530 if 'BOTSID' not in part:531 raise botslib.MappingFormatError(_('"BOTSID" is required in mpath: %(mpaths)s'),{'mpaths':mpaths})532 for key,value in part.items():533 if not isinstance(key,basestring):534 raise botslib.MappingFormatError(_('Keys must be strings in mpath: %(mpaths)s'),{'mpaths':mpaths})535 if not isinstance(value,basestring):536 raise botslib.MappingFormatError(_('Values must be strings in mpath: getrecord(%(mpaths)s)'),{'mpaths':mpaths})537 def _mpath_grammar_check(self,mpaths):538 ''' check of mpaths with grammar. '''539 def _mpath_ok_with_grammar(structure,mpaths):540 ''' inner function, recursive.541 every part of mpaths should be in structure, at right level, have right fields.542 '''543 mpath = mpaths[0]544 for record_definition in structure:545 if record_definition[ID] == mpath['BOTSID'] and record_definition[BOTSIDNR] == mpath['BOTSIDnr']:546 for key in mpath:547 if key == 'BOTSIDnr': #BOTSIDnr is not in grammar, so do not check548 continue549 for field_definition in record_definition[FIELDS]:550 if field_definition[ISFIELD]:551 if key == field_definition[ID]:552 break #check next key553 else:554 if key == field_definition[ID]: #first check compostie-key itself, for repeating composites555 break #check next key556 for grammarsubfield in field_definition[SUBFIELDS]: #loop subfields557 if key == grammarsubfield[ID]:558 break #check next key559 else:560 continue #checking field_defintions561 break #check next key562 else: #Not found in record!563 return False564 #all fields in mpath are correct; go to next level of mpath..565 if mpaths[1:]:566 if not LEVEL in record_definition:567 return False568 return _mpath_ok_with_grammar(record_definition[LEVEL],mpaths[1:])569 else:570 return True #no more levels, all fields found571 else:572 return False573 if not self.structure:574 return575 if not _mpath_ok_with_grammar([self.structure],mpaths):576 raise botslib.MappingFormatError(_('Parameter mpath is not valid according to grammar: %(mpaths)s'),{'mpaths':mpaths})577 def display(self,level=0):578 '''for debugging579 usage eg in mappingscript: inn.root.display()580 '''581 if level == 0:582 print('displaying all nodes in node tree:')583 print(' '*level,self.record)584 for childnode in self.children:585 childnode.display(level+1)586 def stripnode(self):587 ''' removes spaces from all fields in tree.588 used in alt translations where a dict is returned by mappingscript indicating the out-tree should be used as inn.589 the out-tree has been formatted already, this is not OK for fixed formats (idoc!)590 '''591 if self.record is not None:592 for key, value in self.record.items():593 self.record[key] = value.strip()594 for child in self.children:595 child.stripnode()596 def collectlines(self,print_as_row):597 ''' for new edifax routine: collect same nodes in Node.children in a list; for table-row printing.598 ''' 599 new = [] #new list600 for childnode in self.children:601 if childnode.structure[MPATH] in print_as_row:602 if not new: #if new is still empty603 new.append([childnode])604 elif isinstance(new[-1],list) and new[-1][0].record['BOTSID'] == childnode.record['BOTSID']:605 new[-1].append(childnode) #append in tabel-row-list606 else: #other recordID, also print as table-row607 new.append([childnode])608 else: #just append, no change609 new.append(childnode)610 childnode.collectlines(print_as_row) #go recursive611 self.children = new612 def copynode(self):613 ''' make a 'safe' copy of node; return the new node614 '''615 if self.record is None:616 new_node = Node(record=None)617 else:618 new_node = Node(record=dict(self.record))619 for childnode in self.children:620 new_node.append(childnode.copynode())...
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!