forked from KabaevRoman/flake8-copyright-validator
-
Notifications
You must be signed in to change notification settings - Fork 0
/
flake8_copyright_validator.py
125 lines (117 loc) · 4.65 KB
/
flake8_copyright_validator.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
import difflib
import re
from typing import List, Tuple
import importlib_metadata
class CopyrightValidator:
name = __name__
version = importlib_metadata.version(__name__)
copyright_text_list: List[str] = None
custom_escape_sequences: List[Tuple[str, str]] = None
detailed_output: bool = False
update: bool = False
copyright_text: str = None
bytes_to_read: int = 2048
lines_to_exclude = []
symbols_to_replace = ["'"]
def __init__(self, tree, filename) -> None:
self._tree = tree
self._filename = filename
@classmethod
def add_options(cls, parser):
parser.add_option(
'--copyright-text',
help='a text to look for in files',
parse_from_config=True,
)
parser.add_option(
'--copyright-regex',
help='a text to look for in files',
parse_from_config=True,
)
parser.add_option(
'--update',
help='defines if files should be updated with provided copyright text',
action='store_true'
)
parser.add_option(
'--detailed-output',
help='provides detailed output',
action='store_true',
parse_from_config=True,
)
parser.add_option(
'--bytes-to-read',
type=int,
help='number of bytes to read',
parse_from_config=True,
)
parser.add_option(
'--lines-to-exclude',
help='exclude file if line from list found as first line',
parse_from_config=True,
)
parser.add_option(
'--symbols-to-replace',
comma_separated_list=True,
help='symbols you wrap your copyright text with that will be replaced',
parse_from_config=True,
)
@classmethod
def parse_options(cls, manager, options, files):
cls.detailed_output = options.detailed_output
cls.update = options.update
if options.symbols_to_replace:
cls.symbols_to_replace = options.symbols_to_replace
if options.lines_to_exclude:
cls.lines_to_exclude = cls._parse_lines(options.lines_to_exclude, cls.symbols_to_replace)
if options.copyright_text:
cls.copyright_text_list = cls._parse_lines(options.copyright_text, cls.symbols_to_replace)
cls.copyright_text = '\n'.join(cls.copyright_text_list)
if options.copyright_regex:
cls.copyright_regex = cls._parse_lines(options.copyright_regex, cls.symbols_to_replace)
if options.bytes_to_read:
cls.bytes_to_read = options.bytes_to_read
def run(self):
license_lines = self.copyright_text_list
diff = None
with open(self._filename, 'r+') as w:
if self.update:
content = w.read()
else:
content = w.read(self.bytes_to_read)
lines = content.split('\n')
if not lines:
return
for excluded_line in self.lines_to_exclude:
if lines[0].startswith(excluded_line):
return
if self.copyright_regex is not None:
if len(self.copyright_regex) > len(lines):
yield 1, 0, "NCF101 Copyright length mismatch", type(self)
return
for i in range(0, len(self.copyright_regex)):
line = lines[i]
regex = self.copyright_regex[i]
if not re.search(regex, line):
err_msg = f'NCF102 Copyright regex mismatch\n{line if self.detailed_output else ""}'
yield 1, 0, err_msg, type(self)
return
else:
if lines[0:len(license_lines)] != license_lines:
diff = '\n'.join(
[line for line in difflib.unified_diff(license_lines, lines[0:len(license_lines)])])
err_msg = f'NCF100 No copyright found\n{diff if self.detailed_output else ""}'
yield 1, 0, err_msg, type(self)
if self.update and diff:
content = self.copyright_text + '\n' + content
w.seek(0)
w.write(content)
@staticmethod
def _parse_lines(lines_from_options, symbols_to_replace=None) -> List[str]:
if not symbols_to_replace:
symbols_to_replace = []
for symbol_to_replace in symbols_to_replace:
lines_from_options = lines_from_options.replace(symbol_to_replace, '')
lines = lines_from_options.split('\n')
lines.remove('')
return lines