From 01fd3b0adad1dec0c844e6ea96aea234bdf6031f Mon Sep 17 00:00:00 2001
From: Jacob Wahlman <jacwa448@student.liu.se>
Date: Sat, 25 Apr 2020 14:35:17 +0200
Subject: [PATCH] implemented recipe functionality

---
 b_asic/utils.py                  | 18 +++++++++--
 test/test_load_save_structure.py | 53 +++++++++++++++++++++++---------
 2 files changed, 54 insertions(+), 17 deletions(-)

diff --git a/b_asic/utils.py b/b_asic/utils.py
index 42242fd3..11c30073 100644
--- a/b_asic/utils.py
+++ b/b_asic/utils.py
@@ -5,6 +5,7 @@ This module contains functions that are used as utilities by other modules or by
 
 from typing import Optional
 from os import getcwd, path
+import importlib
 
 from b_asic import AbstractOperation
 
@@ -55,13 +56,24 @@ def load_structure(_path: str) -> AbstractOperation:
     
     return None
 
-def load_recipe(module: str) -> None:
+def load_recipe(module: str, _namespace: Optional[dict] = None) -> "Module":
     """Given the module name or the path to a module, import the module and let it evaluate it's content.
-    Returns None as the content from the module will be added to the namespace.
+    Returns the attributes of the module to be added to the namespace.
 
     This runs .py scripts inline by importing them, it currently does no checks for security measure.
 
     Arguments:
     module: The path or name of the module to import from.
+
+    Keyword Arguments:
+    _namespace: The namespace to add the imported vars to. Normally you would want to use globals(). If None return it's own namespace.
     """
-    pass
+    try:
+        if _namespace is None:
+            return importlib.import_module(module)
+
+        return _namespace.update(importlib.import_module(module).__dict__)
+    except Exception as e:
+        print("Unexpected error occured while loading recipe: ", e)
+    
+    return None
diff --git a/test/test_load_save_structure.py b/test/test_load_save_structure.py
index 4881e237..549d772b 100644
--- a/test/test_load_save_structure.py
+++ b/test/test_load_save_structure.py
@@ -53,17 +53,17 @@ class TestSaveStructures:
     
     def test_load_recipe_file(self):
         # Create a file that doesn't exist
-        _file = "".join(choice(ascii_lowercase) for _ in range(4)) + ".py"
-        while path.exists(path.join(getcwd(), _file)):
-            _file = "".join(choice(ascii_lowercase) for _ in range(4)) + ".py"
+        _file = "".join(choice(ascii_lowercase) for _ in range(4))
+        while path.exists(path.join(getcwd(), _file + ".py")):
+            _file = "".join(choice(ascii_lowercase) for _ in range(4))
 
         try:
-            with open(_file, "w+") as handle:
+            with open(_file + ".py", "w+") as handle:
                 # The string is indented that way so the file is properly indented, .strip() did not work idk why
                 handle.write(
 """
 from b_asic import SFG, Output, Addition, Constant
-sfg = SFG(outputs=[Output(Addition(Addition(Constant(2), Constant(3)), Addition(Constant(4), Constant(5))))])
+sfg_recipe = SFG(outputs=[Output(Addition(Addition(Constant(2), Constant(3)), Addition(Constant(4), Constant(5))))])
 """
                 )
         except Exception as e:
@@ -71,17 +71,42 @@ sfg = SFG(outputs=[Output(Addition(Addition(Constant(2), Constant(3)), Addition(
 
         # Not defined yet
         with pytest.raises(NameError):
-            sfg.evaluate() == 14
+            sfg_recipe.evaluate() == 14
 
-        load_recipe(_file)
-        assert sfg.evaluate() == 14
+        load_recipe(_file, globals())
+        assert sfg_recipe.evaluate() == 14
 
-    def test_load_invalid_recipe_file(self):
-        _file = "".join(choice(ascii_lowercase) for _ in range(4)) + ".py"
-        while path.exists(path.join(getcwd(), _file)):
-            _file = "".join(choice(ascii_lowercase) for _ in range(4)) + ".py"
+    def test_load_recipe_file_namespace(self):
+        # Create a file that doesn't exist
+        _file = "".join(choice(ascii_lowercase) for _ in range(4))
+        while path.exists(path.join(getcwd(), _file + ".py")):
+            _file = "".join(choice(ascii_lowercase) for _ in range(4))
 
+        try:
+            with open(_file + ".py", "w+") as handle:
+                # The string is indented that way so the file is properly indented, .strip() did not work idk why
+                handle.write(
+"""
+from b_asic import SFG, Output, Addition, Constant
+sfg_recipe_2 = SFG(outputs=[Output(Addition(Addition(Constant(2), Constant(3)), Addition(Constant(4), Constant(5))))])
+"""
+                )
+        except Exception as e:
+            assert False, f"Could not create file: {e}"
+
+        # Not defined yet
+        with pytest.raises(NameError):
+            sfg_recipe_2.evaluate() == 14
+
+        _namespace = load_recipe(_file)
+        assert _namespace.sfg_recipe_2.evaluate() == 14
+        assert _namespace != globals()
+
+    def test_load_invalid_recipe_file(self):
+        _file = "".join(choice(ascii_lowercase) for _ in range(4))
+        while path.exists(path.join(getcwd(), _file + ".py")):
+            _file = "".join(choice(ascii_lowercase) for _ in range(4))
+    
         load_recipe(_file)
         with pytest.raises(NameError):
-            assert sfg.evaluate() == 14
-            
\ No newline at end of file
+            assert sfg_recipe_3.evaluate() == 14
-- 
GitLab