filecache.py

Tue, 25 Aug 2020 23:37:53 +0300

author
Teemu Piippo <teemu@hecknology.net>
date
Tue, 25 Aug 2020 23:37:53 +0300
changeset 109
b627f8963a84
parent 95
a3536e51f6bc
child 145
fde18c4d6784
permissions
-rw-r--r--

handle file not found more cleanly

54
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
1 import datetime
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
2 import parse
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
3 import os
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
4 from pathlib import Path
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
5 import linetypes
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
6 import math
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
7
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
8 def find_ldraw_file(filename, libraries):
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
9 '''
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
10 Searches the LDraw libraries for the specified file.
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
11 `libraries` must be an iterable of LDraw library root paths.
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
12 '''
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
13 if os.path.sep != "\\":
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
14 filename = filename.replace("\\", os.path.sep)
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
15 for library in libraries:
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
16 for path in [
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
17 Path(library) / filename,
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
18 Path(library) / "parts" / filename,
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
19 Path(library) / "p" / filename,
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
20 ]:
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
21 if path.exists():
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
22 return path
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
23 raise FileNotFoundError(str.format(
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
24 '"{}" not found in the LDraw libraries',
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
25 filename,
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
26 ))
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
27
92
b8d72909d593 improved the mirrored stud check to catch cases where a subfile that contains studs is mirrored
Teemu Piippo <teemu@hecknology.net>
parents: 58
diff changeset
28 def is_logo_stud_name(name):
b8d72909d593 improved the mirrored stud check to catch cases where a subfile that contains studs is mirrored
Teemu Piippo <teemu@hecknology.net>
parents: 58
diff changeset
29 return name in ['stud.dat', 'stud3.dat']
b8d72909d593 improved the mirrored stud check to catch cases where a subfile that contains studs is mirrored
Teemu Piippo <teemu@hecknology.net>
parents: 58
diff changeset
30
54
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
31 class CyclicalReferenceError(Exception):
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
32 pass
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
33
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
34 class SubfileCache:
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
35 class Subfile:
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
36 def __init__(self):
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
37 self.valid = None
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
38 self.flatness = None
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
39 self.description = None
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
40 self.problem = None
92
b8d72909d593 improved the mirrored stud check to catch cases where a subfile that contains studs is mirrored
Teemu Piippo <teemu@hecknology.net>
parents: 58
diff changeset
41 self.has_studs = None # Whether or not it contains studs
54
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
42 self.vertices = set()
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
43 def __init__(self, ldraw_directories):
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
44 '''
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
45 Initializes a new subfile cache
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
46 '''
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
47 self.cache = dict()
58
86014c443635 try to fix crashing
Teemu Piippo <teemu@hecknology.net>
parents: 54
diff changeset
48 if ldraw_directories and isinstance(ldraw_directories[0], str):
86014c443635 try to fix crashing
Teemu Piippo <teemu@hecknology.net>
parents: 54
diff changeset
49 self.ldraw_directories = [
86014c443635 try to fix crashing
Teemu Piippo <teemu@hecknology.net>
parents: 54
diff changeset
50 Path(os.path.expanduser(directory))
86014c443635 try to fix crashing
Teemu Piippo <teemu@hecknology.net>
parents: 54
diff changeset
51 for directory in ldraw_directories
86014c443635 try to fix crashing
Teemu Piippo <teemu@hecknology.net>
parents: 54
diff changeset
52 ]
86014c443635 try to fix crashing
Teemu Piippo <teemu@hecknology.net>
parents: 54
diff changeset
53 else:
86014c443635 try to fix crashing
Teemu Piippo <teemu@hecknology.net>
parents: 54
diff changeset
54 from copy import copy
86014c443635 try to fix crashing
Teemu Piippo <teemu@hecknology.net>
parents: 54
diff changeset
55 self.ldraw_directories = copy(ldraw_directories)
54
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
56 self.reference_stack = []
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
57 def flatness_of(self, filename):
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
58 '''
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
59 Returns the set of all directiones the specified file is flat in.
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
60 '''
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
61 self.prepare_file(filename)
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
62 return self.cache[filename].flatness
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
63 def description_of(self, filename):
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
64 '''
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
65 Returns the description of the specified file
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
66 '''
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
67 self.prepare_file(filename)
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
68 return self.cache[filename].description
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
69 def find_file(self, filename):
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
70 return find_ldraw_file(
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
71 filename = filename,
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
72 libraries = self.ldraw_directories,
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
73 )
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
74 def prepare_file(self, filename):
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
75 '''
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
76 Loads the file if not loaded yet.
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
77 '''
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
78 if filename not in self.cache:
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
79 self._load_subfile(filename)
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
80 return self.cache[filename]
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
81 def _load_subfile(self, filename):
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
82 # ward against cyclical dependencies
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
83 if filename in self.reference_stack:
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
84 raise CyclicalReferenceError(
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
85 ' -> '.join(self.reference_stack + [filename]),
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
86 )
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
87 self.reference_stack.append(filename)
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
88 subfile = SubfileCache.Subfile()
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
89 self.cache[filename] = subfile
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
90 try:
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
91 path = self.find_file(filename)
94
109fb7cf658f added a check for non-DOS line endings
Teemu Piippo <teemu@hecknology.net>
parents: 92
diff changeset
92 with path.open('rb') as file:
54
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
93 model = parse.read_ldraw(
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
94 file,
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
95 ldraw_directories = self.ldraw_directories,
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
96 )
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
97 except (FileNotFoundError, IOError, PermissionError) as error:
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
98 subfile.valid = False
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
99 subfile.problem = str(error)
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
100 else:
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
101 if isinstance(model.body[0], linetypes.MetaCommand):
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
102 subfile.valid = True
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
103 subfile.description = model.body[0].text
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
104 else:
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
105 subfile.valid = False
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
106 subfile.problem = 'Description not found'
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
107 if subfile.valid:
95
a3536e51f6bc fixed the cyclical dependency handling
Teemu Piippo <teemu@hecknology.net>
parents: 94
diff changeset
108 subfile.vertices = set(parse.model_vertices(model, file_cache = self))
54
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
109 subfile.flatness = {'x', 'y', 'z'}
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
110 for vertex in subfile.vertices:
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
111 # Use list(subfile.flatness) for iteration because the
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
112 # actual set may be modified during the loop
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
113 for dimension in list(subfile.flatness):
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
114 if not math.isclose(
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
115 getattr(vertex, dimension),
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
116 0.0,
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
117 abs_tol = 1e-05,
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
118 ):
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
119 subfile.flatness.remove(dimension)
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
120 if not subfile.flatness:
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
121 break
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
122 for subfile_reference in model.subfile_references:
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
123 # Go through all the subfile references so that we catch any
92
b8d72909d593 improved the mirrored stud check to catch cases where a subfile that contains studs is mirrored
Teemu Piippo <teemu@hecknology.net>
parents: 58
diff changeset
124 # cyclical references and to get studs
54
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
125 self.prepare_file(subfile_reference.subfile_path)
92
b8d72909d593 improved the mirrored stud check to catch cases where a subfile that contains studs is mirrored
Teemu Piippo <teemu@hecknology.net>
parents: 58
diff changeset
126 subfile.has_studs = any(
b8d72909d593 improved the mirrored stud check to catch cases where a subfile that contains studs is mirrored
Teemu Piippo <teemu@hecknology.net>
parents: 58
diff changeset
127 self.cache[subfile_reference.subfile_path].has_studs
b8d72909d593 improved the mirrored stud check to catch cases where a subfile that contains studs is mirrored
Teemu Piippo <teemu@hecknology.net>
parents: 58
diff changeset
128 or is_logo_stud_name(subfile_reference.subfile_path)
b8d72909d593 improved the mirrored stud check to catch cases where a subfile that contains studs is mirrored
Teemu Piippo <teemu@hecknology.net>
parents: 58
diff changeset
129 for subfile_reference in model.subfile_references
b8d72909d593 improved the mirrored stud check to catch cases where a subfile that contains studs is mirrored
Teemu Piippo <teemu@hecknology.net>
parents: 58
diff changeset
130 )
54
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
131 self.reference_stack.pop()
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
132
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
133 if __name__ == '__main__':
0c686d10eb49 added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
134 cache = SubfileCache(ldraw_directories = ["~/ldraw"])

mercurial