Fri, 24 May 2019 17:37:10 +0200
added proper handling of syntax errors
| 
3
 
1dc58f44d556
Can now write dat files, added direct color handling
 
Santeri Piippo 
parents:  
diff
changeset
 | 
1 | #!/usr/bin/env python3 | 
| 8 | 2 | from sys import version_info | 
| 3 | if version_info < (3, 4): | |
| 4 | raise RuntimeError('Python 3.4 or newer required') | |
| 5 | ||
| 
3
 
1dc58f44d556
Can now write dat files, added direct color handling
 
Santeri Piippo 
parents:  
diff
changeset
 | 
6 | from parse import parse_ldraw_code | 
| 8 | 7 | from colours import load_colours | 
| 7 | 8 | from geometry import * | 
| 8 | 9 | from pathlib import Path | 
| 13 | 10 | import linetypes | 
| 
3
 
1dc58f44d556
Can now write dat files, added direct color handling
 
Santeri Piippo 
parents:  
diff
changeset
 | 
11 | |
| 
9
 
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
 
Santeri Piippo 
parents: 
8 
diff
changeset
 | 
12 | from os.path import realpath | 
| 
 
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
 
Santeri Piippo 
parents: 
8 
diff
changeset
 | 
13 | script_directory = Path(realpath(__file__)).parent | 
| 
 
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
 
Santeri Piippo 
parents: 
8 
diff
changeset
 | 
14 | |
| 
 
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
 
Santeri Piippo 
parents: 
8 
diff
changeset
 | 
15 | def load_config(filename): | 
| 
 
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
 
Santeri Piippo 
parents: 
8 
diff
changeset
 | 
16 | from configobj import ConfigObj | 
| 
 
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
 
Santeri Piippo 
parents: 
8 
diff
changeset
 | 
17 | from copy import deepcopy | 
| 
 
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
 
Santeri Piippo 
parents: 
8 
diff
changeset
 | 
18 | config = ConfigObj(filename, encoding = 'UTF8') | 
| 
 
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
 
Santeri Piippo 
parents: 
8 
diff
changeset
 | 
19 | read_config = deepcopy(config) | 
| 
 
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
 
Santeri Piippo 
parents: 
8 
diff
changeset
 | 
20 | if 'libraries' not in config: | 
| 
 
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
 
Santeri Piippo 
parents: 
8 
diff
changeset
 | 
21 | config['libraries'] = ['/path/to/ldraw'] | 
| 
 
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
 
Santeri Piippo 
parents: 
8 
diff
changeset
 | 
22 | if config != read_config: | 
| 
 
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
 
Santeri Piippo 
parents: 
8 
diff
changeset
 | 
23 | config.write() | 
| 
34
 
7ed2e831acd4
the program now checks that all ldraw paths are reachable
 
Teemu Piippo <teemu@hecknology.net> 
parents: 
32 
diff
changeset
 | 
24 | check_library_paths(config) | 
| 
9
 
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
 
Santeri Piippo 
parents: 
8 
diff
changeset
 | 
25 | return config | 
| 
 
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
 
Santeri Piippo 
parents: 
8 
diff
changeset
 | 
26 | |
| 21 | 27 | def read_ldraw(file, *, name = '', config): | 
| 28 | model_body = [ | |
| 29 | parse_ldraw_code(line) | |
| 30 | for line in file | |
| 31 | ] | |
| 32 | model = Model(body = model_body) | |
| 33 | model.name = name | |
| 34 | return model | |
| 
3
 
1dc58f44d556
Can now write dat files, added direct color handling
 
Santeri Piippo 
parents:  
diff
changeset
 | 
35 | |
| 
9
 
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
 
Santeri Piippo 
parents: 
8 
diff
changeset
 | 
36 | def library_paths(config): | 
| 
 
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
 
Santeri Piippo 
parents: 
8 
diff
changeset
 | 
37 | for library_path_string in config['libraries']: | 
| 
 
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
 
Santeri Piippo 
parents: 
8 
diff
changeset
 | 
