ldcheck.py

changeset 65
f2dc17b830e0
parent 63
8949af6a4279
equal deleted inserted replaced
64:1c0884f5506e 65:f2dc17b830e0
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))

mercurial