Thu, 26 Aug 2021 19:16:25 +0300
Cleanup ldcheck.py
Remove dependency on configobj. Configuration file replaced with command line arguments and rcfile
3
1dc58f44d556
Can now write dat files, added direct color handling
Santeri Piippo
parents:
diff
changeset
|
1 | #!/usr/bin/env python3 |
146 | 2 | import sys |
3 | if sys.version_info < (3, 4): | |
8 | 4 | raise RuntimeError('Python 3.4 or newer required') |
5 | from colours import load_colours | |
7 | 6 | from geometry import * |
8 | 7 | from pathlib import Path |
13 | 8 | import linetypes |
47
4da025d0b283
added work on header check
Teemu Piippo <teemu@hecknology.net>
parents:
38
diff
changeset
|
9 | import header |
54
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
10 | import parse |
3
1dc58f44d556
Can now write dat files, added direct color handling
Santeri Piippo
parents:
diff
changeset
|
11 | |
146 | 12 | def check_library_paths(library_paths): |
13 | for library_path in library_paths: | |
34
7ed2e831acd4
the program now checks that all ldraw paths are reachable
Teemu Piippo <teemu@hecknology.net>
parents:
32
diff
changeset
|
14 | if not library_path.exists(): |
146 | 15 | raise RuntimeError(str.format( |
16 | 'error: library path {} does not exist', | |
34
7ed2e831acd4
the program now checks that all ldraw paths are reachable
Teemu Piippo <teemu@hecknology.net>
parents:
32
diff
changeset
|
17 | library_path, |
7ed2e831acd4
the program now checks that all ldraw paths are reachable
Teemu Piippo <teemu@hecknology.net>
parents:
32
diff
changeset
|
18 | )) |
7ed2e831acd4
the program now checks that all ldraw paths are reachable
Teemu Piippo <teemu@hecknology.net>
parents:
32
diff
changeset
|
19 | elif not library_path.exists(): |
146 | 20 | raise RuntimeError(str.format( |
21 | 'error: library path {} is not a directory', | |
34
7ed2e831acd4
the program now checks that all ldraw paths are reachable
Teemu Piippo <teemu@hecknology.net>
parents:
32
diff
changeset
|
22 | library_path, |
7ed2e831acd4
the program now checks that all ldraw paths are reachable
Teemu Piippo <teemu@hecknology.net>
parents:
32
diff
changeset
|
23 | )) |
7ed2e831acd4
the program now checks that all ldraw paths are reachable
Teemu Piippo <teemu@hecknology.net>
parents:
32
diff
changeset
|
24 | |
146 | 25 | def find_ldconfig_ldr_paths(libraries): |
26 | for library_path in libraries: | |
17 | 27 | yield from [ |
28 | library_path / path | |
29 | for path in ['LDConfig.ldr', 'ldconfig.ldr'] | |
30 | if (library_path / path).is_file() | |
8 | 31 | ] |
32 | ||
146 | 33 | def load_ldconfig(libraries): |
34 | ldconfig_ldr_paths = list(find_ldconfig_ldr_paths(libraries)) | |
35 | if not ldconfig_ldr_paths: | |
36 | raise RuntimeError('could not find any LDConfig.ldr') | |
37 | for ldconfig_ldr_path in ldconfig_ldr_paths: | |
38 | with ldconfig_ldr_path.open() as ldconfig_ldr: | |
39 | load_colours(ldconfig_ldr) | |
62
f0a6bf48b05e
Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents:
54
diff
changeset
|
40 | |
146 | 41 | def parse_commandline_arguments(): |
42 | import os | |
43 | rcpath = Path(os.path.expanduser('~/.config/ldcheckrc')) | |
44 | if rcpath.exists(): | |
45 | with rcpath.open() as file: | |
46 | rcargs = ['--' + line.strip() for line in file] | |
47 | else: | |
48 | rcargs = [] | |
49 | import argparse | |
50 | class ListProblemTypesAction(argparse.Action): | |
51 | def __init__(self, option_strings, dest, nargs = None, **kwargs): | |
52 | super().__init__(option_strings, dest, nargs = 0, **kwargs) | |
53 | def __call__(self, *args, **kwargs): | |
54 | import testsuite | |
55 | test_suite = testsuite.load_tests() | |
56 | for warning_type in testsuite.all_problem_types(test_suite): | |
57 | print(str.format('{name}: {severity}: "{message}"', | |
58 | name = warning_type.name, | |
59 | severity = warning_type.severity, | |
60 | message = warning_type.placeholder_message(), | |
61 | )) | |
62 | sys.exit(0) | |
26
7c263b864371
Added command line option to list all checks.
Santeri Piippo
parents:
21
diff
changeset
|
63 | parser = argparse.ArgumentParser() |
7c263b864371
Added command line option to list all checks.
Santeri Piippo
parents:
21
diff
changeset
|
64 | parser.add_argument('filename') |
7c263b864371
Added command line option to list all checks.
Santeri Piippo
parents:
21
diff
changeset
|
65 | parser.add_argument('--list', |
146 | 66 | action = ListProblemTypesAction, |
81
e65d82501a38
added better help entries to command line parameters
Teemu Piippo <teemu@hecknology.net>
parents:
77
diff
changeset
|
67 | help = 'lists all possible problem types and exit', |
e65d82501a38
added better help entries to command line parameters
Teemu Piippo <teemu@hecknology.net>
parents:
77
diff
changeset
|
68 | ) |
e65d82501a38
added better help entries to command line parameters
Teemu Piippo <teemu@hecknology.net>
parents:
77
diff
changeset
|
69 | parser.add_argument('--dump', |
e65d82501a38
added better help entries to command line parameters
Teemu Piippo <teemu@hecknology.net>
parents:
77
diff
changeset
|
70 | action = 'store_true', |
e65d82501a38
added better help entries to command line parameters
Teemu Piippo <teemu@hecknology.net>
parents:
77
diff
changeset
|
71 | help = 'dumps the internal parsed structure of the part file', |
26
7c263b864371
Added command line option to list all checks.
Santeri Piippo
parents:
21
diff
changeset
|
72 | ) |
81
e65d82501a38
added better help entries to command line parameters
Teemu Piippo <teemu@hecknology.net>
parents:
77
diff
changeset
|
73 | parser.add_argument('--rebuild', |
e65d82501a38
added better help entries to command line parameters
Teemu Piippo <teemu@hecknology.net>
parents:
77
diff
changeset
|
74 | action = 'store_true', |
e65d82501a38
added better help entries to command line parameters
Teemu Piippo <teemu@hecknology.net>
parents:
77
diff
changeset
|
75 | help = 'parses the part file and prints it back out, used for ' |
e65d82501a38
added better help entries to command line parameters
Teemu Piippo <teemu@hecknology.net>
parents:
77
diff
changeset
|
76 | 'testing whether the program interprets part files correctly', |
e65d82501a38
added better help entries to command line parameters
Teemu Piippo <teemu@hecknology.net>
parents:
77
diff
changeset
|
77 | ) |
92
b8d72909d593
improved the mirrored stud check to catch cases where a subfile that contains studs is mirrored
Teemu Piippo <teemu@hecknology.net>
parents:
85
diff
changeset
|
78 | parser.add_argument('--subfile', |
81
e65d82501a38
added better help entries to command line parameters
Teemu Piippo <teemu@hecknology.net>
parents:
77
diff
changeset
|
79 | action = 'store_true', |
92
b8d72909d593
improved the mirrored stud check to catch cases where a subfile that contains studs is mirrored
Teemu Piippo <teemu@hecknology.net>
parents:
85
diff
changeset
|
80 | help = 'finds a subfile by name and prints out information about it' |
85
4438502fd3e0
fixed the use of moved-to-files check not working if there were non-alphanumerics in the filename
Teemu Piippo <teemu@hecknology.net>
parents:
81
diff
changeset
|
81 | ) |
146 | 82 | parser.add_argument('-l', '--library', action = 'append') |
83 | arglist = rcargs + sys.argv[1:] | |
84 | return parser.parse_args(arglist) | |
85 | ||
86 | def main(): | |
87 | args = parse_commandline_arguments() | |
88 | # Make sure that we have at least one library path specified. | |
89 | if not args.library: | |
90 | raise RuntimeError( | |
91 | 'Please specify libraries using the -l / --library switch.\n' | |
92 | 'For example: -l ~/ldraw or --library=~/ldraw\n' | |
93 | 'Multiple --library switches may be used.') | |
94 | # Prepare the list of libraries. This also expands the ~ for the home | |
95 | # directory | |
96 | import os | |
97 | libraries = [Path(os.path.expanduser(library)) for library in args.library] | |
98 | check_library_paths(libraries) | |
99 | load_ldconfig(libraries) | |
92
b8d72909d593
improved the mirrored stud check to catch cases where a subfile that contains studs is mirrored
Teemu Piippo <teemu@hecknology.net>
parents:
85
diff
changeset
|
100 | if args.subfile: |
146 | 101 | # Subfile debug mode: searches for the specified subfile from the LDraw |
102 | # libraries, opens it as if it was referenced by something and prints | |
103 | # out all information that is calculated from this subfile. | |
54
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
104 | import filecache |
146 | 105 | cache = filecache.SubfileCache(ldraw_directories = libraries) |
54
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
106 | subfile = cache.prepare_file(args.filename) |
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
107 | if not subfile.valid: |
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
108 | print(subfile.problem) |
92
b8d72909d593
improved the mirrored stud check to catch cases where a subfile that contains studs is mirrored
Teemu Piippo <teemu@hecknology.net>
parents:
85
diff
changeset
|
109 | else: |
b8d72909d593
improved the mirrored stud check to catch cases where a subfile that contains studs is mirrored
Teemu Piippo <teemu@hecknology.net>
parents:
85
diff
changeset
|
110 | print('Flat dimensions:', repr(subfile.flatness)) |
85
4438502fd3e0
fixed the use of moved-to-files check not working if there were non-alphanumerics in the filename
Teemu Piippo <teemu@hecknology.net>
parents:
81
diff
changeset
|
111 | print('Description:', repr(subfile.description)) |
92
b8d72909d593
improved the mirrored stud check to catch cases where a subfile that contains studs is mirrored
Teemu Piippo <teemu@hecknology.net>
parents:
85
diff
changeset
|
112 | print('Contains studs:', repr(subfile.has_studs)) |
54
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
113 | else: |
94
109fb7cf658f
added a check for non-DOS line endings
Teemu Piippo <teemu@hecknology.net>
parents:
92
diff
changeset
|
114 | with open(args.filename, 'rb') as file: |
54
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
115 | from os.path import basename |
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
116 | model = parse.read_ldraw( |
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
117 | file, |
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
118 | name = basename(args.filename), |
146 | 119 | ldraw_directories = libraries) |
77
d98502ae1f33
improved header extent scanning
Teemu Piippo <teemu@hecknology.net>
parents:
63
diff
changeset
|
120 | if args.dump: |
146 | 121 | # Dump mode: prints out the structure of the processed LDraw file |
54
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
122 | print('header: ' + type(model.header).__name__) |
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
123 | for key in sorted(dir(model.header)): |
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
124 | if not key.startswith('__'): |
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
125 | print('\t' + key + ': ' + repr(getattr(model.header, key))) |
77
d98502ae1f33
improved header extent scanning
Teemu Piippo <teemu@hecknology.net>
parents:
63
diff
changeset
|
126 | for i, entry in enumerate(model.body): |
d98502ae1f33
improved header extent scanning
Teemu Piippo <teemu@hecknology.net>
parents:
63
diff
changeset
|
127 | if model.header.valid and i == model.header_size: |
146 | 128 | # Mark where the header is considered to end |
77
d98502ae1f33
improved header extent scanning
Teemu Piippo <teemu@hecknology.net>
parents:
63
diff
changeset
|
129 | print('--------- End of header') |
54
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
130 | print(entry) |
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
131 | elif args.rebuild: |
146 | 132 | # Debug rebuild mode: open the file, parse it and turn it back |
133 | # into LDraw code and write it into stdout. This is used to ensure | |
134 | # that LDCheck does not miss any information while parsing files. | |
54
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
135 | for entry in model.body: |
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
136 | print(entry.textual_representation(), end = '\r\n') |
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
137 | else: |
146 | 138 | # Regular mode |
54
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
139 | from testsuite import load_tests, check_model, format_report |
146 | 140 | # load the test suite |
141 | # TODO: maybe add some command line argument to filter tests | |
142 | # in case the user wants to run some specific tests only or | |
143 | # possibly leave some test out | |
54
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
144 | test_suite = load_tests() |
146 | 145 | # use the test suite to check the model |
54
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
146 | report = check_model(model, test_suite) |
146 | 147 | # print out the report |
54
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
148 | print(format_report(report, model, test_suite)) |
146 | 149 | |
150 | if __name__ == '__main__': | |
151 | try: | |
152 | main() | |
153 | except RuntimeError as e: | |
154 | import sys | |
155 | print('error:', str(e), file = sys.stderr) | |
156 | sys.exit(1) |