Skip to content

Commit

Permalink
fix sl parsing to use config.json and to return correct keys
Browse files Browse the repository at this point in the history
  • Loading branch information
sarkafa committed Aug 12, 2024
1 parent deb5de7 commit e49e15f
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 34 deletions.
89 changes: 69 additions & 20 deletions gcode_metadata/metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
from logging import getLogger
from importlib.metadata import version

# pylint: disable=too-many-lines

GCODE_EXTENSIONS = (".gcode", ".gc", ".g", ".gco")
SLA_EXTENSIONS = ("sl1", "sl1s")
CHARS_TO_REMOVE = ["/", "\\", "\"", "(", ")", "[", "]", "'"]
Expand Down Expand Up @@ -763,6 +765,34 @@ def percent_of_m73_data(self):
return (present / count) * 100


class SLKeys:
"""Class that maps keys from config.json to
more readable names"""

def __init__(self, key_to_parse: str):
self.key_to_parse = key_to_parse

KeyMapping = {
"printTime": "estimated_print_time",
"expTime": "exposure_time",
"expTimeFirst": "exposure_time_first",
"layerHeight": "layer_height",
"materialName": "material",
"printerModel": "printer_model"
}

@staticmethod
def keys():
"""Returns all keys"""
return list(SLKeys.KeyMapping.keys()) + list(
SLKeys.KeyMapping.values())

@property
def key(self):
"""Returns correct key"""
return self.KeyMapping.get(self.key_to_parse, self.key_to_parse)


class SLMetaData(MetaData):
"""Class that can extract available metadata and thumbnails from
ziparchives used by SL1 slicers"""
Expand All @@ -771,23 +801,46 @@ class SLMetaData(MetaData):
# thumbnails!

Attrs = {
"printer_model": str,
"printTime": int,
"faded_layers": int,
"exposure_time": float,
"initial_exposure_time": float,
"max_initial_exposure_time": float,
"max_exposure_time": float,
"min_initial_exposure_time": float,
"min_exposure_time": float,
"estimated_print_time": int,
"layer_height": float,
"materialName": str,
"fileCreationTimestamp": str,
"material": str,
"exposure_time": int,
"exposure_time_first": int,
"total_layers": int,
"total_height": int,
"resin_used_ml": int,
"printer_model": str,
}

THUMBNAIL_NAME_PAT = re.compile(
r".*?(?P<dim>\d+x\d+)\.(?P<format>qoi|jpg|png)")

def set_data(self, data: Dict):
"""Helper function to save all items from `data` that
match `self.Attr` in `self.data`.
"""
for attr in SLKeys.keys():
val = data.get(attr)
if not val:
continue
correct_attr = SLKeys(attr).key
conv = self.Attrs[correct_attr]
try:
self.data[correct_attr] = conv(val)
except ValueError:
log.warning("Could not convert using %s: %s", conv, val)

def set_attr(self, name, value):
"""A helper function that saves attributes to `self.data`"""
correct_name = SLKeys(name).key
if correct_name not in self.Attrs:
return
conv = self.Attrs[correct_name]
try:
self.data[correct_name] = conv(value)
except ValueError:
log.warning("Could not convert using %s: %s", conv, value)

def load(self, save_cache=True):
"""Load metadata"""
try:
Expand Down Expand Up @@ -816,16 +869,12 @@ def extract_metadata(path: str) -> Dict[str, str]:
value as value
"""
# pylint: disable=invalid-name
data = {}
data: dict = {}
file_name = "config.json"
with zipfile.ZipFile(path, "r") as zip_file:
for fn in ("config.ini", "prusaslicer.ini"):
config_file = zip_file.read(fn).decode("utf-8")
for line in config_file.splitlines():
key, value = line.split(" = ")
try:
data[key] = json.loads(value)
except json.decoder.JSONDecodeError:
data[key] = value
if file_name not in zip_file.namelist():
return data
data = json.loads(zip_file.read(file_name))
return data

@staticmethod
Expand Down
Binary file added tests/gcodes/Shape-Box.sl1
Binary file not shown.
Binary file removed tests/gcodes/pentagonal-hexecontahedron-1.sl1
Binary file not shown.
32 changes: 18 additions & 14 deletions tests/test_metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -335,26 +335,20 @@ class TestSLMetaData:

def test_sl(self):
"""Basic test."""
fname = os.path.join(gcodes_dir, "pentagonal-hexecontahedron-1.sl1")
fname = os.path.join(gcodes_dir, "Shape-Box.sl1")
meta = get_metadata(fname, False)

assert meta.data == {
'printer_model': 'SL1',
'printTime': 8720,
'faded_layers': 10,
'exposure_time': 7.5,
'initial_exposure_time': 35.0,
'max_initial_exposure_time': 300.0,
'max_exposure_time': 120.0,
'min_initial_exposure_time': 1.0,
'min_exposure_time': 1.0,
'estimated_print_time': 2722,
'exposure_time': 2,
'exposure_time_first': 25,
'layer_height': 0.05,
'materialName': 'Prusa Orange Tough @0.05',
'fileCreationTimestamp': '2020-09-17 at 13:53:21 UTC'
'material': 'Prusament Resin Tough Prusa Orange @0.05 SL1S',
'printer_model': 'SL1S'
}

assert len(meta.thumbnails["400x400_PNG"]) == 19688
assert len(meta.thumbnails["800x480_PNG"]) == 64524
assert len(meta.thumbnails["400x400_PNG"]) == 26948
assert len(meta.thumbnails["800x480_PNG"]) == 77796

def test_sl_empty_file(self):
"""Test a file that is empty"""
Expand All @@ -370,3 +364,13 @@ def test_sl1_chunk_read(self):
chunk_meta = get_meta_class(fname)
chunk_read_file(chunk_meta, fname)
assert chunk_meta.data == {}

def test_set_attr_same_as_set_data(self):
fname = os.path.join(gcodes_dir, "Shape-Box.sl1")
meta = get_metadata(fname, False)
# read from set_attr
meta_cls = get_meta_class(fname, "Shape-Box.sl1")
raw_meta = meta_cls.extract_metadata(fname)
for attr, value in raw_meta.items():
meta_cls.set_attr(attr, value)
assert meta_cls.data == meta.data

0 comments on commit e49e15f

Please sign in to comment.