cleanup

Sat, 08 Jun 2019 11:17:17 +0300

author
Teemu Piippo <teemu@hecknology.net>
date
Sat, 08 Jun 2019 11:17:17 +0300
changeset 65
f2dc17b830e0
parent 64
1c0884f5506e

cleanup

ldcheck.py file | annotate | diff | comparison | revisions
linetypes.py file | annotate | diff | comparison | revisions
parse.py file | annotate | diff | comparison | revisions
testsuite.py file | annotate | diff | comparison | revisions
webfront.py file | annotate | diff | comparison | revisions
--- a/ldcheck.py	Sat Jun 08 01:51:50 2019 +0300
+++ b/ldcheck.py	Sat Jun 08 11:17:17 2019 +0300
@@ -1,66 +1,47 @@
 #!/usr/bin/env python3
+'''
+    Main LDCheck commandline program.
+'''
 from sys import version_info
 if version_info < (3, 4):
     raise RuntimeError('Python 3.4 or newer required')
 
-from colours import load_colours
 from geometry import *
-from pathlib import Path
 import linetypes
 import header
 import parse
-
-from os.path import realpath
-script_directory = Path(realpath(__file__)).parent
-
-def load_config(filename):
-    from configobj import ConfigObj
-    from copy import deepcopy
-    config = ConfigObj(filename, encoding = 'UTF8')
-    read_config = deepcopy(config)
-    if 'libraries' not in config:
-        config['libraries'] = ['/path/to/ldraw']
-    if config != read_config:
-        config.write()
-    check_library_paths(config)
-    return config
-
-def library_paths(config):
-    for library_path_string in config['libraries']:
-        yield Path(library_path_string).expanduser()
+import config
+import colours
 
-def check_library_paths(config):
-    from sys import exit
-    problems = False
-    have_paths = False
-    for library_path in library_paths(config):
-        have_paths = True
-        if not library_path.exists():
-            problems = True
-            print(str.format(
-                'Library path {} does not exist',
-                library_path,
-            ))
-        elif not library_path.exists():
-            problems = True
-            print(str.format(
-                'Library path {} is not a directory',
-                library_path,
-            ))
-    if not have_paths:
-        print('No LDraw path specified')
-        problems = True
-    if problems:
-        print('Please fix ldcheck.cfg')
-        exit(1)
-
-def find_ldconfig_ldr_paths(config):
-    for library_path in library_paths(config):
-        yield from [
-            library_path / path
-            for path in ['LDConfig.ldr', 'ldconfig.ldr']
-            if (library_path / path).is_file()
-        ]
+def format_report(report, model):
+    '''
+        Formats the report from the test suite so as to be
+        printed in the console.
+    '''
+    import colorama
+    colorama.init()
+    messages = []
+    for problem in report['problems']:
+        if problem.severity == 'hold':
+            text_colour = colorama.Fore.LIGHTRED_EX
+        elif problem.severity == 'warning':
+            text_colour = colorama.Fore.LIGHTBLUE_EX
+        else:
+            text_colour = ''
+        ldraw_code = model.body[problem.body_index].textual_representation()
+        message = str.format(
+            '{text_colour}{model_name}:{line_number}: {problem_type}: {message}'
+            '{colour_reset}\n\t{ldraw_code}',
+            text_colour = text_colour,
+            model_name = model.name,
+            line_number = problem.line_number,
+            problem_type = problem.severity,
+            message = str(problem),
+            colour_reset = colorama.Fore.RESET,
+            ldraw_code = ldraw_code,
+        )
+        messages.append(message)
+    return '\n'.join(messages)
 
 import argparse
 
@@ -92,14 +73,14 @@
     parser.add_argument('--rebuild', action = 'store_true')
     parser.add_argument('--flatness', action = 'store_true')
     args = parser.parse_args()
-    config = load_config('ldcheck.cfg')
-    for ldconfig_ldr_path in find_ldconfig_ldr_paths(config):
+    config_object = config.load_config('ldcheck.cfg')
+    for ldconfig_ldr_path in config.find_ldconfig_ldr_paths(config_object):
         with ldconfig_ldr_path.open() as ldconfig_ldr:
-            load_colours(ldconfig_ldr)
+            colours.load_colours(ldconfig_ldr)
     if args.flatness:
         import filecache
         cache = filecache.SubfileCache(
-            ldraw_directories = config['libraries'],
+            ldraw_directories = config_object['libraries'],
         )
         subfile = cache.prepare_file(args.filename)
         if not subfile.valid:
