1 #!/usr/bin/env python3 |
1 #!/usr/bin/env python3 |
|
2 ''' |
|
3 Main LDCheck commandline program. |
|
4 ''' |
2 from sys import version_info |
5 from sys import version_info |
3 if version_info < (3, 4): |
6 if version_info < (3, 4): |
4 raise RuntimeError('Python 3.4 or newer required') |
7 raise RuntimeError('Python 3.4 or newer required') |
5 |
8 |
6 from colours import load_colours |
|
7 from geometry import * |
9 from geometry import * |
8 from pathlib import Path |
|
9 import linetypes |
10 import linetypes |
10 import header |
11 import header |
11 import parse |
12 import parse |
|
13 import config |
|
14 import colours |
12 |
15 |
13 from os.path import realpath |
16 def format_report(report, model): |
14 script_directory = Path(realpath(__file__)).parent |
17 ''' |
15 |
18 Formats the report from the test suite so as to be |
16 def load_config(filename): |
19 printed in the console. |
17 from configobj import ConfigObj |
20 ''' |
18 from copy import deepcopy |
21 import colorama |
19 config = ConfigObj(filename, encoding = 'UTF8') |
22 colorama.init() |
20 read_config = deepcopy(config) |
23 messages = [] |
21 if 'libraries' not in config: |
24 for problem in report['problems']: |
22 config['libraries'] = ['/path/to/ldraw'] |
25 if problem.severity == 'hold': |
23 if config != read_config: |
26 text_colour = colorama.Fore.LIGHTRED_EX |
24 config.write() |
27 elif problem.severity == 'warning': |
25 check_library_paths(config) |
28 text_colour = colorama.Fore.LIGHTBLUE_EX |
26 return config |
29 else: |
27 |
30 text_colour = '' |
28 def library_paths(config): |
31 ldraw_code = model.body[problem.body_index].textual_representation() |
29 for library_path_string in config['libraries']: |
32 message = str.format( |
30 yield Path(library_path_string).expanduser() |
33 '{text_colour}{model_name}:{line_number}: {problem_type}: {message}' |
31 |
34 '{colour_reset}\n\t{ldraw_code}', |
32 def check_library_paths(config): |
35 text_colour = text_colour, |
33 from sys import exit |
36 model_name = model.name, |
34 problems = False |
37 line_number = problem.line_number, |
35 have_paths = False |
38 problem_type = problem.severity, |
36 for library_path in library_paths(config): |
39 message = str(problem), |
37 have_paths = True |
40 colour_reset = colorama.Fore.RESET, |
38 if not library_path.exists(): |
41 ldraw_code = ldraw_code, |
39 problems = True |
42 ) |
40 print(str.format( |
43 messages.append(message) |
41 'Library path {} does not exist', |
44 return '\n'.join(messages) |
42 library_path, |
|
43 )) |
|
44 elif not library_path.exists(): |
|
45 problems = True |
|
46 print(str.format( |
|
47 'Library path {} is not a directory', |
|
48 library_path, |
|
49 )) |
|
50 if not have_paths: |
|
51 print('No LDraw path specified') |
|
52 problems = True |
|
53 if problems: |
|
54 print('Please fix ldcheck.cfg') |
|
55 exit(1) |
|
56 |
|
57 def find_ldconfig_ldr_paths(config): |
|
58 for library_path in library_paths(config): |
|
59 yield from [ |
|
60 library_path / path |
|
61 for path in ['LDConfig.ldr', 'ldconfig.ldr'] |
|
62 if (library_path / path).is_file() |
|
63 ] |
|
64 |
45 |
65 import argparse |
46 import argparse |
66 |
47 |
67 class ListTestSuiteAction(argparse.Action): |
48 class ListTestSuiteAction(argparse.Action): |
68 def __init__(self, option_strings, dest, nargs = None, **kwargs): |
49 def __init__(self, option_strings, dest, nargs = None, **kwargs): |
90 ) |
71 ) |
91 parser.add_argument('--dump-structure', action = 'store_true') |
72 parser.add_argument('--dump-structure', action = 'store_true') |
92 parser.add_argument('--rebuild', action = 'store_true') |
73 parser.add_argument('--rebuild', action = 'store_true') |
93 parser.add_argument('--flatness', action = 'store_true') |
74 parser.add_argument('--flatness', action = 'store_true') |
94 args = parser.parse_args() |
75 args = parser.parse_args() |
95 config = load_config('ldcheck.cfg') |
76 config_object = config.load_config('ldcheck.cfg') |
96 for ldconfig_ldr_path in find_ldconfig_ldr_paths(config): |
77 for ldconfig_ldr_path in config.find_ldconfig_ldr_paths(config_object): |
97 with ldconfig_ldr_path.open() as ldconfig_ldr: |
78 with ldconfig_ldr_path.open() as ldconfig_ldr: |
98 load_colours(ldconfig_ldr) |
79 colours.load_colours(ldconfig_ldr) |
99 if args.flatness: |
80 if args.flatness: |
100 import filecache |
81 import filecache |
101 cache = filecache.SubfileCache( |
82 cache = filecache.SubfileCache( |
102 ldraw_directories = config['libraries'], |
83 ldraw_directories = config_object['libraries'], |
103 ) |
84 ) |
104 subfile = cache.prepare_file(args.filename) |
85 subfile = cache.prepare_file(args.filename) |
105 if not subfile.valid: |
86 if not subfile.valid: |
106 print(subfile.problem) |
87 print(subfile.problem) |
107 else: |
88 else: |
116 with open(args.filename) as file: |
97 with open(args.filename) as file: |
117 from os.path import basename |
98 from os.path import basename |
118 model = parse.read_ldraw( |
99 model = parse.read_ldraw( |
119 file, |
100 file, |
120 name = basename(args.filename), |
101 name = basename(args.filename), |
121 ldraw_directories = config['libraries']) |
102 ldraw_directories = config_object['libraries']) |
122 if args.dump_structure: |
103 if args.dump_structure: |
123 print('header: ' + type(model.header).__name__) |
104 print('header: ' + type(model.header).__name__) |
124 for key in sorted(dir(model.header)): |
105 for key in sorted(dir(model.header)): |
125 if not key.startswith('__'): |
106 if not key.startswith('__'): |
126 print('\t' + key + ': ' + repr(getattr(model.header, key))) |
107 print('\t' + key + ': ' + repr(getattr(model.header, key))) |
128 print(entry) |
109 print(entry) |
129 elif args.rebuild: |
110 elif args.rebuild: |
130 for entry in model.body: |
111 for entry in model.body: |
131 print(entry.textual_representation(), end = '\r\n') |
112 print(entry.textual_representation(), end = '\r\n') |
132 else: |
113 else: |
133 from testsuite import load_tests, check_model, format_report |
114 import testsuite |
134 test_suite = load_tests() |
115 test_suite = testsuite.load_tests() |
135 report = check_model(model, test_suite) |
116 report = testsuite.check_model(model, test_suite) |
136 print(format_report(report, model, test_suite)) |
117 print(format_report(report, model)) |