From df4f5820cea5c8786f118bf94adb950afe6b2aab Mon Sep 17 00:00:00 2001
From: Sebastian Koslowski <koslowski@kit.edu>
Date: Wed, 11 Nov 2015 18:48:28 +0100
Subject: grc: some clean-up

---
 grc/python/Generator.py | 32 +++++++++++++++++---------------
 1 file changed, 17 insertions(+), 15 deletions(-)

(limited to 'grc/python/Generator.py')

diff --git a/grc/python/Generator.py b/grc/python/Generator.py
index f064c7528f..ddd32ca355 100644
--- a/grc/python/Generator.py
+++ b/grc/python/Generator.py
@@ -24,6 +24,7 @@ import tempfile
 import shlex
 import codecs
 from distutils.spawn import find_executable
+
 from Cheetah.Template import Template
 
 from .. gui import Messages
@@ -152,11 +153,12 @@ class TopBlockGenerator(object):
         """
         output = list()
 
-        title = self._flow_graph.get_option('title') or self._flow_graph.get_option('id').replace('_', ' ').title()
-        imports = self._flow_graph.get_imports()
-        variables = self._flow_graph.get_variables()
-        parameters = self._flow_graph.get_parameters()
-        monitors = self._flow_graph.get_monitors()
+        fg = self._flow_graph
+        title = fg.get_option('title') or fg.get_option('id').replace('_', ' ').title()
+        imports = fg.get_imports()
+        variables = fg.get_variables()
+        parameters = fg.get_parameters()
+        monitors = fg.get_monitors()
 
         # list of blocks not including variables and imports and parameters and disabled
         def _get_block_sort_text(block):
@@ -172,7 +174,7 @@ class TopBlockGenerator(object):
             return code
 
         blocks = expr_utils.sort_objects(
-            filter(lambda b: b.get_enabled() and not b.get_bypassed(), self._flow_graph.iter_blocks()),
+            filter(lambda b: b.get_enabled() and not b.get_bypassed(), fg.iter_blocks()),
             lambda b: b.get_id(), _get_block_sort_text
         )
         # List of regular blocks (all blocks minus the special ones)
@@ -186,14 +188,14 @@ class TopBlockGenerator(object):
 
         # Filter out virtual sink connections
         cf = lambda c: not (c.is_bus() or c.is_msg() or c.get_sink().get_parent().is_virtual_sink())
-        connections = filter(cf, self._flow_graph.get_enabled_connections())
+        connections = filter(cf, fg.get_enabled_connections())
 
-        # Get the virtual blocks and resolve their conenctions
+        # Get the virtual blocks and resolve their connections
         virtual = filter(lambda c: c.get_source().get_parent().is_virtual_source(), connections)
         for connection in virtual:
             source = connection.get_source().resolve_virtual_source()
             sink = connection.get_sink()
-            resolved = self._flow_graph.get_parent().Connection(flow_graph=self._flow_graph, porta=source, portb=sink)
+            resolved = fg.get_parent().Connection(flow_graph=fg, porta=source, portb=sink)
             connections.append(resolved)
             # Remove the virtual connection
             connections.remove(connection)
@@ -203,7 +205,7 @@ class TopBlockGenerator(object):
         # that bypass the selected block and remove the existing ones. This allows adjacent
         # bypassed blocks to see the newly created connections to downstream blocks,
         # allowing them to correctly construct bypass connections.
-        bypassed_blocks = self._flow_graph.get_bypassed_blocks()
+        bypassed_blocks = fg.get_bypassed_blocks()
         for block in bypassed_blocks:
             # Get the upstream connection (off of the sink ports)
             # Use *connections* not get_connections()
@@ -222,7 +224,7 @@ class TopBlockGenerator(object):
                     # Ignore disabled connections
                     continue
                 sink_port = sink.get_sink()
-                connection = self._flow_graph.get_parent().Connection(flow_graph=self._flow_graph, porta=source_port, portb=sink_port)
+                connection = fg.get_parent().Connection(flow_graph=fg, porta=source_port, portb=sink_port)
                 connections.append(connection)
                 # Remove this sink connection
                 connections.remove(sink)
@@ -235,8 +237,8 @@ class TopBlockGenerator(object):
             c.get_source().get_parent().get_id(), c.get_sink().get_parent().get_id()
         ))
 
-        connection_templates = self._flow_graph.get_parent().get_connection_templates()
-        msgs = filter(lambda c: c.is_msg(), self._flow_graph.get_enabled_connections())
+        connection_templates = fg.get_parent().get_connection_templates()
+        msgs = filter(lambda c: c.is_msg(), fg.get_enabled_connections())
         # list of variable names
         var_ids = [var.get_id() for var in parameters + variables]
         # prepend self.
@@ -244,7 +246,7 @@ class TopBlockGenerator(object):
         # list of callbacks
         callbacks = [
             expr_utils.expr_replace(cb, replace_dict)
-            for cb in sum([block.get_callbacks() for block in self._flow_graph.get_enabled_blocks()], [])
+            for cb in sum([block.get_callbacks() for block in fg.get_enabled_blocks()], [])
         ]
         # map var id to callbacks
         var_id2cbs = dict([
@@ -255,7 +257,7 @@ class TopBlockGenerator(object):
         namespace = {
             'title': title,
             'imports': imports,
-            'flow_graph': self._flow_graph,
+            'flow_graph': fg,
             'variables': variables,
             'parameters': parameters,
             'monitors': monitors,
-- 
cgit v1.2.3


From 635bb2d62420001e4a0c34b3898aa259775e43b8 Mon Sep 17 00:00:00 2001
From: Sebastian Koslowski <koslowski@kit.edu>
Date: Wed, 2 Dec 2015 17:45:06 +0100
Subject: grc: add embedded python modules

---
 grc/blocks/epy_module.xml | 33 +++++++++++++++++++++++++++++++++
 grc/gui/Param.py          |  2 +-
 grc/python/FlowGraph.py   | 22 ++++++++++++++++++----
 grc/python/Generator.py   |  8 ++++++--
 grc/python/Param.py       |  2 +-
 5 files changed, 59 insertions(+), 8 deletions(-)
 create mode 100644 grc/blocks/epy_module.xml

(limited to 'grc/python/Generator.py')

diff --git a/grc/blocks/epy_module.xml b/grc/blocks/epy_module.xml
new file mode 100644
index 0000000000..6d6d71804c
--- /dev/null
+++ b/grc/blocks/epy_module.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0"?>
+<block>
+	<name>Python Module</name>
+	<key>epy_module</key>
+	<category>Misc</category>
+	<import>import $id  # embedded python module</import>
+	<make></make>
+	<param>
+		<name>Code</name>
+		<key>source_code</key>
+		<value># this module will be imported in the into your flowgraph</value>
+		<type>_multiline_python_external</type>
+		<hide>part</hide>
+	</param>
+	<doc>This block lets you embed a python module in your flowgraph.
+
+Code you put in this module is accessible in other blocks using the ID of this
+block. Example:
+
+If you put
+
+    a = 2
+
+    def double(arg):
+        return 2 * arg
+
+in a Python Module Block with the ID 'stuff' you can use code like
+
+    stuff.a  # evals to 2
+    stuff.double(3)  # evals to 6
+
+to set parameters of other blocks in your flowgraph.</doc>
+</block>
diff --git a/grc/gui/Param.py b/grc/gui/Param.py
index 515c345a73..6884d6530a 100644
--- a/grc/gui/Param.py
+++ b/grc/gui/Param.py
@@ -345,7 +345,7 @@ class FileParam(EntryParam):
 
 PARAM_MARKUP_TMPL="""\
 #set $foreground = $param.is_valid() and 'black' or 'red'
