Skip to content

Commit dfa5f32

Browse files
committed
Use md5 hash
* added a test to check if different arguments returned different cache hits * added a test for TypeErrors from Workplane arguments
1 parent 9ae8f46 commit dfa5f32

File tree

2 files changed

+39
-20
lines changed

2 files changed

+39
-20
lines changed

plugins/cq_cache/cq_cache.py

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
from OCP.BRepTools import BRepTools
1010
from OCP.BRep import BRep_Builder
1111
from OCP.TopoDS import TopoDS_Shape
12+
from itertools import chain
13+
import hashlib
1214

1315

1416
TEMPDIR_PATH = tempfile.gettempdir()
@@ -74,24 +76,19 @@ def build_file_name(fct, *args, **kwargs):
7476
Returns a file name given the specified function and args.
7577
If the function and the args are the same this function returns the same filename
7678
"""
77-
SPACER = "_"
78-
file_name = fct.__name__
79-
for arg in args:
80-
if isinstance(arg, cq.Workplane):
81-
raise TypeError(
82-
"Can not cache a function that accepts Workplane objects as argument"
83-
)
84-
file_name += SPACER + str(hash(arg))
85-
for kwarg_value in kwargs.values():
86-
if isinstance(kwarg_value, cq.Workplane):
87-
raise TypeError(
88-
"Can not cache a function that accepts Workplane objects as argument"
89-
)
90-
file_name += SPACER + str(hash(kwarg_value))
91-
file_name = bytes(file_name, "utf-8")
92-
return base64.urlsafe_b64encode(file_name).decode(
93-
"utf-8"
94-
) # compacts the long string of hash ints into a urlsafe string
79+
if cq.Workplane in (type(x) for x in chain(args, kwargs.values())):
80+
raise TypeError(
81+
"Can not cache a function that accepts Workplane objects as argument"
82+
)
83+
84+
# hash all relevant variables
85+
hasher = hashlib.md5()
86+
for val in [fct.__name__, args.__repr__(), kwargs.__repr__()]:
87+
hasher.update(bytes(val, "utf-8"))
88+
# encode the hash as a filesystem safe string
89+
filename = base64.urlsafe_b64encode(hasher.digest()).decode("utf-8")
90+
# strip the padding
91+
return filename.rstrip("=")
9592

9693

9794
def clear_cq_cache():

tests/test_cq_cache.py

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from plugins.cq_cache.cq_cache import cq_cache, clear_cq_cache, get_cache_dir_size
44
import tempfile
55
import os
6+
import pytest
67

78
TEMPDIR_PATH = tempfile.gettempdir()
89
CACHE_DIR_NAME = "cadquery_geom_cache"
@@ -38,8 +39,17 @@ def test_cache_file_creation():
3839
cube2 = cube(1, 1, 1)
3940
files = os.listdir(CACHE_DIR_PATH)
4041
assert len(files) == 2
41-
assert "Y3ViZV8xXzFfMQ==.brep" in files
42-
assert "Y3ViZV8xXzFfMQ==" in files
42+
assert "Fv2MB2hDeoH6xwu4aBh5wA.brep" in files
43+
assert "Fv2MB2hDeoH6xwu4aBh5wA" in files
44+
45+
46+
def test_cache_unique():
47+
clear_cq_cache()
48+
for _ in range(2):
49+
cube1 = cube(1, 1, 1)
50+
cube2 = cube(2, 2, 2)
51+
assert cube1.BoundingBox().zlen == pytest.approx(1)
52+
assert cube2.BoundingBox().zlen == pytest.approx(2)
4353

4454

4555
def test_not_exceeding_size():
@@ -78,3 +88,15 @@ def cube(a, b, c):
7888
cube4 = cube(1, 1, 1)
7989
assert isinstance(cube3, cq.Solid)
8090
assert isinstance(cube4, cq.Solid)
91+
92+
93+
def test_workplane_typeerror():
94+
@cq_cache(CACHE_SIZE)
95+
def wp(a, kwarg=None):
96+
return a
97+
98+
with pytest.raises(TypeError):
99+
wp(cq.Workplane())
100+
101+
with pytest.raises(TypeError):
102+
wp(1, kwarg=cq.Workplane())

0 commit comments

Comments
 (0)