1
1
# This file is part of the Prusa firmware
2
2
# Copyright (C) 2020 Prusa Research a.s. - www.prusa3d.com
3
3
# SPDX-License-Identifier: GPL-3.0-or-later
4
-
5
4
"""
6
5
Base classes for SL1 errors and warnings
7
6
"""
8
7
9
8
import functools
10
9
import json
11
10
import re
12
- from enum import unique , IntEnum
11
+ from enum import IntEnum , unique
13
12
from pathlib import Path
14
- from typing import List , TextIO , Dict
13
+ from typing import Dict , List , TextIO , Optional
15
14
16
15
import yaml
17
16
@@ -31,17 +30,23 @@ class Printer(IntEnum):
31
30
MK4 = 0x000D
32
31
IX = 0x0010
33
32
XL = 0x0011
34
- MK35 = 0x0017
35
33
MK39 = 0x0015
36
- NEXT = 0x0019
34
+ MK35 = 0x0017
35
+ HONEYBEE = 0x0019
36
+ MK4S = 0x001A
37
+ MK39S = 0x001B
38
+ MK35S = 0x001C
39
+ M1 = 0x001D
40
+ COREONE = 0x001F
37
41
38
42
39
43
@unique
40
44
class Category (IntEnum ):
41
45
"""
42
46
Prusa error category codes
43
47
44
- This mapping is taken from general Prusa guidelines on errors, do not modify.
48
+ This mapping is taken from general Prusa guidelines on errors, do not
49
+ modify.
45
50
"""
46
51
47
52
MECHANICAL = 1 # Mechanical failures, engines XYZ, tower
@@ -62,16 +67,15 @@ class Code:
62
67
"""
63
68
64
69
# pylint: disable = too-many-arguments
65
- def __init__ (
66
- self ,
67
- printer : Printer ,
68
- category : Category ,
69
- error : int ,
70
- title : str ,
71
- message : str ,
72
- approved : bool ,
73
- action : List [str ] = None
74
- ):
70
+ # pylint: disable = too-many-positional-arguments
71
+ def __init__ (self ,
72
+ printer : Printer ,
73
+ category : Category ,
74
+ error : int ,
75
+ title : str ,
76
+ message : str ,
77
+ approved : bool ,
78
+ action : Optional [List [str ]] = None ):
75
79
if printer .value < 0 or printer .value > 99 :
76
80
raise ValueError (f"Printer class { printer } out of range" )
77
81
if category .value < 0 or category .value > 9 :
@@ -165,8 +169,9 @@ def approved(self):
165
169
"""
166
170
Whenever the message text was approved for use in production system
167
171
168
- Unapproved tests are not supposed to be translated. This is planed to raise warnings and prevent the resulting
169
- build from being used in production.
172
+ Unapproved tests are not supposed to be translated. This is planed
173
+ to raise warnings and prevent the resulting build from being used in
174
+ production.
170
175
"""
171
176
return self ._approved
172
177
@@ -212,7 +217,10 @@ def get_codes(cls) -> Dict[str, Code]:
212
217
213
218
:return: Member code dict
214
219
"""
215
- return {item : var for item , var in vars (cls ).items () if isinstance (var , Code )}
220
+ return {
221
+ item : var
222
+ for item , var in vars (cls ).items () if isinstance (var , Code )
223
+ }
216
224
217
225
@classmethod
218
226
def get (cls , code : str ):
@@ -225,7 +233,10 @@ def get(cls, code: str):
225
233
:return: Code instance
226
234
"""
227
235
if not cls ._code_map :
228
- cls ._code_map = {code .code : code for code in cls .get_codes ().values ()}
236
+ cls ._code_map = {
237
+ code .code : code
238
+ for code in cls .get_codes ().values ()
239
+ }
229
240
return cls ._code_map [code ]
230
241
231
242
@classmethod
@@ -236,7 +247,13 @@ def dump_json(cls, file: TextIO) -> None:
236
247
:param file: Where to dump
237
248
:return: None
238
249
"""
239
- obj = {name .lower (): {"code" : code .code , "message" : code .message } for name , code in cls .get_codes ().items ()}
250
+ obj = {
251
+ name .lower (): {
252
+ "code" : code .code ,
253
+ "message" : code .message
254
+ }
255
+ for name , code in cls .get_codes ().items ()
256
+ }
240
257
return json .dump (obj , file , indent = True )
241
258
242
259
@classmethod
@@ -284,7 +301,9 @@ def dump_qml_dictionary(cls, file: TextIO):
284
301
:return: None
285
302
"""
286
303
file .write ("import QtQuick 2.10\n " )
287
- file .write ("/* Generated by sla-errors. Your edits to this file will be lost. */\n " )
304
+ file .write (
305
+ "/* Generated by sla-errors. Your edits to this file will be lost. */\n "
306
+ )
288
307
file .write ("pragma Singleton\n " )
289
308
file .write ("Item {\n " )
290
309
file .write ("\t readonly property var messages:{\n " )
@@ -304,7 +323,9 @@ def dump_cpp_ts(cls, file: TextIO):
304
323
:param file: Where to dump
305
324
:return: None
306
325
"""
307
- file .write ("// Generated translation string definitions for all defined error messages\n " )
326
+ file .write (
327
+ "// Generated translation string definitions for all defined error messages\n "
328
+ )
308
329
for code in cls .get_codes ().values ():
309
330
if code .message :
310
331
file .write (f"QT_TR_NOOP({ code .raw_message } );\n " )
@@ -329,7 +350,9 @@ def dump_google_docs(cls, file: TextIO) -> None:
329
350
for name , code in cls .get_codes ().items ():
330
351
message = code .message if code .message else ""
331
352
category = f"{ c2docs [code .category ]} \t { code .category .value } "
332
- file .write (f'SL1\t 10\t { category } \t { code .error } \t "{ name } "\t "{ message } "\t { code .code } \n ' )
353
+ file .write (
354
+ f'SL1\t 10\t { category } \t { code .error } \t "{ name } "\t "{ message } "\t { code .code } \n '
355
+ )
333
356
334
357
@classmethod
335
358
def dump_yaml (cls , file : TextIO ) -> None :
@@ -342,9 +365,13 @@ def dump_yaml(cls, file: TextIO) -> None:
342
365
codes = []
343
366
344
367
for name , code in cls .get_codes ().items ():
345
- codes .append (
346
- {"code" : code .raw_code , "title" : name , "text" : code .message , "id" : name , "approved" : code .approved , }
347
- )
368
+ codes .append ({
369
+ "code" : code .raw_code ,
370
+ "title" : name ,
371
+ "text" : code .message ,
372
+ "id" : name ,
373
+ "approved" : code .approved ,
374
+ })
348
375
349
376
yaml .dump ({"Errors" : codes }, file , sort_keys = False )
350
377
@@ -359,7 +386,8 @@ def unique_codes(cls):
359
386
used = set ()
360
387
for name , code in cls .get_codes ().items ():
361
388
if code .code in used :
362
- raise ValueError (f"Code { name } with value { code .code } is duplicate!" )
389
+ raise ValueError (
390
+ f"Code { name } with value { code .code } is duplicate!" )
363
391
used .add (code .code )
364
392
365
393
return cls
@@ -375,7 +403,8 @@ def unique_titles(cls):
375
403
used = set ()
376
404
for name , code in cls .get_codes ().items ():
377
405
if code .title in used :
378
- raise ValueError (f"Code { name } with title { code .title } is duplicate!" )
406
+ raise ValueError (
407
+ f"Code { name } with title { code .title } is duplicate!" )
379
408
used .add (code .title )
380
409
381
410
return cls
@@ -407,8 +436,23 @@ def yaml_codes(src_path: Path):
407
436
"""
408
437
409
438
def decor (cls ):
410
- for identifier , code in decode_yaml (src_path ):
411
- setattr (cls , identifier , code )
439
+ with src_path .open ("r" ) as src_file :
440
+ data = yaml .safe_load (src_file )
441
+ assert "Errors" in data
442
+
443
+ code_re = re .compile (
444
+ r"^(?P<printer>[0-9][0-9])(?P<category>[0-9])(?P<error>[0-9][0-9])$"
445
+ )
446
+ for entry in data ["Errors" ]:
447
+ code_parts = code_re .match (entry ["code" ]).groupdict ()
448
+ printer = Printer (int (code_parts ["printer" ]))
449
+ category = Category (int (code_parts ["category" ]))
450
+ error = int (code_parts ["error" ])
451
+ action = entry .get ("action" , [])
452
+ setattr (
453
+ cls , entry ["id" ],
454
+ Code (printer , category , error , entry ["title" ], entry ["text" ],
455
+ entry ["approved" ], action ))
412
456
return cls
413
457
414
458
return decor
0 commit comments