@@ -118,7 +99,7 @@
             model = parse.read_ldraw(
                 file,
                 name = basename(args.filename),
-                ldraw_directories = config['libraries'])
+                ldraw_directories = config_object['libraries'])
             if args.dump_structure:
                 print('header: ' + type(model.header).__name__)
                 for key in sorted(dir(model.header)):
@@ -130,7 +111,7 @@
                 for entry in model.body:
                     print(entry.textual_representation(), end = '\r\n')
             else:
-                from testsuite import load_tests, check_model, format_report
-                test_suite = load_tests()
-                report = check_model(model, test_suite)
-                print(format_report(report, model, test_suite))
+                import testsuite
+                test_suite = testsuite.load_tests()
+                report = testsuite.check_model(model, test_suite)
+                print(format_report(report, model))
--- a/linetypes.py	Sat Jun 08 01:51:50 2019 +0300
+++ b/linetypes.py	Sat Jun 08 11:17:17 2019 +0300
@@ -1,3 +1,8 @@
+#!/usr/bin/env python3
+'''
+    Classes for formally storing LDraw objects
+'''
+
 def ldraw_str(value):
     ' Like str() except removes unneeded ".0"-suffixes '
     rep = str(value)
--- a/parse.py	Sat Jun 08 01:51:50 2019 +0300
+++ b/parse.py	Sat Jun 08 11:17:17 2019 +0300
@@ -1,3 +1,7 @@
+#!/usr/bin/env python3
+'''
+    Routines for parsing LDraw code.
+'''
 import linetypes
 import re
 from geometry import *
--- a/testsuite.py	Sat Jun 08 01:51:50 2019 +0300
+++ b/testsuite.py	Sat Jun 08 11:17:17 2019 +0300
@@ -1,6 +1,13 @@
+#!/usr/bin/env python3
+'''
+    Routines for assembling the test suite, and running it on a model.
+'''
 from warnings import warn
 
 class ProblemType:
+    '''
+        Represents a type of issue in the part
+    '''
     severities = ['hold', 'warning'] # in descending order
     def __init__(self, name, severity, message):
         if severity not in ProblemType.severities:
@@ -18,6 +25,10 @@
             **args,
         )
     def placeholder_message(self):
+        '''
+            Returns the error message of this problem type, with placeholders
+            filled in.
+        '''
         if callable(self.message):
             import inspect
             spec = inspect.getfullargspec(self.message)
@@ -30,6 +41,9 @@
             return self.message
 
 class Problem:
+    '''
+        Represents a single issue in the part
+    '''
     def __init__(self, problem_class, bad_object, **args):
         self.problem_class = problem_class
         self.severity = problem_class.severity
@@ -42,6 +56,10 @@
             return self.problem_class.message
 
 def problem_type(problem_name, **args):
+    '''
+        A decorator that creates a new ProblemType and attaches it to the
+        decoratable function.
+    '''
     def wrapper(function):
         if not hasattr(function, 'ldcheck_problem_types'):
             function.ldcheck_problem_types = {}
@@ -51,6 +69,10 @@
     return wrapper
 
 def report_problem(problem_name, *, bad_object, **args):
+    '''
+        Called from test functions to report issues. This gets later mapped
+        into Problem objects.
+    '''
     return {'type': problem_name, 'bad-object': bad_object, 'args': args}
 
 def name_of_package(package):
@@ -87,6 +109,9 @@
     return test_suite
 
 def problem_key(problem):
+    '''
+        Sorts problems by rank and line number.
+    '''
     rank = ProblemType.severities.index(problem.severity) # sort by severity
     return (rank, problem.line_number)
 
@@ -100,6 +125,9 @@
     return problem_object
 
 def check_model(model, test_suite = None):
+    '''
+        Runs the test suite on the model and prepares a report.
+    '''
     if not test_suite:
         test_suite = load_tests()
     problems = []
@@ -123,65 +151,18 @@
         'problems': sorted(problems, key = problem_key),
     }
 
