示例#1
0
    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
示例#2
0
 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})
示例#3
0
    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])
示例#4
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
示例#5
0
 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
示例#6
0
 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
示例#7
0
 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
示例#8
0
    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
示例#9
0
 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
示例#10
0
 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})
示例#11
0
 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)
示例#12
0
 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
示例#13
0
 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
示例#14
0
 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]})
示例#15
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})
示例#16
0
    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
示例#17
0
 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