-<span foreground="$foreground" font_desc="$font"><b>$encode($param.get_name()): </b>$encode(repr($param))</span>"""
+<span foreground="$foreground" font_desc="$font"><b>$encode($param.get_name()): </b>$encode(repr($param).replace('\\n',' '))</span>"""
 
 PARAM_LABEL_MARKUP_TMPL="""\
 #set $foreground = $modified and 'blue' or $param.is_valid() and 'black' or 'red'
diff --git a/grc/python/FlowGraph.py b/grc/python/FlowGraph.py
index bedf9ccf33..686dae70fa 100644
--- a/grc/python/FlowGraph.py
+++ b/grc/python/FlowGraph.py
@@ -17,6 +17,7 @@ along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 """
 import re
+import imp
 from operator import methodcaller
 
 from . import expr_utils
@@ -203,6 +204,12 @@ class FlowGraph(_FlowGraph, _GUIFlowGraph):
                           self.iter_enabled_blocks())
         return monitors
 
+    def get_python_modules(self):
+        """Iterate over custom code block ID and Source"""
+        for block in self.iter_enabled_blocks():
+            if block.get_key() == 'epy_module':
+                yield block.get_id(), block.get_param('source_code').get_value()
+
     def get_bussink(self):
         bussink = filter(lambda b: _bussink_searcher.search(b.get_key()), self.get_enabled_blocks())
 
