def getloop(self, *mpaths): ''' generator. Returns one by one the nodes as indicated in mpath ''' #check validity mpaths if not mpaths or not isinstance(mpaths, tuple): raise botslib.MappingFormatError( _(u'must be dicts in tuple: getloop($mpath)'), mpath=mpaths) for part in mpaths: if not isinstance(part, dict): raise botslib.MappingFormatError( _(u'must be dicts in tuple: getloop($mpath)'), mpath=mpaths) if not 'BOTSID' in part: raise botslib.MappingFormatError( _(u'section without "BOTSID": getloop($mpath)'), mpath=mpaths) for key, value in part.iteritems(): if not isinstance(key, basestring): raise botslib.MappingFormatError( _(u'keys must be strings: getloop($mpath)'), mpath=mpaths) if not isinstance(value, basestring): raise botslib.MappingFormatError( _(u'values must be strings: getloop($mpath)'), mpath=mpaths) for terug in self._getloopcore(*mpaths): botsglobal.logmap.debug(u'getloop %s returns "%s".', mpaths, terug.record) yield terug
def enhancedget(self,mpaths): ''' to get QUERIES or SUBTRANSLATION; mpath can be - dict: do get(mpath); can not be a mpath with multiple - tuple: do get(mpath); can be multiple dicts in mapth - list: for each listmembr do a get(); append the results - function: function should return a value (or None, if not found) ''' if isinstance(mpaths,dict): return self.get(mpaths) elif isinstance(mpaths,tuple): return self.get(*mpaths) elif isinstance(mpaths,list): collect = u'' for mpath in mpaths: if isinstance(mpath,dict): found = self.get(mpath) elif isinstance(mpath,tuple): found = self.get(*mpath) else: raise botslib.MappingFormatError(_(u'Member in list %(mpath)s must be dict or tuple (in enhancedget).'),{'mpath':mpaths}) if found: collect += found return collect elif callable(mpaths): return mpaths(thisnode=self) else: raise botslib.MappingFormatError(_(u'Must be dict, list or tuple: enhancedget(%(mpath)s)'),{'mpath':mpaths})
def putloop(self, *mpaths): if not mpaths or not isinstance(mpaths, tuple): raise botslib.MappingFormatError( _(u'must be dicts in tuple: putloop($mpath)'), mpath=mpaths) for part in mpaths: if not isinstance(part, dict): raise botslib.MappingFormatError( _(u'must be dicts in tuple: putloop($mpath)'), mpath=mpaths) #check: 'BOTSID' is required #check: all values should be strings for part in mpaths: if not 'BOTSID' in part: raise botslib.MappingFormatError( _(u'section without "BOTSID": putloop($mpath)'), mpath=mpaths) for key, value in part.iteritems(): if not isinstance(key, basestring): raise botslib.MappingFormatError( _(u'keys must be strings: putloop($mpath)'), mpath=mpaths) if value is None: return False #~ if not isinstance(value,basestring): #~ raise botslib.MappingFormatError(_(u'values must be strings in putloop%s'%(str(mpaths))) part[key] = unicode(value).strip() if self.sameoccurence(mpaths[0]): if len(mpaths) == 1: return self return self._putloopcore(*mpaths[1:]) else: raise botslib.MappingRootError( _(u'error in root putloop "$mpath".'), mpath=mpaths[0])
def put(self,*mpaths,**kwargs): #sanity check of mpaths if not mpaths or not isinstance(mpaths,tuple): raise botslib.MappingFormatError(_(u'Must be dicts in tuple: put(%(mpath)s)'),{'mpath':mpaths}) for part in mpaths: if not isinstance(part,dict): raise botslib.MappingFormatError(_(u'Must be dicts in tuple: put(%(mpath)s)'),{'mpath':mpaths}) if 'BOTSID' not in part: raise botslib.MappingFormatError(_(u'Section without "BOTSID": put(%(mpath)s)'),{'mpath':mpaths}) for key,value in part.iteritems(): if value is None: botsglobal.logmap.debug(u'"None" in put %(mpaths)s.',{'mpaths':unicode(mpaths)}) return False if not isinstance(key,basestring): raise botslib.MappingFormatError(_(u'Keys must be strings: put(%(mpath)s)'),{'mpath':mpaths}) if isinstance(value,list): #empty is not useful, drop it (like None) if not value: botsglobal.logmap.debug(u'Empty list in put %(mpaths)s.',{'mpaths':unicode(mpaths)}) return False else: if kwargs.get('strip',True): part[key] = unicode(value).strip() #leading and trailing spaces are stripped from the values else: part[key] = unicode(value) #used for fixed ISA header of x12 if 'BOTSIDnr' not in part: part['BOTSIDnr'] = u'1' if self._sameoccurence(mpaths[0]): self._putcore(mpaths[1:]) else: raise botslib.MappingRootError(_(u'Error in root put "%(mpath)s".'),{'mpath':mpaths[0]}) botsglobal.logmap.debug(u'"True" for put %(mpaths)s',{'mpaths':unicode(mpaths)}) return True
def change(self,where,change): ''' where: node to find. change is applied to found node uses first matching node for 'where'. ''' self._mpath_sanity_check(where) for part in where: if 'BOTSIDnr' not in part: part['BOTSIDnr'] = u'1' #sanity check 'change' parameter if not isinstance(change,dict): raise botslib.MappingFormatError(_(u'Parameter "change" must be dict: change(where=%(where)s,change=%(change)s)'), {'where':where,'change':change}) change.pop('BOTSID','nep') #remove 'BOTSID' from change. BOTSID can not be changed change.pop('BOTSIDnr','nep') #remove 'BOTSIDnr' from change. BOTSIDnr can not be changed for key,value in change.iteritems(): if not isinstance(key,basestring): raise botslib.MappingFormatError(_(u'Keys in "change" must be strings: change(where=%(where)s,change=%(change)s)'), {'where':where,'change':change}) if not isinstance(value,basestring) and value is not None: #if None, item is deleted raise botslib.MappingFormatError(_(u'Values in "change" must be strings or "None": change(where=%(where)s,change=%(change)s)'), {'where':where,'change':change}) terug = self._changecore(where,change) botsglobal.logmap.debug(u'"%(terug)s" for change(where=%(where)s,change=%(change)s)',{'terug':terug,'where':unicode(where),'change':unicode(change)}) return terug
def sort(self,*mpaths): ''' sort nodes. eg in mappingscript: inn.sort({'BOTSID':'UNH'},{'BOTSID':'LIN','C212.7140':None}) This will sort the LIN segments by article number. ''' if Node.checklevel: self._mpath_sanity_check(mpaths[:-1]) #sanity check of last part of mpaths: None only allowed in last section of Mpath; check last part if not isinstance(mpaths[-1],dict): raise botslib.MappingFormatError(_(u'Must be dicts in tuple: get(%(mpath)s)'),{'mpath':mpaths}) if 'BOTSID' not in mpaths[-1]: raise botslib.MappingFormatError(_(u'Last section without "BOTSID": get(%(mpath)s)'),{'mpath':mpaths}) count = 0 for key,value in mpaths[-1].iteritems(): if not isinstance(key,basestring): raise botslib.MappingFormatError(_(u'Keys must be strings in last section: get(%(mpath)s)'),{'mpath':mpaths}) if value is None: count += 1 elif not isinstance(value,basestring): raise botslib.MappingFormatError(_(u'Values must be strings (or none) in last section: get(%(mpath)s)'),{'mpath':mpaths}) if count > 1: raise botslib.MappingFormatError(_(u'Max one "None" in last section: get(%(mpath)s)'),{'mpath':mpaths}) for part in mpaths: if 'BOTSIDnr' not in part: part['BOTSIDnr'] = u'1' if Node.checklevel == 2: self._mpath_grammar_check(mpaths) comparekey = mpaths[1:] #does not work with checklevel == 2, so temporary set checklevel to 0 remember = Node.checklevel Node.checklevel = 0 try: self.children.sort(key=lambda s: s.get(*comparekey)) finally: Node.checklevel = remember
def get(self,*mpaths): ''' get value of a field in a record from a edi-message mpath is xpath-alike query to identify the record/field function returns 1 value; return None if nothing found. if more than one value can be found: first one is returned starts searching in current node, then deeper ''' if Node.checklevel: self._mpath_sanity_check(mpaths[:-1]) #sanity check of last part of mpaths: None only allowed in last section of Mpath; check last part if not isinstance(mpaths[-1],dict): raise botslib.MappingFormatError(_(u'Must be dicts in tuple: get(%(mpath)s)'),{'mpath':mpaths}) if 'BOTSID' not in mpaths[-1]: raise botslib.MappingFormatError(_(u'Last section without "BOTSID": get(%(mpath)s)'),{'mpath':mpaths}) count = 0 for key,value in mpaths[-1].iteritems(): if not isinstance(key,basestring): raise botslib.MappingFormatError(_(u'Keys must be strings in last section: get(%(mpath)s)'),{'mpath':mpaths}) if value is None: count += 1 elif not isinstance(value,basestring): raise botslib.MappingFormatError(_(u'Values must be strings (or none) in last section: get(%(mpath)s)'),{'mpath':mpaths}) if count > 1: raise botslib.MappingFormatError(_(u'Max one "None" in last section: get(%(mpath)s)'),{'mpath':mpaths}) for part in mpaths: if 'BOTSIDnr' not in part: part['BOTSIDnr'] = u'1' if Node.checklevel == 2: self._mpath_grammar_check(mpaths) terug = self._getcore(mpaths) botsglobal.logmap.debug(u'"%(terug)s" for get%(mpaths)s',{'terug':terug,'mpaths':unicode(mpaths)}) return terug
def put(self, *mpaths, **kwargs): if not mpaths or not isinstance(mpaths, tuple): raise botslib.MappingFormatError( _(u'must be dicts in tuple: put($mpath)'), mpath=mpaths) for part in mpaths: if not isinstance(part, dict): raise botslib.MappingFormatError( _(u'must be dicts in tuple: put($mpath)'), mpath=mpaths) #check: 'BOTSID' is required #check: all values should be strings for part in mpaths: if not 'BOTSID' in part: raise botslib.MappingFormatError( _(u'section without "BOTSID": put($mpath)'), mpath=mpaths) for key, value in part.iteritems(): if value is None: botsglobal.logmap.debug(u'"None" in put %s.', str(mpaths)) return False if not isinstance(key, basestring): raise botslib.MappingFormatError( _(u'keys must be strings: put($mpath)'), mpath=mpaths) if kwargs and 'strip' in kwargs and kwargs['strip'] == False: part[key] = unicode( value) #used for fixed ISA header of x12 else: part[key] = unicode(value).strip( ) #leading and trailing spaces are stripped from the values if self.sameoccurence(mpaths[0]): self._putcore(*mpaths[1:]) else: raise botslib.MappingRootError(_(u'error in root put "$mpath".'), mpath=mpaths[0]) botsglobal.logmap.debug(u'"True" for put %s', str(mpaths)) return True
def get(self, *mpaths): ''' get value of a field in a record from a edi-message mpath is xpath-alike query to identify the record/field function returns 1 value; return None if nothing found. if more than one value can be found: first one is returned starts searching in current node, then deeper ''' if not mpaths or not isinstance(mpaths, tuple): raise botslib.MappingFormatError( _(u'must be dicts in tuple: get($mpath)'), mpath=mpaths) for part in mpaths: if not isinstance(part, dict): raise botslib.MappingFormatError( _(u'must be dicts in tuple: get($mpath)'), mpath=mpaths) #check: None only allowed in last section of Mpath (check firsts sections) #check: 'BOTSID' is required #check: all values should be strings for part in mpaths[:-1]: if not 'BOTSID' in part: raise botslib.MappingFormatError( _(u'section without "BOTSID": get($mpath)'), mpath=mpaths) for key, value in part.iteritems(): if not isinstance(key, basestring): raise botslib.MappingFormatError( _(u'keys must be strings: get($mpath)'), mpath=mpaths) if not isinstance(value, basestring): raise botslib.MappingFormatError( _(u'values must be strings: get($mpath)'), mpath=mpaths) #check: None only allowed in last section of Mpath (check last section) #check: 'BOTSID' is required #check: all values should be strings if not 'BOTSID' in mpaths[-1]: raise botslib.MappingFormatError( _(u'last section without "BOTSID": get($mpath)'), mpath=mpaths) count = 0 for key, value in mpaths[-1].iteritems(): if not isinstance(key, basestring): raise botslib.MappingFormatError( _(u'keys must be strings in last section: get($mpath)'), mpath=mpaths) if value is None: count += 1 elif not isinstance(value, basestring): raise botslib.MappingFormatError(_( u'values must be strings (or none) in last section: get($mpath)' ), mpath=mpaths) if count > 1: raise botslib.MappingFormatError( _(u'max one "None" in last section: get($mpath)'), mpath=mpaths) #go get it! terug = self._getcore(*mpaths) botsglobal.logmap.debug(u'"%s" for get%s', terug, str(mpaths)) return terug
def _mpath_sanity_check(mpaths): ''' sanity check of mpaths. ''' if not isinstance(mpaths,tuple): raise botslib.MappingFormatError(_(u'Parameter mpath must be tuple: %(mpaths)s'),{'mpaths':mpaths}) for part in mpaths: if not isinstance(part,dict): raise botslib.MappingFormatError(_(u'Parameter mpath must be dicts in a tuple: %(mpaths)s'),{'mpaths':mpaths}) if 'BOTSID' not in part: raise botslib.MappingFormatError(_(u'"BOTSID" is required in mpath: %(mpaths)s'),{'mpaths':mpaths}) for key,value in part.iteritems(): if not isinstance(key,basestring): raise botslib.MappingFormatError(_(u'Keys must be strings in mpath: %(mpaths)s'),{'mpaths':mpaths}) if not isinstance(value,basestring): raise botslib.MappingFormatError(_(u'Values must be strings in mpath: getrecord(%(mpaths)s)'),{'mpaths':mpaths})
def enhancedget(self, mpaths, replace=False): ''' to get QUERIES or SUBTRANSLATION while parsing edifile; mpath can be - dict: do get(mpath); can not be a mpath with multiple - tuple: do get(mpath); can be multiple dicts in mapth - list: for each listmembr do a get(); append the results Used by: - QUERIES - SUBTRANSLATION ''' if isinstance(mpaths, dict): return self.get(mpaths) elif isinstance(mpaths, tuple): return self.get(*mpaths) elif isinstance(mpaths, list): collect = u'' for mpath in mpaths: found = self.get(mpath) if found: if replace: found = found.replace('.', '_') collect += found return collect else: raise botslib.MappingFormatError( _(u'must be dict, list or tuple: enhancedget($mpath)'), mpath=mpaths)
def delete(self,*mpaths): ''' delete the last record of mpath if found (first: find/identify record, than delete).''' self._mpath_sanity_check(mpaths) if len(mpaths) == 1: raise botslib.MappingFormatError(_(u'Only one dict: not allowed. Use different solution: delete(%(mpath)s)'),{'mpath':mpaths}) for part in mpaths: if 'BOTSIDnr' not in part: part['BOTSIDnr'] = u'1' terug = bool(self._deletecore(mpaths)) botsglobal.logmap.debug(u'"%(terug)s" for delete%(mpaths)s',{'terug':terug,'mpaths':unicode(mpaths)}) return terug #return False if not removed, return True if removed
def delete(self, *mpaths): ''' delete the last record of mpath if found (first: find/identify, than delete. ''' if not mpaths or not isinstance(mpaths, tuple): raise botslib.MappingFormatError( _(u'must be dicts in tuple: delete($mpath)'), mpath=mpaths) if len(mpaths) == 1: raise botslib.MappingFormatError(_( u'only one dict: not allowed. Use different solution: delete($mpath)' ), mpath=mpaths) #check: None only allowed in last section of Mpath (check firsts sections) #check: 'BOTSID' is required #check: all values should be strings for part in mpaths: if not isinstance(part, dict): raise botslib.MappingFormatError( _(u'must be dicts in tuple: delete($mpath)'), mpath=mpaths) if not 'BOTSID' in part: raise botslib.MappingFormatError( _(u'section without "BOTSID": delete($mpath)'), mpath=mpaths) for key, value in part.iteritems(): if not isinstance(key, basestring): raise botslib.MappingFormatError( _(u'keys must be strings: delete($mpath)'), mpath=mpaths) if not isinstance(value, basestring): raise botslib.MappingFormatError( _(u'values must be strings: delete($mpath)'), mpath=mpaths) #go get it! terug = bool(self._deletecore(*mpaths)) botsglobal.logmap.debug(u'"%s" for delete%s', terug, str(mpaths)) return terug #return False if not removed, return True if removed
def putloop(self,*mpaths): #sanity check of mpaths if not mpaths or not isinstance(mpaths,tuple): raise botslib.MappingFormatError(_(u'Must be dicts in tuple: putloop(%(mpath)s)'),{'mpath':mpaths}) for part in mpaths: if not isinstance(part,dict): raise botslib.MappingFormatError(_(u'Must be dicts in tuple: putloop(%(mpath)s)'),{'mpath':mpaths}) if 'BOTSID' not in part: raise botslib.MappingFormatError(_(u'Section without "BOTSID": putloop(%(mpath)s)'),{'mpath':mpaths}) for key,value in part.iteritems(): if not isinstance(key,basestring): raise botslib.MappingFormatError(_(u'Keys must be strings: putloop(%(mpath)s)'),{'mpath':mpaths}) if value is None: return False part[key] = unicode(value).strip() if 'BOTSIDnr' not in part: part['BOTSIDnr'] = u'1' if self._sameoccurence(mpaths[0]): if len(mpaths)==1: return self return self._putloopcore(mpaths[1:]) else: raise botslib.MappingRootError(_(u'Error in root putloop "%(mpath)s".'),{'mpath':mpaths[0]})
def _mpath_grammar_check(self,mpaths): ''' check of mpaths with grammar. ''' def _mpath_ok_with_grammar(structure,mpaths): ''' inner function, recursive. every part of mpaths should be in structure, at right level, have right fields. ''' mpath = mpaths[0] for record_definition in structure: if record_definition[ID] == mpath['BOTSID'] and record_definition[BOTSIDNR] == mpath['BOTSIDnr']: for key in mpath: if key == 'BOTSIDnr': #BOTSIDnr is not in grammar, so do not check continue for field_definition in record_definition[FIELDS]: if field_definition[ISFIELD]: if key == field_definition[ID]: break #check next key else: if key == field_definition[ID]: #first check compostie-key itself, for repeating composites break #check next key for grammarsubfield in field_definition[SUBFIELDS]: #loop subfields if key == grammarsubfield[ID]: break #check next key else: continue #checking field_defintions break #check next key else: #Not found in record! return False #all fields in mpath are correct; go to next level of mpath.. if mpaths[1:]: if not LEVEL in record_definition: return False return _mpath_ok_with_grammar(record_definition[LEVEL],mpaths[1:]) else: return True #no more levels, all fields found else: return False if not self.structure: return if not _mpath_ok_with_grammar([self.structure],mpaths): raise botslib.MappingFormatError(_(u'Parameter mpath is not valid according to grammar: %(mpaths)s'),{'mpaths':mpaths})
def _canonicalfields(self, node_instance, record_definition): ''' For all fields: check M/C, format. Fields are not sorted (a dict can not be sorted). Fields are never added. ''' noderecord = node_instance.record for field_definition in record_definition[ FIELDS]: #loop over fields in grammar if field_definition[ISFIELD]: #if field (no composite) if field_definition[MAXREPEAT] == 1: #if non-repeating value = noderecord.get(field_definition[ID]) if not value: if field_definition[MANDATORY]: self.add2errorlist( _(u'[F02]%(linpos)s: Record "%(mpath)s" field "%(field)s" is mandatory.\n' ) % { 'linpos': node_instance.linpos(), 'mpath': self.mpathformat(record_definition[MPATH]), 'field': field_definition[ID] }) continue noderecord[field_definition[ID]] = self._formatfield( value, field_definition, record_definition, node_instance) else: #repeating field; #a list of values; values can be empty or None; at least one field should have value, else dropped valuelist = noderecord.get(field_definition[ID]) if valuelist is None: #empty lists are already catched in node.put() if field_definition[MANDATORY]: self.add2errorlist( _(u'[F41]%(linpos)s: Record "%(mpath)s" repeating field "%(field)s" is mandatory.\n' ) % { 'linpos': node_instance.linpos(), 'mpath': self.mpathformat(record_definition[MPATH]), 'field': field_definition[ID] }) continue if not isinstance(valuelist, list): raise botslib.MappingFormatError( _(u'Repeating field: must be a list: put(%(valuelist)s)' ), {'mpath': valuelist}) if len(valuelist) > field_definition[MAXREPEAT]: self.add2errorlist( _(u'[F42]%(linpos)s: Record "%(mpath)s" repeating field "%(field)s" occurs %(occurs)s times, max is %(max)s.\n' ) % { 'linpos': node_instance.linpos(), 'mpath': self.mpathformat( record_definition[MPATH]), 'field': field_definition[ID], 'occurs': len(valuelist), 'max': field_definition[MAXREPEAT] }) newlist = [] repeating_field_has_data = False for value in valuelist: if value is None: value = '' else: value = unicode(value).strip() if value: repeating_field_has_data = True newlist.append( self._formatfield(value, field_definition, record_definition, node_instance)) if not repeating_field_has_data: if field_definition[MANDATORY]: self.add2errorlist( _(u'[F43]%(linpos)s: Record "%(mpath)s" repeating field "%(field)s" is mandatory.\n' ) % { 'linpos': node_instance.linpos(), 'mpath': self.mpathformat(record_definition[MPATH]), 'field': field_definition[ID] }) del noderecord[field_definition[ID]] continue noderecord[field_definition[ID]] = newlist else: #composite if field_definition[MAXREPEAT] == 1: #non-repeating compostie #first check if there is any data att all in this composite for grammarsubfield in field_definition[SUBFIELDS]: if noderecord.get(grammarsubfield[ID]): break #composite has data. else: #composite has no data if field_definition[MANDATORY]: self.add2errorlist( _(u'[F03]%(linpos)s: Record "%(mpath)s" composite "%(field)s" is mandatory.\n' ) % { 'linpos': node_instance.linpos(), 'mpath': self.mpathformat(record_definition[MPATH]), 'field': field_definition[ID] }) continue #there is no data in composite, so do nothing #there is data in the composite! for grammarsubfield in field_definition[ SUBFIELDS]: #loop subfields value = noderecord.get(grammarsubfield[ID]) if not value: if grammarsubfield[MANDATORY]: self.add2errorlist( _(u'[F04]%(linpos)s: Record "%(mpath)s" subfield "%(field)s" is mandatory.\n' ) % { 'linpos': node_instance.linpos(), 'mpath': self.mpathformat( record_definition[MPATH]), 'field': grammarsubfield[ID] }) continue noderecord[grammarsubfield[ID]] = self._formatfield( value, grammarsubfield, record_definition, node_instance) else: #if repeating composite: list of dicts valuelist = noderecord.get(field_definition[ID]) #~ print 'valuelist',valuelist if valuelist is None: #empty lists are catched in node.put() if field_definition[MANDATORY]: self.add2errorlist( _(u'[F44]%(linpos)s: Record "%(mpath)s" repeating composite "%(field)s" is mandatory.\n' ) % { 'linpos': node_instance.linpos(), 'mpath': self.mpathformat(record_definition[MPATH]), 'field': field_definition[ID] }) continue if not isinstance(valuelist, list): raise botslib.MappingFormatError( _(u'Repeating composite: must be a list: put(%(valuelist)s)' ), {'mpath': valuelist}) if len(valuelist) > field_definition[MAXREPEAT]: self.add2errorlist( _(u'[F45]%(linpos)s: Record "%(mpath)s" repeating composite "%(field)s" occurs %(occurs)s times, max is %(max)s.\n' ) % { 'linpos': node_instance.linpos(), 'mpath': self.mpathformat( record_definition[MPATH]), 'field': field_definition[ID], 'occurs': len(valuelist), 'max': field_definition[MAXREPEAT] }) #is a list of composites; each composite is a dict. #loop over composites/dicts, create a new list #- dict can be empty: {}. check if: composite contains data or is empty #- if composite is not-empty, check M/C of elements in composite #- keys should be basestring. #- convert values to unicode #- check if there is data for whole repeating composite newlist = [] repeating_composite_has_data = False for comp in valuelist: if not isinstance(comp, dict): raise botslib.MappingFormatError( _(u'Repeating composite: each composite must be a dict: put(%(valuelist)s)' ), {'mpath': valuelist}) #check each dict, convert values to unicode #also: check if dict has data at all composite_has_data = False for key, value in comp.iteritems(): if not isinstance(key, basestring): raise botslib.MappingFormatError( _(u'Repeating composite: keys must be strings: put(%(mpath)s)' ), {'mpath': valuelist}) if value is None: comp[key] = u'' else: comp[key] = unicode(value).strip( ) #leading and trailing spaces are stripped from the values if comp[key]: composite_has_data = True if composite_has_data: repeating_composite_has_data = True for grammarsubfield in field_definition[ SUBFIELDS]: #loop subfields value = comp.get(grammarsubfield[ID]) if not value: if grammarsubfield[MANDATORY]: self.add2errorlist( _(u'[F46]%(linpos)s: Record "%(mpath)s" subfield "%(field)s" in repeating composite is mandatory.\n' ) % { 'linpos': node_instance.linpos(), 'mpath': self.mpathformat( record_definition[MPATH]), 'field': grammarsubfield[ID] }) continue comp[grammarsubfield[ID]] = self._formatfield( value, grammarsubfield, record_definition, node_instance) else: comp = {} newlist.append(comp) if not repeating_composite_has_data: if field_definition[MANDATORY]: self.add2errorlist( _(u'[F47]%(linpos)s: Record "%(mpath)s" repeating composite "%(field)s" is mandatory.\n' ) % { 'linpos': node_instance.linpos(), 'mpath': self.mpathformat(record_definition[MPATH]), 'field': field_definition[ID] }) del noderecord[field_definition[ID]] else: noderecord[field_definition[ID]] = newlist
def change(self, where, change): ''' ''' #find first matching node using 'where'. Do not look at other matching nodes (is a feature) #prohibit change of BOTSID? mpaths = where #diff from getcore if not mpaths or not isinstance(mpaths, tuple): raise botslib.MappingFormatError(_( u'parameter "where" must be tuple: change(where=$where,change=$change)' ), where=where, change=change) #check: 'BOTSID' is required #check: all values should be strings for part in mpaths: if not isinstance(part, dict): raise botslib.MappingFormatError(_( u'parameter "where" must be dicts in a tuple: change(where=$where,change=$change)' ), where=where, change=change) if not 'BOTSID' in part: raise botslib.MappingFormatError(_( u'section without "BOTSID": change(where=$where,change=$change)' ), where=where, change=change) for key, value in part.iteritems(): if not isinstance(key, basestring): raise botslib.MappingFormatError(_( u'keys must be strings: change(where=$where,change=$change)' ), where=where, change=change) if not isinstance(value, basestring): raise botslib.MappingFormatError(_( u'values must be strings: change(where=$where,change=$change)' ), where=where, change=change) #check change parameter if not change or not isinstance(change, dict): raise botslib.MappingFormatError(_( u'parameter "change" must be dict: change(where=$where,change=$change)' ), where=where, change=change) #remove 'BOTSID' from change. #check: all values should be strings change.pop('BOTSID', 'nep') for key, value in change.iteritems(): if not isinstance(key, basestring): raise botslib.MappingFormatError(_( u'keys in "change" must be strings: change(where=$where,change=$change)' ), where=where, change=change) if not isinstance(value, basestring) and value is not None: raise botslib.MappingFormatError(_( u'values in "change" must be strings or "None": change(where=$where,change=$change)' ), where=where, change=change) #go get it! terug = self._changecore(where, change) botsglobal.logmap.debug(u'"%s" for change(where=%s,change=%s)', terug, str(where), str(change)) return terug