summaryrefslogtreecommitdiff
path: root/grc/core
diff options
context:
space:
mode:
Diffstat (limited to 'grc/core')
-rw-r--r--grc/core/Block.py25
-rw-r--r--grc/core/CMakeLists.txt2
-rw-r--r--grc/core/Config.py4
-rw-r--r--grc/core/Connection.py13
-rw-r--r--grc/core/Constants.py3
-rw-r--r--grc/core/Element.py2
-rw-r--r--grc/core/Element.pyi54
-rw-r--r--grc/core/FlowGraph.py22
-rw-r--r--grc/core/Param.py128
-rw-r--r--grc/core/Platform.py41
-rw-r--r--grc/core/Port.py16
-rw-r--r--grc/core/generator/CMakeLists.txt2
-rw-r--r--grc/core/generator/Generator.py8
-rw-r--r--grc/core/generator/flow_graph.tmpl80
-rw-r--r--grc/core/utils/CMakeLists.txt1
-rw-r--r--grc/core/utils/odict.py4
-rw-r--r--grc/core/utils/shlex.py47
17 files changed, 225 insertions, 227 deletions
diff --git a/grc/core/Block.py b/grc/core/Block.py
index f8179b113f..fba9371963 100644
--- a/grc/core/Block.py
+++ b/grc/core/Block.py
@@ -24,7 +24,7 @@ from Cheetah.Template import Template
from .utils import epy_block_io, odict
from . Constants import (
- BLOCK_FLAG_NEED_QT_GUI, BLOCK_FLAG_NEED_WX_GUI,
+ BLOCK_FLAG_NEED_QT_GUI,
ADVANCED_PARAM_TAB, DEFAULT_PARAM_TAB,
BLOCK_FLAG_THROTTLE, BLOCK_FLAG_DISABLE_BYPASS,
BLOCK_FLAG_DEPRECATED,
@@ -41,7 +41,7 @@ def _get_elem(lst, key):
try:
return lst[_get_keys(lst).index(key)]
except ValueError:
- raise ValueError('Key "{0}" not found in {1}.'.format(key, _get_keys(lst)))
+ raise ValueError('Key "{}" not found in {}.'.format(key, _get_keys(lst)))
class Block(Element):
@@ -121,7 +121,7 @@ class Block(Element):
key = param.get_key()
# Test against repeated keys
if key in self.get_param_keys():
- raise Exception('Key "{0}" already exists in params'.format(key))
+ raise Exception('Key "{}" already exists in params'.format(key))
# Store the param
self.get_params().append(param)
# Create the source objects
@@ -130,7 +130,7 @@ class Block(Element):
key = source.get_key()
# Test against repeated keys
if key in self.get_source_keys():
- raise Exception('Key "{0}" already exists in sources'.format(key))
+ raise Exception('Key "{}" already exists in sources'.format(key))
# Store the port
self.get_sources().append(source)
self.back_ofthe_bus(self.get_sources())
@@ -140,7 +140,7 @@ class Block(Element):
key = sink.get_key()
# Test against repeated keys
if key in self.get_sink_keys():
- raise Exception('Key "{0}" already exists in sinks'.format(key))
+ raise Exception('Key "{}" already exists in sinks'.format(key))
# Store the port
self.get_sinks().append(sink)
self.back_ofthe_bus(self.get_sinks())
@@ -250,9 +250,9 @@ class Block(Element):
check_res = self.resolve_dependencies(check)
try:
if not self.get_parent().evaluate(check_res):
- self.add_error_message('Check "{0}" failed.'.format(check))
+ self.add_error_message('Check "{}" failed.'.format(check))
except:
- self.add_error_message('Check "{0}" did not evaluate.'.format(check))
+ self.add_error_message('Check "{}" did not evaluate.'.format(check))
# For variables check the value (only if var_value is used
if self.is_variable and self._var_value != '$value':
@@ -261,7 +261,7 @@ class Block(Element):
value = self.get_var_value()
self.get_parent().evaluate(value)
except Exception as err:
- self.add_error_message('Value "{0}" cannot be evaluated:\n{1}'.format(value, err))
+ self.add_error_message('Value "{}" cannot be evaluated:\n{}'.format(value, err))
# check if this is a GUI block and matches the selected generate option
current_generate_option = self.get_parent().get_option('generate_options')
@@ -272,10 +272,9 @@ class Block(Element):
self.get_name().upper().startswith(label)
)
if block_requires_mode and current_generate_option not in valid_options:
- self.add_error_message("Can't generate this block in mode: {0} ".format(
+ self.add_error_message("Can't generate this block in mode: {} ".format(
repr(current_generate_option)))
- check_generate_mode('WX GUI', BLOCK_FLAG_NEED_WX_GUI, ('wx_gui',))
check_generate_mode('QT GUI', BLOCK_FLAG_NEED_QT_GUI, ('qt_gui', 'hb_qt_gui'))
if self._epy_reload_error:
self.get_param('_source_code').add_error_message(str(self._epy_reload_error))
@@ -390,7 +389,7 @@ class Block(Element):
callback = self.resolve_dependencies(callback)
if 'self.' in callback:
return callback
- return 'self.{0}.{1}'.format(self.get_id(), callback)
+ return 'self.{}.{}'.format(self.get_id(), callback)
return map(make_callback, self._callbacks)
def is_virtual_sink(self):
@@ -587,7 +586,7 @@ class Block(Element):
return True
def __str__(self):
- return 'Block - {0} - {1}({2})'.format(self.get_id(), self.get_name(), self.get_key())
+ return 'Block - {} - {}({})'.format(self.get_id(), self.get_name(), self.get_key())
def get_id(self):
return self.get_param('id').get_value()
@@ -702,7 +701,7 @@ class Block(Element):
try:
return str(Template(tmpl, n))
except Exception as err:
- return "Template error: {0}\n {1}".format(tmpl, err)
+ return "Template error: {}\n {}".format(tmpl, err)
##############################################
# Controller Modify
diff --git a/grc/core/CMakeLists.txt b/grc/core/CMakeLists.txt
index 51b0dacba6..f340127873 100644
--- a/grc/core/CMakeLists.txt
+++ b/grc/core/CMakeLists.txt
@@ -22,7 +22,6 @@ file(GLOB py_files "*.py")
GR_PYTHON_INSTALL(
FILES ${py_files}
DESTINATION ${GR_PYTHON_DIR}/gnuradio/grc/core
- COMPONENT "grc"
)
file(GLOB dtd_files "*.dtd")
@@ -30,7 +29,6 @@ file(GLOB dtd_files "*.dtd")
install(
FILES ${dtd_files} default_flow_graph.grc
DESTINATION ${GR_PYTHON_DIR}/gnuradio/grc/core
- COMPONENT "grc"
)
add_subdirectory(generator)
diff --git a/grc/core/Config.py b/grc/core/Config.py
index 78ff344998..744ad06ba9 100644
--- a/grc/core/Config.py
+++ b/grc/core/Config.py
@@ -32,10 +32,12 @@ class Config(object):
hier_block_lib_dir = os.environ.get('GRC_HIER_PATH', Constants.DEFAULT_HIER_BLOCK_LIB_DIR)
- def __init__(self, prefs_file, version, version_parts=None):
+ def __init__(self, prefs_file, version, version_parts=None, name=None):
self.prefs = prefs_file
self.version = version
self.version_parts = version_parts or version[1:].split('-', 1)[0].split('.')[:3]
+ if name:
+ self.name = name
@property
def block_paths(self):
diff --git a/grc/core/Connection.py b/grc/core/Connection.py
index 49eae69c82..c028d89ddc 100644
--- a/grc/core/Connection.py
+++ b/grc/core/Connection.py
@@ -75,16 +75,13 @@ class Connection(Element):
pass
def __str__(self):
- return 'Connection (\n\t{0}\n\t\t{1}\n\t{2}\n\t\t{3}\n)'.format(
+ return 'Connection (\n\t{}\n\t\t{}\n\t{}\n\t\t{}\n)'.format(
self.get_source().get_parent(),
self.get_source(),
self.get_sink().get_parent(),
self.get_sink(),
)
- def is_msg(self):
- return self.get_source().get_type() == self.get_sink().get_type() == 'msg'
-
def is_bus(self):
return self.get_source().get_type() == self.get_sink().get_type() == 'bus'
@@ -102,7 +99,7 @@ class Connection(Element):
source_domain = self.get_source().get_domain()
sink_domain = self.get_sink().get_domain()
if (source_domain, sink_domain) not in platform.connection_templates:
- self.add_error_message('No connection known for domains "{0}", "{1}"'.format(
+ self.add_error_message('No connection known for domains "{}", "{}"'.format(
source_domain, sink_domain))
too_many_other_sinks = (
not platform.domains.get(source_domain, []).get('multiple_sinks', False) and
@@ -114,15 +111,15 @@ class Connection(Element):
)
if too_many_other_sinks:
self.add_error_message(
- 'Domain "{0}" can have only one downstream block'.format(source_domain))
+ 'Domain "{}" can have only one downstream block'.format(source_domain))
if too_many_other_sources:
self.add_error_message(
- 'Domain "{0}" can have only one upstream block'.format(sink_domain))
+ 'Domain "{}" can have only one upstream block'.format(sink_domain))
source_size = Constants.TYPE_TO_SIZEOF[self.get_source().get_type()] * self.get_source().get_vlen()
sink_size = Constants.TYPE_TO_SIZEOF[self.get_sink().get_type()] * self.get_sink().get_vlen()
if source_size != sink_size:
- self.add_error_message('Source IO size "{0}" does not match sink IO size "{1}".'.format(source_size, sink_size))
+ self.add_error_message('Source IO size "{}" does not match sink IO size "{}".'.format(source_size, sink_size))
def get_enabled(self):
"""
diff --git a/grc/core/Constants.py b/grc/core/Constants.py
index 61a44d0c78..edd3442a94 100644
--- a/grc/core/Constants.py
+++ b/grc/core/Constants.py
@@ -48,7 +48,6 @@ DEFAULT_DOMAIN = GR_STREAM_DOMAIN
BLOCK_FLAG_THROTTLE = 'throttle'
BLOCK_FLAG_DISABLE_BYPASS = 'disable_bypass'
BLOCK_FLAG_NEED_QT_GUI = 'need_qt_gui'
-BLOCK_FLAG_NEED_WX_GUI = 'need_wx_gui'
BLOCK_FLAG_DEPRECATED = 'deprecated'
# Block States
@@ -109,7 +108,6 @@ CORE_TYPES = ( # name, key, sizeof, color
('Integer 16', 's16', 2, GRC_COLOR_YELLOW),
('Integer 8', 's8', 1, GRC_COLOR_PURPLE_A400),
('Bits (unpacked byte)', 'bit', 1, GRC_COLOR_PURPLE_A100),
- ('Message Queue', 'msg', 0, GRC_COLOR_DARK_GREY),
('Async Message', 'message', 0, GRC_COLOR_GREY),
('Bus Connection', 'bus', 0, GRC_COLOR_WHITE),
('Wildcard', '', 0, GRC_COLOR_WHITE),
@@ -148,4 +146,3 @@ SHORT_VECTOR_COLOR_SPEC = '#CCCC33'
BYTE_VECTOR_COLOR_SPEC = '#CC66CC'
ID_COLOR_SPEC = '#DDDDDD'
WILDCARD_COLOR_SPEC = '#FFFFFF'
-MSG_COLOR_SPEC = '#777777'
diff --git a/grc/core/Element.py b/grc/core/Element.py
index d80753d8fa..67c36e12b4 100644
--- a/grc/core/Element.py
+++ b/grc/core/Element.py
@@ -66,7 +66,7 @@ class Element(object):
error_messages = list(self._error_messages) # Make a copy
for child in filter(lambda c: c.get_enabled() and not c.get_bypassed(), self.get_children()):
for msg in child.get_error_messages():
- error_messages.append("{0}:\n\t{1}".format(child, msg.replace("\n", "\n\t")))
+ error_messages.append("{}:\n\t{}".format(child, msg.replace("\n", "\n\t")))
return error_messages
def rewrite(self):
diff --git a/grc/core/Element.pyi b/grc/core/Element.pyi
new file mode 100644
index 0000000000..c81180a33e
--- /dev/null
+++ b/grc/core/Element.pyi
@@ -0,0 +1,54 @@
+# Copyright 2008, 2009, 2015, 2016 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
+
+from . import Platform, FlowGraph, Block
+
+def lazy_property(func):
+ return func
+
+
+class Element(object):
+
+ def __init__(self, parent=None):
+ ...
+
+ @property
+ def parent(self):
+ ...
+
+ def get_parent_by_type(self, cls):
+ parent = self.parent
+ if parent is None:
+ return None
+ elif isinstance(parent, cls):
+ return parent
+ else:
+ return parent.get_parent_by_type(cls)
+
+ @lazy_property
+ def parent_platform(self): -> Platform.Platform
+ ...
+
+ @lazy_property
+ def parent_flowgraph(self): -> FlowGraph.FlowGraph
+ ...
+
+ @lazy_property
+ def parent_block(self): -> Block.Block
+ ...
+
+
diff --git a/grc/core/FlowGraph.py b/grc/core/FlowGraph.py
index 48563eefb1..ecae11cf1a 100644
--- a/grc/core/FlowGraph.py
+++ b/grc/core/FlowGraph.py
@@ -16,16 +16,16 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
import imp
-import time
from itertools import ifilter, chain
from operator import methodcaller, attrgetter
-
import re
+import sys
+import time
from . import Messages
from .Constants import FLOW_GRAPH_FILE_FORMAT_VERSION
from .Element import Element
-from .utils import odict, expr_utils
+from .utils import odict, expr_utils, shlex
_parameter_matcher = re.compile('^(parameter)$')
_monitors_searcher = re.compile('(ctrlport_monitor)')
@@ -64,7 +64,7 @@ class FlowGraph(Element):
self._options_block = self.new_block('options')
def __str__(self):
- return 'FlowGraph - {0}({1})'.format(self.get_option('title'), self.get_option('id'))
+ return 'FlowGraph - {}({})'.format(self.get_option('title'), self.get_option('id'))
##############################################
# TODO: Move these to new generator package
@@ -186,6 +186,16 @@ class FlowGraph(Element):
"""
return self._options_block.get_param(key).get_evaluated()
+ def get_run_command(self, file_path, split=False):
+ run_command = self.get_option('run_command')
+ try:
+ run_command = run_command.format(
+ python=shlex.quote(sys.executable),
+ filename=shlex.quote(file_path))
+ return shlex.split(run_command) if split else run_command
+ except Exception as e:
+ raise ValueError("Can't parse run command {!r}: {}".format(run_command, e))
+
##############################################
# Access Elements
##############################################
@@ -410,7 +420,7 @@ class FlowGraph(Element):
cwd=self.grc_file_path
)
if file_path: # grc file found. load and get block
- self.platform.load_and_generate_flow_graph(file_path)
+ self.platform.load_and_generate_flow_graph(file_path, hier_only=True)
block = self.new_block(key) # can be None
if not block: # looks like this block key cannot be found
@@ -461,7 +471,7 @@ class FlowGraph(Element):
self.connect(source_port, sink_port)
except LookupError as e:
Messages.send_error_load(
- 'Connection between {0}({1}) and {2}({3}) could not be made.\n\t{4}'.format(
+ 'Connection between {}({}) and {}({}) could not be made.\n\t{}'.format(
source_block_id, source_key, sink_block_id, sink_key, e))
errors = True
diff --git a/grc/core/Param.py b/grc/core/Param.py
index afa478b3a2..a9a664f74a 100644
--- a/grc/core/Param.py
+++ b/grc/core/Param.py
@@ -30,7 +30,7 @@ from .utils import odict
import __builtin__
-ID_BLACKLIST = ['self', 'options', 'gr', 'blks2', 'wxgui', 'wx', 'math', 'forms', 'firdes'] + dir(__builtin__)
+ID_BLACKLIST = ['self', 'options', 'gr', 'math', 'firdes'] + dir(__builtin__)
try:
from gnuradio import gr
ID_BLACKLIST.extend(attr for attr in dir(gr.top_block()) if not attr.startswith('_'))
@@ -49,14 +49,14 @@ def _get_elem(lst, key):
try:
return lst[_get_keys(lst).index(key)]
except ValueError:
- raise ValueError('Key "{0}" not found in {1}.'.format(key, _get_keys(lst)))
+ raise ValueError('Key "{}" not found in {}.'.format(key, _get_keys(lst)))
def num_to_str(num):
""" Display logic for numbers """
def eng_notation(value, fmt='g'):
"""Convert a number to a string in engineering notation. E.g., 5e-9 -> 5n"""
- template = '{0:' + fmt + '}{1}'
+ template = '{:' + fmt + '}{}'
magnitude = abs(value)
for exp, symbol in zip(range(9, -15-1, -3), 'GMk munpf'):
factor = 10 ** exp
@@ -92,15 +92,15 @@ class Option(Element):
try:
key, value = opt.split(':')
except:
- raise Exception('Error separating "{0}" into key:value'.format(opt))
+ raise Exception('Error separating "{}" into key:value'.format(opt))
# Test against repeated keys
if key in self._opts:
- raise Exception('Key "{0}" already exists in option'.format(key))
+ raise Exception('Key "{}" already exists in option'.format(key))
# Store the option
self._opts[key] = value
def __str__(self):
- return 'Option {0}({1})'.format(self.get_name(), self.get_key())
+ return 'Option {}({})'.format(self.get_name(), self.get_key())
def get_name(self):
return self._name
@@ -180,26 +180,26 @@ class Param(Element):
key = option.get_key()
# Test against repeated keys
if key in self.get_option_keys():
- raise Exception('Key "{0}" already exists in options'.format(key))
+ raise Exception('Key "{}" already exists in options'.format(key))
# Store the option
self.get_options().append(option)
# Test the enum options
if self.is_enum():
# Test against options with identical keys
if len(set(self.get_option_keys())) != len(self.get_options()):
- raise Exception('Options keys "{0}" are not unique.'.format(self.get_option_keys()))
+ raise Exception('Options keys "{}" are not unique.'.format(self.get_option_keys()))
# Test against inconsistent keys in options
opt_keys = self.get_options()[0].get_opt_keys()
for option in self.get_options():
if set(opt_keys) != set(option.get_opt_keys()):
- raise Exception('Opt keys "{0}" are not identical across all options.'.format(opt_keys))
+ raise Exception('Opt keys "{}" are not identical across all options.'.format(opt_keys))
# If a value is specified, it must be in the options keys
if value or value in self.get_option_keys():
self._value = value
else:
self._value = self.get_option_keys()[0]
if self.get_value() not in self.get_option_keys():
- raise Exception('The value "{0}" is not in the possible values of "{1}".'.format(self.get_value(), self.get_option_keys()))
+ raise Exception('The value "{}" is not in the possible values of "{}".'.format(self.get_value(), self.get_option_keys()))
else:
self._value = value or ''
self._default = value
@@ -215,7 +215,7 @@ class Param(Element):
'hex', 'string', 'bool',
'file_open', 'file_save', '_multiline', '_multiline_python_external',
'id', 'stream_id',
- 'grid_pos', 'notebook', 'gui_hint',
+ 'gui_hint',
'import',
)
@@ -290,7 +290,7 @@ class Param(Element):
return self.get_value()
def __str__(self):
- return 'Param - {0}({1})'.format(self.get_name(), self.get_key())
+ return 'Param - {}({})'.format(self.get_name(), self.get_key())
def get_color(self):
"""
@@ -317,8 +317,6 @@ class Param(Element):
'string': Constants.BYTE_VECTOR_COLOR_SPEC,
'id': Constants.ID_COLOR_SPEC,
'stream_id': Constants.ID_COLOR_SPEC,
- 'grid_pos': Constants.INT_VECTOR_COLOR_SPEC,
- 'notebook': Constants.INT_VECTOR_COLOR_SPEC,
'raw': Constants.WILDCARD_COLOR_SPEC,
}[self.get_type()]
except:
@@ -354,9 +352,6 @@ class Param(Element):
return 'part'
except:
pass
- # Hide empty grid positions
- if self.get_key() in ('grid_pos', 'notebook') and not self.get_value():
- return 'part'
return hide
def validate(self):
@@ -366,7 +361,7 @@ class Param(Element):
"""
Element.validate(self)
if self.get_type() not in self.get_types():
- self.add_error_message('Type "{0}" is not a possible type.'.format(self.get_type()))
+ self.add_error_message('Type "{}" is not a possible type.'.format(self.get_type()))
self._evaluated = None
try:
@@ -405,30 +400,30 @@ class Param(Element):
try:
e = self.get_parent().get_parent().evaluate(v)
except Exception, e:
- raise Exception('Value "{0}" cannot be evaluated:\n{1}'.format(v, e))
+ raise Exception('Value "{}" cannot be evaluated:\n{}'.format(v, e))
# Raise an exception if the data is invalid
if t == 'raw':
return e
elif t == 'complex':
if not isinstance(e, COMPLEX_TYPES):
- raise Exception('Expression "{0}" is invalid for type complex.'.format(str(e)))
+ raise Exception('Expression "{}" is invalid for type complex.'.format(str(e)))
return e
elif t == 'real' or t == 'float':
if not isinstance(e, REAL_TYPES):
- raise Exception('Expression "{0}" is invalid for type float.'.format(str(e)))
+ raise Exception('Expression "{}" is invalid for type float.'.format(str(e)))
return e
elif t == 'int':
if not isinstance(e, INT_TYPES):
- raise Exception('Expression "{0}" is invalid for type integer.'.format(str(e)))
+ raise Exception('Expression "{}" is invalid for type integer.'.format(str(e)))
return e
elif t == 'hex':
return hex(e)
elif t == 'bool':
if not isinstance(e, bool):
- raise Exception('Expression "{0}" is invalid for type bool.'.format(str(e)))
+ raise Exception('Expression "{}" is invalid for type bool.'.format(str(e)))
return e
else:
- raise TypeError('Type "{0}" not handled'.format(t))
+ raise TypeError('Type "{}" not handled'.format(t))
#########################
# Numeric Vector Types
#########################
@@ -440,28 +435,28 @@ class Param(Element):
try:
e = self.get_parent().get_parent().evaluate(v)
except Exception, e:
- raise Exception('Value "{0}" cannot be evaluated:\n{1}'.format(v, e))
+ raise Exception('Value "{}" cannot be evaluated:\n{}'.format(v, e))
# Raise an exception if the data is invalid
if t == 'complex_vector':
if not isinstance(e, VECTOR_TYPES):
self._lisitify_flag = True
e = [e]
if not all([isinstance(ei, COMPLEX_TYPES) for ei in e]):
- raise Exception('Expression "{0}" is invalid for type complex vector.'.format(str(e)))
+ raise Exception('Expression "{}" is invalid for type complex vector.'.format(str(e)))
return e
elif t == 'real_vector' or t == 'float_vector':
if not isinstance(e, VECTOR_TYPES):
self._lisitify_flag = True
e = [e]
if not all([isinstance(ei, REAL_TYPES) for ei in e]):
- raise Exception('Expression "{0}" is invalid for type float vector.'.format(str(e)))
+ raise Exception('Expression "{}" is invalid for type float vector.'.format(str(e)))
return e
elif t == 'int_vector':
if not isinstance(e, VECTOR_TYPES):
self._lisitify_flag = True
e = [e]
if not all([isinstance(ei, INT_TYPES) for ei in e]):
- raise Exception('Expression "{0}" is invalid for type integer vector.'.format(str(e)))
+ raise Exception('Expression "{}" is invalid for type integer vector.'.format(str(e)))
return e
#########################
# String Types
@@ -484,20 +479,20 @@ class Param(Element):
elif t == 'id':
# Can python use this as a variable?
if not _check_id_matcher.match(v):
- raise Exception('ID "{0}" must begin with a letter and may contain letters, numbers, and underscores.'.format(v))
+ raise Exception('ID "{}" must begin with a letter and may contain letters, numbers, and underscores.'.format(v))
ids = [param.get_value() for param in self.get_all_params(t, 'id')]
if v in ID_BLACKLIST:
- raise Exception('ID "{0}" is blacklisted.'.format(v))
+ raise Exception('ID "{}" is blacklisted.'.format(v))
if self._key == 'id':
# Id should only appear once, or zero times if block is disabled
if ids.count(v) > 1:
- raise Exception('ID "{0}" is not unique.'.format(v))
+ raise Exception('ID "{}" is not unique.'.format(v))
else:
# Id should exist to be a reference
if ids.count(v) < 1:
- raise Exception('ID "{0}" does not exist.'.format(v))
+ raise Exception('ID "{}" does not exist.'.format(v))
return v
@@ -514,11 +509,11 @@ class Param(Element):
if self.get_parent().is_virtual_sink():
# Id should only appear once, or zero times if block is disabled
if ids.count(v) > 1:
- raise Exception('Stream ID "{0}" is not unique.'.format(v))
+ raise Exception('Stream ID "{}" is not unique.'.format(v))
# Check that the virtual source's steam id is found
if self.get_parent().is_virtual_source():
if v not in ids:
- raise Exception('Stream ID "{0}" is not found.'.format(v))
+ raise Exception('Stream ID "{}" is not found.'.format(v))
return v
#########################
@@ -558,65 +553,6 @@ class Param(Element):
return self._ws
return GuiHint(widget_str)
#########################
- # Grid Position Type
- #########################
- elif t == 'grid_pos':
- if not v:
- # Allow for empty grid pos
- return ''
- e = self.get_parent().get_parent().evaluate(v)
- if not isinstance(e, (list, tuple)) or len(e) != 4 or not all([isinstance(ei, int) for ei in e]):
- raise Exception('A grid position must be a list of 4 integers.')
- row, col, row_span, col_span = e
- # Check row, col
- if row < 0 or col < 0:
- raise Exception('Row and column must be non-negative.')
- # Check row span, col span
- if row_span <= 0 or col_span <= 0:
- raise Exception('Row and column span must be greater than zero.')
- # Get hostage cell parent
- try:
- my_parent = self.get_parent().get_param('notebook').evaluate()
- except:
- my_parent = ''
- # Calculate hostage cells
- for r in range(row_span):
- for c in range(col_span):
- self._hostage_cells.append((my_parent, (row+r, col+c)))
- # Avoid collisions
- params = filter(lambda p: p is not self, self.get_all_params('grid_pos'))
- for param in params:
- for parent, cell in param._hostage_cells:
- if (parent, cell) in self._hostage_cells:
- raise Exception('Another graphical element is using parent "{0}", cell "{1}".'.format(str(parent), str(cell)))
- return e
- #########################
- # Notebook Page Type
- #########################
- elif t == 'notebook':
- if not v:
- # Allow for empty notebook
- return ''
-
- # Get a list of all notebooks
- notebook_blocks = filter(lambda b: b.get_key() == 'notebook', self.get_parent().get_parent().get_enabled_blocks())
- # Check for notebook param syntax
- try:
- notebook_id, page_index = map(str.strip, v.split(','))
- except:
- raise Exception('Bad notebook page format.')
- # Check that the notebook id is valid
- try:
- notebook_block = filter(lambda b: b.get_id() == notebook_id, notebook_blocks)[0]
- except:
- raise Exception('Notebook id "{0}" is not an existing notebook id.'.format(notebook_id))
-
- # Check that page index exists
- if int(page_index) not in range(len(notebook_block.get_param('labels').evaluate())):
- raise Exception('Page index "{0}" is not a valid index number.'.format(page_index))
- return notebook_id, page_index
-
- #########################
# Import Type
#########################
elif t == 'import':
@@ -625,14 +561,14 @@ class Param(Element):
try:
exec v in n
except ImportError:
- raise Exception('Import "{0}" failed.'.format(v))
+ raise Exception('Import "{}" failed.'.format(v))
except Exception:
- raise Exception('Bad import syntax: "{0}".'.format(v))
+ raise Exception('Bad import syntax: "{}".'.format(v))
return filter(lambda k: str(k) != '__builtins__', n.keys())
#########################
else:
- raise TypeError('Type "{0}" not handled'.format(t))
+ raise TypeError('Type "{}" not handled'.format(t))
def to_code(self):
"""
diff --git a/grc/core/Platform.py b/grc/core/Platform.py
index 297e8b0ae5..b73dade2e8 100644
--- a/grc/core/Platform.py
+++ b/grc/core/Platform.py
@@ -75,7 +75,7 @@ class Platform(Element):
self.build_block_library()
def __str__(self):
- return 'Platform - {0}({1})'.format(self.config.key, self.config.name)
+ return 'Platform - {}({})'.format(self.config.key, self.config.name)
@staticmethod
def find_file_in_paths(filename, paths, cwd):
@@ -93,42 +93,43 @@ class Platform(Element):
if os.path.exists(os.path.normpath(file_path)):
return file_path
- def load_and_generate_flow_graph(self, file_path):
+ def load_and_generate_flow_graph(self, file_path, out_path=None, hier_only=False):
"""Loads a flow graph from file and generates it"""
Messages.set_indent(len(self._auto_hier_block_generate_chain))
- Messages.send('>>> Loading: %r\n' % file_path)
+ Messages.send('>>> Loading: {}\n'.format(file_path))
if file_path in self._auto_hier_block_generate_chain:
Messages.send(' >>> Warning: cyclic hier_block dependency\n')
- return False
+ return None, None
self._auto_hier_block_generate_chain.add(file_path)
try:
flow_graph = self.get_new_flow_graph()
flow_graph.grc_file_path = file_path
- # Other, nested higiter_blocks might be auto-loaded here
+ # Other, nested hier_blocks might be auto-loaded here
flow_graph.import_data(self.parse_flow_graph(file_path))
flow_graph.rewrite()
flow_graph.validate()
if not flow_graph.is_valid():
raise Exception('Flowgraph invalid')
- if not flow_graph.get_option('generate_options').startswith('hb'):
+ if hier_only and not flow_graph.get_option('generate_options').startswith('hb'):
raise Exception('Not a hier block')
except Exception as e:
- Messages.send('>>> Load Error: {0}: {1}\n'.format(file_path, str(e)))
- return False
+ Messages.send('>>> Load Error: {}: {}\n'.format(file_path, str(e)))
+ return None, None
finally:
self._auto_hier_block_generate_chain.discard(file_path)
Messages.set_indent(len(self._auto_hier_block_generate_chain))
try:
- Messages.send('>>> Generating: {0}\n'.format(file_path))
- generator = self.Generator(flow_graph, file_path)
+ generator = self.Generator(flow_graph, out_path or file_path)
+ Messages.send('>>> Generating: {}\n'.format(generator.file_path))
generator.write()
except Exception as e:
- Messages.send('>>> Generate Error: {0}: {1}\n'.format(file_path, str(e)))
- return False
+ Messages.send('>>> Generate Error: {}: {}\n'.format(file_path, str(e)))
+ return None, None
- self.load_block_xml(generator.get_file_path_xml())
- return True
+ if flow_graph.get_option('generate_options').startswith('hb'):
+ self.load_block_xml(generator.get_file_path_xml())
+ return flow_graph, generator.file_path
def build_block_library(self):
"""load the blocks and block tree from the search paths"""
@@ -192,7 +193,7 @@ class Platform(Element):
block = self.Block(self._flow_graph, n)
key = block.get_key()
if key in self.blocks:
- print >> sys.stderr, 'Warning: Block with key "{0}" already exists.\n\tIgnoring: {1}'.format(key, xml_file)
+ print >> sys.stderr, 'Warning: Block with key "{}" already exists.\n\tIgnoring: {}'.format(key, xml_file)
else: # Store the block
self.blocks[key] = block
self._blocks_n[key] = n
@@ -227,10 +228,10 @@ class Platform(Element):
key = n.find('key')
if not key:
- print >> sys.stderr, 'Warning: Domain with emtpy key.\n\tIgnoring: {0}'.format(xml_file)
+ print >> sys.stderr, 'Warning: Domain with emtpy key.\n\tIgnoring: {}'.format(xml_file)
return
if key in self.domains: # test against repeated keys
- print >> sys.stderr, 'Warning: Domain with key "{0}" already exists.\n\tIgnoring: {1}'.format(key, xml_file)
+ print >> sys.stderr, 'Warning: Domain with key "{}" already exists.\n\tIgnoring: {}'.format(key, xml_file)
return
#to_bool = lambda s, d: d if s is None else s.lower() not in ('false', 'off', '0', '')
@@ -245,7 +246,7 @@ class Platform(Element):
gtk.gdk.color_parse(color)
except (ValueError, ImportError):
if color: # no color is okay, default set in GUI
- print >> sys.stderr, 'Warning: Can\'t parse color code "{0}" for domain "{1}" '.format(color, key)
+ print >> sys.stderr, 'Warning: Can\'t parse color code "{}" for domain "{}" '.format(color, key)
color = None
self.domains[key] = dict(
@@ -257,9 +258,9 @@ class Platform(Element):
for connection_n in n.findall('connection'):
key = (connection_n.find('source_domain'), connection_n.find('sink_domain'))
if not all(key):
- print >> sys.stderr, 'Warning: Empty domain key(s) in connection template.\n\t{0}'.format(xml_file)
+ print >> sys.stderr, 'Warning: Empty domain key(s) in connection template.\n\t{}'.format(xml_file)
elif key in self.connection_templates:
- print >> sys.stderr, 'Warning: Connection template "{0}" already exists.\n\t{1}'.format(key, xml_file)
+ print >> sys.stderr, 'Warning: Connection template "{}" already exists.\n\t{}'.format(key, xml_file)
else:
self.connection_templates[key] = connection_n.find('make') or ''
diff --git a/grc/core/Port.py b/grc/core/Port.py
index acf4eea3d4..8549656c9b 100644
--- a/grc/core/Port.py
+++ b/grc/core/Port.py
@@ -150,8 +150,6 @@ class Port(Element):
elif n['domain'] == GR_MESSAGE_DOMAIN:
n['key'] = n['name']
n['type'] = 'message' # For port color
- if n['type'] == 'msg':
- n['key'] = 'msg'
if not n.find('key'):
n['key'] = str(next(block.port_counters[dir == 'source']))
@@ -174,9 +172,9 @@ class Port(Element):
def __str__(self):
if self.is_source:
- return 'Source - {0}({1})'.format(self.get_name(), self.get_key())
+ return 'Source - {}({})'.format(self.get_name(), self.get_key())
if self.is_sink:
- return 'Sink - {0}({1})'.format(self.get_name(), self.get_key())
+ return 'Sink - {}({})'.format(self.get_name(), self.get_key())
def get_types(self):
return Constants.TYPE_TO_SIZEOF.keys()
@@ -186,18 +184,12 @@ class Port(Element):
def validate(self):
if self.get_type() not in self.get_types():
- self.add_error_message('Type "{0}" is not a possible type.'.format(self.get_type()))
+ self.add_error_message('Type "{}" is not a possible type.'.format(self.get_type()))
platform = self.get_parent().get_parent().get_parent()
if self.get_domain() not in platform.domains:
- self.add_error_message('Domain key "{0}" is not registered.'.format(self.get_domain()))
+ self.add_error_message('Domain key "{}" is not registered.'.format(self.get_domain()))
if not self.get_enabled_connections() and not self.get_optional():
self.add_error_message('Port is not connected.')
- # Message port logic
- if self.get_type() == 'msg':
- if self.get_nports():
- self.add_error_message('A port of type "msg" cannot have "nports" set.')
- if self.get_vlen() != 1:
- self.add_error_message('A port of type "msg" must have a "vlen" of 1.')
def rewrite(self):
"""
diff --git a/grc/core/generator/CMakeLists.txt b/grc/core/generator/CMakeLists.txt
index 4bdd59a7a2..492ad7c4ad 100644
--- a/grc/core/generator/CMakeLists.txt
+++ b/grc/core/generator/CMakeLists.txt
@@ -22,11 +22,9 @@ file(GLOB py_files "*.py")
GR_PYTHON_INSTALL(
FILES ${py_files}
DESTINATION ${GR_PYTHON_DIR}/gnuradio/grc/core/generator
- COMPONENT "grc"
)
install(FILES
flow_graph.tmpl
DESTINATION ${GR_PYTHON_DIR}/gnuradio/grc/core/generator
- COMPONENT "grc"
)
diff --git a/grc/core/generator/Generator.py b/grc/core/generator/Generator.py
index 8c1cd9a6b0..dda226c6b2 100644
--- a/grc/core/generator/Generator.py
+++ b/grc/core/generator/Generator.py
@@ -133,10 +133,6 @@ class TopBlockGenerator(object):
def _get_block_sort_text(block):
code = block.get_make().replace(block.get_id(), ' ')
try:
- code += block.get_param('notebook').get_value() # Older gui markup w/ wxgui
- except:
- pass
- try:
code += block.get_param('gui_hint').get_value() # Newer gui markup w/ qtgui
except:
pass
@@ -165,7 +161,7 @@ class TopBlockGenerator(object):
# Filter out virtual sink connections
def cf(c):
- return not (c.is_bus() or c.is_msg() or c.get_sink().get_parent().is_virtual_sink())
+ return not (c.is_bus() or c.get_sink().get_parent().is_virtual_sink())
connections = filter(cf, fg.get_enabled_connections())
# Get the virtual blocks and resolve their connections
@@ -214,7 +210,6 @@ class TopBlockGenerator(object):
))
connection_templates = fg.get_parent().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]
@@ -243,7 +238,6 @@ class TopBlockGenerator(object):
'blocks': blocks,
'connections': connections,
'connection_templates': connection_templates,
- 'msgs': msgs,
'generate_options': self._generate_options,
'callbacks': callbacks,
}
diff --git a/grc/core/generator/flow_graph.tmpl b/grc/core/generator/flow_graph.tmpl
index 1ef251c46b..2adb555486 100644
--- a/grc/core/generator/flow_graph.tmpl
+++ b/grc/core/generator/flow_graph.tmpl
@@ -11,7 +11,6 @@
##@param parameters the parameter blocks
##@param blocks the signal blocks
##@param connections the connections
-##@param msgs the msg type connections
##@param generate_options the type of flow graph
##@param callbacks variable id map to callback strings
########################################################
@@ -36,9 +35,13 @@ $DIVIDER
import threading
#end if
+#if $generate_options == 'qt_gui'
+from distutils.version import StrictVersion
+#end if
+
## Call XInitThreads as the _very_ first thing.
## After some Qt import, it's too late
-#if $generate_options in ('wx_gui', 'qt_gui')
+#if $generate_options == 'qt_gui'
if __name__ == '__main__':
import ctypes
import sys
@@ -72,28 +75,13 @@ $imp
##Create Class
## Write the class declaration for a top or hier block.
## The parameter names are the arguments to __init__.
-## Determine the absolute icon path (wx gui only).
## Setup the IO signature (hier block only).
########################################################
#set $class_name = $flow_graph.get_option('id')
#set $param_str = ', '.join(['self'] + ['%s=%s'%(param.get_id(), param.get_make()) for param in $parameters])
-#if $generate_options == 'wx_gui'
- #import gtk
- #set $icon = gtk.IconTheme().lookup_icon('gnuradio-grc', 32, 0)
-
-
-class $(class_name)(grc_wxgui.top_block_gui):
-
- def __init__($param_str):
- grc_wxgui.top_block_gui.__init__(self, title="$title")
- #if $icon
- _icon_path = "$icon.get_filename()"
- self.SetIcon(wx.Icon(_icon_path, wx.BITMAP_TYPE_ANY))
- #end if
-#elif $generate_options == 'qt_gui'
+#if $generate_options == 'qt_gui'
from gnuradio import qtgui
-
class $(class_name)(gr.top_block, Qt.QWidget):
def __init__($param_str):
@@ -118,7 +106,14 @@ class $(class_name)(gr.top_block, Qt.QWidget):
self.top_layout.addLayout(self.top_grid_layout)
self.settings = Qt.QSettings("GNU Radio", "$class_name")
- self.restoreGeometry(self.settings.value("geometry").toByteArray())
+
+ try:
+ if StrictVersion(Qt.qVersion()) < StrictVersion("5.0.0"):
+ self.restoreGeometry(self.settings.value("geometry").toByteArray())
+ else:
+ self.restoreGeometry(self.settings.value("geometry"))
+ except:
+ pass
#elif $generate_options == 'no_gui'
@@ -198,18 +193,6 @@ gr.io_signaturev($(len($io_sigs)), $(len($io_sigs)), [$(', '.join($size_strs))])
$indent($var.get_var_make())
#end for
########################################################
-##Create Message Queues
-########################################################
-#if $msgs
-
- $DIVIDER
- # Message Queues
- $DIVIDER
-#end if
-#for $msg in $msgs
- $(msg.get_source().get_parent().get_id())_msgq_out = $(msg.get_sink().get_parent().get_id())_msgq_in = gr.msg_queue(2)
-#end for
-########################################################
##Create Blocks
########################################################
#if $blocks
@@ -338,19 +321,22 @@ $short_id#slurp
def argument_parser():
- #set $desc_args = 'usage="%prog: [options]", option_class=eng_option'
+ #set $arg_parser_args = ''
#if $flow_graph.get_option('description')
- #set $desc_args += ', description=description'
+ #set $arg_parser_args = 'description=description'
description = $repr($flow_graph.get_option('description'))
#end if
- parser = OptionParser($desc_args)
+ parser = ArgumentParser($arg_parser_args)
#for $param in $parameters
#set $type = $param.get_param('type').get_value()
#if $type
#silent $params_eq_list.append('%s=options.%s'%($param.get_id(), $param.get_id()))
- parser.add_option(
- "$make_short_id($param)", "--$param.get_id().replace('_', '-')", dest="$param.get_id()", type="$type", default=$make_default($type, $param),
- help="Set $($param.get_param('label').get_evaluated() or $param.get_id()) [default=%default]")
+ parser.add_argument(
+ #if $make_short_id($param)
+ "$make_short_id($param)", #slurp
+ #end if
+ "--$param.get_id().replace('_', '-')", dest="$param.get_id()", type=$type, default=$make_default($type, $param),
+ help="Set $($param.get_param('label').get_evaluated() or $param.get_id()) [default=%(default)r]")
#end if
#end for
return parser
@@ -360,27 +346,15 @@ def argument_parser():
def main(top_block_cls=$(class_name), options=None):
#if $parameters
if options is None:
- options, _ = argument_parser().parse_args()
+ options = argument_parser().parse_args()
#end if
#if $flow_graph.get_option('realtime_scheduling')
if gr.enable_realtime_scheduling() != gr.RT_OK:
print "Error: failed to enable real-time scheduling."
#end if
- #if $generate_options == 'wx_gui'
- tb = top_block_cls($(', '.join($params_eq_list)))
- #if $flow_graph.get_option('max_nouts')
- tb.Run($flow_graph.get_option('run'), $flow_graph.get_option('max_nouts'))
- #else
- tb.Start($flow_graph.get_option('run'))
- #for $m in $monitors
- (tb.$m.get_id()).start()
- #end for
- tb.Wait()
- #end if
- #elif $generate_options == 'qt_gui'
- from distutils.version import StrictVersion
- if StrictVersion(Qt.qVersion()) >= StrictVersion("4.5.0"):
+ #if $generate_options == 'qt_gui'
+ if StrictVersion("4.5.0") <= StrictVersion(Qt.qVersion()) < StrictVersion("5.0.0"):
style = gr.prefs().get_string('qtgui', 'style', 'raster')
Qt.QApplication.setGraphicsSystem(style)
qapp = Qt.QApplication(sys.argv)
@@ -401,7 +375,7 @@ def main(top_block_cls=$(class_name), options=None):
def quitting():
tb.stop()
tb.wait()
- qapp.connect(qapp, Qt.SIGNAL("aboutToQuit()"), quitting)
+ qapp.aboutToQuit.connect(quitting)
#for $m in $monitors
if $m.has_param('en'):
if $m.get_param('en').get_value():
diff --git a/grc/core/utils/CMakeLists.txt b/grc/core/utils/CMakeLists.txt
index 2528fbc43c..3ba65258a5 100644
--- a/grc/core/utils/CMakeLists.txt
+++ b/grc/core/utils/CMakeLists.txt
@@ -22,5 +22,4 @@ file(GLOB py_files "*.py")
GR_PYTHON_INSTALL(
FILES ${py_files}
DESTINATION ${GR_PYTHON_DIR}/gnuradio/grc/core/utils
- COMPONENT "grc"
)
diff --git a/grc/core/utils/odict.py b/grc/core/utils/odict.py
index 9d69082600..85927e869f 100644
--- a/grc/core/utils/odict.py
+++ b/grc/core/utils/odict.py
@@ -59,7 +59,7 @@ class odict(DictMixin):
"""
index = (pos_key is None) and len(self._keys) or self._keys.index(pos_key)
if key in self._keys:
- raise KeyError('Cannot insert, key "{0}" already exists'.format(str(key)))
+ raise KeyError('Cannot insert, key "{}" already exists'.format(str(key)))
self._keys.insert(index+1, key)
self._data[key] = val
@@ -75,7 +75,7 @@ class odict(DictMixin):
"""
index = (pos_key is not None) and self._keys.index(pos_key) or 0
if key in self._keys:
- raise KeyError('Cannot insert, key "{0}" already exists'.format(str(key)))
+ raise KeyError('Cannot insert, key "{}" already exists'.format(str(key)))
self._keys.insert(index, key)
self._data[key] = val
diff --git a/grc/core/utils/shlex.py b/grc/core/utils/shlex.py
new file mode 100644
index 0000000000..6b620fa396
--- /dev/null
+++ b/grc/core/utils/shlex.py
@@ -0,0 +1,47 @@
+# Copyright 2016 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio 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 3, or (at your option)
+# any later version.
+#
+# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+
+from __future__ import absolute_import
+
+import re
+import shlex
+
+# back port from python3
+
+_find_unsafe = re.compile(r'[^\w@%+=:,./-]').search
+
+
+def _shlex_quote(s):
+ """Return a shell-escaped version of the string *s*."""
+ if not s:
+ return "''"
+ if _find_unsafe(s) is None:
+ return s
+
+ # use single quotes, and put single quotes into double quotes
+ # the string $'b is then quoted as '$'"'"'b'
+ return "'" + s.replace("'", "'\"'\"'") + "'"
+
+
+if not hasattr(shlex, 'quote'):
+ quote = _shlex_quote
+else:
+ quote = shlex.quote
+
+split = shlex.split