summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohnathan Corgan <johnathan@corganlabs.com>2016-02-03 11:59:50 -0800
committerJohnathan Corgan <johnathan@corganlabs.com>2016-02-03 11:59:50 -0800
commit1049fa0bbde029f5435ee6e5cd8e28d1d275ce7c (patch)
tree4451e884bcf40b050d1e05f74ca26e767b8d9c9c
parent5632236167e81694947d992918a8035fa1bc2972 (diff)
parent13b69807d0881c233f0cd5b73e5a07425852777c (diff)
Merge branch 'master' into next
-rw-r--r--gnuradio-runtime/lib/hier_block2_detail.cc40
-rw-r--r--gnuradio-runtime/lib/hier_block2_detail.h1
-rw-r--r--gr-digital/include/gnuradio/digital/pfb_clock_sync_ccf.h11
-rw-r--r--gr-digital/include/gnuradio/digital/pfb_clock_sync_fff.h11
-rw-r--r--gr-digital/lib/pfb_clock_sync_ccf_impl.cc24
-rw-r--r--gr-digital/lib/pfb_clock_sync_ccf_impl.h5
-rw-r--r--gr-digital/lib/pfb_clock_sync_fff_impl.cc23
-rw-r--r--gr-digital/lib/pfb_clock_sync_fff_impl.h3
-rwxr-xr-xgr-digital/python/digital/qa_pfb_clock_sync.py104
-rw-r--r--gr-qtgui/grc/qtgui_freq_sink_x.xml2
-rw-r--r--grc/gui/Messages.py2
-rw-r--r--grc/python/Block.py7
-rw-r--r--grc/python/Generator.py49
-rw-r--r--grc/python/epy_block_io.py12
14 files changed, 241 insertions, 53 deletions
diff --git a/gnuradio-runtime/lib/hier_block2_detail.cc b/gnuradio-runtime/lib/hier_block2_detail.cc
index 60910d0dd9..0d0ddf55ba 100644
--- a/gnuradio-runtime/lib/hier_block2_detail.cc
+++ b/gnuradio-runtime/lib/hier_block2_detail.cc
@@ -328,11 +328,45 @@ namespace gr {
}
void
+ hier_block2_detail::refresh_io_signature()
+ {
+ int min_inputs = d_owner->input_signature()->min_streams();
+ int max_inputs = d_owner->input_signature()->max_streams();
+ int min_outputs = d_owner->output_signature()->min_streams();
+ int max_outputs = d_owner->output_signature()->max_streams();
+
+ if(max_inputs == io_signature::IO_INFINITE ||
+ max_outputs == io_signature::IO_INFINITE ||
+ (min_inputs != max_inputs) ||(min_outputs != max_outputs) ) {
+ std::stringstream msg;
+ msg << "Hierarchical blocks do not yet support arbitrary or"
+ << " variable numbers of inputs or outputs (" << d_owner->name() << ")";
+ throw std::runtime_error(msg.str());
+ }
+
+ // Check for # input change
+ if ((signed)d_inputs.size() != max_inputs)
+ {
+ d_inputs.resize(max_inputs);
+ }
+
+ // Check for # output change
+ if ((signed)d_outputs.size() != max_outputs)
+ {
+ d_outputs.resize(max_outputs);
+ d_min_output_buffer.resize(max_outputs, 0);
+ d_max_output_buffer.resize(max_outputs, 0);
+ }
+ }
+
+ void
hier_block2_detail::connect_input(int my_port, int port,
basic_block_sptr block)
{
std::stringstream msg;
+ refresh_io_signature();
+
if(my_port < 0 || my_port >= (signed)d_inputs.size()) {
msg << "input port " << my_port << " out of range for " << block;
throw std::invalid_argument(msg.str());
@@ -356,6 +390,8 @@ namespace gr {
{
std::stringstream msg;
+ refresh_io_signature();
+
if(my_port < 0 || my_port >= (signed)d_outputs.size()) {
msg << "output port " << my_port << " out of range for " << block;
throw std::invalid_argument(msg.str());
@@ -376,6 +412,8 @@ namespace gr {
{
std::stringstream msg;
+ refresh_io_signature();
+
if(my_port < 0 || my_port >= (signed)d_inputs.size()) {
msg << "input port number " << my_port << " out of range for " << block;
throw std::invalid_argument(msg.str());
@@ -399,6 +437,8 @@ namespace gr {
{
std::stringstream msg;
+ refresh_io_signature();
+
if(my_port < 0 || my_port >= (signed)d_outputs.size()) {
msg << "output port number " << my_port << " out of range for " << block;
throw std::invalid_argument(msg.str());
diff --git a/gnuradio-runtime/lib/hier_block2_detail.h b/gnuradio-runtime/lib/hier_block2_detail.h
index 8c38c3754a..a5584fe92a 100644
--- a/gnuradio-runtime/lib/hier_block2_detail.h
+++ b/gnuradio-runtime/lib/hier_block2_detail.h
@@ -71,6 +71,7 @@ namespace gr {
endpoint_vector_t d_outputs; // Single internal endpoint per external output
basic_block_vector_t d_blocks;
+ void refresh_io_signature();
void connect_input(int my_port, int port, basic_block_sptr block);
void connect_output(int my_port, int port, basic_block_sptr block);
void disconnect_input(int my_port, int port, basic_block_sptr block);
diff --git a/gr-digital/include/gnuradio/digital/pfb_clock_sync_ccf.h b/gr-digital/include/gnuradio/digital/pfb_clock_sync_ccf.h
index 4d489d1534..118435289c 100644
--- a/gr-digital/include/gnuradio/digital/pfb_clock_sync_ccf.h
+++ b/gr-digital/include/gnuradio/digital/pfb_clock_sync_ccf.h
@@ -187,7 +187,16 @@ namespace gr {
virtual void update_gains() = 0;
/*!
- * Resets the filterbank's filter taps with the new prototype filter
+ * Resets the filterbank's filter taps with the new prototype filter.
+ */
+ virtual void update_taps(const std::vector<float> &taps) = 0;
+
+ /*!
+ * Used to set the taps of the filters in the filterbank and
+ * differential filterbank.
+ *
+ * WARNING: this should not be used externally and will be moved
+ * to a private funtion in the next API.
*/
virtual void set_taps(const std::vector<float> &taps,
std::vector< std::vector<float> > &ourtaps,
diff --git a/gr-digital/include/gnuradio/digital/pfb_clock_sync_fff.h b/gr-digital/include/gnuradio/digital/pfb_clock_sync_fff.h
index c3034579a5..b774ee49aa 100644
--- a/gr-digital/include/gnuradio/digital/pfb_clock_sync_fff.h
+++ b/gr-digital/include/gnuradio/digital/pfb_clock_sync_fff.h
@@ -187,7 +187,16 @@ namespace gr {
virtual void update_gains() = 0;
/*!
- * Resets the filterbank's filter taps with the new prototype filter
+ * Resets the filterbank's filter taps with the new prototype filter.
+ */
+ virtual void update_taps(const std::vector<float> &taps) = 0;
+
+ /*!
+ * Used to set the taps of the filters in the filterbank and
+ * differential filterbank.
+ *
+ * WARNING: this should not be used externally and will be moved
+ * to a private funtion in the next API.
*/
virtual void set_taps(const std::vector<float> &taps,
std::vector< std::vector<float> > &ourtaps,
diff --git a/gr-digital/lib/pfb_clock_sync_ccf_impl.cc b/gr-digital/lib/pfb_clock_sync_ccf_impl.cc
index c8e1221c90..314ff94b0b 100644
--- a/gr-digital/lib/pfb_clock_sync_ccf_impl.cc
+++ b/gr-digital/lib/pfb_clock_sync_ccf_impl.cc
@@ -134,6 +134,14 @@ namespace gr {
ninput_items_required[i] = (noutput_items + history()) * (d_sps/d_osps);
}
+ void
+ pfb_clock_sync_ccf_impl::update_taps(const std::vector<float> &taps)
+ {
+ d_updated_taps = taps;
+ d_updated = true;
+ }
+
+
/*******************************************************************
SET FUNCTIONS
*******************************************************************/
@@ -279,8 +287,6 @@ namespace gr {
// Make sure there is enough output space for d_osps outputs/input.
set_output_multiple(d_osps);
-
- d_updated = true;
}
void
@@ -397,6 +403,15 @@ namespace gr {
gr_complex *in = (gr_complex *) input_items[0];
gr_complex *out = (gr_complex *) output_items[0];
+ if(d_updated) {
+ std::vector<float> dtaps;
+ create_diff_taps(d_updated_taps, dtaps);
+ set_taps(d_updated_taps, d_taps, d_filters);
+ set_taps(dtaps, d_dtaps, d_diff_filters);
+ d_updated = false;
+ return 0; // history requirements may have changed.
+ }
+
float *err = NULL, *outrate = NULL, *outk = NULL;
if(output_items.size() == 4) {
err = (float *) output_items[1];
@@ -404,11 +419,6 @@ namespace gr {
outk = (float*)output_items[3];
}
- if(d_updated) {
- d_updated = false;
- return 0; // history requirements may have changed.
- }
-
std::vector<tag_t> tags;
get_tags_in_range(tags, 0, nitems_read(0),
nitems_read(0)+d_sps*noutput_items,
diff --git a/gr-digital/lib/pfb_clock_sync_ccf_impl.h b/gr-digital/lib/pfb_clock_sync_ccf_impl.h
index 015e037275..535628189f 100644
--- a/gr-digital/lib/pfb_clock_sync_ccf_impl.h
+++ b/gr-digital/lib/pfb_clock_sync_ccf_impl.h
@@ -47,6 +47,7 @@ namespace gr {
std::vector<kernel::fir_filter_ccf*> d_diff_filters;
std::vector< std::vector<float> > d_taps;
std::vector< std::vector<float> > d_dtaps;
+ std::vector<float> d_updated_taps;
float d_k;
float d_rate;
@@ -73,9 +74,11 @@ namespace gr {
void setup_rpc();
void update_gains();
-
+
void forecast(int noutput_items, gr_vector_int &ninput_items_required);
+ void update_taps(const std::vector<float> &taps);
+
void set_taps(const std::vector<float> &taps,
std::vector< std::vector<float> > &ourtaps,
std::vector<kernel::fir_filter_ccf*> &ourfilter);
diff --git a/gr-digital/lib/pfb_clock_sync_fff_impl.cc b/gr-digital/lib/pfb_clock_sync_fff_impl.cc
index beb6bf5579..09c72495a0 100644
--- a/gr-digital/lib/pfb_clock_sync_fff_impl.cc
+++ b/gr-digital/lib/pfb_clock_sync_fff_impl.cc
@@ -131,6 +131,13 @@ namespace gr {
ninput_items_required[i] = (noutput_items + history()) * (d_sps/d_osps);
}
+ void
+ pfb_clock_sync_fff_impl::update_taps(const std::vector<float> &taps)
+ {
+ d_updated_taps = taps;
+ d_updated = true;
+ }
+
/*******************************************************************
SET FUNCTIONS
*******************************************************************/
@@ -258,8 +265,6 @@ namespace gr {
// Make sure there is enough output space for d_osps outputs/input.
set_output_multiple(d_osps);
-
- d_updated = true;
}
void
@@ -376,6 +381,15 @@ namespace gr {
float *in = (float *) input_items[0];
float *out = (float *) output_items[0];
+ if(d_updated) {
+ std::vector<float> dtaps;
+ create_diff_taps(d_updated_taps, dtaps);
+ set_taps(d_updated_taps, d_taps, d_filters);
+ set_taps(dtaps, d_dtaps, d_diff_filters);
+ d_updated = false;
+ return 0; // history requirements may have changed.
+ }
+
float *err = NULL, *outrate = NULL, *outk = NULL;
if(output_items.size() == 4) {
err = (float *) output_items[1];
@@ -383,11 +397,6 @@ namespace gr {
outk = (float*)output_items[3];
}
- if(d_updated) {
- d_updated = false;
- return 0; // history requirements may have changed.
- }
-
int i = 0, count = 0;
// produce output as long as we can and there are enough input samples
diff --git a/gr-digital/lib/pfb_clock_sync_fff_impl.h b/gr-digital/lib/pfb_clock_sync_fff_impl.h
index 2c88341c55..7bbbd995d1 100644
--- a/gr-digital/lib/pfb_clock_sync_fff_impl.h
+++ b/gr-digital/lib/pfb_clock_sync_fff_impl.h
@@ -47,6 +47,7 @@ namespace gr {
std::vector<kernel::fir_filter_fff*> d_diff_filters;
std::vector< std::vector<float> > d_taps;
std::vector< std::vector<float> > d_dtaps;
+ std::vector<float> d_updated_taps;
float d_k;
float d_rate;
@@ -74,6 +75,8 @@ namespace gr {
void forecast(int noutput_items, gr_vector_int &ninput_items_required);
+ void update_taps(const std::vector<float> &taps);
+
void set_taps(const std::vector<float> &taps,
std::vector< std::vector<float> > &ourtaps,
std::vector<kernel::fir_filter_fff*> &ourfilter);
diff --git a/gr-digital/python/digital/qa_pfb_clock_sync.py b/gr-digital/python/digital/qa_pfb_clock_sync.py
index 3c8074b154..e16a99338e 100755
--- a/gr-digital/python/digital/qa_pfb_clock_sync.py
+++ b/gr-digital/python/digital/qa_pfb_clock_sync.py
@@ -1,27 +1,28 @@
#!/usr/bin/env python
#
# Copyright 2011,2013 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.
-#
+#
import random
import cmath
+import time
from gnuradio import gr, gr_unittest, filter, digital, blocks
@@ -43,7 +44,7 @@ class test_pfb_clock_sync(gr_unittest.TestCase):
init_phase = nfilts/2
max_rate_deviation = 0.5
osps = 1
-
+
ntaps = 11 * int(sps*nfilts)
taps = filter.firdes.root_raised_cosine(nfilts, nfilts*sps,
1.0, excess_bw, ntaps)
@@ -52,7 +53,7 @@ class test_pfb_clock_sync(gr_unittest.TestCase):
nfilts, init_phase,
max_rate_deviation,
osps)
-
+
data = 10000*[complex(1,0), complex(-1,0)]
self.src = blocks.vector_source_c(data, False)
@@ -69,7 +70,7 @@ class test_pfb_clock_sync(gr_unittest.TestCase):
self.tb.connect(self.src, self.rrc_filter, self.test, self.snk)
self.tb.run()
-
+
expected_result = 10000*[complex(1,0), complex(-1,0)]
dst_data = self.snk.data()
@@ -82,7 +83,7 @@ class test_pfb_clock_sync(gr_unittest.TestCase):
#for e,d in zip(expected_result, dst_data):
# print e, d
-
+
self.assertComplexTuplesAlmostEqual(expected_result, dst_data, 1)
@@ -96,7 +97,7 @@ class test_pfb_clock_sync(gr_unittest.TestCase):
init_phase = nfilts/2
max_rate_deviation = 0.5
osps = 1
-
+
ntaps = 11 * int(sps*nfilts)
taps = filter.firdes.root_raised_cosine(nfilts, nfilts*sps,
1.0, excess_bw, ntaps)
@@ -105,7 +106,7 @@ class test_pfb_clock_sync(gr_unittest.TestCase):
nfilts, init_phase,
max_rate_deviation,
osps)
-
+
data = 10000*[1, -1]
self.src = blocks.vector_source_f(data, False)
@@ -122,7 +123,7 @@ class test_pfb_clock_sync(gr_unittest.TestCase):
self.tb.connect(self.src, self.rrc_filter, self.test, self.snk)
self.tb.run()
-
+
expected_result = 10000*[1, -1]
dst_data = self.snk.data()
@@ -135,9 +136,86 @@ class test_pfb_clock_sync(gr_unittest.TestCase):
#for e,d in zip(expected_result, dst_data):
# print e, d
-
+
self.assertFloatTuplesAlmostEqual(expected_result, dst_data, 1)
+ def test03(self):
+ # Test resting of taps
+ excess_bw0 = 0.35
+ excess_bw1 = 0.22
+
+ sps = 4
+ loop_bw = cmath.pi/100.0
+ nfilts = 32
+ init_phase = nfilts/2
+ max_rate_deviation = 0.5
+ osps = 1
+
+ ntaps = 11 * int(sps*nfilts)
+ taps = filter.firdes.root_raised_cosine(nfilts, nfilts*sps,
+ 1.0, excess_bw0, ntaps)
+
+ self.test = digital.pfb_clock_sync_ccf(sps, loop_bw, taps,
+ nfilts, init_phase,
+ max_rate_deviation,
+ osps)
+
+ self.src = blocks.null_source(gr.sizeof_gr_complex)
+ self.snk = blocks.null_sink(gr.sizeof_gr_complex)
+
+ self.tb.connect(self.src, self.test, self.snk)
+ self.tb.start()
+ time.sleep(0.1)
+
+ taps = filter.firdes.root_raised_cosine(nfilts, nfilts*sps,
+ 1.0, excess_bw1, ntaps)
+
+ self.test.update_taps(taps)
+
+ self.tb.stop()
+ self.tb.wait()
+
+ self.assertTrue(True)
+
+ def test03_f(self):
+ # Test resting of taps
+ excess_bw0 = 0.35
+ excess_bw1 = 0.22
+
+ sps = 4
+ loop_bw = cmath.pi/100.0
+ nfilts = 32
+ init_phase = nfilts/2
+ max_rate_deviation = 0.5
+ osps = 1
+
+ ntaps = 11 * int(sps*nfilts)
+ taps = filter.firdes.root_raised_cosine(nfilts, nfilts*sps,
+ 1.0, excess_bw0, ntaps)
+
+ self.test = digital.pfb_clock_sync_fff(sps, loop_bw, taps,
+ nfilts, init_phase,
+ max_rate_deviation,
+ osps)
+
+ self.src = blocks.null_source(gr.sizeof_float)
+ self.snk = blocks.null_sink(gr.sizeof_float)
+
+ self.tb.connect(self.src, self.test, self.snk)
+ self.tb.start()
+ time.sleep(0.1)
+
+ taps = filter.firdes.root_raised_cosine(nfilts, nfilts*sps,
+ 1.0, excess_bw1, ntaps)
+
+ self.test.update_taps(taps)
+
+ self.tb.stop()
+ self.tb.wait()
+
+ self.assertTrue(True)
+
+
if __name__ == '__main__':
gr_unittest.run(test_pfb_clock_sync, "test_pfb_clock_sync.xml")
diff --git a/gr-qtgui/grc/qtgui_freq_sink_x.xml b/gr-qtgui/grc/qtgui_freq_sink_x.xml
index 538ff3f3c8..d7c3139849 100644
--- a/gr-qtgui/grc/qtgui_freq_sink_x.xml
+++ b/gr-qtgui/grc/qtgui_freq_sink_x.xml
@@ -110,7 +110,7 @@ $(gui_hint()($win))</make>
<key>fftsize</key>
<value>1024</value>
<type>int</type>
- <hide>#if $type.t == 'message' then 'all' else 'all'#</hide>
+ <hide>#if $type.t == 'message' then 'all' else 'none'#</hide>
</param>
<param>
diff --git a/grc/gui/Messages.py b/grc/gui/Messages.py
index 32c6cf108e..551a8ce753 100644
--- a/grc/gui/Messages.py
+++ b/grc/gui/Messages.py
@@ -122,7 +122,7 @@ def send_fail_gen(error):
def send_start_exec(file_path):
- send('\nExecuting: %r\n' % file_path)
+ send('\nExecuting: %s\n' % file_path)
def send_verbose_exec(verbose):
diff --git a/grc/python/Block.py b/grc/python/Block.py
index 239352de1f..f5c994dc05 100644
--- a/grc/python/Block.py
+++ b/grc/python/Block.py
@@ -272,7 +272,7 @@ class Block(_Block, _GUIBlock):
self._make = '{}({})'.format(blk_io.cls, ', '.join(
'{0}=${0}'.format(key) for key, _ in blk_io.params))
- params = dict()
+ params = {}
for param in list(self._params):
if hasattr(param, '__epy_param__'):
params[param.get_key()] = param
@@ -293,7 +293,7 @@ class Block(_Block, _GUIBlock):
def update_ports(label, ports, port_specs, direction):
ports_to_remove = list(ports)
iter_ports = iter(ports)
- ports_new = list()
+ ports_new = []
port_current = next(iter_ports, None)
for key, port_type in port_specs:
reuse_port = (
@@ -306,6 +306,9 @@ class Block(_Block, _GUIBlock):
port, port_current = port_current, next(iter_ports, None)
else:
n = odict(dict(name=label + str(key), type=port_type, key=key))
+ if port_type == 'message':
+ n['name'] = key
+ n['optional'] = '1'
port = platform.Port(block=self, n=n, dir=direction)
ports_new.append(port)
# replace old port list with new one
diff --git a/grc/python/Generator.py b/grc/python/Generator.py
index d688beba15..56e3a6e78f 100644
--- a/grc/python/Generator.py
+++ b/grc/python/Generator.py
@@ -23,6 +23,7 @@ import subprocess
import tempfile
import shlex
import codecs
+import re # for shlex_quote
from distutils.spawn import find_executable
from Cheetah.Template import Template
@@ -125,24 +126,30 @@ class TopBlockGenerator(object):
Returns:
a popen object
"""
- def args_to_string(args):
- """Accounts for spaces in args"""
- return ' '.join(repr(arg) if ' ' in arg else arg for arg in args)
-
run_command = self._flow_graph.get_option('run_command')
- cmds = shlex.split(run_command.format(python=sys.executable,
- filename=self.get_file_path()))
+ try:
+ run_command = run_command.format(
+ python=shlex_quote(sys.executable),
+ filename=shlex_quote(self.get_file_path()))
+ run_command_args = shlex.split(run_command)
+ except Exception as e:
+ raise ValueError("Can't parse run command {!r}: {}".format(run_command, e))
# when in no gui mode on linux, use a graphical terminal (looks nice)
xterm_executable = find_executable(XTERM_EXECUTABLE)
if self._generate_options == 'no_gui' and xterm_executable:
- cmds = [xterm_executable, '-e', args_to_string(cmds)]
+ run_command_args = [xterm_executable, '-e', run_command]
- Messages.send_start_exec(args_to_string(cmds))
- p = subprocess.Popen(
- args=cmds, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
- shell=False, universal_newlines=True)
- return p
+ # this does not reproduce a shell executable command string, if a graphical
+ # terminal is used. Passing run_command though shlex_quote would do it but
+ # it looks really ugly and confusing in the console panel.
+ Messages.send_start_exec(' '.join(run_command_args))
+
+ return subprocess.Popen(
+ args=run_command_args,
+ stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
+ shell=False, universal_newlines=True
+ )
def _build_python_code_from_template(self):
"""
@@ -420,3 +427,21 @@ class QtHierBlockGenerator(HierBlockGenerator):
"\n${gui_hint()($win)}"
)
return n
+
+
+###########################################################
+# 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("'", "'\"'\"'") + "'"
diff --git a/grc/python/epy_block_io.py b/grc/python/epy_block_io.py
index 8d3ce1caa1..e089908a01 100644
--- a/grc/python/epy_block_io.py
+++ b/grc/python/epy_block_io.py
@@ -39,10 +39,8 @@ def _blk_class(source_code):
raise ValueError("Can't interpret source code: " + str(e))
for var in ns.itervalues():
if inspect.isclass(var)and issubclass(var, gr.gateway.gateway_block):
- break
- else:
- raise ValueError('No python block class found in code')
- return var
+ return var
+ raise ValueError('No python block class found in code')
def extract(cls):
@@ -55,7 +53,7 @@ def extract(cls):
cls_name = cls.__name__
if len(defaults) + 1 != len(spec.args):
- raise ValueError("Need all default values")
+ raise ValueError("Need all __init__ arguments to have default values")
try:
instance = cls()
@@ -66,9 +64,9 @@ def extract(cls):
params = list(zip(spec.args[1:], defaults))
sinks = _ports(instance.in_sig(),
- pmt.to_python(instance.message_ports_in()))
+ pmt.to_python(instance.message_ports_in()))
sources = _ports(instance.out_sig(),
- pmt.to_python(instance.message_ports_out()))
+ pmt.to_python(instance.message_ports_out()))
return BlockIO(name, cls_name, params, sinks, sources, doc)