Navigation


Changeset 1487:5c2d061a8c8e in freeDiameter for contrib


Ignore:
Timestamp:
Mar 27, 2020, 1:32:27 PM (4 years ago)
Author:
Luke Mewburn <luke@mewburn.net>
Branch:
default
Phase:
public
Message:

csv_to_fd: improve validation

When an AVP Code or Name is duplicate, differentiate
between a duplicate entry (AVPs are equivalent)
versus an actual mismatch.

Consistent AVP formatting in errors.

Collect all errors and display at end of each file parse,
instead of exiting on first error.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • contrib/tools/csv_to_fd

    r1479 r1487  
    122122                'Unsigned64', 'Float32', 'Float64', 'Grouped')
    123123                and self.datatype not in DERIVED_TO_BASE):
    124             raise ValueError('AVP "{}" invalid data type "{}"'.format(
    125                 self.name, self.datatype))
     124            raise ValueError('{} invalid data type "{}"'.format(
     125                self.description(), self.datatype))
    126126        # Validate flags
    127127        flags = collections.Counter()
     
    133133                ]:
    134134            if not self._flags_re.match(val):
    135                 raise ValueError('AVP "{}" invalid {} Flags "{}"'.format(
    136                     self.name, desc, val))
     135                raise ValueError('{} invalid {} Flags "{}"'.format(
     136                    self.description(), desc, val))
    137137            flags.update(val)
    138138        # Check occurrence of M,V in Must,May,ShouldNot,MustNot
     
    140140            # TODO: can AVP flags not appear at all?
    141141            # if flags[flag] == 0:
    142             #     raise ValueError('AVP "{}" Flag "{}" not set'.format(
    143             #         self.name, flag))
     142            #     raise ValueError('{} Flag "{}" not set'.format(
     143            #         self.description(), flag))
    144144            if flags[flag] > 1:
    145                 raise ValueError('AVP "{}" Flag "{}" set {} times'.format(
    146                     self.name, flag, flags[flag]))
     145                raise ValueError('{} Flag "{}" set {} times'.format(
     146                    self.description(), flag, flags[flag]))
    147147        # Compare V presence against vendor
    148148        if 'V' in self.must:
    149149            if self.vendor == 0:
    150                 raise ValueError('AVP "{}" Flag "V" set for vendor 0'.format(
    151                     self.name))
     150                raise ValueError('{} Flag "V" set for vendor 0'.format(
     151                    self.description()))
    152152        else:
    153153            if self.vendor != 0:
    154                 raise ValueError(
    155                     'AVP "{}" Flag "V" not set for vendor {}'.format(
    156                         self.name, self.vendor))
     154                raise ValueError('{} Flag "V" not set for vendor {}'.format(
     155                    self.description(), self.vendor))
    157156
    158157    @property
    159158    def __dict__(self):
    160159        return {s: getattr(self, s) for s in self.__slots__}
     160
     161    def __eq__(self, other):
     162        """Equality comparison of Avp instances.
     163        Considered equal if name, vendor, code, datatype, and flags are equal.
     164        """
     165        if other is self:
     166            return True
     167        if type(other) is not type(self):
     168            return NotImplemented
     169        return (
     170            other.name, other.vendor, other.code, other.datatype,
     171            other.must, other.may, other.shouldnot, other.mustnot,
     172            ) == (
     173            self.name, self.vendor, self.code, self.datatype,
     174            self.must, self.may, self.shouldnot, self.mustnot,
     175            )
     176
     177    def __ne__(self, other):
     178        return not self == other
     179
     180    def description(self):
     181        return 'AVP "{}" ({})'.format(self.name, self.code)
    161182
    162183
     
    393414
    394415
     416def avp_conflict(description, avp, conflict):
     417    """Raise error for duplicate or conflicting AVPs.
     418    """
     419    if avp == conflict:
     420        raise ValueError(
     421            '{} {} duplicated in'
     422            ' file "{}" line {}'.format(
     423                avp.description(), description,
     424                conflict.filename, conflict.line_num))
     425    else:
     426        raise ValueError(
     427            '{} {} conflicts with {}'
     428            ' in file "{}" line {}'.format(
     429                avp.description(), description,
     430                conflict.description(),
     431                conflict.filename, conflict.line_num))
     432
     433
    395434def main():
     435    """Main application entry.
     436    """
    396437
    397438    # Build dict of name: NameProcessor
     
    454495            standard = ''
    455496            vendor = 0
     497            errors = []
    456498            for row in csvdata:
    457499                try:
     
    480522                        if avp.code in avp_codes[avp.vendor]:
    481523                            conflict = avp_codes[avp.vendor][avp.code]
    482                             raise ValueError(
    483                                 'AVP vendor {} code {} already present'
    484                                 ' in file "{}" line {}'.format(
    485                                     avp.vendor, avp.code,
    486                                     conflict.filename, conflict.line_num))
     524                            avp_conflict('Code', avp, conflict)
    487525                        avp_codes[avp.vendor][avp.code] = avp
    488526                        # Ensure AVP vendor/name not already defined
    489527                        if avp.name in avp_names[avp.vendor]:
    490528                            conflict = avp_names[avp.vendor][avp.name]
    491                             raise ValueError(
    492                                 'AVP vendor {} name "{}" already present'
    493                                 ' in file "{}" line {}'.format(
    494                                     avp.vendor, avp.name,
    495                                     conflict.filename, conflict.line_num))
     529                            avp_conflict('Name', avp, conflict)
    496530                        avp_names[avp.vendor][avp.name] = avp
    497531                        # Process AVP
    498532                        avpproc.avp(avp)
    499533                except ValueError as e:
    500                     sys.stderr.write('CSV file "{}" line {}: {}\n'.format(
     534                    errors.append('CSV file "{}" line {}: {}\n'.format(
    501535                        filename, csvdata.line_num, e))
    502                     sys.exit(1)
     536            if errors:
     537                sys.stderr.write(''.join(errors))
     538                sys.exit(1)
    503539
    504540    # Generate result
Note: See TracChangeset for help on using the changeset viewer.