38 | yield Path(library_path_string).expanduser() | 
| 
 
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
 
Santeri Piippo 
parents: 
8 
diff
changeset
 | 
39 | |
| 
34
 
7ed2e831acd4
the program now checks that all ldraw paths are reachable
 
Teemu Piippo <teemu@hecknology.net> 
parents: 
32 
diff
changeset
 | 
40 | def check_library_paths(config): | 
| 
 
7ed2e831acd4
the program now checks that all ldraw paths are reachable
 
Teemu Piippo <teemu@hecknology.net> 
parents: 
32 
diff
changeset
 | 
41 | from sys import exit | 
| 
 
7ed2e831acd4
the program now checks that all ldraw paths are reachable
 
Teemu Piippo <teemu@hecknology.net> 
parents: 
32 
diff
changeset
 | 
42 | problems = False | 
| 
36
 
2753aad79678
now checks that paths are specified
 
Teemu Piippo <teemu@hecknology.net> 
parents: 
34 
diff
changeset
 | 
43 | have_paths = False | 
| 
34
 
7ed2e831acd4
the program now checks that all ldraw paths are reachable
 
Teemu Piippo <teemu@hecknology.net> 
parents: 
32 
diff
changeset
 | 
44 | for library_path in library_paths(config): | 
| 
36
 
2753aad79678
now checks that paths are specified
 
Teemu Piippo <teemu@hecknology.net> 
parents: 
34 
diff
changeset
 | 
45 | have_paths = True | 
| 
34
 
7ed2e831acd4
the program now checks that all ldraw paths are reachable
 
Teemu Piippo <teemu@hecknology.net> 
parents: 
32 
diff
changeset
 | 
46 | if not library_path.exists(): | 
| 
 
7ed2e831acd4
the program now checks that all ldraw paths are reachable
 
Teemu Piippo <teemu@hecknology.net> 
parents: 
32 
diff
changeset
 | 
47 | problems = True | 
| 
 
7ed2e831acd4
the program now checks that all ldraw paths are reachable
 
Teemu Piippo <teemu@hecknology.net> 
parents: 
32 
diff
changeset
 | 
48 | print(str.format( | 
| 
 
7ed2e831acd4
the program now checks that all ldraw paths are reachable
 
Teemu Piippo <teemu@hecknology.net> 
parents: 
32 
diff
changeset
 | 
49 | 'Library path {} does not exist', | 
| 
 
7ed2e831acd4
the program now checks that all ldraw paths are reachable
 
Teemu Piippo <teemu@hecknology.net> 
parents: 
32 
diff
changeset
 | 
50 | library_path, | 
| 
 
7ed2e831acd4
the program now checks that all ldraw paths are reachable
 
Teemu Piippo <teemu@hecknology.net> 
parents: 
32 
diff
changeset
 | 
51 | )) | 
| 
 
7ed2e831acd4
the program now checks that all ldraw paths are reachable
 
Teemu Piippo <teemu@hecknology.net> 
parents: 
32 
diff
changeset
 | 
52 | elif not library_path.exists(): | 
| 
 
7ed2e831acd4
the program now checks that all ldraw paths are reachable
 
Teemu Piippo <teemu@hecknology.net> 
parents: 
32 
diff
changeset
 | 
53 | problems = True | 
| 
 
7ed2e831acd4
the program now checks that all ldraw paths are reachable
 
Teemu Piippo <teemu@hecknology.net> 
parents: 
32 
diff
changeset
 | 
54 | print(str.format( | 
| 
 
7ed2e831acd4
the program now checks that all ldraw paths are reachable
 
Teemu Piippo <teemu@hecknology.net> 
parents: 
32 
diff
changeset
 | 
55 | 'Library path {} is not a directory', | 
| 
 
7ed2e831acd4
the program now checks that all ldraw paths are reachable
 
Teemu Piippo <teemu@hecknology.net> 
parents: 
32 
diff
changeset
 | 
56 | library_path, | 
| 
 
7ed2e831acd4
the program now checks that all ldraw paths are reachable
 
Teemu Piippo <teemu@hecknology.net> 
parents: 
32 
diff
changeset
 | 
57 | )) | 
| 
36
 
