File: check_parse_and_dump.py

package info (click to toggle)
python-debian 1.1.0
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,272 kB
  • sloc: python: 13,612; makefile: 239; sh: 25
file content (118 lines) | stat: -rwxr-xr-x 4,218 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#!/usr/bin/python3

# vim: fileencoding=utf-8
#
# Copyright (C) 2014       Google, Inc.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation, either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

"""Check the format and dumpability of debian/copyright filenames on stdin.

Usage:

    find /tmp/packages -type f -name copyright | ./check_parse_and_dump.py

The --suppress_warnings and --summary flags can be used to make the program
output less verbose.
"""

import argparse
import codecs
import sys
from typing import Any
import warnings

from debian import copyright


def parse_args() -> argparse.Namespace:
    parser = argparse.ArgumentParser()
    parser.add_argument('--summary', action='store_true',
                        help='Whether to print only a summary')
    parser.add_argument('--suppress_warnings', action='store_true',
                        help='Whether to suppress copyright warnings')
    return parser.parse_args()


def main() -> None:
    args = parse_args()

    if args.suppress_warnings:
        warnings.filterwarnings('ignore', module='debian.copyright')

    problems: dict[tuple[int, str], list[tuple[str, Any]]] = {}

    total = 0
    for filename in sys.stdin:
        total += 1
        filename = filename.rstrip()
        with open(filename, encoding='utf-8') as f:
            try:
                c = copyright.Copyright(f)
            except Exception as e:
                problems.setdefault((1, 'Parse failures'), []).append(
                    (filename, e))
                continue

            try:
                c.dump()
            except Exception as e:
                problems.setdefault((2, 'Dump failures'), []).append(
                    (filename, e))

            if not c.header.known_format():
                problems.setdefault((3, 'Unknown format'), []).append(
                    (filename, c.header.format))

            invalid_globs = []
            globs_with_leading_dot_slash = []
            globs_with_trailing_comma = []
            globs_with_double_star = []
            for p in c.all_files_paragraphs():
                try:
                    p.files_pattern()
                except Exception as e:
                    invalid_globs.append(e)
                for glob in p.files:
                    if glob.startswith('./'):
                        globs_with_leading_dot_slash.append(glob)
                    if glob.endswith(','):
                        globs_with_trailing_comma.append(glob)
                    if '**' in glob:
                        globs_with_double_star.append(glob)

            if invalid_globs:
                problems.setdefault((4, 'Invalid glob'), []).append(
                    (filename, invalid_globs))
            if globs_with_leading_dot_slash:
                problems.setdefault((5, 'Globs with leading ./'), []).append(
                    (filename, globs_with_leading_dot_slash))
            if globs_with_trailing_comma:
                problems.setdefault((6, 'Globs with trailing ,'), []).append(
                    (filename, globs_with_trailing_comma))
            if globs_with_double_star:
                problems.setdefault((7, 'Globs with **'), []).append(
                    (filename, globs_with_double_star))

    f_out = codecs.getwriter(encoding='utf-8')(sys.stdout)
    for (_, heading), details in sorted(problems.items()):
        f_out.write(f"\n{heading}: ({len(details)} / {total})\n")
        if not args.summary:
            for filename, problem in details:
                f_out.write(f" {filename}: {problem}\n")


if __name__ == '__main__':
    main()