39 reason = element.reason |
39 reason = element.reason |
40 ) |
40 ) |
41 for element in model.body |
41 for element in model.body |
42 if isinstance(element, linetypes.Error) |
42 if isinstance(element, linetypes.Error) |
43 ) |
43 ) |
44 |
|
45 @problem_type('bad-header', |
|
46 severity = 'hold', |
|
47 message = lambda reason: str.format('bad header: {}', reason), |
|
48 ) |
|
49 @problem_type('no-license-set', |
|
50 severity = 'hold', |
|
51 message = 'no license set', |
|
52 ) |
|
53 @problem_type('non-ca-license', |
|
54 severity = 'hold', |
|
55 message = 'no new non-CA-submits are accepted', |
|
56 ) |
|
57 def bad_header(model): |
|
58 import header |
|
59 ca_license = 'Redistributable under CCAL version 2.0 : see CAreadme.txt' |
|
60 if isinstance(model.header, header.BadHeader): |
|
61 yield report_problem( |
|
62 'bad-header', |
|
63 bad_object = model.body[model.header.index], |
|
64 reason = model.header.reason, |
|
65 ) |
|
66 elif not model.header.license: |
|
67 yield report_problem( |
|
68 'no-license-set', |
|
69 bad_object = model.body[0], |
|
70 ) |
|
71 elif model.header.license != ca_license: |
|
72 yield report_problem( |
|
73 'non-ca-license', |
|
74 bad_object = model.find_first_header_object('license'), |
|
75 ) |
|
76 |
|
77 @problem_type('bfc-nocertify', |
|
78 severity = 'hold', |
|
79 message = 'all new parts must be BFC certified', |
|
80 ) |
|
81 def nocertify_test(model): |
|
82 import header |
|
83 if model.header.valid and model.header.bfc == 'NOCERTIFY': |
|
84 yield report_problem( |
|
85 'bfc-nocertify', |
|
86 bad_object = model.find_first_header_object('bfc'), |
|
87 ) |
|
88 |
|
89 @problem_type('physical-colour-part', |
|
90 severity = 'hold', |
|
91 message = 'no new physical colour parts are accepted', |
|
92 ) |
|
93 def physical_colours_test(model): |
|
94 if model.header.valid and 'Physical_Colour' in model.header.qualifiers: |
|
95 yield report_problem( |
|
96 'physical-colour-part', |
|
97 bad_object = model.find_first_header_object('part type'), |
|
98 ) |
|
99 |
|
100 @problem_type('unofficial-part', |
|
101 severity = 'hold', |
|
102 message = 'new parts must be unofficial', |
|
103 ) |
|
104 def unofficiality_test(model): |
|
105 if model.header.valid and not model.header.filetype.startswith('Unofficial_'): |
|
106 yield report_problem( |
|
107 'unofficial-part', |
|
108 bad_object = model.find_first_header_object('part type') |
|
109 ) |
|
110 |
|
111 @problem_type('primitive-ccw', |
|
112 severity = 'hold', |
|
113 message = 'primitives must have CCW winding', |
|
114 ) |
|
115 @problem_type('no-bfc-line', |
|
116 severity = 'hold', |
|
117 message = 'BFC declaration is missing', |
|
118 ) |
|
119 def header_bfc_test(model): |
|
120 if model.header.valid and not model.header.bfc: |
|
121 yield report_problem( |
|
122 'no-bfc-line', |
|
123 bad_object = model.body[0], |
|
124 ) |
|
125 elif model.header.valid \ |
|
126 and model.header.filetype.endswith('Primitive') \ |
|
127 and model.header.bfc != 'CERTIFY CCW': |
|
128 yield report_problem( |
|
129 'primitive-bfc-ccw', |
|
130 bad_object = model.find_first_header_object('bfc'), |
|
131 ) |
|
132 |
|
133 @problem_type('keywords-for-nonparts', |
|
134 severity = 'warning', |
|
135 message = lambda type: str.format( |
|
136 'keywords are not allowed for {type} files', |
|
137 type = type, |
|
138 ), |
|
139 ) |
|
140 def keywords_tests(model): |
|
141 if model.header.valid: |
|
142 if model.header.keywords \ |
|
143 and model.header.effective_filetype != 'Part': |
|
144 yield report_problem( |
|
145 'keywords-for-nonparts', |
|
146 bad_object = model.find_first_header_object('keywords'), |
|
147 type = model.header.effective_filetype, |
|
148 ) |
|
149 |
|
150 @problem_type('bad-colour-24-nonline', |
|
151 severity = 'hold', |
|
152 message = 'colour 24 used on non-lines', |
|
153 ) |
|
154 @problem_type('bad-colour-24-line', |
|
155 severity = 'hold', |
|
156 message = 'line with colour other than 24', |
|
157 ) |
|
158 def colour_24_test(model): |
|
159 for element in model.body: |
|
160 if hasattr(element, 'colour'): |
|
161 is_line = isinstance(element, linetypes.LineSegment) |
|
162 if not is_line and element.colour.index == 24: |
|
163 yield report_problem('bad-colour-24-nonline', bad_object = element) |
|
164 if is_line and element.colour.index != 24: |
|
165 yield report_problem('bad-colour-24-line', bad_object = element) |
|
166 |
|
167 @problem_type('moved-to-with-extension', |
|
168 severity = 'hold', |
|
169 message = 'moved-to files must not contain the ' |
|
170 '".dat"-extension in the description', |
|
171 ) |
|
172 def moved_to_with_extension_test(model): |
|
173 if model.header.valid \ |
|
174 and model.header.description.startswith('~Moved to') \ |
|
175 and '.dat' in model.header.description: |
|
176 yield report_problem( |
|
177 'moved-to-with-extension', |
|
178 bad_object = model.body[0], |
|
179 ) |
|
180 |
|
181 @problem_type('bfc-invertnext-not-on-subfile', |
|
182 severity = 'hold', |
|
183 message = '"BFC INVERTNEXT" not followed by a type-1 line', |
|
184 ) |
|
185 def bfc_invertnext_not_on_subfile_test(model): |
|
186 def get_invertnexts(model): |
|
187 yield from [ |
|
188 (index, element) |
|
189 for index, element in enumerate(model.body) |
|
190 if isinstance(element, linetypes.MetaCommand) \ |
|
191 and element.text == 'BFC INVERTNEXT' |
|
192 ] |
|
193 def has_subfile_after_invertnext(index): |
|
194 index_subfile = index + 1 # subfile reference should be on the next line |
|
195 if index_subfile >= len(model.body): |
|
196 return False # past the end... |
|
197 else: |
|
198 element = model.body[index_subfile] |
|
199 return isinstance(element, linetypes.SubfileReference) |
|
200 for index, invertnext in get_invertnexts(model): |
|
201 if not has_subfile_after_invertnext(index): |
|
202 yield report_problem('bfc-invertnext-not-on-subfile', |
|
203 bad_object = model.body[index], |
|
204 ) |
|
205 |
44 |
206 @problem_type('unknown-metacommand', |
45 @problem_type('unknown-metacommand', |
207 severity = 'hold', |
46 severity = 'hold', |
208 message = lambda command_text: str.format( |
47 message = lambda command_text: str.format( |
209 'unknown or deprecated metacommand: {command_text}', |
48 'unknown or deprecated metacommand: {command_text}', |
244 'bad-line-endings', |
83 'bad-line-endings', |
245 bad_object = model.body[model.line_ending_errors['first-at']], |
84 bad_object = model.body[model.line_ending_errors['first-at']], |
246 count = model.line_ending_errors['count'], |
85 count = model.line_ending_errors['count'], |
247 ) |
86 ) |
248 |
87 |
|
88 @problem_type('bfc-invertnext-not-on-subfile', |
|
89 severity = 'hold', |
|
90 message = '"BFC INVERTNEXT" not followed by a type-1 line', |
|
91 ) |
|
92 def bfc_invertnext_not_on_subfile_test(model): |
|
93 def get_invertnexts(model): |
|
94 yield from [ |
|
95 (index, element) |
|
96 for index, element in enumerate(model.body) |
|
97 if isinstance(element, linetypes.MetaCommand) \ |
|
98 and element.text == 'BFC INVERTNEXT' |
|
99 ] |
|
100 def has_subfile_after_invertnext(index): |
|
101 index_subfile = index + 1 # subfile reference should be on the next line |
|
102 if index_subfile >= len(model.body): |
|
103 return False # past the end... |
|
104 else: |
|
105 element = model.body[index_subfile] |
|
106 return isinstance(element, linetypes.SubfileReference) |
|
107 for index, invertnext in get_invertnexts(model): |
|
108 if not has_subfile_after_invertnext(index): |
|
109 yield report_problem('bfc-invertnext-not-on-subfile', |
|
110 bad_object = model.body[index], |
|
111 ) |
|
112 |
249 manifest = { |
113 manifest = { |
250 'tests': [ |
114 'tests': [ |
251 colours_test, |
115 colours_test, |
252 syntax_errors, |
116 syntax_errors, |
253 bad_header, |
|
254 nocertify_test, |
|
255 physical_colours_test, |
|
256 unofficiality_test, |
|
257 header_bfc_test, |
|
258 keywords_tests, |
|
259 colour_24_test, |
|
260 moved_to_with_extension_test, |
|
261 bfc_invertnext_not_on_subfile_test, |
117 bfc_invertnext_not_on_subfile_test, |
262 metacommands_test, |
118 metacommands_test, |
263 line_endings_test, |
119 line_endings_test, |
264 ], |
120 ], |
265 } |
121 } |