2753aad79678
now checks that paths are specified
 
Teemu Piippo <teemu@hecknology.net> 
parents: 
34 
diff
changeset
 | 
58 | if not have_paths: | 
| 
 
2753aad79678
now checks that paths are specified
 
Teemu Piippo <teemu@hecknology.net> 
parents: 
34 
diff
changeset
 | 
59 | print('No LDraw path specified') | 
| 
 
2753aad79678
now checks that paths are specified
 
Teemu Piippo <teemu@hecknology.net> 
parents: 
34 
diff
changeset
 | 
60 | problems = True | 
| 
34
 
7ed2e831acd4
the program now checks that all ldraw paths are reachable
 
Teemu Piippo <teemu@hecknology.net> 
parents: 
32 
diff
changeset
 | 
61 | if problems: | 
| 
 
7ed2e831acd4
the program now checks that all ldraw paths are reachable
 
Teemu Piippo <teemu@hecknology.net> 
parents: 
32 
diff
changeset
 | 
62 | print('Please fix ldcheck.cfg') | 
| 
 
7ed2e831acd4
the program now checks that all ldraw paths are reachable
 
Teemu Piippo <teemu@hecknology.net> 
parents: 
32 
diff
changeset
 | 
63 | exit(1) | 
| 
 
7ed2e831acd4
the program now checks that all ldraw paths are reachable
 
Teemu Piippo <teemu@hecknology.net> 
parents: 
32 
diff
changeset
 | 
64 | |
| 
9
 
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
 
Santeri Piippo 
parents: 
8 
diff
changeset
 | 
65 | def find_ldconfig_ldr_paths(config): | 
| 
 
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
 
Santeri Piippo 
parents: 
8 
diff
changeset
 | 
66 | for library_path in library_paths(config): | 
| 17 | 67 | yield from [ | 
| 68 | library_path / path | |
| 69 | for path in ['LDConfig.ldr', 'ldconfig.ldr'] | |
| 70 | if (library_path / path).is_file() | |
| 8 | 71 | ] | 
| 72 | ||
| 13 | 73 | class Model: | 
| 17 | 74 | def __init__(self, body): | 
| 75 | self.body = body | |
| 76 | self.body_offset = 0 | |
| 21 | 77 | def filter_by_type(self, type): | 
| 17 | 78 | yield from [ | 
| 79 | element | |
| 80 | for element in self.body | |
| 21 | 81 | if isinstance(element, type) | 
| 17 | 82 | ] | 
| 21 | 83 | @property | 
| 84 | def subfile_references(self): | |
| 85 | yield from self.filter_by_type(linetypes.SubfileReference) | |
| 86 | @property | |
| 87 | def line_segments(self): | |
| 88 | yield from self.filter_by_type(linetypes.LineSegment) | |
| 89 | @property | |
| 90 | def triangles(self): | |
| 91 | yield from self.filter_by_type(linetypes.Triangle) | |
| 92 | @property | |
| 93 | def quadrilaterals(self): | |
| 94 | yield from self.filter_by_type(linetypes.Quadrilateral) | |
| 13 | 95 | |
| 
26
 
7c263b864371
Added command line option to list all checks.
 
Santeri Piippo 
parents: 
21 
diff
changeset
 | 
96 | import argparse | 
| 
 
7c263b864371
Added command line option to list all checks.
 
Santeri Piippo 
parents: 
21 
diff
changeset
 | 
97 | class ListTestSuiteAction(argparse.Action): | 
| 
 
7c263b864371
Added command line option to list all checks.
 
Santeri Piippo 
parents: 
21 
diff
changeset
 | 
98 | def __init__(self, option_strings, dest, nargs = None, **kwargs): | 
| 
 
7c263b864371
Added command line option to list all checks.
 
Santeri Piippo 
parents: 
21 
diff
changeset
 | 
99 | super().__init__(option_strings, dest, nargs = 0, **kwargs) | 
| 
 
