Sat, 08 Jun 2019 01:32:25 +0300
Problem reporting revamp, program is now aware of its problem types
16 | 1 | from warnings import warn |
2 | ||
62
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
3 | class ProblemType: |
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
4 | severities = ['error', 'notice'] # in descending order |
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
5 | def __init__(self, name, severity, message): |
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
6 | if severity not in ProblemType.severities: |
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
7 | raise ValueError(str.format( |
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
8 | 'bad severity {severity!r}', |
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
9 | severity = severity, |
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
10 | )) |
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
11 | self.name = name |
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
12 | self.severity = severity |
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
13 | self.message = message |
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
14 | def __call__(self, bad_object, **args): |
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
15 | return Problem( |
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
16 | problem_class = self, |
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
17 | bad_object = bad_object, |
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
18 | **args, |
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
19 | ) |
13 | 20 | |
62
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
21 | class Problem: |
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
22 | def __init__(self, problem_class, bad_object, **args): |
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
23 | self.problem_class = problem_class |
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
24 | self.severity = problem_class.severity |
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
25 | self.object = bad_object |
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
26 | self.args = args |
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
27 | def __str__(self): |
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
28 | if callable(self.problem_class.message): |
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
29 | return self.problem_class.message(**self.args) |
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
30 | else: |
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
31 | return self.problem_class.message |
16 | 32 | |
62
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
33 | def problem_type(problem_name, **args): |
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
34 | def wrapper(function): |
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
35 | if not hasattr(function, 'ldcheck_problem_types'): |
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
36 | function.ldcheck_problem_types = {} |
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
37 | new_type = ProblemType(name = problem_name, **args) |
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
38 | function.ldcheck_problem_types[problem_name] = new_type |
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
39 | return function |
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
40 | return wrapper |
16 | 41 | |
62
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
42 | def report_problem(problem_name, *, bad_object, **args): |
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
43 | return {'type': problem_name, 'bad-object': bad_object, 'args': args} |
32
75f44d3063da
Reworked web front, problems are now sorted by category as well as line number
Santeri Piippo
parents:
29
diff
changeset
|
44 | |
37
e46fa477007b
Fix operation under Python 3.4
Teemu Piippo <teemu@hecknology.net>
parents:
32
diff
changeset
|
45 | def name_of_package(package): |
e46fa477007b
Fix operation under Python 3.4
Teemu Piippo <teemu@hecknology.net>
parents:
32
diff
changeset
|
46 | if isinstance(package, tuple): |
e46fa477007b
Fix operation under Python 3.4
Teemu Piippo <teemu@hecknology.net>
parents:
32
diff
changeset
|
47 | return package[1] |
e46fa477007b
Fix operation under Python 3.4
Teemu Piippo <teemu@hecknology.net>
parents:
32
diff
changeset
|
48 | else: |
e46fa477007b
Fix operation under Python 3.4
Teemu Piippo <teemu@hecknology.net>
parents:
32
diff
changeset
|
49 | return package.name |
e46fa477007b
Fix operation under Python 3.4
Teemu Piippo <teemu@hecknology.net>
parents:
32
diff
changeset
|
50 | |
16 | 51 | def test_discovery(): |
52 | ''' | |
53 | Finds all test modules and yields their names. | |
54 | ''' | |
55 | from pkgutil import walk_packages | |
56 | import tests | |
57 | yield from sorted( | |
37
e46fa477007b
Fix operation under Python 3.4
Teemu Piippo <teemu@hecknology.net>
parents:
32
diff
changeset
|
58 | 'tests.' + name_of_package(result) |
16 | 59 | for result in walk_packages(tests.__path__) |
60 | ) | |
61 | ||
62 | def load_tests(): | |
63 | ''' | |
64 | Imports test modules and combines their manifests into a test suite. | |
65 | ''' | |
62
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
66 | test_suite = {'tests': []} |
16 | 67 | for module_name in test_discovery(): |
68 | from importlib import import_module | |
69 | module = import_module(module_name) | |
70 | if hasattr(module, 'manifest'): | |
71 | # Merge the data from the manifest | |
62
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
72 | test_suite['tests'] += module.manifest['tests'] |
16 | 73 | else: |
74 | warn(str.format('Module {} does not have a manifest', module_name)) | |
62
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
75 | test_suite['tests'].sort(key = lambda f: f.__name__) |
16 | 76 | return test_suite |
77 | ||
32
75f44d3063da
Reworked web front, problems are now sorted by category as well as line number
Santeri Piippo
parents:
29
diff
changeset
|
78 | def problem_key(problem): |
62
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
79 | rank = ProblemType.severities.index(problem.severity) # sort by severity |
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
80 | return (rank, problem.line_number) |
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
81 | |
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
82 | def build_problem(test_function, problem_params): |
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
83 | problem_name = problem_params['type'] |
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
84 | problem_type = test_function.ldcheck_problem_types[problem_name] |
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
85 | problem_object = problem_type( |
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
86 | bad_object = problem_params['bad-object'], |
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
87 | **problem_params['args'], |
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
88 | ) |
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
89 | return problem_object |
32
75f44d3063da
Reworked web front, problems are now sorted by category as well as line number
Santeri Piippo
parents:
29
diff
changeset
|
90 | |
17 | 91 | def check_model(model, test_suite = None): |
92 | if not test_suite: | |
93 | test_suite = load_tests() | |
32
75f44d3063da
Reworked web front, problems are now sorted by category as well as line number
Santeri Piippo
parents:
29
diff
changeset
|
94 | problems = [] |
17 | 95 | line_numbers = { |
47
4da025d0b283
added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
37
diff
changeset
|
96 | element: (i, i + 1) |
17 | 97 | for i, element in enumerate(model.body) |
98 | } | |
62
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
99 | for test_function in test_suite['tests']: |
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
100 | for problem_params in test_function(model): |
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
101 | problem = build_problem(test_function, problem_params) |
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
102 | # add line numbers to the problem |
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
103 | problem.body_index, problem.line_number \ |
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
104 | = line_numbers[problem.object] |
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
105 | problem.object = None |
32
75f44d3063da
Reworked web front, problems are now sorted by category as well as line number
Santeri Piippo
parents:
29
diff
changeset
|
106 | problems.append(problem) |
75f44d3063da
Reworked web front, problems are now sorted by category as well as line number
Santeri Piippo
parents:
29
diff
changeset
|
107 | return { |
75f44d3063da
Reworked web front, problems are now sorted by category as well as line number
Santeri Piippo
parents:
29
diff
changeset
|
108 | 'passed': not any( |
62
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
109 | problem.severity == 'error' |
32
75f44d3063da
Reworked web front, problems are now sorted by category as well as line number
Santeri Piippo
parents:
29
diff
changeset
|
110 | for problem in problems |
75f44d3063da
Reworked web front, problems are now sorted by category as well as line number
Santeri Piippo
parents:
29
diff
changeset
|
111 | ), |
75f44d3063da
Reworked web front, problems are now sorted by category as well as line number
Santeri Piippo
parents:
29
diff
changeset
|
112 | 'problems': sorted(problems, key = problem_key), |
75f44d3063da
Reworked web front, problems are now sorted by category as well as line number
Santeri Piippo
parents:
29
diff
changeset
|
113 | } |
17 | 114 | |
29 | 115 | def problem_text(problem, test_suite): |
62
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
116 | message = problem.problem_class.message |
29 | 117 | if callable(message): |
62
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
118 | message = message(**problem.args) |
29 | 119 | return message |
120 | ||
121 | def format_report_html(report, model, test_suite): | |
32
75f44d3063da
Reworked web front, problems are now sorted by category as well as line number
Santeri Piippo
parents:
29
diff
changeset
|
122 | messages = [] |
75f44d3063da
Reworked web front, problems are now sorted by category as well as line number
Santeri Piippo
parents:
29
diff
changeset
|
123 | for problem in report['problems']: |
62
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
124 | ldraw_code = model.body[problem.body_index].textual_representation() |
29 | 125 | message = str.format( |
126 | '<li class="{problem_type}">{model_name}:{line_number}:' | |
127 | '{problem_type}: {message}<br />{ldraw_code}</li>', | |
128 | model_name = model.name, | |
62
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
129 | line_number = problem.line_number, |
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
130 | problem_type = problem.severity, |
29 | 131 | message = problem_text(problem, test_suite), |
132 | ldraw_code = ldraw_code, | |
133 | ) | |
32
75f44d3063da
Reworked web front, problems are now sorted by category as well as line number
Santeri Piippo
parents:
29
diff
changeset
|
134 | messages.append(message) |
75f44d3063da
Reworked web front, problems are now sorted by category as well as line number
Santeri Piippo
parents:
29
diff
changeset
|
135 | return '\n'.join(messages) |
29 | 136 | |
17 | 137 | def format_report(report, model, test_suite): |
18 | 138 | import colorama |
139 | colorama.init() | |
32
75f44d3063da
Reworked web front, problems are now sorted by category as well as line number
Santeri Piippo
parents:
29
diff
changeset
|
140 | messages = [] |
75f44d3063da
Reworked web front, problems are now sorted by category as well as line number
Santeri Piippo
parents:
29
diff
changeset
|
141 | for problem in report['problems']: |
62
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
142 | if problem.severity == 'error': |
18 | 143 | text_colour = colorama.Fore.LIGHTRED_EX |
62
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
144 | elif problem.severity == 'notice': |
32
75f44d3063da
Reworked web front, problems are now sorted by category as well as line number
Santeri Piippo
parents:
29
diff
changeset
|
145 | text_colour = colorama.Fore.LIGHTBLUE_EX |
18 | 146 | else: |
147 | text_colour = '' | |
62
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
148 | ldraw_code = model.body[problem.body_index].textual_representation() |
17 | 149 | message = str.format( |
18 | 150 | '{text_colour}{model_name}:{line_number}: {problem_type}: {message}' |
19 | 151 | '{colour_reset}\n\t{ldraw_code}', |
18 | 152 | text_colour = text_colour, |
153 | model_name = model.name, | |
62
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
154 | line_number = problem.line_number, |
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
155 | problem_type = problem.severity, |
29 | 156 | message = problem_text(problem, test_suite), |
18 | 157 | colour_reset = colorama.Fore.RESET, |
19 | 158 | ldraw_code = ldraw_code, |
17 | 159 | ) |
32
75f44d3063da
Reworked web front, problems are now sorted by category as well as line number
Santeri Piippo
parents:
29
diff
changeset
|
160 | messages.append(message) |
75f44d3063da
Reworked web front, problems are now sorted by category as well as line number
Santeri Piippo
parents:
29
diff
changeset
|
161 | return '\n'.join(messages) |
17 | 162 | |
62
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
163 | def all_warning_types(test_suite): |
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
164 | for test_function in test_suite['tests']: |
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
165 | yield from test_function.ldcheck_problem_types.values() |
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
166 | |
16 | 167 | if __name__ == '__main__': |
168 | from pprint import pprint | |
169 | pprint(load_tests()) |