diff options
author | 2023-02-26 16:47:00 +0600 | |
---|---|---|
committer | 2023-02-26 16:58:33 +0600 | |
commit | 95f4ac3b93577904db02b4ddc74434cb07b59521 (patch) | |
tree | 6e4d141a85638f79171a65d68c25c5f20b90c5f4 /validate-csv-data | |
download | distro-info-data-shopno-95f4ac3b93577904db02b4ddc74434cb07b59521.tar.gz distro-info-data-shopno-95f4ac3b93577904db02b4ddc74434cb07b59521.zip |
Initial releasedebian/0.1
Signed-off-by: Mubashshir <ahm@jadupc.com>
Diffstat (limited to '')
-rwxr-xr-x | validate-csv-data | 158 |
1 files changed, 158 insertions, 0 deletions
diff --git a/validate-csv-data b/validate-csv-data new file mode 100755 index 0000000..397b2c4 --- /dev/null +++ b/validate-csv-data @@ -0,0 +1,158 @@ +#!/usr/bin/python + +# Copyright (C) 2012, Benjamin Drung <bdrung@debian.org> +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""Validates a given Debian or Ubuntu distro-info CSV file.""" + +import csv +import datetime +import optparse +import os +import sys + +_COLUMNS = { + "debian": ("version", "codename", "series", "created", "release", "eol"), + "ubuntu": ("version", "codename", "series", "created", "release", "eol", + "eol-server"), +} +_DATES = ("created", "release", "eol", "eol-server") +_EARLIER_DATES = ( + ("created", "release"), + ("release", "eol"), + ("eol", "eol-server"), +) +_STRINGS = { + "debian": ("codename", "series"), + "ubuntu": ("version", "codename", "series"), +} + +def convert_date(string): + """Convert a date string in ISO 8601 into a datetime object.""" + if not string: + date = None + else: + parts = [int(x) for x in string.split("-")] + if len(parts) == 3: + (year, month, day) = parts + date = datetime.date(year, month, day) + else: + raise ValueError("Date not in ISO 8601 format.") + return date + +def error(filename, line, message, *args): + """Prints an error message""" + print >> sys.stderr, "%s:%i: %s." % (filename, line, message % args) + +def validate(filename, distro): + """Validates a given CSV file. + + Returns True if the given CSV file is valid and otherwise False. + """ + failures = 0 + content = open(filename).readlines() + # Remove comments + for line in xrange(len(content)): + if content[line].startswith("#"): + content[line] = "\n" + csvreader = csv.DictReader(content) + for row in csvreader: + # Check for missing columns + for column in _COLUMNS[distro]: + if not column in row: + msg = "Column `%s' is missing" + error(filename, csvreader.line_num, msg, column) + failures += 1 + # Check for additinal columns + for column in row: + if not column in _COLUMNS[distro]: + msg = "Additional column `%s' is specified" + error(filename, csvreader.line_num, msg, column) + failures += 1 + # Check required strings columns + for column in _STRINGS[distro]: + if column in row and not row[column]: + msg = "Empty column `%s' specified" + error(filename, csvreader.line_num, msg, column) + failures += 1 + # Check dates + for column in _DATES: + if column in row: + try: + row[column] = convert_date(row[column]) + except ValueError: + msg = "Invalid date `%s' in column `%s'" + error(filename, csvreader.line_num, msg, row[column], + column) + failures += 1 + row[column] = None + # Check required date columns + column = "created" + if column in row and not row[column]: + msg = "No date specified in column `%s'" + error(filename, csvreader.line_num, msg, column) + failures += 1 + # Compare dates + for (date1, date2) in _EARLIER_DATES: + if date2 in row and row[date2]: + if date1 in row and row[date1]: + # date1 needs to be earlier than date2 + if row[date1] >= row[date2]: + msg = ("Date %s of column `%s' needs to be later " + "than %s of column `%s'") + error(filename, csvreader.line_num, msg, + row[date2].isoformat(), date2, + row[date1].isoformat(), date1) + failures += 1 + else: + # date1 needs to be specified if date1 is specified + msg = ("A date needs to be specified in column `%s' due " + "to the given date in column `%s'") + error(filename, csvreader.line_num, msg, date1, date2) + failures += 1 + + return failures == 0 + +def main(): + """Main function with command line parameter parsing.""" + script_name = os.path.basename(sys.argv[0]) + usage = "%s -d|-u csv-file" % (script_name) + parser = optparse.OptionParser(usage=usage) + + parser.add_option("-d", "--debian", dest="debian", action="store_true", + default=False, help="validate a Debian CSV file") + parser.add_option("-u", "--ubuntu", dest="ubuntu", action="store_true", + default=False, help="validate an Ubuntu CSV file") + + (options, args) = parser.parse_args() + + if len(args) == 0: + parser.error("No CSV file specified.") + elif len(args) > 1: + parser.error("Multiple CSV files specified: %s" % (", ".join(args))) + + if len([x for x in [options.debian, options.ubuntu] if x]) != 1: + parser.error("You have to select exactly one of --debian, --ubuntu.") + if options.debian: + distro = "debian" + else: + distro = "ubuntu" + + if validate(args[0], distro): + return 0 + else: + return 1 + +if __name__ == "__main__": + sys.exit(main()) |