7c263b864371
Added command line option to list all checks.
 
Santeri Piippo 
parents: 
21 
diff
changeset
 | 
100 | def __call__(self, *args, **kwargs): | 
| 
 
7c263b864371
Added command line option to list all checks.
 
Santeri Piippo 
parents: 
21 
diff
changeset
 | 
101 | from testsuite import load_tests | 
| 
 
7c263b864371
Added command line option to list all checks.
 
Santeri Piippo 
parents: 
21 
diff
changeset
 | 
102 | from sys import exit | 
| 
 
7c263b864371
Added command line option to list all checks.
 
Santeri Piippo 
parents: 
21 
diff
changeset
 | 
103 | from re import sub | 
| 
 
7c263b864371
Added command line option to list all checks.
 
Santeri Piippo 
parents: 
21 
diff
changeset
 | 
104 | test_suite = load_tests() | 
| 
 
7c263b864371
Added command line option to list all checks.
 
Santeri Piippo 
parents: 
21 
diff
changeset
 | 
105 | for test_name in sorted(test_suite['tests'].keys()): | 
| 
 
7c263b864371
Added command line option to list all checks.
 
Santeri Piippo 
parents: 
21 
diff
changeset
 | 
106 | test_function = test_suite['tests'][test_name] | 
| 
 
7c263b864371
Added command line option to list all checks.
 
Santeri Piippo 
parents: 
21 
diff
changeset
 | 
107 | help = sub(r'\s+', ' ', test_function.__doc__ or '').strip() | 
| 
 
7c263b864371
Added command line option to list all checks.
 
Santeri Piippo 
parents: 
21 
diff
changeset
 | 
108 | print(test_name + ': ' + help) | 
| 
 
7c263b864371
Added command line option to list all checks.
 
Santeri Piippo 
parents: 
21 
diff
changeset
 | 
109 | exit(0) | 
| 
 
7c263b864371
Added command line option to list all checks.
 
Santeri Piippo 
parents: 
21 
diff
changeset
 | 
110 | |
| 
3
 
1dc58f44d556
Can now write dat files, added direct color handling
 
Santeri Piippo 
parents:  
diff
changeset
 | 
111 | if __name__ == '__main__': | 
| 
 
1dc58f44d556
Can now write dat files, added direct color handling
 
Santeri Piippo 
parents:  
diff
changeset
 | 
112 | from sys import argv | 
| 
26
 
7c263b864371
Added command line option to list all checks.
 
Santeri Piippo 
parents: 
21 
diff
changeset
 | 
113 | parser = argparse.ArgumentParser() | 
| 
 
7c263b864371
Added command line option to list all checks.
 
Santeri Piippo 
parents: 
21 
diff
changeset
 | 
114 | parser.add_argument('filename') | 
| 
 
7c263b864371
Added command line option to list all checks.
 
Santeri Piippo 
parents: 
21 
diff
changeset
 | 
115 | parser.add_argument('--list', | 
| 
 
7c263b864371
Added command line option to list all checks.
 
Santeri Piippo 
parents: 
21 
diff
changeset
 | 
116 | action = ListTestSuiteAction, | 
| 
 
7c263b864371
Added command line option to list all checks.
 
Santeri Piippo 
parents: 
21 
diff
changeset
 | 
117 | help = 'Lists all possible checks and exit', | 
| 
 
7c263b864371
Added command line option to list all checks.
 
Santeri Piippo 
parents: 
21 
diff
changeset
 | 
118 | ) | 
| 
38
 
66c9591b733d
added proper handling of syntax errors
 
Teemu Piippo <teemu@hecknology.net> 
parents: 
36 
diff
changeset
 | 
119 | parser.add_argument('--dump-structure', action = 'store_true') | 
| 
 
66c9591b733d
added proper handling of syntax errors
 
Teemu Piippo <teemu@hecknology.net> 
parents: 
36 
diff
changeset
 | 
120 | parser.add_argument('--rebuild', action = 'store_true') | 
| 
26
 
7c263b864371
Added command line option to list all checks.
 