@@ -213,8 +220,6 @@ class FlowGraph(_FlowGraph, _GUIFlowGraph):
 
         return False
 
-
-
     def get_bussrc(self):
         bussrc = filter(lambda b: _bussrc_searcher.search(b.get_key()), self.get_enabled_blocks())
 
@@ -278,9 +283,18 @@ class FlowGraph(_FlowGraph, _GUIFlowGraph):
             #reload namespace
             n = dict()
             #load imports
-            for imp in self.get_imports():
-                try: exec imp in n
+            for code in self.get_imports():
+                try: exec code in n
                 except: pass
+
+            for id, code in self.get_python_modules():
+                try:
+                    module = imp.new_module(id)
+                    exec code in module.__dict__
+                    n[id] = module
+                except:
+                    pass
+
             #load parameters
             np = dict()
             for parameter in self.get_parameters():
diff --git a/grc/python/Generator.py b/grc/python/Generator.py
index ddd32ca355..d688beba15 100644
--- a/grc/python/Generator.py
+++ b/grc/python/Generator.py
@@ -181,10 +181,14 @@ class TopBlockGenerator(object):
         blocks = filter(lambda b: b not in (imports + parameters), blocks)
 
         for block in blocks:
-            if block.get_key() == 'epy_block':
-                file_path = os.path.join(self._dirname, block.get_id() + '.py')
+            key = block.get_key()
+            file_path = os.path.join(self._dirname, block.get_id() + '.py')
+            if key == 'epy_block':
                 src = block.get_param('_source_code').get_value()
                 output.append((file_path, src))
+            elif key == 'epy_module':
+                src = block.get_param('source_code').get_value()
+                output.append((file_path, src))
 
         # Filter out virtual sink connections
         cf = lambda c: not (c.is_bus() or c.is_msg() or c.get_sink().get_parent().is_virtual_sink())
diff --git a/grc/python/Param.py b/grc/python/Param.py
index 746f677e46..e60f613f00 100644
--- a/grc/python/Param.py
+++ b/grc/python/Param.py
@@ -31,7 +31,7 @@ from Constants import VECTOR_TYPES, COMPLEX_TYPES, REAL_TYPES, INT_TYPES
 from gnuradio import eng_notation
 
 _check_id_matcher = re.compile('^[a-z|A-Z]\w*$')
-_show_id_matcher = re.compile('^(variable\w*|parameter|options|notebook)$')
+_show_id_matcher = re.compile('^(variable\w*|parameter|options|notebook|epy_module)$')
 
 
 #blacklist certain ids, its not complete, but should help
-- 
cgit v1.2.3