forked from jeff-dh/SolidPython
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathparse_scad.py
More file actions
99 lines (76 loc) · 3.33 KB
/
parse_scad.py
File metadata and controls
99 lines (76 loc) · 3.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
import hashlib
import pickle
from functools import partial
from pathlib import Path
from collections import namedtuple
from ..config import config
from .object_base import OpenSCADConstant
from .utils import escape_openscad_identifier
from .object_factory import create_openscad_wrapper_from_symbols
callables_entry = namedtuple("callables_entry", ["name", "args", "kwargs"])
# ===========
# = Parsing =
# ===========
def get_pickle_filename(filename):
md5 = hashlib.md5()
md5.update(filename.as_posix().encode('utf-8'))
filename_hash = md5.hexdigest()
with open(filename, mode='rb') as f:
d = hashlib.md5()
for buf in iter(partial(f.read, 128), b''):
d.update(buf)
file_content_hash = d.hexdigest()
pickle_filename = Path(filename_hash).with_suffix("." + file_content_hash).name
return config.pickle_cache_dir / pickle_filename, filename_hash
def check_pickle_cache(filename):
if not config.enable_pickle_cache:
return None, None, False
pickle_filename, _ = get_pickle_filename(filename)
#create pickle_cache_dir if neccessary
if not config.pickle_cache_dir.exists():
config.pickle_cache_dir.mkdir(parents=True)
#if the file exists, load and return it
if pickle_filename.exists():
with pickle_filename.open("rb") as f:
pickler = pickle.Unpickler(f)
callables = pickler.load()
global_vars = pickler.load()
return callables, global_vars, True
return None, None, False
def update_pickle_cache(filename, callables, global_vars):
if not config.enable_pickle_cache:
return
pickle_filename, filename_hash = get_pickle_filename(filename)
#delete old files which correspond to this (absolute) filename(_hash)
for f in pickle_filename.parent.glob(filename_hash + "*"):
Path.unlink(f)
#write the callables and global_vars to disk
with pickle_filename.open("wb") as f:
pickler = pickle.Pickler(f)
pickler.dump(callables)
pickler.dump(global_vars)
def get_scad_file_as_dict(filename):
assert(filename.is_absolute())
#check whether we have a valid up to date pickled version of it
callables, global_vars, cache_is_valid = check_pickle_cache(filename)
if not cache_is_valid:
#otherwise parse the file
from ..libs.py_scadparser import scad_parser
modules, functions, global_vars = scad_parser.parseFile(filename)
callables = []
for c in modules + functions:
#args = [p.name for p in c.parameters if not p.optional]
#kwargs = [p.name for p in c.parameters if p.optional]
kwargs = [p.name for p in c.parameters]
callables.append(callables_entry(c.name, [], kwargs))
#write the read version to disk so we can probably use it the next time
update_pickle_cache(filename, callables, global_vars)
#create a wrapper for each callable and add it to the dict
new_namespace_dict = {}
for c in callables:
wrapper = create_openscad_wrapper_from_symbols(c.name, [], c.kwargs)
new_namespace_dict[escape_openscad_identifier(c.name)] = wrapper
for c in global_vars:
new_namespace_dict[escape_openscad_identifier(c.name)] = \
OpenSCADConstant(c.name)
return new_namespace_dict