tests/subfiles.py

changeset 54
0c686d10eb49
parent 37
e46fa477007b
child 55
388df1fa18a2
--- a/tests/subfiles.py	Wed May 29 16:36:23 2019 +0300
+++ b/tests/subfiles.py	Thu May 30 12:03:53 2019 +0300
@@ -1,8 +1,10 @@
 from testsuite import warning, error
+import testsuite
 from geometry import *
 from os.path import dirname
 from pathlib import Path
 from configparser import ConfigParser
+import math
 ini_path = Path(dirname(__file__)) / 'library-standards.ini'
 library_standards = ConfigParser()
 
@@ -83,10 +85,72 @@
                 axes = interesting_axes,
                 scaling = scaling)
 
+def dependent_subfile_tests(model):
+    '''
+        Tests subfile references for such qualities that are dependent on the
+        actual contents of the subfiles. Checks whether moved-to files are used.
+        Checks whether flat subfiles are scaled in the flat direction.
+    '''
+    import filecache
+    cache = filecache.SubfileCache(model.ldraw_directories)
+    failed_subfiles = set()
+    for subfile_reference in model.subfile_references:
+        path = subfile_reference.subfile_path.lower()
+        if path in failed_subfiles:
+            # Already proven to be a bad apple, don't complain twice
+            pass
+        else:
+            try:
+                subfile = cache.prepare_file(path)
+            except filecache.CyclicalReferenceError as e:
+                failed_subfiles.add(path)
+                yield error(subfile_reference, 'cyclical-reference',
+                    chain = str(e),
+                )
+            if not subfile.valid:
+                yield error(subfile_reference, 'bad-subfile',
+                    path = path,
+                    problem_text = subfile.problem,
+                )
+                failed_subfiles.add(path)
+            import re
+            match = re.search(r'^\~Moved(?: to (\w+))?$', subfile.description)
+            if match:
+                yield error(subfile_reference, 'moved-file-used',
+                    moved_file = path,
+                    new_file = match.group(1))
+            scaling_vector = subfile_reference.matrix.scaling_vector()
+            scaled_dimensions = {
+                dimension
+                for dimension in subfile.flatness
+                if not math.isclose(
+                    getattr(scaling_vector, dimension),
+                    1,
+                    abs_tol = 1.0e-05
+                )
+            }
+            scaled_flat_dimensions = subfile.flatness & scaled_dimensions
+            if scaled_flat_dimensions:
+                yield testsuite.notice(subfile_reference, 'unnecessary-scaling',
+                    scaled_flat_dimensions = scaled_flat_dimensions,
+                    scaling_vector = scaling_vector,
+                )
+
+def dimensions_description(dimensions):
+    sorted_dims = sorted(dimensions)
+    if len(sorted_dims) == 1:
+        return sorted_dims[0] + ' dimension'
+    else:
+        return str.format('{} and {} dimensions',
+            ', '.join(sorted_dims[:-1]),
+            sorted_dims[-1],
+        )
+
 manifest = {
     'tests': {
         'determinant': determinant_test,
         'scaling-legality': scaling_legality_test,
+        'dependent-subfiles': dependent_subfile_tests,
     },
     'messages': {
         'zero-determinant': 'matrix determinant is zero '
@@ -96,5 +160,23 @@
                 primitive,
                 scaling_description(scaling, axes),
             ),
+        'cyclical-reference': lambda chain:
+            str.format('cyclical subfile dependency: {chain}',
+                **locals(),
+            ),
+        'bad-subfile': lambda path, problem_text:
+            str.format('cannot process subfile "{path}": {problem_text}',
+                **locals(),
+            ),
+        'moved-file-used': lambda moved_file, new_file:
+            str.format('subfile "{moved_file}" has been moved to "{new_file}"',
+                **locals(),
+            ),
+        'unnecessary-scaling': lambda scaled_flat_dimensions, scaling_vector:
+            str.format(
+                'subfile unnecessarily scaled in the {dims} ({scaling})',
+                dims = dimensions_description(scaled_flat_dimensions),
+                scaling = scaling_description(scaling_vector),
+            )
     },
 }

mercurial