This repository has been archived by the owner on Mar 6, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
copyright_checker.py
140 lines (118 loc) · 6.05 KB
/
copyright_checker.py
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# Wildland Project
#
# Copyright (C) 2021 Golem Foundation
#
# Authors:
# Aleksander Kapera <aleksander.kapera@besidethepark.com>
#
# 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 3 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, see <https://www.gnu.org/licenses/>.
#
# SPDX-License-Identifier: GPL-3.0-or-later
"""
Custom checker extension for pylint. Checks if file has correctly formatted copyright
header on the top of the file.
Provides disable keywords which include:
* copyright-violation = doesn't check for copyright notice at all
* copyright-formatting = doesn't check if copyright is correctly formatted only if it exists
* copyright-author-formatting = ignores if a list of authors is incorrectly formatted
"""
import re
from io import BufferedReader
from pylint.interfaces import IRawChecker
from pylint.checkers import BaseChecker
class CopyrightChecker(BaseChecker):
__implements__ = IRawChecker
name = 'copyright-checker'
COPYRIGHT_VIOLATION = 'copyright-violation'
COPYRIGHT_FORMATTING = 'copyright-formatting'
COPYRIGHT_AUTHOR_FORMATTING = 'copyright-author-formatting'
msgs = {
'C5001': ('No copyright message provided',
COPYRIGHT_VIOLATION,
'Each .py file should contain copyright message at the top'),
'C5002': ('Incorrect copyright message format at line: "%s". Expected format: "%s"',
COPYRIGHT_FORMATTING,
'Correct formatting can be found in copyright_template file'),
'C5003': ('Incorrect copyright author format at line: "%s". Example of correct author '
'line: #\t\tJoe Doe <joe@doe.com>',
COPYRIGHT_AUTHOR_FORMATTING,
'Correct formatting can be found in copyright_template file'),
}
options = ()
priority = -1
def process_module(self, node):
"""
If node doesn't contain disable comment, check if file has correctly formatted copyright
notice.
"""
# ignore __init__.py files, it cannot be implemented in .pylintrc file because disabling
# checks for that file doesn't work
if re.search(r'__init__\.py$', node.file) is None:
with node.stream() as file_stream, open('copyright_template', 'r') as template_stream:
file_index, template_index = 0, 0
template_lines = template_stream.readlines()
file_line = file_stream.readline().decode('utf-8')
pylint_disable_regex = f'# pylint:.*disable=.*({self.COPYRIGHT_VIOLATION}|'\
f'{self.COPYRIGHT_FORMATTING}|'\
f'{self.COPYRIGHT_AUTHOR_FORMATTING})'
if re.match(pylint_disable_regex, file_line):
# contains copyright disable comment, skip check
return
if file_line.strip() == '#!/usr/bin/env python3':
file_line = file_stream.readline().decode('utf-8')
file_index += 1
while template_index < len(template_lines):
template_line = template_lines[template_index]
if template_line.strip() == '# Authors:':
if file_line.strip() != '# Authors:':
# copyright header doesn't have any authors, skip check
template_index += 3
template_line = template_lines[template_index]
else:
template_index += 1
file_index, template_index = self.check_authors(file_stream,
template_lines,
file_index,
template_index)
if template_line.strip() != '# Authors:':
matched = re.match(template_line, file_line)
args = file_line, template_line.strip()
if matched is None:
if template_index != 0:
# copyright notice is incorrectly formatted
self.add_message(self.COPYRIGHT_FORMATTING,
line=file_index,
args=args)
else:
# file doesn't have copyright notice
self.add_message(self.COPYRIGHT_VIOLATION, line=0)
break
file_line = file_stream.readline().decode('utf-8')
file_index += 1
template_index += 1
def check_authors(self, file_stream: BufferedReader, template_lines: [str], file_index: int,
template_index: int):
"""
Check if 'authors' section of a copyright notice is correctly formatted.
"""
file_line = file_stream.readline().decode('utf-8')
template_line = template_lines[template_index]
while "#" != file_line.strip():
if re.match(template_line, file_line) is None:
self.add_message(self.COPYRIGHT_AUTHOR_FORMATTING, line=file_index, args=file_line)
file_index += 1
file_line = file_stream.readline().decode('utf-8')
return file_index, template_index + 1
def register(linter):
linter.register_checker(CopyrightChecker(linter))