[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Commit-gnuradio] [gnuradio] 05/18: grc-refactor: fixes, type-testing-fl
From: |
git |
Subject: |
[Commit-gnuradio] [gnuradio] 05/18: grc-refactor: fixes, type-testing-flags, FlowGraph.py, (more) |
Date: |
Sun, 24 Apr 2016 19:19:37 +0000 (UTC) |
This is an automated email from the git hooks/post-receive script.
jcorgan pushed a commit to branch master
in repository gnuradio.
commit ed6e9a484ddddbbadf19584f6606d2c9e36de823
Author: Sebastian Koslowski <address@hidden>
Date: Sun Feb 7 13:44:59 2016 +0100
grc-refactor: fixes, type-testing-flags, FlowGraph.py, (more)
---
grc/gui/ActionHandler.py | 2 +-
grc/gui/Block.py | 19 +-
grc/gui/FlowGraph.py | 46 +-
grc/gui/Port.py | 18 +-
grc/model/Block.py | 11 +-
grc/model/Connection.py | 10 +-
grc/model/Constants.py | 8 +-
grc/model/Element.py | 33 +-
grc/model/FlowGraph.py | 763 +++++++++++-------------------
grc/model/Param.py | 5 +-
grc/model/Platform.py | 22 +-
grc/model/Port.py | 21 +-
grc/model/{ => generator}/Generator.py | 18 +-
grc/model/generator/__init__.py | 1 +
grc/model/{ => generator}/flow_graph.tmpl | 0
grc/model/utils/__init__.py | 6 +
grc/model/utils/complexity.py | 49 ++
17 files changed, 451 insertions(+), 581 deletions(-)
diff --git a/grc/gui/ActionHandler.py b/grc/gui/ActionHandler.py
index 1702475..b219ed2 100644
--- a/grc/gui/ActionHandler.py
+++ b/grc/gui/ActionHandler.py
@@ -232,7 +232,7 @@ class ActionHandler:
if y < y_min:
y_min = y
- for connection in block.get_connections():
+ for connection in block.connections:
# Get id of connected blocks
source_id =
connection.get_source().get_parent().get_id()
diff --git a/grc/gui/Block.py b/grc/gui/Block.py
index 97b4e96..2439c32 100644
--- a/grc/gui/Block.py
+++ b/grc/gui/Block.py
@@ -32,7 +32,7 @@ from .Constants import (
from . Element import Element
from ..model.odict import odict
from ..model.Param import num_to_str
-
+from ..model.utils.complexity import calculate_flowgraph_complexity
from ..model.Block import Block as _Block
BLOCK_MARKUP_TMPL="""\
@@ -138,10 +138,10 @@ class Block(Element, _Block):
delta_coor: requested delta coordinate (dX, dY) to move
Returns:
- The delta coordinate possible to move while keeping the block on
the canvas
+ The delta coordinate possible to move while keeping the block on
the canvas
or the input (dX, dY) on failure
"""
- dX, dY = delta_coor
+ dX, dY = delta_coor
try:
fgW, fgH = self.get_parent().get_size()
@@ -150,7 +150,7 @@ class Block(Element, _Block):
sW, sH = self.W, self.H
else:
sW, sH = self.H, self.W
-
+
if x + dX < 0:
dX = -x
elif dX + x + sW >= fgW:
@@ -162,7 +162,7 @@ class Block(Element, _Block):
except:
pass
- return ( dX, dY )
+ return ( dX, dY )
def get_rotation(self):
"""
@@ -196,7 +196,7 @@ class Block(Element, _Block):
def create_labels(self):
"""Create the labels for the signal block."""
Element.create_labels(self)
- self._bg_color = self.is_dummy_block() and
Colors.MISSING_BLOCK_BACKGROUND_COLOR or \
+ self._bg_color = self.is_dummy_block and
Colors.MISSING_BLOCK_BACKGROUND_COLOR or \
self.get_bypassed() and Colors.BLOCK_BYPASSED_COLOR
or \
self.get_enabled() and Colors.BLOCK_ENABLED_COLOR or
Colors.BLOCK_DISABLED_COLOR
@@ -207,7 +207,7 @@ class Block(Element, _Block):
layout.set_markup(Utils.parse_template(BLOCK_MARKUP_TMPL, block=self,
font=BLOCK_FONT))
self.label_width, self.label_height = layout.get_pixel_size()
#display the params
- if self.is_dummy_block():
+ if self.is_dummy_block:
markups = [
'<span foreground="black" font_desc="{font}"><b>key:
</b>{key}</span>'.format(font=PARAM_FONT, key=self._key)
]
@@ -274,7 +274,8 @@ class Block(Element, _Block):
# Show the flowgraph complexity on the top block if enabled
if Actions.TOGGLE_SHOW_FLOWGRAPH_COMPLEXITY.get_active() and
self.get_key() == "options":
- complexity = "Complexity:
{}bal".format(num_to_str(self.get_parent().get_complexity()))
+ complexity = calculate_flowgraph_complexity(self.get_parent())
+ complexity = "Complexity: {}bal".format(num_to_str(complexity))
layout = gtk.DrawingArea().create_pango_layout('')
layout.set_markup(Utils.parse_template(COMMENT_COMPLEXITY_MARKUP_TMPL,
@@ -314,7 +315,7 @@ class Block(Element, _Block):
Element.draw(
self, gc, window, bg_color=self._bg_color,
border_color=self.is_highlighted() and Colors.HIGHLIGHT_COLOR or
- self.is_dummy_block() and
Colors.MISSING_BLOCK_BORDER_COLOR or Colors.BORDER_COLOR,
+ self.is_dummy_block and
Colors.MISSING_BLOCK_BORDER_COLOR or Colors.BORDER_COLOR,
)
#draw label image
if self.is_horizontal():
diff --git a/grc/gui/FlowGraph.py b/grc/gui/FlowGraph.py
index e975595..0c66a7e 100644
--- a/grc/gui/FlowGraph.py
+++ b/grc/gui/FlowGraph.py
@@ -19,7 +19,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA
import random
import functools
-from itertools import chain
+from itertools import chain, count
from operator import methodcaller
from distutils.spawn import find_executable
@@ -65,6 +65,22 @@ class FlowGraph(Element, _Flowgraph):
self._external_updaters = {}
+ def _get_unique_id(self, base_id=''):
+ """
+ Get a unique id starting with the base id.
+
+ Args:
+ base_id: the id starts with this and appends a count
+
+ Returns:
+ a unique id
+ """
+ for index in count():
+ block_id = '{}_{}'.format(base_id, index)
+ if block_id not in (b.get_id() for b in self.blocks):
+ break
+ return block_id
+
def install_external_editor(self, param):
target = (param.get_parent().get_id(), param.get_key())
@@ -163,7 +179,7 @@ class FlowGraph(Element, _Flowgraph):
#get connections between selected blocks
connections = filter(
lambda c: c.get_source().get_parent() in blocks and
c.get_sink().get_parent() in blocks,
- self.get_connections(),
+ self.connections,
)
clipboard = (
(x_min, y_min),
@@ -202,7 +218,7 @@ class FlowGraph(Element, _Flowgraph):
if param_key == 'id':
old_id2block[param_value] = block
#if the block id is not unique, get a new block id
- if param_value in [bluck.get_id() for bluck in
self.get_blocks()]:
+ if param_value in (blk.get_id() for blk in self.blocks):
param_value = self._get_unique_id(param_value)
#set value to key
block.get_param(param_key).set_value(param_value)
@@ -284,7 +300,7 @@ class FlowGraph(Element, _Flowgraph):
"""
for selected_block in self.get_selected_blocks():
delta_coordinate =
selected_block.bound_move_delta(delta_coordinate)
-
+
for selected_block in self.get_selected_blocks():
selected_block.move(delta_coordinate)
self.element_moved = True
@@ -346,7 +362,7 @@ class FlowGraph(Element, _Flowgraph):
# draw comments first
if Actions.TOGGLE_SHOW_BLOCK_COMMENTS.get_active():
- for block in self.iter_blocks():
+ for block in self.blocks:
if block.get_enabled():
block.draw_comment(gc, window)
#draw multi select rectangle
@@ -364,8 +380,8 @@ class FlowGraph(Element, _Flowgraph):
window.draw_rectangle(gc, False, x, y, w, h)
#draw blocks on top of connections
hide_disabled_blocks = Actions.TOGGLE_HIDE_DISABLED_BLOCKS.get_active()
- blocks = sorted(self.iter_blocks(), key=methodcaller('get_enabled'))
- for element in chain(self.iter_connections(), blocks):
+ blocks = sorted(self.blocks, key=methodcaller('get_enabled'))
+ for element in chain(self.connections, blocks):
if hide_disabled_blocks and not element.get_enabled():
continue # skip hidden disabled blocks and connections
element.draw(gc, window)
@@ -452,13 +468,13 @@ class FlowGraph(Element, _Flowgraph):
if not selected_element: continue
# hidden disabled connections, blocks and their ports can not be
selected
if Actions.TOGGLE_HIDE_DISABLED_BLOCKS.get_active() and (
- selected_element.is_block() and not
selected_element.get_enabled() or
- selected_element.is_connection() and not
selected_element.get_enabled() or
- selected_element.is_port() and not
selected_element.get_parent().get_enabled()
+ selected_element.is_block and not
selected_element.get_enabled() or
+ selected_element.is_connection and not
selected_element.get_enabled() or
+ selected_element.is_port and not
selected_element.get_parent().get_enabled()
):
continue
#update the selected port information
- if selected_element.is_port():
+ if selected_element.is_port:
if not coor_m: selected_port = selected_element
selected_element = selected_element.get_parent()
selected.add(selected_element)
@@ -482,7 +498,8 @@ class FlowGraph(Element, _Flowgraph):
"""
selected = set()
for selected_element in self.get_selected_elements():
- if selected_element.is_connection(): selected.add(selected_element)
+ if selected_element.is_connection:
+ selected.add(selected_element)
return list(selected)
def get_selected_blocks(self):
@@ -494,7 +511,8 @@ class FlowGraph(Element, _Flowgraph):
"""
selected = set()
for selected_element in self.get_selected_elements():
- if selected_element.is_block(): selected.add(selected_element)
+ if selected_element.is_block:
+ selected.add(selected_element)
return list(selected)
def get_selected_block(self):
@@ -669,7 +687,7 @@ class FlowGraph(Element, _Flowgraph):
adj.set_value(adj_val-SCROLL_DISTANCE)
adj.emit('changed')
#remove the connection if selected in drag event
- if len(self.get_selected_elements()) == 1 and
self.get_selected_element().is_connection():
+ if len(self.get_selected_elements()) == 1 and
self.get_selected_element().is_connection:
Actions.ELEMENT_DELETE()
#move the selected elements and record the new coordinate
if not self.get_ctrl_mask():
diff --git a/grc/gui/Port.py b/grc/gui/Port.py
index 28d3b4d..c281cbd 100644
--- a/grc/gui/Port.py
+++ b/grc/gui/Port.py
@@ -64,7 +64,7 @@ class Port(_Port, Element):
rotation = self.get_rotation()
#get all sibling ports
ports = self.get_parent().get_sources_gui() \
- if self.is_source() else self.get_parent().get_sinks_gui()
+ if self.is_source else self.get_parent().get_sinks_gui()
ports = filter(lambda p: not p.get_hide(), ports)
#get the max width
self.W = max([port.W for port in ports] + [PORT_MIN_WIDTH])
@@ -82,27 +82,27 @@ class Port(_Port, Element):
index = length-index-1
port_separation = PORT_SEPARATION \
- if not self.get_parent().has_busses[self.is_source()] \
+ if not self.get_parent().has_busses[self.is_source] \
else max([port.H for port in ports]) + PORT_SPACING
offset = (self.get_parent().H - (length-1)*port_separation - self.H)/2
#create areas and connector coordinates
- if (self.is_sink() and rotation == 0) or (self.is_source() and
rotation == 180):
+ if (self.is_sink and rotation == 0) or (self.is_source and rotation ==
180):
x = -W
y = port_separation*index+offset
self.add_area((x, y), (W, self.H))
self._connector_coordinate = (x-1, y+self.H/2)
- elif (self.is_source() and rotation == 0) or (self.is_sink() and
rotation == 180):
+ elif (self.is_source and rotation == 0) or (self.is_sink and rotation
== 180):
x = self.get_parent().W
y = port_separation*index+offset
self.add_area((x, y), (W, self.H))
self._connector_coordinate = (x+1+W, y+self.H/2)
- elif (self.is_source() and rotation == 90) or (self.is_sink() and
rotation == 270):
+ elif (self.is_source and rotation == 90) or (self.is_sink and rotation
== 270):
y = -W
x = port_separation*index+offset
self.add_area((x, y), (self.H, W))
self._connector_coordinate = (x+self.H/2, y-1)
- elif (self.is_sink() and rotation == 90) or (self.is_source() and
rotation == 270):
+ elif (self.is_sink and rotation == 90) or (self.is_source and rotation
== 270):
y = self.get_parent().W
x = port_separation*index+offset
self.add_area((x, y), (self.H, W))
@@ -145,7 +145,7 @@ class Port(_Port, Element):
Element.draw(
self, gc, window, bg_color=self._bg_color,
border_color=self.is_highlighted() and Colors.HIGHLIGHT_COLOR or
- self.get_parent().is_dummy_block() and
Colors.MISSING_BLOCK_BORDER_COLOR or
+ self.get_parent().is_dummy_block and
Colors.MISSING_BLOCK_BORDER_COLOR or
Colors.BORDER_COLOR,
)
if not self._areas_list or self._label_hidden():
@@ -177,8 +177,8 @@ class Port(_Port, Element):
Returns:
the direction in degrees
"""
- if self.is_source(): return self.get_rotation()
- elif self.is_sink(): return (self.get_rotation() + 180)%360
+ if self.is_source: return self.get_rotation()
+ elif self.is_sink: return (self.get_rotation() + 180)%360
def get_connector_length(self):
"""
diff --git a/grc/model/Block.py b/grc/model/Block.py
index ae3169c..8af3e98 100644
--- a/grc/model/Block.py
+++ b/grc/model/Block.py
@@ -71,6 +71,8 @@ def _get_elem(lst, key):
class Block(Element):
+ is_block = True
+
def __init__(self, flow_graph, n):
"""
Make a new block from nested data.
@@ -237,6 +239,11 @@ class Block(Element):
self._epy_source_hash = -1 # for epy blocks
self._epy_reload_error = None
+ if self._bussify_sink:
+ self.bussify({'name': 'bus', 'type': 'bus'}, 'sink')
+ if self._bussify_source:
+ self.bussify({'name': 'bus', 'type': 'bus'}, 'source')
+
def get_bus_structure(self, direction):
if direction == 'source':
bus_structure = self._bus_structure_source
@@ -300,6 +307,7 @@ class Block(Element):
"""
Add and remove ports to adjust for the nports.
"""
+ Element.rewrite(self)
# Check and run any custom rewrite function for this block
getattr(self, 'rewrite_' + self._key, lambda: None)()
@@ -601,9 +609,6 @@ class Block(Element):
def get_id(self):
return self.get_param('id').get_value()
- def is_block(self):
- return True
-
def get_name(self):
return self._name
diff --git a/grc/model/Connection.py b/grc/model/Connection.py
index 7cef4ad..a7b428d 100644
--- a/grc/model/Connection.py
+++ b/grc/model/Connection.py
@@ -25,6 +25,8 @@ from .odict import odict
class Connection(Element):
+ is_connection = True
+
def __init__(self, flow_graph, porta, portb):
"""
Make a new connection given the parent and 2 ports.
@@ -42,9 +44,9 @@ class Connection(Element):
source = sink = None
# Separate the source and sink
for port in (porta, portb):
- if port.is_source():
+ if port.is_source:
source = port
- if port.is_sink():
+ else:
sink = port
if not source:
raise ValueError('Connection could not isolate source')
@@ -57,7 +59,7 @@ class Connection(Element):
if not len(source.get_associated_ports()) ==
len(sink.get_associated_ports()):
raise ValueError('port connections must have same cardinality')
# Ensure that this connection (source -> sink) is unique
- for connection in self.get_parent().get_connections():
+ for connection in flow_graph.connections:
if connection.get_source() is source and connection.get_sink() is
sink:
raise LookupError('This connection between source and sink is
not unique.')
self._source = source
@@ -81,8 +83,6 @@ class Connection(Element):
self.get_sink(),
)
- def is_connection(self): return True
-
def is_msg(self):
return self.get_source().get_type() == self.get_sink().get_type() ==
'msg'
diff --git a/grc/model/Constants.py b/grc/model/Constants.py
index d77dffc..f1dae1d 100644
--- a/grc/model/Constants.py
+++ b/grc/model/Constants.py
@@ -45,6 +45,8 @@ BLOCKS_DIRS = filter( # filter blank strings
DATA_DIR = os.path.dirname(__file__)
FLOW_GRAPH_DTD = os.path.join(DATA_DIR, 'flow_graph.dtd')
BLOCK_TREE_DTD = os.path.join(DATA_DIR, 'block_tree.dtd')
+BLOCK_DTD = os.path.join(DATA_DIR, 'block.dtd')
+DEFAULT_FLOW_GRAPH = os.path.join(DATA_DIR, 'default_flow_graph.grc')
# File format versions:
# 0: undefined / legacy
@@ -79,12 +81,6 @@ TOP_BLOCK_FILE_MODE = stat.S_IRUSR | stat.S_IWUSR |
stat.S_IXUSR | stat.S_IRGRP
stat.S_IWGRP | stat.S_IXGRP | stat.S_IROTH
HIER_BLOCK_FILE_MODE = stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP |
stat.S_IWGRP | stat.S_IROTH
-# Data files
-DATA_DIR = os.path.dirname(__file__)
-FLOW_GRAPH_TEMPLATE = os.path.join(DATA_DIR, 'flow_graph.tmpl')
-BLOCK_DTD = os.path.join(DATA_DIR, 'block.dtd')
-DEFAULT_FLOW_GRAPH = os.path.join(DATA_DIR, 'default_flow_graph.grc')
-
# Define types, native python + numpy
VECTOR_TYPES = (tuple, list, set, numpy.ndarray)
COMPLEX_TYPES = [complex, numpy.complex, numpy.complex64, numpy.complex128]
diff --git a/grc/model/Element.py b/grc/model/Element.py
index 6716cd6..c999d67 100644
--- a/grc/model/Element.py
+++ b/grc/model/Element.py
@@ -90,34 +90,17 @@ class Element(object):
return list()
##############################################
- # Type testing methods
+ # Type testing
##############################################
- def is_element(self):
- return True
-
- def is_platform(self):
- return False
-
- def is_flow_graph(self):
- return False
-
- def is_connection(self):
- return False
-
- def is_block(self):
- return False
+ is_platform = False
- def is_dummy_block(self):
- return False
+ is_flow_graph = False
- def is_source(self):
- return False
+ is_block = False
+ is_dummy_block = False
- def is_sink(self):
- return False
+ is_connection = False
- def is_port(self):
- return False
+ is_port = False
- def is_param(self):
- return False
+ is_param = False
diff --git a/grc/model/FlowGraph.py b/grc/model/FlowGraph.py
index 0aea145..fd391c6 100644
--- a/grc/model/FlowGraph.py
+++ b/grc/model/FlowGraph.py
@@ -1,26 +1,25 @@
-"""
-Copyright 2008-2015 Free Software Foundation, Inc.
-This file is part of GNU Radio
-
-GNU Radio Companion is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-GNU Radio Companion is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
-"""
+# Copyright 2008-2015 Free Software Foundation, Inc.
+# This file is part of GNU Radio
+#
+# GNU Radio Companion is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# GNU Radio Companion is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# 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
import time
from operator import methodcaller
-from itertools import ifilter
+from itertools import ifilter, chain
from ..gui import Messages
@@ -38,36 +37,10 @@ _bus_struct_sink_searcher =
re.compile('^(bus_structure_sink)$')
_bus_struct_src_searcher = re.compile('^(bus_structure_source)$')
-def _initialize_dummy_block(block, block_n):
- """
- This is so ugly... dummy-fy a block
- Modify block object to get the behaviour for a missing block
- """
-
- block._key = block_n.find('key')
- block.is_dummy_block = lambda: True
- block.is_valid = lambda: False
- block.get_enabled = lambda: False
- for param_n in block_n.findall('param'):
- if param_n['key'] not in block.get_param_keys():
- new_param_n = odict({'key': param_n['key'], 'name':
param_n['key'], 'type': 'string'})
- params = block.get_parent().get_parent().Param(block=block,
n=new_param_n)
- block.get_params().append(params)
-
-
-def _dummy_block_add_port(block, key, dir):
- """ This is so ugly... Add a port to a dummy-field block """
- port_n = odict({'name': '?', 'key': key, 'type': ''})
- port = block.get_parent().get_parent().Port(block=block, n=port_n, dir=dir)
- if port.is_source():
- block.get_sources().append(port)
- else:
- block.get_sinks().append(port)
- return port
-
-
class FlowGraph(Element):
+ is_flow_graph = True
+
def __init__(self, platform):
"""
Make a flow graph from the arguments.
@@ -78,214 +51,27 @@ class FlowGraph(Element):
Returns:
the flow graph object
"""
- self.grc_file_path = ''
- # Initialize
Element.__init__(self, platform)
self._elements = []
self._timestamp = time.ctime()
- # Inital blank import
- self.import_data()
- self.n = {}
- self.n_hash = -1
- self._renew_eval_ns = True
- self._eval_cache = {}
+ self.platform = platform # todo: make this a lazy prop
+ self.blocks = []
+ self.connections = []
- def _get_unique_id(self, base_id=''):
- """
- Get a unique id starting with the base id.
+ self._eval_cache = {}
+ self.namespace = {}
- Args:
- base_id: the id starts with this and appends a count
+ self.grc_file_path = ''
- Returns:
- a unique id
- """
- index = 0
- while True:
- id = '{}_{}'.format(base_id, index)
- index += 1
- # Make sure that the id is not used by another block
- if not filter(lambda b: b.get_id() == id, self.get_blocks()):
return id
+ self.import_data()
def __str__(self):
return 'FlowGraph - {}({})'.format(self.get_option('title'),
self.get_option('id'))
- def get_complexity(self):
- """ Determines the complexity of a flowgraph """
- dbal = 0
- block_list = self.get_blocks()
- for block in block_list:
- # Skip options block
- if block.get_key() == 'options':
- continue
-
- # Don't worry about optional sinks?
- sink_list = filter(lambda c: not c.get_optional(),
block.get_sinks())
- source_list = filter(lambda c: not c.get_optional(),
block.get_sources())
- sinks = float(len(sink_list))
- sources = float(len(source_list))
- base = max(min(sinks, sources), 1)
-
- # Port ratio multiplier
- if min(sinks, sources) > 0:
- multi = sinks / sources
- multi = (1 / multi) if multi > 1 else multi
- else:
- multi = 1
-
- # Connection ratio multiplier
- sink_multi = max(float(sum(map(lambda c: len(c.get_connections()),
sink_list)) / max(sinks, 1.0)), 1.0)
- source_multi = max(float(sum(map(lambda c:
len(c.get_connections()), source_list)) / max(sources, 1.0)), 1.0)
- dbal = dbal + (base * multi * sink_multi * source_multi)
-
- elements = float(len(self.get_elements()))
- connections = float(len(self.get_connections()))
- disabled_connections = len(filter(lambda c: not c.get_enabled(),
self.get_connections()))
- blocks = float(len(block_list))
- variables = elements - blocks - connections
- enabled = float(len(self.get_enabled_blocks()))
-
- # Disabled multiplier
- if enabled > 0:
- disabled_multi = 1 / (max(1 - ((blocks - enabled) / max(blocks,
1)), 0.05))
- else:
- disabled_multi = 1
-
- # Connection multiplier (How many connections )
- if (connections - disabled_connections) > 0:
- conn_multi = 1 / (max(1 - (disabled_connections / max(connections,
1)), 0.05))
- else:
- conn_multi = 1
-
- final = round(max((dbal - 1) * disabled_multi * conn_multi *
connections, 0.0) / 1000000, 6)
- return final
-
- def _eval(self, code, namespace, namespace_hash):
- """
- Evaluate the code with the given namespace.
-
- Args:
- code: a string with python code
- namespace: a dict representing the namespace
- namespace_hash: a unique hash for the namespace
-
- Returns:
- the resultant object
- """
- if not code:
- raise Exception('Cannot evaluate empty statement.')
- my_hash = hash(code) ^ namespace_hash
-
- # Cache if does not exist
- if my_hash not in self._eval_cache:
- self._eval_cache[my_hash] = eval(code, namespace, namespace)
- # Return from cache
- return self._eval_cache[my_hash]
-
- def get_hier_block_stream_io(self, direction):
- """
- Get a list of stream io signatures for this flow graph.
-
- Args:
- direction: a string of 'in' or 'out'
-
- Returns:
- a list of dicts with: type, label, vlen, size, optional
- """
- return filter(lambda p: p['type'] != "message",
- self.get_hier_block_io(direction))
-
- def get_hier_block_message_io(self, direction):
- """
- Get a list of message io signatures for this flow graph.
-
- Args:
- direction: a string of 'in' or 'out'
-
- Returns:
- a list of dicts with: type, label, vlen, size, optional
- """
- return filter(lambda p: p['type'] == "message",
- self.get_hier_block_io(direction))
-
- def get_hier_block_io(self, direction):
- """
- Get a list of io ports for this flow graph.
-
- Args:
- direction: a string of 'in' or 'out'
-
- Returns:
- a list of dicts with: type, label, vlen, size, optional
- """
- pads = self.get_pad_sources() if direction in ('sink', 'in') else \
- self.get_pad_sinks() if direction in ('source', 'out') else []
- ports = []
- for pad in pads:
- master = {
- 'label': str(pad.get_param('label').get_evaluated()),
- 'type': str(pad.get_param('type').get_evaluated()),
- 'vlen': str(pad.get_param('vlen').get_value()),
- 'size': pad.get_param('type').get_opt('size'),
- 'optional': bool(pad.get_param('optional').get_evaluated()),
- }
- num_ports = pad.get_param('num_streams').get_evaluated()
- if num_ports > 1:
- for i in xrange(num_ports):
- clone = master.copy()
- clone['label'] += str(i)
- ports.append(clone)
- else:
- ports.append(master)
- return ports
-
- def get_pad_sources(self):
- """
- Get a list of pad source blocks sorted by id order.
-
- Returns:
- a list of pad source blocks in this flow graph
- """
- pads = filter(lambda b: b.get_key() == 'pad_source',
self.get_enabled_blocks())
- return sorted(pads, lambda x, y: cmp(x.get_id(), y.get_id()))
-
- def get_pad_sinks(self):
- """
- Get a list of pad sink blocks sorted by id order.
-
- Returns:
- a list of pad sink blocks in this flow graph
- """
- pads = filter(lambda b: b.get_key() == 'pad_sink',
self.get_enabled_blocks())
- return sorted(pads, lambda x, y: cmp(x.get_id(), y.get_id()))
-
- def get_pad_port_global_key(self, port):
- """
- Get the key for a port of a pad source/sink to use in connect()
- This takes into account that pad blocks may have multiple ports
-
- Returns:
- the key (str)
- """
- key_offset = 0
- pads = self.get_pad_sources() if port.is_source() else
self.get_pad_sinks()
- for pad in pads:
- # using the block param 'type' instead of the port domain here
- # to emphasize that hier block generation is domain agnostic
- is_message_pad = pad.get_param('type').get_evaluated() == "message"
- if port.get_parent() == pad:
- if is_message_pad:
- key = pad.get_param('label').get_value()
- else:
- key = str(key_offset + int(port.get_key()))
- return key
- else:
- # assuming we have either only sources or sinks
- if not is_message_pad:
- key_offset += len(pad.get_ports())
- return -1
-
+ ##############################################
+ # TODO: Move these to new generator package
+ ##############################################
def get_imports(self):
"""
Get a set of all import statments in this flow graph namespace.
@@ -362,7 +148,7 @@ class FlowGraph(Element):
"""
Get an iterator of all blocks that are enabled and not bypassed.
"""
- return ifilter(methodcaller('get_enabled'), self.iter_blocks())
+ return ifilter(methodcaller('get_enabled'), self.blocks)
def get_enabled_blocks(self):
"""
@@ -380,7 +166,7 @@ class FlowGraph(Element):
Returns:
a list of blocks
"""
- return filter(methodcaller('get_bypassed'), self.iter_blocks())
+ return filter(methodcaller('get_bypassed'), self.blocks)
def get_enabled_connections(self):
"""
@@ -389,68 +175,7 @@ class FlowGraph(Element):
Returns:
a list of connections
"""
- return filter(methodcaller('get_enabled'), self.get_connections())
-
- def _get_new_block(self, key):
- """
- Get a new block of the specified key.
- Add the block to the list of elements.
-
- Args:
- key: the block key
-
- Returns:
- the new block or None if not found
- """
- if key not in self.get_parent().get_block_keys():
- return None
- block = self.get_parent().get_new_block(self, key)
- self.get_elements().append(block)
- if block._bussify_sink:
- block.bussify({'name': 'bus', 'type': 'bus'}, 'sink')
- if block._bussify_source:
- block.bussify({'name': 'bus', 'type': 'bus'}, 'source')
- return block
-
- def connect(self, porta, portb):
- """
- Create a connection between porta and portb.
-
- Args:
- porta: a port
- portb: another port
- @throw Exception bad connection
-
- Returns:
- the new connection
- """
- connection = self.get_parent().Connection(flow_graph=self,
porta=porta, portb=portb)
- self.get_elements().append(connection)
- return connection
-
- def remove_element(self, element):
- """
- Remove the element from the list of elements.
- If the element is a port, remove the whole block.
- If the element is a block, remove its connections.
- If the element is a connection, just remove the connection.
- """
- if element not in self.get_elements():
- return
- # Found a port, set to parent signal block
- if element.is_port():
- element = element.get_parent()
- # Remove block, remove all involved connections
- if element.is_block():
- for port in element.get_ports():
- map(self.remove_element, port.get_connections())
- if element.is_connection():
- if element.is_bus():
- cons_list = []
- for i in map(lambda a: a.get_connections(),
element.get_source().get_associated_ports()):
- cons_list.extend(i)
- map(self.remove_element, cons_list)
- self.get_elements().remove(element)
+ return filter(methodcaller('get_enabled'), self.connections)
def get_option(self, key):
"""
@@ -465,29 +190,14 @@ class FlowGraph(Element):
"""
return self._options_block.get_param(key).get_evaluated()
- def is_flow_graph(self):
- return True
-
##############################################
# Access Elements
##############################################
def get_block(self, id):
- for block in self.iter_blocks():
+ for block in self.blocks:
if block.get_id() == id:
return block
- raise KeyError('No block with ID {0!r}'.format(id))
-
- def iter_blocks(self):
- return ifilter(methodcaller('is_block'), self.get_elements())
-
- def get_blocks(self):
- return list(self.iter_blocks())
-
- def iter_connections(self):
- return ifilter(methodcaller('is_connection'), self.get_elements())
-
- def get_connections(self):
- return list(self.iter_connections())
+ raise KeyError('No block with ID {!r}'.format(id))
def get_elements(self):
"""
@@ -497,75 +207,65 @@ class FlowGraph(Element):
Returns:
the element list
"""
- options_block_count = self._elements.count(self._options_block)
+ options_block_count = self.blocks.count(self._options_block)
if not options_block_count:
- self._elements.append(self._options_block)
+ self.blocks.append(self._options_block)
for i in range(options_block_count-1):
- self._elements.remove(self._options_block)
- return self._elements
+ self.blocks.remove(self._options_block)
+
+ return self.blocks + self.connections
get_children = get_elements
- # TODO >>> THIS SUCKS #
def rewrite(self):
"""
Flag the namespace to be renewed.
"""
- def reconnect_bus_blocks():
- for block in self.get_blocks():
-
- if 'bus' in map(lambda a: a.get_type(),
block.get_sources_gui()):
- for i in range(len(block.get_sources_gui())):
- if len(block.get_sources_gui()[i].get_connections()) >
0:
- source = block.get_sources_gui()[i]
- sink = []
- for j in range(len(source.get_connections())):
-
sink.append(source.get_connections()[j].get_sink())
- for elt in source.get_connections():
- self.remove_element(elt)
- for j in sink:
- self.connect(source, j)
- self._renew_eval_ns = True
-
- def refactor_bus_structure():
-
- for block in self.get_blocks():
- for direc in ['source', 'sink']:
- if direc == 'source':
- get_p = block.get_sources
- get_p_gui = block.get_sources_gui
- bus_structure = block.form_bus_structure('source')
- else:
- get_p = block.get_sinks
- get_p_gui = block.get_sinks_gui
- bus_structure = block.form_bus_structure('sink')
-
- if 'bus' in map(lambda a: a.get_type(), get_p_gui()):
- if len(get_p_gui()) > len(bus_structure):
- times = range(len(bus_structure), len(get_p_gui()))
- for i in times:
- for connect in
get_p_gui()[-1].get_connections():
- block.get_parent().remove_element(connect)
- get_p().remove(get_p_gui()[-1])
- elif len(get_p_gui()) < len(bus_structure):
- n = {'name': 'bus', 'type': 'bus'}
- if True in map(lambda a:
isinstance(a.get_nports(), int), get_p()):
- n['nports'] = str(1)
-
- times = range(len(get_p_gui()), len(bus_structure))
-
- for i in times:
- n['key'] = str(len(get_p()))
- n = odict(n)
- port =
block.get_parent().get_parent().Port(block=block, n=n, dir=direc)
- get_p().append(port)
-
- for child in self.get_children():
+ self.renew_namespace()
+ for child in chain(self.blocks, self.connections):
child.rewrite()
- refactor_bus_structure()
- reconnect_bus_blocks()
+ self.bus_ports_rewrite()
+
+ def renew_namespace(self):
+ namespace = {}
+ # Load imports
+ for expr in self.get_imports():
+ try:
+ exec expr in namespace
+ except:
+ pass
+
+ for id, expr in self.get_python_modules():
+ try:
+ module = imp.new_module(id)
+ exec expr in module.__dict__
+ namespace[id] = module
+ except:
+ pass
+
+ # Load parameters
+ np = {} # params don't know each other
+ for parameter in self.get_parameters():
+ try:
+ value = eval(parameter.get_param('value').to_code(), namespace)
+ np[parameter.get_id()] = value
+ except:
+ pass
+ namespace.update(np) # Merge param namespace
+
+ # Load variables
+ for variable in self.get_variables():
+ try:
+ value = eval(variable.get_var_value(), namespace)
+ namespace[variable.get_id()] = value
+ except:
+ pass
+
+ self.namespace.clear()
+ self._eval_cache.clear()
+ self.namespace.update(namespace)
def evaluate(self, expr):
"""
@@ -578,66 +278,76 @@ class FlowGraph(Element):
Returns:
the evaluated data
"""
- if self._renew_eval_ns:
- self._renew_eval_ns = False
- # Reload namespace
- n = dict()
- # Load imports
- 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():
- try:
- e = eval(parameter.get_param('value').to_code(), n, n)
- np[parameter.get_id()] = e
- except:
- pass
- n.update(np) # Merge param namespace
- # Load variables
- for variable in self.get_variables():
- try:
- e = eval(variable.get_var_value(), n, n)
- n[variable.get_id()] = e
- except:
- pass
- # Make namespace public
- self.n = n
- self.n_hash = hash(str(n))
# Evaluate
- e = self._eval(expr, self.n, self.n_hash)
- return e
+ if not expr:
+ raise Exception('Cannot evaluate empty statement.')
+ return self._eval_cache.setdefault(expr, eval(expr, self.namespace))
+
+ ##############################################
+ # Add/remove stuff
+ ##############################################
def get_new_block(self, key):
- """Try to auto-generate the block from file if missing"""
- block = self._get_new_block(key)
- if not block:
- platform = self.get_parent()
- # we're before the initial fg rewrite(), so no evaluated values!
- # --> use raw value instead
- path_param = self._options_block.get_param('hier_block_src_path')
- file_path = platform.find_file_in_paths(
- filename=key + '.' + platform.get_key(),
- paths=path_param.get_value(),
- cwd=self.grc_file_path
- )
- if file_path: # grc file found. load and get block
- platform.load_and_generate_flow_graph(file_path)
- block = self._get_new_block(key) # can be None
+ """
+ Get a new block of the specified key.
+ Add the block to the list of elements.
+
+ Args:
+ key: the block key
+
+ Returns:
+ the new block or None if not found
+ """
+ try:
+ block = self.platform.get_new_block(self, key)
+ self.blocks.append(block)
+ except KeyError:
+ block = None
return block
+ def connect(self, porta, portb):
+ """
+ Create a connection between porta and portb.
+
+ Args:
+ porta: a port
+ portb: another port
+ @throw Exception bad connection
+
+ Returns:
+ the new connection
+ """
+
+ connection = self.platform.Connection(
+ flow_graph=self, porta=porta, portb=portb)
+ self.connections.append(connection)
+ return connection
+
+ def remove_element(self, element):
+ """
+ Remove the element from the list of elements.
+ If the element is a port, remove the whole block.
+ If the element is a block, remove its connections.
+ If the element is a connection, just remove the connection.
+ """
+ if element.is_port:
+ # Found a port, set to parent signal block
+ element = element.get_parent()
+
+ if element in self.blocks:
+ # Remove block, remove all involved connections
+ for port in element.get_ports():
+ map(self.remove_element, port.get_connections())
+ self.blocks.remove(element)
+
+ elif element in self.connections:
+ if element.is_bus():
+ cons_list = []
+ for i in map(lambda a: a.get_connections(),
element.get_source().get_associated_ports()):
+ cons_list.extend(i)
+ map(self.remove_element, cons_list)
+ self.connections.remove(element)
+
##############################################
# Import/Export Methods
##############################################
@@ -650,12 +360,12 @@ class FlowGraph(Element):
a nested data odict
"""
# sort blocks and connections for nicer diffs
- blocks = sorted(self.iter_blocks(), key=lambda b: (
+ blocks = sorted(self.blocks, key=lambda b: (
b.get_key() != 'options', # options to the front
not b.get_key().startswith('variable'), # then vars
str(b)
))
- connections = sorted(self.get_connections(), key=str)
+ connections = sorted(self.connections, key=str)
n = odict()
n['timestamp'] = self._timestamp
n['block'] = [b.export_data() for b in blocks]
@@ -676,11 +386,13 @@ class FlowGraph(Element):
n: the nested data odict
"""
errors = False
- self._elements = list() # remove previous elements
+ # Remove previous elements
+ del self.blocks[:]
+ del self.connections[:]
# set file format
try:
instructions = n.find('_instructions') or {}
- file_format = int(instructions.get('format', '0')) or
self._guess_file_format_1(n)
+ file_format = int(instructions.get('format', '0')) or
_guess_file_format_1(n)
except:
file_format = 0
@@ -693,6 +405,20 @@ class FlowGraph(Element):
key = block_n.find('key')
block = self._options_block if key == 'options' else
self.get_new_block(key)
+ if not block:
+ platform = self.get_parent()
+ # we're before the initial fg rewrite(), so no evaluated
values!
+ # --> use raw value instead
+ path_param =
self._options_block.get_param('hier_block_src_path')
+ file_path = platform.find_file_in_paths(
+ filename=key + '.' + platform.get_key(),
+ paths=path_param.get_value(),
+ cwd=self.grc_file_path
+ )
+ if file_path: # grc file found. load and get block
+ platform.load_and_generate_flow_graph(file_path)
+ block = self.get_new_block(key) # can be None
+
if not block: # looks like this block key cannot be found
# create a dummy block instead
block = self.get_new_block('dummy_block')
@@ -745,40 +471,125 @@ class FlowGraph(Element):
self.rewrite() # global rewrite
return errors
- @staticmethod
- def _update_old_message_port_keys(source_key, sink_key, source_block,
sink_block):
- """
- Backward compatibility for message port keys
+ ##############################################
+ # Needs to go
+ ##############################################
+ def bus_ports_rewrite(self):
+ # todo: move to block.rewrite()
+ for block in self.blocks:
+ for direc in ['source', 'sink']:
+ if direc == 'source':
+ get_p = block.get_sources
+ get_p_gui = block.get_sources_gui
+ bus_structure = block.form_bus_structure('source')
+ else:
+ get_p = block.get_sinks
+ get_p_gui = block.get_sinks_gui
+ bus_structure = block.form_bus_structure('sink')
+
+ if 'bus' in map(lambda a: a.get_type(), get_p_gui()):
+ if len(get_p_gui()) > len(bus_structure):
+ times = range(len(bus_structure), len(get_p_gui()))
+ for i in times:
+ for connect in get_p_gui()[-1].get_connections():
+ block.get_parent().remove_element(connect)
+ get_p().remove(get_p_gui()[-1])
+ elif len(get_p_gui()) < len(bus_structure):
+ n = {'name': 'bus', 'type': 'bus'}
+ if True in map(
+ lambda a: isinstance(a.get_nports(), int),
+ get_p()):
+ n['nports'] = str(1)
+
+ times = range(len(get_p_gui()), len(bus_structure))
+
+ for i in times:
+ n['key'] = str(len(get_p()))
+ n = odict(n)
+ port = block.get_parent().get_parent().Port(
+ block=block, n=n, dir=direc)
+ get_p().append(port)
+
+ if 'bus' in map(lambda a: a.get_type(),
+ block.get_sources_gui()):
+ for i in range(len(block.get_sources_gui())):
+ if len(block.get_sources_gui()[
+ i].get_connections()) > 0:
+ source = block.get_sources_gui()[i]
+ sink = []
+
+ for j in range(len(source.get_connections())):
+ sink.append(
+ source.get_connections()[j].get_sink())
+ for elt in source.get_connections():
+ self.remove_element(elt)
+ for j in sink:
+ self.connect(source, j)
- Message ports use their names as key (like in the 'connect' method).
- Flowgraph files from former versions still have numeric keys stored for
- message connections. These have to be replaced by the name of the
- respective port. The correct message port is deduced from the integer
- value of the key (assuming the order has not changed).
- The connection ends are updated only if both ends translate into a
- message port.
- """
- try:
- # get ports using the "old way" (assuming liner indexed keys)
- source_port = source_block.get_sources()[int(source_key)]
- sink_port = sink_block.get_sinks()[int(sink_key)]
- if source_port.get_type() == "message" and sink_port.get_type() ==
"message":
- source_key, sink_key = source_port.get_key(),
sink_port.get_key()
- except (ValueError, IndexError):
- pass
- return source_key, sink_key # do nothing
-
- @staticmethod
- def _guess_file_format_1(n):
- """ Try to guess the file format for flow-graph files without version
tag """
- try:
- has_non_numeric_message_keys = any(not (
- connection_n.find('source_key').isdigit() and
- connection_n.find('sink_key').isdigit()
- ) for connection_n in n.find('flow_graph').findall('connection'))
- if has_non_numeric_message_keys:
- return 1
- except:
- pass
- return 0
+def _update_old_message_port_keys(source_key, sink_key, source_block,
sink_block):
+ """
+ Backward compatibility for message port keys
+
+ Message ports use their names as key (like in the 'connect' method).
+ Flowgraph files from former versions still have numeric keys stored for
+ message connections. These have to be replaced by the name of the
+ respective port. The correct message port is deduced from the integer
+ value of the key (assuming the order has not changed).
+
+ The connection ends are updated only if both ends translate into a
+ message port.
+ """
+ try:
+ # get ports using the "old way" (assuming liner indexed keys)
+ source_port = source_block.get_sources()[int(source_key)]
+ sink_port = sink_block.get_sinks()[int(sink_key)]
+ if source_port.get_type() == "message" and sink_port.get_type() ==
"message":
+ source_key, sink_key = source_port.get_key(), sink_port.get_key()
+ except (ValueError, IndexError):
+ pass
+ return source_key, sink_key # do nothing
+
+
+def _guess_file_format_1(n):
+ """
+ Try to guess the file format for flow-graph files without version tag
+ """
+ try:
+ has_non_numeric_message_keys = any(not (
+ connection_n.find('source_key').isdigit() and
+ connection_n.find('sink_key').isdigit()
+ ) for connection_n in n.find('flow_graph').findall('connection'))
+ if has_non_numeric_message_keys:
+ return 1
+ except:
+ pass
+ return 0
+
+
+def _initialize_dummy_block(block, block_n):
+ """
+ This is so ugly... dummy-fy a block
+ Modify block object to get the behaviour for a missing block
+ """
+
+ block._key = block_n.find('key')
+ block.is_dummy_block = lambda: True
+ block.is_valid = lambda: False
+ block.get_enabled = lambda: False
+ for param_n in block_n.findall('param'):
+ if param_n['key'] not in block.get_param_keys():
+ new_param_n = odict({'key': param_n['key'], 'name':
param_n['key'], 'type': 'string'})
+ params = block.get_parent().get_parent().Param(block=block,
n=new_param_n)
+ block.get_params().append(params)
+
+
+def _dummy_block_add_port(block, key, dir):
+ """ This is so ugly... Add a port to a dummy-field block """
+ port_n = odict({'name': '?', 'key': key, 'type': ''})
+ port = block.get_parent().get_parent().Port(block=block, n=port_n, dir=dir)
+ if port.is_source():
+ block.get_sources().append(port)
+ else:
+ block.get_sinks().append(port)
+ return port
diff --git a/grc/model/Param.py b/grc/model/Param.py
index e00be7e..f064097 100644
--- a/grc/model/Param.py
+++ b/grc/model/Param.py
@@ -121,6 +121,8 @@ class Option(Element):
class Param(Element):
+ is_param = True
+
def __init__(self, block, n):
"""
Make a new param from nested data.
@@ -666,9 +668,6 @@ class Param(Element):
def get_tab_label(self):
return self._tab_label
- def is_param(self):
- return True
-
def get_name(self):
return self.get_parent().resolve_dependencies(self._name).strip()
diff --git a/grc/model/Platform.py b/grc/model/Platform.py
index c08a8ed..f04dd04 100644
--- a/grc/model/Platform.py
+++ b/grc/model/Platform.py
@@ -19,25 +19,24 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA
import os
import sys
-
from gnuradio import gr
-from .Constants import BLOCK_TREE_DTD, FLOW_GRAPH_DTD, DOMAIN_DTD
-from .Element import Element
-
-from . import ParseXML
-from .odict import odict
-
-from . import extract_docs
+from . import ParseXML, extract_docs
from .Constants import (
+ BLOCK_TREE_DTD, FLOW_GRAPH_DTD, DOMAIN_DTD,
HIER_BLOCKS_LIB_DIR, BLOCK_DTD, DEFAULT_FLOW_GRAPH, BLOCKS_DIRS,
PREFS_FILE, CORE_TYPES, PREFS_FILE_OLD,
)
-from .Generator import Generator
-from .. gui import Messages
+from .Element import Element
+from .odict import odict
+from ..gui import Messages
+from .generator import Generator
class Platform(Element):
+
+ is_platform = True
+
def __init__(self):
"""
Make a platform for gnuradio.
@@ -341,9 +340,6 @@ class Platform(Element):
def __str__(self):
return 'Platform - {}({})'.format(self.get_key(), self.get_name())
- def is_platform(self):
- return True
-
def get_new_flow_graph(self):
return self.FlowGraph(platform=self)
diff --git a/grc/model/Port.py b/grc/model/Port.py
index ede7735..bfa4810 100644
--- a/grc/model/Port.py
+++ b/grc/model/Port.py
@@ -100,6 +100,8 @@ def _get_sink_from_virtual_sink_port(vsp, traversed=[]):
class Port(Element):
+ is_port = True
+
def __init__(self, block, n, dir):
"""
Make a new port from nested data.
@@ -139,9 +141,9 @@ class Port(Element):
self._clones = [] # References to cloned ports (for nports > 1)
def __str__(self):
- if self.is_source():
+ if self.is_source:
return 'Source - {}({})'.format(self.get_name(), self.get_key())
- if self.is_sink():
+ if self.is_sink:
return 'Sink - {}({})'.format(self.get_name(), self.get_key())
def get_types(self):
@@ -180,9 +182,11 @@ class Port(Element):
# Reset type and vlen
self._type = ''
self._vlen = ''
+
Element.rewrite(self)
hide =
self.get_parent().resolve_dependencies(self._hide).strip().lower()
self._hide_evaluated = False if hide in ('false', 'off', '0') else
bool(hide)
+
# Update domain if was deduced from (dynamic) port type
type_ = self.get_type()
if self._domain == GR_STREAM_DOMAIN and type_ == "message":
@@ -199,7 +203,7 @@ class Port(Element):
return _get_source_from_virtual_source_port(self)
def resolve_empty_type(self):
- if self.is_sink():
+ if self.is_sink:
try:
src = _get_source_from_virtual_sink_port(self)
if not src.is_type_empty():
@@ -209,7 +213,7 @@ class Port(Element):
sink = _get_sink_from_virtual_sink_port(self)
if not sink.is_type_empty():
return sink
- if self.is_source():
+ if self.is_source:
try:
src = _get_source_from_virtual_source_port(self)
if not src.is_type_empty():
@@ -344,15 +348,14 @@ class Port(Element):
def get_key(self):
return self._key
+ @property
def is_sink(self):
return self._dir == 'sink'
+ @property
def is_source(self):
return self._dir == 'source'
- def is_port(self):
- return True
-
def get_type(self):
return self.get_parent().resolve_dependencies(self._type)
@@ -369,7 +372,7 @@ class Port(Element):
Returns:
a list of connection objects
"""
- connections = self.get_parent().get_parent().get_connections()
+ connections = self.get_parent().get_parent().connections
connections = filter(lambda c: c.get_source() is self or c.get_sink()
is self, connections)
return connections
@@ -386,7 +389,7 @@ class Port(Element):
if not self.get_type() == 'bus':
return [self]
else:
- if self.is_source():
+ if self.is_source:
get_ports = self.get_parent().get_sources
bus_structure =
self.get_parent().current_bus_structure['source']
else:
diff --git a/grc/model/Generator.py b/grc/model/generator/Generator.py
similarity index 98%
rename from grc/model/Generator.py
rename to grc/model/generator/Generator.py
index f11766f..27cb24a 100644
--- a/grc/model/Generator.py
+++ b/grc/model/generator/Generator.py
@@ -28,17 +28,19 @@ from distutils.spawn import find_executable
from Cheetah.Template import Template
-from . import ParseXML
-from .odict import odict
-from .Constants import BLOCK_FLAG_NEED_QT_GUI
+from .. import ParseXML, expr_utils
+from ..odict import odict
-from . import expr_utils
-from . Constants import (
- TOP_BLOCK_FILE_MODE, FLOW_GRAPH_TEMPLATE,
+from grc.model.Constants import (
+ TOP_BLOCK_FILE_MODE, BLOCK_FLAG_NEED_QT_GUI,
XTERM_EXECUTABLE, HIER_BLOCK_FILE_MODE, HIER_BLOCKS_LIB_DIR, BLOCK_DTD
)
-from .. gui import Messages
+from grc.gui import Messages
+
+
+DATA_DIR = os.path.dirname(__file__)
+FLOW_GRAPH_TEMPLATE = os.path.join(DATA_DIR, 'flow_graph.tmpl')
class Generator(object):
@@ -184,7 +186,7 @@ class TopBlockGenerator(object):
return code
blocks = expr_utils.sort_objects(
- filter(lambda b: b.get_enabled() and not b.get_bypassed(),
fg.iter_blocks()),
+ filter(lambda b: b.get_enabled() and not b.get_bypassed(),
fg.blocks),
lambda b: b.get_id(), _get_block_sort_text
)
# List of regular blocks (all blocks minus the special ones)
diff --git a/grc/model/generator/__init__.py b/grc/model/generator/__init__.py
new file mode 100644
index 0000000..fb1e441
--- /dev/null
+++ b/grc/model/generator/__init__.py
@@ -0,0 +1 @@
+from .Generator import Generator
diff --git a/grc/model/flow_graph.tmpl b/grc/model/generator/flow_graph.tmpl
similarity index 100%
rename from grc/model/flow_graph.tmpl
rename to grc/model/generator/flow_graph.tmpl
diff --git a/grc/model/utils/__init__.py b/grc/model/utils/__init__.py
new file mode 100644
index 0000000..805d6f4
--- /dev/null
+++ b/grc/model/utils/__init__.py
@@ -0,0 +1,6 @@
+# -*- coding: utf-8 -*-
+""""""
+
+__author__ = "Sebastian Koslowski"
+__email__ = "address@hidden"
+__copyright__ = "Copyright 2015, Sebastian Koslowski"
diff --git a/grc/model/utils/complexity.py b/grc/model/utils/complexity.py
new file mode 100644
index 0000000..baa8040
--- /dev/null
+++ b/grc/model/utils/complexity.py
@@ -0,0 +1,49 @@
+
+def calculate_flowgraph_complexity(flowgraph):
+ """ Determines the complexity of a flowgraph """
+ dbal = 0
+ for block in flowgraph.blocks:
+ # Skip options block
+ if block.get_key() == 'options':
+ continue
+
+ # Don't worry about optional sinks?
+ sink_list = filter(lambda c: not c.get_optional(), block.get_sinks())
+ source_list = filter(lambda c: not c.get_optional(),
block.get_sources())
+ sinks = float(len(sink_list))
+ sources = float(len(source_list))
+ base = max(min(sinks, sources), 1)
+
+ # Port ratio multiplier
+ if min(sinks, sources) > 0:
+ multi = sinks / sources
+ multi = (1 / multi) if multi > 1 else multi
+ else:
+ multi = 1
+
+ # Connection ratio multiplier
+ sink_multi = max(float(sum(map(lambda c: len(c.get_connections()),
sink_list)) / max(sinks, 1.0)), 1.0)
+ source_multi = max(float(sum(map(lambda c: len(c.get_connections()),
source_list)) / max(sources, 1.0)), 1.0)
+ dbal = dbal + (base * multi * sink_multi * source_multi)
+
+ blocks = float(len(flowgraph.blocks))
+ connections = float(len(flowgraph.connections))
+ elements = blocks + connections
+ disabled_connections = len(filter(lambda c: not c.get_enabled(),
flowgraph.connections))
+ variables = elements - blocks - connections
+ enabled = float(len(flowgraph.get_enabled_blocks()))
+
+ # Disabled multiplier
+ if enabled > 0:
+ disabled_multi = 1 / (max(1 - ((blocks - enabled) / max(blocks, 1)),
0.05))
+ else:
+ disabled_multi = 1
+
+ # Connection multiplier (How many connections )
+ if (connections - disabled_connections) > 0:
+ conn_multi = 1 / (max(1 - (disabled_connections / max(connections,
1)), 0.05))
+ else:
+ conn_multi = 1
+
+ final = round(max((dbal - 1) * disabled_multi * conn_multi * connections,
0.0) / 1000000, 6)
+ return final
- [Commit-gnuradio] [gnuradio] 06/18: grc-refactor: rename grc/model/ to grc/core/, (continued)
- [Commit-gnuradio] [gnuradio] 06/18: grc-refactor: rename grc/model/ to grc/core/, git, 2016/04/24
- [Commit-gnuradio] [gnuradio] 08/18: grc-refactor: Platform.py fixes, FlowGraphProxy, git, 2016/04/24
- [Commit-gnuradio] [gnuradio] 02/18: grc-refactor: clean-up grc directory, git, 2016/04/24
- [Commit-gnuradio] [gnuradio] 09/18: grc-refactor: move Messages to core, git, 2016/04/24
- [Commit-gnuradio] [gnuradio] 07/18: grc-refactor: cmake fixes and more reorganizing, git, 2016/04/24
- [Commit-gnuradio] [gnuradio] 13/18: grc-refactoring: move template arg to param, git, 2016/04/24
- [Commit-gnuradio] [gnuradio] 14/18: grc-refactor: fix fg load, git, 2016/04/24
- [Commit-gnuradio] [gnuradio] 12/18: grc-refactor: remove (hopefully) all deps to GR in core/ and gui/, git, 2016/04/24
- [Commit-gnuradio] [gnuradio] 18/18: Merge branch 'maint_grcwg' into refactoring, git, 2016/04/24
- [Commit-gnuradio] [gnuradio] 11/18: grc-refactor: move gui prefs to gui, git, 2016/04/24
- [Commit-gnuradio] [gnuradio] 05/18: grc-refactor: fixes, type-testing-flags, FlowGraph.py, (more),
git <=
- [Commit-gnuradio] [gnuradio] 01/18: grc-refactor: move grc.base to grc.python.base, git, 2016/04/24
- [Commit-gnuradio] [gnuradio] 10/18: grc-refactor: Platform.py, git, 2016/04/24
- [Commit-gnuradio] [gnuradio] 17/18: grc-refactor: CMake fixes, start-up script cleaned up, git, 2016/04/24
- [Commit-gnuradio] [gnuradio] 16/18: Merge remote-tracking branch 'upstream/master' into refactoring, git, 2016/04/24
- [Commit-gnuradio] [gnuradio] 04/18: grc-refactor: Cleaning up code style to match PEP8., git, 2016/04/24
- [Commit-gnuradio] [gnuradio] 03/18: grc-refactor: Moved code from grc.model.base to grc.model, git, 2016/04/24