Skip to content

Commit

Permalink
Added save/load cache functions to metadata
Browse files Browse the repository at this point in the history
  • Loading branch information
Michal Zoubek authored and ondratu committed Feb 12, 2021
1 parent 7d6174f commit eff730f
Show file tree
Hide file tree
Showing 12 changed files with 965 additions and 67 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -128,4 +128,5 @@ dmypy.json
# Pyre type checker
.pyre/

.idea
# .idea stuff
.idea
1 change: 1 addition & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ ChnageLog
* introduce errors.TOKEN signaling if a token is available
* add ironing to FDM metadata
* introduce `File.size` as a settable property
* added functions for save/load cache of data

0.2.0 (2020-12-14)

Expand Down
61 changes: 33 additions & 28 deletions prusa/connect/printer/metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,33 @@
import zipfile
from typing import Dict, Any, List
from .const import GCODE_EXTENSIONS
from logging import getLogger


class UnknownGcodeFileType(ValueError):
# pylint: disable=missing-class-docstring
...


def thumbnail_from_bytes(data_input):
"""Parse thumbnail from bytes to string format because
of JSON serialization requirements"""
converted_data = dict()
for key, value in data_input.items():
if type(value) is bytes:
converted_data[key] = str(value, 'utf-8')
return converted_data


def thumbnail_to_bytes(data_input):
"""Parse thumbnail from string to original bytes format"""
converted_data = dict()
for key, value in data_input.items():
if key == "thumbnails":
for key_, value_ in value.items():
converted_data[key_] = bytes(value_, 'utf-8')


class MetaData:
"""Base MetaData class"""

Expand All @@ -29,32 +49,24 @@ def __init__(self, path: str):
self.path = path
self.thumbnails = {}
self.data = {}
self.log = getLogger()

def check_cache_time(self):
"""If cache is older than file, returns True"""
def check_fresh(self):
"""If cache is fresher than file, returns True"""
file_time_created = os.path.getctime(self.path)
try:
cache_time_created = os.path.getctime(self.path + ".cache")
file_time_created = os.path.getctime(self.path)
if cache_time_created > file_time_created:
return True
return file_time_created < cache_time_created
except FileNotFoundError:
return True
return False

def save_cache(self):
"""Take metadata from source file and save them as JSON to
<file_name>.cache file"""
try:
if self.check_cache_time():
def parse_from_bytes(data_input):
"""Parse thumbnail from bytes to string format because
of JSON serialization requirements"""
for key, value in data_input.items():
if type(value) is bytes:
data_input[key] = str(value, 'utf-8')
return data_input

thumbnails = parse_from_bytes(self.thumbnails)

# If original file is fresher than cache, create a new cache
if not self.check_fresh():
thumbnails = thumbnail_from_bytes(self.thumbnails)
with open(self.path + ".cache", "w") as file:
dict_data = {
"path": self.path,
Expand All @@ -63,27 +75,20 @@ def parse_from_bytes(data_input):
}
json.dump(dict_data, file, indent=2)
except PermissionError:
raise Exception("You don't have permission for save file here")
self.log.warning("You don't have permission for save file here")

def load_cache(self):
"""Load metadata values from <file_name>.cache file"""
try:
with open(self.path + ".cache", "r") as file:
cache_data = json.load(file)

def parse_to_bytes(data_input):
"""Parse thumbnail from string to original bytes format"""
for key, value in data_input.items():
if key == "thumbnails":
for key_, value_ in value.items():
value[key_] = bytes(value_, 'utf-8')
parse_to_bytes(cache_data)

thumbnail_to_bytes(cache_data)
self.path = cache_data["path"]
self.thumbnails = cache_data["thumbnails"]
self.data = cache_data["data"]

except json.decoder.JSONDecodeError as err:
except (json.decoder.JSONDecodeError, FileNotFoundError, KeyError)\
as err:
raise ValueError(
"JSON data not found or in incorrect format") from err

Expand Down
427 changes: 427 additions & 0 deletions tests/gcodes/metadata/fdn_filename.gcode

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"path": "/home/michal/git/Prusa-Connect-SDK-Printer/tests/gcodes/metadata/fdn_filename_empty.gcode",
"path": "/home/michal/git/Prusa-Connect-SDK-Printer/tests/gcodes/metadata/fdn_filename.gcode",
"thumbnails": {
"16x16": "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABjUlEQVR4AbWQTUsCURSGZ2Wr3AVpVpYGIWJ+po7OOOM44zh+jSRJoOVHSkSLolW7fkAE0a5F7ou20S7oj/hT3jw3EKGyGmjg3MvMfZ/nzD0c9x/P4vycuxNzXVIVNhfa9B502iXaZ0IUvsh6hm/HCXxXJPpScFP1vc4Cp4v+7FP338LTxWCyWYEfWqERE5wK7qEVwWQe46X90o9ZEtDAOZvNZun+j60QHPY5iYvH47jaifwJfj6MoZncQCQSGXGiKEIVefRTHjzth3+Ge1Fc17agCDzS6TSYQJZllFQZZ6Ibw0YA97sB3NX9NOlJx1vTh962C+3EOnRFgiRJEAQBHC0kyOfzMA0N3ZgLzbATg8QyzjNrOEmtojsGD6JL6Ke9KOsqyxIzEZBNVVUUi0U0qkV0eQ+OkitMthd0sL3Le1GvGDAMg2VJkMlkPgR0jWw2y8ylUgm1Wg0dncdA9qMlh9DSEjBNk51RhrLE5HI5cNSdimyKokDTNNalXC4zqFKpMJC+0RnBlC0UCtB1He91MLXiB9IHtQAAAABJRU5ErkJggg==",
"220x124": "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"
Expand Down
Loading

0 comments on commit eff730f

Please sign in to comment.