From 10e312d69af18b7f2cd6b6135527ac4efb05ffbc Mon Sep 17 00:00:00 2001
From: Jacob Wahlman <jacwa448@student.liu.se>
Date: Wed, 22 Apr 2020 14:51:45 +0200
Subject: [PATCH] Added save and load of data structures, updated w/
 requirement

---
 b_asic/utils.py                  | 34 ++++++++++++++++++++++++++------
 setup.py                         |  3 ++-
 test/test_load_save_structure.py | 20 +------------------
 3 files changed, 31 insertions(+), 26 deletions(-)

diff --git a/b_asic/utils.py b/b_asic/utils.py
index d8df7767..7cca1f15 100644
--- a/b_asic/utils.py
+++ b/b_asic/utils.py
@@ -4,12 +4,14 @@ This module contains functions that are used as utilities by other modules or by
 """
 
 from typing import Optional
-import pickle
+from os import getcwd, path
 
 from b_asic import AbstractOperation
 
+import dill  # Used instead of pickle to support serializing lambda functions
 
-def save_structure(struct: AbstractOperation, path: Optional[str] = None) -> str: 
+
+def save_structure(struct: AbstractOperation, _path: Optional[str] = None, _name: Optional[str] = None) -> str: 
     """Saves the structure to a specific path using the pickle module.
     Returns the path to the struct if save succeeds.
     
@@ -17,15 +19,35 @@ def save_structure(struct: AbstractOperation, path: Optional[str] = None) -> str
     struct: The structure to save.
 
     Keyword Arguments:
-    path: The path to which the structure will be saved.
+    _path: The path (str) to which the structure will be saved.
+    _name: The name (str) of the file to be saved. Only used if _path is not defined and is not None.
     """
-    pass
+    try:
+        _name = _name if _name is not None else f"{struct.type_name}.pickle"
+
+        if _path is None:
+            _path = path.join(getcwd(), _name)
 
-def load_structure(path: str) -> AbstractOperation:
+        print(_path)
+        with open(_path, "wb") as handle:
+            dill.dump(struct, handle, protocol=dill.HIGHEST_PROTOCOL)
+    except Exception as e:
+        print("Unexpected error occured while saving structure: ", e)
+        return None
+    
+    return _path
+
+def load_structure(_path: str) -> AbstractOperation:
     """Saves the structure to a specific path using the pickle module.
     Returns the struct that was loaded from the path.
 
     Keyword Arguments:
     path: The path to which the structure will be loaded from.
     """
-    pass
\ No newline at end of file
+    try:
+        with open(_path, "rb") as handle:
+            return dill.load(handle)
+    except Exception as e:
+        print("Unexpected error occured while saving structure: ", e)
+    
+    return None
diff --git a/setup.py b/setup.py
index 43d55d40..d8427686 100644
--- a/setup.py
+++ b/setup.py
@@ -71,7 +71,8 @@ setuptools.setup(
     install_requires = [
         "pybind11>=2.3.0",
         "numpy",
-        "install_qt_binding"
+        "install_qt_binding",
+        "dill>=0.3.1.1"
     ],
     packages = ["b_asic"],
     ext_modules = [CMakeExtension("b_asic")],
diff --git a/test/test_load_save_structure.py b/test/test_load_save_structure.py
index d1515820..193753b6 100644
--- a/test/test_load_save_structure.py
+++ b/test/test_load_save_structure.py
@@ -20,22 +20,4 @@ class TestSaveStructures:
         _sfg = load_structure(path)
         
         assert isinstance(_sfg, SFG)
-        assert sfg.components == _sfg.components
-
-    def test_save_sfg_custom_path(self, large_operation_tree):
-        sfg = SFG(outputs=[Output(large_operation_tree)])
-        path = save_structure(sfg, path="structures/test")
-        
-        assert path is not None
-        assert isfile(path)
-
-    def test_load_sfg_custom_path(self, large_operation_tree):
-        sfg = SFG(outputs=[Output(large_operation_tree)])
-        path = save_structure(sfg, path="structures/test")
-        _sfg = load_structure(path)
-
-        assert isinstance(_sfg, SFG)
-        assert sfg.components == _sfg.components   
-
-
-
+        assert sfg.evaluate() == _sfg.evaluate()
-- 
GitLab