Santeri Piippo 
parents: 
21 
diff
changeset
 | 
121 | args = parser.parse_args() | 
| 
9
 
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
 
Santeri Piippo 
parents: 
8 
diff
changeset
 | 
122 | config = load_config('ldcheck.cfg') | 
| 
 
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
 
Santeri Piippo 
parents: 
8 
diff
changeset
 | 
123 | for ldconfig_ldr_path in find_ldconfig_ldr_paths(config): | 
| 8 | 124 | with ldconfig_ldr_path.open() as ldconfig_ldr: | 
| 125 | load_colours(ldconfig_ldr) | |
| 
26
 
7c263b864371
Added command line option to list all checks.
 
Santeri Piippo 
parents: 
21 
diff
changeset
 | 
126 | with open(args.filename) as file: | 
| 18 | 127 | from os.path import basename | 
| 
26
 
7c263b864371
Added command line option to list all checks.
 
Santeri Piippo 
parents: 
21 
diff
changeset
 | 
128 | model = read_ldraw( | 
| 
 
7c263b864371
Added command line option to list all checks.
 
Santeri Piippo 
parents: 
21 
diff
changeset
 | 
129 | file, | 
| 
 
7c263b864371
Added command line option to list all checks.
 
Santeri Piippo 
parents: 
21 
diff
changeset
 | 
130 | name = basename(args.filename), | 
| 
 
7c263b864371
Added command line option to list all checks.
 
Santeri Piippo 
parents: 
21 
diff
changeset
 | 
131 | config = config, | 
| 
 
7c263b864371
Added command line option to list all checks.
 
Santeri Piippo 
parents: 
21 
diff
changeset
 | 
132 | ) | 
| 
38
 
66c9591b733d
added proper handling of syntax errors
 
Teemu Piippo <teemu@hecknology.net> 
parents: 
36 
diff
changeset
 | 
133 | if args.dump_structure: | 
| 
 
66c9591b733d
added proper handling of syntax errors
 
Teemu Piippo <teemu@hecknology.net> 
parents: 
36 
diff
changeset
 | 
134 | for entry in model.body: | 
| 
 
66c9591b733d
added proper handling of syntax errors
 
Teemu Piippo <teemu@hecknology.net> 
parents: 
36 
diff
changeset
 | 
135 | print(entry) | 
| 
 
66c9591b733d
added proper handling of syntax errors
 
Teemu Piippo <teemu@hecknology.net> 
parents: 
36 
diff
changeset
 | 
136 | elif args.rebuild: | 
| 
 
66c9591b733d
added proper handling of syntax errors
 
Teemu Piippo <teemu@hecknology.net> 
parents: 
36 
diff
changeset
 | 
137 | for entry in model.body: | 
| 
 
66c9591b733d
added proper handling of syntax errors
 
Teemu Piippo <teemu@hecknology.net> 
parents: 
36 
diff
changeset
 | 
138 | print(entry.textual_representation(), end = '\r\n') | 
| 
 
66c9591b733d
added proper handling of syntax errors
 
Teemu Piippo <teemu@hecknology.net> 
parents: 
36 
diff
changeset
 | 
139 | else: | 
| 
 
66c9591b733d
added proper handling of syntax errors
 
Teemu Piippo <teemu@hecknology.net> 
parents: 
36 
diff
changeset
 | 
140 | from testsuite import load_tests, check_model, format_report | 
| 
 
66c9591b733d
added proper handling of syntax errors
 
Teemu Piippo <teemu@hecknology.net> 
parents: 
36 
diff
changeset
 | 
141 | test_suite = load_tests() | 
| 
 
66c9591b733d
added proper handling of syntax errors
 
Teemu Piippo <teemu@hecknology.net> 
parents: 
36 
diff
changeset
 | 
142 | report = check_model(model, test_suite) | 
| 
 
66c9591b733d
added proper handling of syntax errors
 
Teemu Piippo <teemu@hecknology.net> 
parents: 
36 
diff
changeset
 | 
143 | print(format_report(report, model, test_suite)) |