-def problem_text(problem, test_suite):
-    message = problem.problem_class.message
-    if callable(message):
-        message = message(**problem.args)
-    return message
-
-def format_report_html(report, model, test_suite):
-    messages = []
-    for problem in report['problems']:
-        ldraw_code = model.body[problem.body_index].textual_representation()
-        message = str.format(
-            '<li class="{problem_type}">{model_name}:{line_number}:'
-            '{problem_type}: {message}<br />{ldraw_code}</li>',
-            model_name = model.name,
-            line_number = problem.line_number,
-            problem_type = problem.severity,
-            message = problem_text(problem, test_suite),
-            ldraw_code = ldraw_code,
-        )
-        messages.append(message)
-    return '\n'.join(messages)
-
-def format_report(report, model, test_suite):
-    import colorama
-    colorama.init()
-    messages = []
-    for problem in report['problems']:
-        if problem.severity == 'hold':
-            text_colour = colorama.Fore.LIGHTRED_EX
-        elif problem.severity == 'warning':
-            text_colour = colorama.Fore.LIGHTBLUE_EX
-        else:
-            text_colour = ''
-        ldraw_code = model.body[problem.body_index].textual_representation()
-        message = str.format(
-            '{text_colour}{model_name}:{line_number}: {problem_type}: {message}'
-            '{colour_reset}\n\t{ldraw_code}',
-            text_colour = text_colour,
-            model_name = model.name,
-            line_number = problem.line_number,
-            problem_type = problem.severity,
-            message = problem_text(problem, test_suite),
-            colour_reset = colorama.Fore.RESET,
-            ldraw_code = ldraw_code,
-        )
-        messages.append(message)
-    return '\n'.join(messages)
-
 def iterate_problems(test_suite):
+    '''
+        Yields all problem types.
+    '''
     for test_function in test_suite['tests']:
         yield from test_function.ldcheck_problem_types.values()
     
 def all_problem_types(test_suite):
+    '''
+        Returns a sorted list of problem types.
+    '''
     return sorted(
         iterate_problems(test_suite),
         key = lambda problem_type: problem_type.name
     )
-    
-
-if __name__ == '__main__':
-    from pprint import pprint
-    pprint(load_tests())
--- a/webfront.py	Sat Jun 08 01:51:50 2019 +0300
+++ b/webfront.py	Sat Jun 08 11:17:17 2019 +0300
@@ -1,47 +1,48 @@
 #!/usr/bin/env python3
-from flask import Flask, render_template, redirect, request
-from ldcheck import load_config, load_colours, find_ldconfig_ldr_paths
-from parse import read_ldraw
-from testsuite import load_tests, check_model, problem_text, all_problem_types
+import flask
+import testsuite
+import config
+import parse
+import colours
 
-app = Flask('LDCheck')
+app = flask.Flask('LDCheck')
 
 @app.route('/', methods = ['GET', 'POST'])
 def web_front():
-    test_suite = load_tests()
+    test_suite = testsuite.load_tests()
+    request = flask.request
     if request.method == 'POST':
         # check if the post request has the file part
         if 'file' not in request.files or not request.files['file'].filename:
-            return redirect(request.url)
+            return flask.redirect(request.url)
         file = request.files['file']
         filename = file.filename
-        config = load_config('ldcheck.cfg')
-        for ldconfig_ldr_path in find_ldconfig_ldr_paths(config):
+        config_object = config.load_config('ldcheck.cfg')
+        for ldconfig_ldr_path in config.find_ldconfig_ldr_paths(config_object):
             with ldconfig_ldr_path.open() as ldconfig_ldr:
-                load_colours(ldconfig_ldr)
-        model = read_ldraw(
+                colours.load_colours(ldconfig_ldr)
+        model = parse.read_ldraw(
             file.stream,
             name = filename,
-            ldraw_directories = config['libraries'],
+            ldraw_directories = config_object['libraries'],
         )
-        report = check_model(model, test_suite)
+        report = testsuite.check_model(model, test_suite)
 
         # Amend human-readable messages into the report
         for problem in report['problems']:
             object = model.body[problem.body_index]
-            problem.message_str = problem_text(problem, test_suite)
+            problem.message_str = str(problem)
             problem.ldraw_code = object.textual_representation()
-        return render_template('webfront.html',
+        return flask.render_template('webfront.html',
             report = report,
             name = filename,
-            problem_types = all_problem_types(test_suite)
+            problem_types = testsuite.all_problem_types(test_suite)
         )
     else:
-        test_suite = load_tests()
-        return render_template('webfront.html',
+        return flask.render_template('webfront.html',
             report = None,
             name = None,
-            problem_types = all_problem_types(test_suite)
+            problem_types = testsuite.all_problem_types(test_suite)
         )
 
 @app.route('/static/<path:path>')

mercurial