summaryrefslogtreecommitdiff
path: root/grc/core
diff options
context:
space:
mode:
Diffstat (limited to 'grc/core')
-rw-r--r--grc/core/Config.py9
-rw-r--r--grc/core/Connection.py6
-rw-r--r--grc/core/Constants.py49
-rw-r--r--grc/core/FlowGraph.py53
-rw-r--r--grc/core/Messages.py5
-rw-r--r--grc/core/__init__.py1
-rw-r--r--grc/core/blocks/__init__.py1
-rw-r--r--grc/core/blocks/_build.py12
-rw-r--r--grc/core/blocks/_templates.py3
-rw-r--r--grc/core/blocks/block.py94
-rw-r--r--grc/core/blocks/dummy.py7
-rw-r--r--grc/core/blocks/embedded_python.py11
-rw-r--r--grc/core/blocks/virtual.py9
-rw-r--r--grc/core/cache.py4
-rw-r--r--grc/core/errors.py1
-rw-r--r--grc/core/generator/FlowGraphProxy.py11
-rw-r--r--grc/core/generator/Generator.py1
-rw-r--r--grc/core/generator/cpp_hier_block.py14
-rw-r--r--grc/core/generator/cpp_top_block.py117
-rw-r--r--grc/core/generator/hier_block.py4
-rw-r--r--grc/core/generator/top_block.py60
-rw-r--r--grc/core/io/yaml.py10
-rw-r--r--grc/core/params/dtypes.py25
-rw-r--r--grc/core/params/param.py63
-rw-r--r--grc/core/params/template_arg.py1
-rw-r--r--grc/core/platform.py47
-rw-r--r--grc/core/ports/_virtual_connections.py17
-rw-r--r--grc/core/ports/port.py31
-rw-r--r--grc/core/schema_checker/block.py6
-rw-r--r--grc/core/utils/backports/chainmap.py15
-rw-r--r--grc/core/utils/descriptors/_lazy.py1
-rw-r--r--grc/core/utils/descriptors/evaluated.py9
-rw-r--r--grc/core/utils/epy_block_io.py9
-rw-r--r--grc/core/utils/expr_utils.py12
-rw-r--r--grc/core/utils/extract_docs.py9
-rw-r--r--grc/core/utils/flow_graph_complexity.py9
36 files changed, 454 insertions, 282 deletions
diff --git a/grc/core/Config.py b/grc/core/Config.py
index 73cc135861..374a3f2316 100644
--- a/grc/core/Config.py
+++ b/grc/core/Config.py
@@ -17,13 +17,16 @@ class Config(object):
license = __doc__.strip()
website = 'https://www.gnuradio.org/'
- hier_block_lib_dir = os.environ.get('GRC_HIER_PATH', Constants.DEFAULT_HIER_BLOCK_LIB_DIR)
+ hier_block_lib_dir = os.environ.get(
+ 'GRC_HIER_PATH', Constants.DEFAULT_HIER_BLOCK_LIB_DIR)
def __init__(self, version, version_parts=None, name=None, prefs=None):
self._gr_prefs = prefs if prefs else DummyPrefs()
self.version = version
- self.version_parts = version_parts or version[1:].split('-', 1)[0].split('.')[:3]
- self.enabled_components = self._gr_prefs.get_string('grc', 'enabled_components', '')
+ self.version_parts = version_parts or version[1:].split(
+ '-', 1)[0].split('.')[:3]
+ self.enabled_components = self._gr_prefs.get_string(
+ 'grc', 'enabled_components', '')
if name:
self.name = name
diff --git a/grc/core/Connection.py b/grc/core/Connection.py
index b1c7196e3d..a341abe72a 100644
--- a/grc/core/Connection.py
+++ b/grc/core/Connection.py
@@ -96,12 +96,14 @@ class Connection(Element):
if source_dtype != sink_dtype and source_dtype not in ALIASES_OF.get(
sink_dtype, set()
):
- self.add_error_message('Source IO type "{}" does not match sink IO type "{}".'.format(source_dtype, sink_dtype))
+ self.add_error_message('Source IO type "{}" does not match sink IO type "{}".'.format(
+ source_dtype, sink_dtype))
source_size = self.source_port.item_size
sink_size = self.sink_port.item_size
if source_size != sink_size:
- self.add_error_message('Source IO size "{}" does not match sink IO size "{}".'.format(source_size, sink_size))
+ self.add_error_message(
+ 'Source IO size "{}" does not match sink IO size "{}".'.format(source_size, sink_size))
##############################################
# Import/Export Methods
diff --git a/grc/core/Constants.py b/grc/core/Constants.py
index 953676ffde..93adec26be 100644
--- a/grc/core/Constants.py
+++ b/grc/core/Constants.py
@@ -41,7 +41,7 @@ DEFAULT_DOMAIN = GR_STREAM_DOMAIN
# File creation modes
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
+ 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
PARAM_TYPE_NAMES = {
@@ -50,7 +50,7 @@ PARAM_TYPE_NAMES = {
'complex_vector', 'real_vector', 'float_vector', 'int_vector',
'hex', 'string', 'bool',
'file_open', 'file_save', 'dir_select', '_multiline', '_multiline_python_external',
- 'id', 'stream_id','name',
+ 'id', 'stream_id', 'name',
'gui_hint',
'import',
}
@@ -89,31 +89,31 @@ GRC_COLOR_GREY = '#BDBDBD'
GRC_COLOR_WHITE = '#FFFFFF'
CORE_TYPES = ( # name, key, sizeof, color
- ('Complex Float 64', 'fc64', 16, GRC_COLOR_BROWN),
- ('Complex Float 32', 'fc32', 8, GRC_COLOR_BLUE),
- ('Complex Integer 64', 'sc64', 16, GRC_COLOR_LIGHT_GREEN),
- ('Complex Integer 32', 'sc32', 8, GRC_COLOR_GREEN),
- ('Complex Integer 16', 'sc16', 4, GRC_COLOR_AMBER),
- ('Complex Integer 8', 'sc8', 2, GRC_COLOR_PURPLE),
- ('Float 64', 'f64', 8, GRC_COLOR_CYAN),
- ('Float 32', 'f32', 4, GRC_COLOR_ORANGE),
- ('Integer 64', 's64', 8, GRC_COLOR_LIME),
- ('Integer 32', 's32', 4, GRC_COLOR_TEAL),
- ('Integer 16', 's16', 2, GRC_COLOR_YELLOW),
- ('Integer 8', 's8', 1, GRC_COLOR_PURPLE_A400),
- ('Bits (unpacked byte)', 'bit', 1, GRC_COLOR_PURPLE_A100),
- ('Async Message', 'message', 0, GRC_COLOR_GREY),
- ('Bus Connection', 'bus', 0, GRC_COLOR_WHITE),
- ('Wildcard', '', 0, GRC_COLOR_WHITE),
+ ('Complex Float 64', 'fc64', 16, GRC_COLOR_BROWN),
+ ('Complex Float 32', 'fc32', 8, GRC_COLOR_BLUE),
+ ('Complex Integer 64', 'sc64', 16, GRC_COLOR_LIGHT_GREEN),
+ ('Complex Integer 32', 'sc32', 8, GRC_COLOR_GREEN),
+ ('Complex Integer 16', 'sc16', 4, GRC_COLOR_AMBER),
+ ('Complex Integer 8', 'sc8', 2, GRC_COLOR_PURPLE),
+ ('Float 64', 'f64', 8, GRC_COLOR_CYAN),
+ ('Float 32', 'f32', 4, GRC_COLOR_ORANGE),
+ ('Integer 64', 's64', 8, GRC_COLOR_LIME),
+ ('Integer 32', 's32', 4, GRC_COLOR_TEAL),
+ ('Integer 16', 's16', 2, GRC_COLOR_YELLOW),
+ ('Integer 8', 's8', 1, GRC_COLOR_PURPLE_A400),
+ ('Bits (unpacked byte)', 'bit', 1, GRC_COLOR_PURPLE_A100),
+ ('Async Message', 'message', 0, GRC_COLOR_GREY),
+ ('Bus Connection', 'bus', 0, GRC_COLOR_WHITE),
+ ('Wildcard', '', 0, GRC_COLOR_WHITE),
)
ALIAS_TYPES = {
'complex': (8, GRC_COLOR_BLUE),
- 'float': (4, GRC_COLOR_ORANGE),
- 'int': (4, GRC_COLOR_TEAL),
- 'short': (2, GRC_COLOR_YELLOW),
- 'byte': (1, GRC_COLOR_PURPLE_A400),
- 'bits': (1, GRC_COLOR_PURPLE_A100),
+ 'float': (4, GRC_COLOR_ORANGE),
+ 'int': (4, GRC_COLOR_TEAL),
+ 'short': (2, GRC_COLOR_YELLOW),
+ 'byte': (1, GRC_COLOR_PURPLE_A400),
+ 'bits': (1, GRC_COLOR_PURPLE_A100),
}
ALIASES_OF = {
@@ -135,4 +135,5 @@ ALIASES_OF = {
}
TYPE_TO_SIZEOF = {key: sizeof for name, key, sizeof, color in CORE_TYPES}
-TYPE_TO_SIZEOF.update((key, sizeof) for key, (sizeof, _) in ALIAS_TYPES.items())
+TYPE_TO_SIZEOF.update((key, sizeof)
+ for key, (sizeof, _) in ALIAS_TYPES.items())
diff --git a/grc/core/FlowGraph.py b/grc/core/FlowGraph.py
index ad42371bb8..ae567d003d 100644
--- a/grc/core/FlowGraph.py
+++ b/grc/core/FlowGraph.py
@@ -68,7 +68,8 @@ class FlowGraph(Element):
Returns:
a sorted list of variable blocks in order of dependency (indep -> dep)
"""
- variables = [block for block in self.iter_enabled_blocks() if block.is_variable]
+ variables = [block for block in self.iter_enabled_blocks()
+ if block.is_variable]
return expr_utils.sort_objects(variables, attrgetter('name'), methodcaller('get_var_make'))
def get_parameters(self):
@@ -78,7 +79,8 @@ class FlowGraph(Element):
Returns:
a list of parameterized variables
"""
- parameters = [b for b in self.iter_enabled_blocks() if b.key == 'parameter']
+ parameters = [b for b in self.iter_enabled_blocks()
+ if b.key == 'parameter']
return parameters
def get_snippets(self):
@@ -126,7 +128,8 @@ class FlowGraph(Element):
"""
Get a list of all ControlPort monitors
"""
- monitors = [b for b in self.iter_enabled_blocks() if 'ctrlport_monitor' in b.key]
+ monitors = [b for b in self.iter_enabled_blocks()
+ if 'ctrlport_monitor' in b.key]
return monitors
def get_python_modules(self):
@@ -189,7 +192,8 @@ class FlowGraph(Element):
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))
+ raise ValueError(
+ "Can't parse run command {!r}: {}".format(run_command, e))
def get_imported_names(self):
"""
@@ -241,7 +245,8 @@ class FlowGraph(Element):
# this is ok behavior, unfortunately we could be hiding other import bugs
pass
except Exception:
- log.exception('Failed to evaluate import expression "{0}"'.format(expr), exc_info=True)
+ log.exception('Failed to evaluate import expression "{0}"'.format(
+ expr), exc_info=True)
pass
self.imported_names = list(namespace.keys())
@@ -252,17 +257,20 @@ class FlowGraph(Element):
exec(expr, module.__dict__)
namespace[id] = module
except Exception:
- log.exception('Failed to evaluate expression in module {0}'.format(id), exc_info=True)
+ log.exception(
+ 'Failed to evaluate expression in module {0}'.format(id), exc_info=True)
pass
# Load parameters
np = {} # params don't know each other
for parameter_block in self.get_parameters():
try:
- value = eval(parameter_block.params['value'].to_code(), namespace)
+ value = eval(
+ parameter_block.params['value'].to_code(), namespace)
np[parameter_block.name] = value
except Exception:
- log.exception('Failed to evaluate parameter block {0}'.format(parameter_block.name), exc_info=True)
+ log.exception('Failed to evaluate parameter block {0}'.format(
+ parameter_block.name), exc_info=True)
pass
namespace.update(np) # Merge param namespace
@@ -273,13 +281,16 @@ class FlowGraph(Element):
for variable_block in self.get_variables():
try:
variable_block.rewrite()
- value = eval(variable_block.value, namespace, variable_block.namespace)
+ value = eval(variable_block.value, namespace,
+ variable_block.namespace)
namespace[variable_block.name] = value
- self.namespace.update(namespace) # rewrite on subsequent blocks depends on an updated self.namespace
- except TypeError: #Type Errors may happen, but that doesn't matter as they are displayed in the gui
+ # rewrite on subsequent blocks depends on an updated self.namespace
+ self.namespace.update(namespace)
+ except TypeError: # Type Errors may happen, but that doesn't matter as they are displayed in the gui
pass
except Exception:
- log.exception('Failed to evaluate variable block {0}'.format(variable_block.name), exc_info=True)
+ log.exception('Failed to evaluate variable block {0}'.format(
+ variable_block.name), exc_info=True)
pass
self._eval_cache.clear()
@@ -397,7 +408,8 @@ class FlowGraph(Element):
cwd=self.grc_file_path
)
if file_path: # grc file found. load and get block
- self.parent_platform.load_and_generate_flow_graph(file_path, hier_only=True)
+ self.parent_platform.load_and_generate_flow_graph(
+ file_path, hier_only=True)
return self.new_block(block_id) # can be None
def import_data(self, data):
@@ -424,7 +436,8 @@ class FlowGraph(Element):
block = (
self.new_block(block_id) or
self._build_depending_hier_block(block_id) or
- self.new_block(block_id='_dummy', missing_block_id=block_id, **block_data)
+ self.new_block(block_id='_dummy',
+ missing_block_id=block_id, **block_data)
)
block.import_data(**block_data)
@@ -443,7 +456,8 @@ class FlowGraph(Element):
if block.is_dummy_block:
port = block.add_missing_port(key, dir)
else:
- raise LookupError('%s key %r not in %s block keys' % (dir, key, dir))
+ raise LookupError(
+ '%s key %r not in %s block keys' % (dir, key, dir))
return port
had_connect_errors = False
@@ -461,8 +475,10 @@ class FlowGraph(Element):
src_port_id, snk_port_id, source_block, sink_block)
# build the connection
- source_port = verify_and_get_port(src_port_id, source_block, 'source')
- sink_port = verify_and_get_port(snk_port_id, sink_block, 'sink')
+ source_port = verify_and_get_port(
+ src_port_id, source_block, 'source')
+ sink_port = verify_and_get_port(
+ snk_port_id, sink_block, 'sink')
self.connect(source_port, sink_port)
@@ -478,7 +494,8 @@ class FlowGraph(Element):
# Flowgraph errors depending on disabled blocks are not displayed
# in the error dialog box
# So put a message into the Property window of the dummy block
- block.add_error_message('Block id "{}" not found.'.format(block.key))
+ block.add_error_message(
+ 'Block id "{}" not found.'.format(block.key))
self.rewrite() # global rewrite
return had_connect_errors
diff --git a/grc/core/Messages.py b/grc/core/Messages.py
index e6297d98c8..778a6baaab 100644
--- a/grc/core/Messages.py
+++ b/grc/core/Messages.py
@@ -5,7 +5,6 @@
#
-
import traceback
import sys
@@ -43,6 +42,7 @@ def send(message):
for messenger in MESSENGERS_LIST:
messenger(_indent + message)
+
# register stdout by default
register_messenger(sys.stdout.write)
@@ -117,7 +117,8 @@ def send_fail_save(file_path):
def send_fail_connection(msg=''):
- send('>>> Error: Cannot create connection.\n' + ('\t{}\n'.format(msg) if msg else ''))
+ send('>>> Error: Cannot create connection.\n' +
+ ('\t{}\n'.format(msg) if msg else ''))
def send_fail_load_preferences(prefs_file_path):
diff --git a/grc/core/__init__.py b/grc/core/__init__.py
index 8b13789179..e69de29bb2 100644
--- a/grc/core/__init__.py
+++ b/grc/core/__init__.py
@@ -1 +0,0 @@
-
diff --git a/grc/core/blocks/__init__.py b/grc/core/blocks/__init__.py
index a80121e8bf..cc5297ece4 100644
--- a/grc/core/blocks/__init__.py
+++ b/grc/core/blocks/__init__.py
@@ -21,6 +21,7 @@ def register_build_in(cls):
build_ins[cls.key] = cls
return cls
+
from .dummy import DummyBlock
from .embedded_python import EPyBlock, EPyModule
from .virtual import VirtualSink, VirtualSource
diff --git a/grc/core/blocks/_build.py b/grc/core/blocks/_build.py
index 40155fc84f..91ebef1a42 100644
--- a/grc/core/blocks/_build.py
+++ b/grc/core/blocks/_build.py
@@ -79,7 +79,8 @@ def build_ports(ports_raw, direction):
port_id = port.setdefault('id', str(next(stream_port_ids)))
if port_id in port_ids:
- raise Exception('Port id "{}" already exists in {}s'.format(port_id, direction))
+ raise Exception(
+ 'Port id "{}" already exists in {}s'.format(port_id, direction))
port_ids.add(port_id)
ports.append(port)
@@ -137,16 +138,19 @@ def _single_mako_expr(value, block_id):
return None
value = value.strip()
if not (value.startswith('${') and value.endswith('}')):
- raise ValueError('{} is not a mako substitution in {}'.format(value, block_id))
+ raise ValueError(
+ '{} is not a mako substitution in {}'.format(value, block_id))
return value[2:-1].strip()
def _validate_option_attributes(param_data, block_id):
if param_data['dtype'] != 'enum':
- send_warning('{} - option_attributes are for enums only, ignoring'.format(block_id))
+ send_warning(
+ '{} - option_attributes are for enums only, ignoring'.format(block_id))
del param_data['option_attributes']
else:
for key in list(param_data['option_attributes'].keys()):
if key in dir(str):
del param_data['option_attributes'][key]
- send_warning('{} - option_attribute "{}" overrides str, ignoring'.format(block_id, key))
+ send_warning(
+ '{} - option_attribute "{}" overrides str, ignoring'.format(block_id, key))
diff --git a/grc/core/blocks/_templates.py b/grc/core/blocks/_templates.py
index 37775cea1d..8ed69c6eac 100644
--- a/grc/core/blocks/_templates.py
+++ b/grc/core/blocks/_templates.py
@@ -16,12 +16,15 @@ from ..errors import TemplateError
# The utils dict contains convenience functions
# that can be called from any template
+
+
def no_quotes(string, fallback=None):
if len(string) > 2:
if str(string)[0] + str(string)[-1] in ("''", '""'):
return str(string)[1:-1]
return str(fallback if fallback else string)
+
utils = {'no_quotes': no_quotes}
diff --git a/grc/core/blocks/block.py b/grc/core/blocks/block.py
index 86c408f617..89f96f96c8 100644
--- a/grc/core/blocks/block.py
+++ b/grc/core/blocks/block.py
@@ -22,6 +22,7 @@ from ._flags import Flags
from ..base import Element
from ..utils.descriptors import lazy_property
+
def _get_elem(iterable, key):
items = list(iterable)
for item in items:
@@ -39,7 +40,7 @@ class Block(Element):
key = ''
label = ''
category = []
- vtype = '' # This is only used for variables when we want C++ output
+ vtype = '' # This is only used for variables when we want C++ output
flags = Flags('')
documentation = {'': ''}
@@ -67,13 +68,16 @@ class Block(Element):
if self.key == 'options':
self.params['id'].hide = 'part'
- self.sinks = [port_factory(parent=self, **params) for params in self.inputs_data]
- self.sources = [port_factory(parent=self, **params) for params in self.outputs_data]
+ self.sinks = [port_factory(parent=self, **params)
+ for params in self.inputs_data]
+ self.sources = [port_factory(parent=self, **params)
+ for params in self.outputs_data]
self.active_sources = [] # on rewrite
self.active_sinks = [] # on rewrite
- self.states = {'state': True, 'bus_source': False, 'bus_sink': False, 'bus_structure': None}
+ self.states = {'state': True, 'bus_source': False,
+ 'bus_sink': False, 'bus_structure': None}
self.block_namespace = {}
self.deprecated = self.is_deprecated()
@@ -81,7 +85,8 @@ class Block(Element):
# This is a workaround to allow embedded python blocks/modules to load as there is
# currently 'cpp' in the flags by default caused by the other built-in blocks
if hasattr(self, 'cpp_templates'):
- self.orig_cpp_templates = self.cpp_templates # The original template, in case we have to edit it when transpiling to C++
+ # The original template, in case we have to edit it when transpiling to C++
+ self.orig_cpp_templates = self.cpp_templates
self.current_bus_structure = {'source': None, 'sink': None}
@@ -100,8 +105,8 @@ class Block(Element):
except:
return None
-
# region Rewrite_and_Validation
+
def rewrite(self):
"""
Add and remove ports to adjust for the nports.
@@ -125,7 +130,8 @@ class Block(Element):
self.update_bus_logic()
# disconnect hidden ports
- self.parent_flowgraph.disconnect(*[p for p in self.ports() if p.hidden])
+ self.parent_flowgraph.disconnect(
+ *[p for p in self.ports() if p.hidden])
self.active_sources = [p for p in self.sources if not p.hidden]
self.active_sinks = [p for p in self.sinks if not p.hidden]
@@ -142,11 +148,12 @@ class Block(Element):
# this is ok behavior, unfortunately we could be hiding other import bugs
pass
except Exception:
- self.add_error_message(f'Failed to evaluate import expression {imports!r}')
+ self.add_error_message(
+ f'Failed to evaluate import expression {imports!r}')
def update_bus_logic(self):
###############################
- ## Bus Logic
+ # Bus Logic
###############################
for direc in {'source', 'sink'}:
@@ -170,13 +177,12 @@ class Block(Element):
removed_bus_connections.append(c)
ports.remove(port)
-
if (bus_state):
struct = self.form_bus_structure(direc)
self.current_bus_structure[direc] = struct
# Hide ports that are not part of the bus structure
- #TODO: Blocks where it is desired to only have a subset
+ # TODO: Blocks where it is desired to only have a subset
# of ports included in the bus still has some issues
for idx, port in enumerate(ports):
if any([idx in bus for bus in self.current_bus_structure[direc]]):
@@ -187,19 +193,20 @@ class Block(Element):
# Add the Bus Ports to the list of ports
for i in range(len(struct)):
# self.sinks = [port_factory(parent=self, **params) for params in self.inputs_data]
- port = self.parent.parent.make_port(self, direction=direc, id=str(len(ports)), label='bus', dtype='bus', bus_struct=struct[i])
+ port = self.parent.parent.make_port(self, direction=direc, id=str(
+ len(ports)), label='bus', dtype='bus', bus_struct=struct[i])
ports.append(port)
for (saved_port, connection) in zip(removed_bus_ports, removed_bus_connections):
if port.key == saved_port.key:
- self.parent_flowgraph.connections.remove(connection)
+ self.parent_flowgraph.connections.remove(
+ connection)
if saved_port.is_source:
connection.source_port = port
if saved_port.is_sink:
connection.sink_port = port
self.parent_flowgraph.connections.add(connection)
-
else:
self.current_bus_structure[direc] = None
@@ -209,8 +216,6 @@ class Block(Element):
port.hidden = port.stored_hidden_state
port.stored_hidden_state = None
-
-
def _rewrite_nports(self, ports):
for port in ports:
if hasattr(port, 'master_port'): # Not a master port and no left-over clones
@@ -218,7 +223,7 @@ class Block(Element):
port.vlen = port.master_port.vlen
continue
nports = port.multiplicity
- for clone in port.clones[nports-1:]:
+ for clone in port.clones[nports - 1:]:
# Remove excess connections
self.parent_flowgraph.disconnect(clone)
port.remove_clone(clone)
@@ -245,9 +250,11 @@ class Block(Element):
for expr in self.asserts:
try:
if not self.evaluate(expr):
- self.add_error_message('Assertion "{}" failed.'.format(expr))
+ self.add_error_message(
+ 'Assertion "{}" failed.'.format(expr))
except Exception:
- self.add_error_message('Assertion "{}" did not evaluate.'.format(expr))
+ self.add_error_message(
+ 'Assertion "{}" did not evaluate.'.format(expr))
def _validate_generate_mode_compat(self):
"""check if this is a GUI block and matches the selected generate option"""
@@ -261,7 +268,8 @@ class Block(Element):
self.add_error_message("Can't generate this block in mode: {} ".format(
repr(current_generate_option)))
- check_generate_mode('QT GUI', Flags.NEED_QT_GUI, ('qt_gui', 'hb_qt_gui'))
+ check_generate_mode('QT GUI', Flags.NEED_QT_GUI,
+ ('qt_gui', 'hb_qt_gui'))
def _validate_output_language_compat(self):
"""check if this block supports the selected output language"""
@@ -269,19 +277,23 @@ class Block(Element):
if current_output_language == 'cpp':
if 'cpp' not in self.flags:
- self.add_error_message("This block does not support C++ output.")
+ self.add_error_message(
+ "This block does not support C++ output.")
if self.key == 'parameter':
if not self.params['type'].value:
- self.add_error_message("C++ output requires you to choose a parameter type.")
+ self.add_error_message(
+ "C++ output requires you to choose a parameter type.")
def _validate_var_value(self):
"""or variables check the value (only if var_value is used)"""
if self.is_variable and self.value != 'value':
try:
- self.parent_flowgraph.evaluate(self.value, local_namespace=self.namespace)
+ self.parent_flowgraph.evaluate(
+ self.value, local_namespace=self.namespace)
except Exception as err:
- self.add_error_message('Value "{}" cannot be evaluated:\n{}'.format(self.value, err))
+ self.add_error_message(
+ 'Value "{}" cannot be evaluated:\n{}'.format(self.value, err))
# endregion
# region Properties
@@ -458,7 +470,7 @@ class Block(Element):
# For container types we must also determine the type of the template parameter(s)
return 'std::vector<' + get_type(str(evaluated[0]), type(evaluated[0])) + '>'
- except IndexError: # empty list
+ except IndexError: # empty list
return 'std::vector<std::string>'
if _vtype == dict:
@@ -466,9 +478,9 @@ class Block(Element):
# For container types we must also determine the type of the template parameter(s)
key = list(evaluated)[0]
val = list(evaluated.values())[0]
- return 'std::map<' + get_type(str(key), type(key)) + ', ' + get_type(str(val), type(val)) +'>'
+ return 'std::map<' + get_type(str(key), type(key)) + ', ' + get_type(str(val), type(val)) + '>'
- except IndexError: # empty dict
+ except IndexError: # empty dict
return 'std::map<std::string, std::string>'
else:
@@ -480,12 +492,12 @@ class Block(Element):
# The r-value for these types must be transformed to create legal C++ syntax.
if self.vtype in ['bool', 'gr_complex'] or 'std::map' in self.vtype or 'std::vector' in self.vtype:
evaluated = ast.literal_eval(value)
- self.cpp_templates['var_make'] = self.cpp_templates['var_make'].replace('${value}', self.get_cpp_value(evaluated))
+ self.cpp_templates['var_make'] = self.cpp_templates['var_make'].replace(
+ '${value}', self.get_cpp_value(evaluated))
if 'string' in self.vtype:
self.cpp_templates['includes'].append('#include <string>')
-
def get_cpp_value(self, pyval):
if type(pyval) == int or type(pyval) == float:
@@ -494,8 +506,10 @@ class Block(Element):
# Check for PI and replace with C++ constant
pi_re = r'^(math|numpy|np|scipy|sp)\.pi$'
if re.match(pi_re, str(pyval)):
- val_str = re.sub(pi_re, 'boost::math::constants::pi<double>()', val_str)
- self.cpp_templates['includes'].append('#include <boost/math/constants/constants.hpp>')
+ val_str = re.sub(
+ pi_re, 'boost::math::constants::pi<double>()', val_str)
+ self.cpp_templates['includes'].append(
+ '#include <boost/math/constants/constants.hpp>')
return str(pyval)
@@ -503,7 +517,8 @@ class Block(Element):
return str(pyval)[0].lower() + str(pyval)[1:]
elif type(pyval) == complex:
- self.cpp_templates['includes'].append('#include <gnuradio/gr_complex.h>')
+ self.cpp_templates['includes'].append(
+ '#include <gnuradio/gr_complex.h>')
evaluated = ast.literal_eval(str(pyval).strip())
return '{' + str(evaluated.real) + ', ' + str(evaluated.imag) + '}'
@@ -523,7 +538,8 @@ class Block(Element):
self.cpp_templates['includes'].append('#include <map>')
val_str = '{'
for key in pyval:
- val_str += '{' + self.get_cpp_value(key) + ', ' + self.get_cpp_value(pyval[key]) + '}, '
+ val_str += '{' + self.get_cpp_value(key) + \
+ ', ' + self.get_cpp_value(pyval[key]) + '}, '
if len(val_str) > 1:
# truncate to trim superfluous ', ' from the end
@@ -535,7 +551,6 @@ class Block(Element):
self.cpp_templates['includes'].append('#include <string>')
return '"' + pyval + '"'
-
def is_virtual_sink(self):
return self.key == 'virtual_sink'
@@ -561,8 +576,8 @@ class Block(Element):
print(exception.message)
return False
-
# Block bypassing
+
def get_bypassed(self):
"""
Check if the block is bypassed
@@ -618,7 +633,8 @@ class Block(Element):
@property
def namespace(self):
# update block namespace
- self.block_namespace.update({key:param.get_evaluated() for key, param in self.params.items()})
+ self.block_namespace.update(
+ {key: param.get_evaluated() for key, param in self.params.items()})
return self.block_namespace
@property
@@ -721,7 +737,7 @@ class Block(Element):
struct = [range(len(ports))]
# struct = list(range(len(ports)))
- #TODO for more complicated port structures, this code is needed but not working yet
+ # TODO for more complicated port structures, this code is needed but not working yet
if any([p.multiplicity for p in ports]):
structlet = []
last = 0
@@ -736,8 +752,8 @@ class Block(Element):
continue
if p.multiplicity > 1:
- cnt = p.multiplicity-1
- structlet.append([idx+j for j in range(p.multiplicity)])
+ cnt = p.multiplicity - 1
+ structlet.append([idx + j for j in range(p.multiplicity)])
else:
structlet.append([idx])
diff --git a/grc/core/blocks/dummy.py b/grc/core/blocks/dummy.py
index 5cdc05a9df..8147eededb 100644
--- a/grc/core/blocks/dummy.py
+++ b/grc/core/blocks/dummy.py
@@ -9,6 +9,7 @@ from . import Block, register_build_in
from ._build import build_params
+
@register_build_in
class DummyBlock(Block):
@@ -19,12 +20,14 @@ class DummyBlock(Block):
def __init__(self, parent, missing_block_id, parameters, **_):
self.key = missing_block_id
- self.parameters_data = build_params([], False, False, self.flags, self.key)
+ self.parameters_data = build_params(
+ [], False, False, self.flags, self.key)
super(DummyBlock, self).__init__(parent=parent)
param_factory = self.parent_platform.make_param
for param_id in parameters:
- self.params.setdefault(param_id, param_factory(parent=self, id=param_id, dtype='string'))
+ self.params.setdefault(param_id, param_factory(
+ parent=self, id=param_id, dtype='string'))
def is_valid(self):
return False
diff --git a/grc/core/blocks/embedded_python.py b/grc/core/blocks/embedded_python.py
index 051ba70317..893dcda948 100644
--- a/grc/core/blocks/embedded_python.py
+++ b/grc/core/blocks/embedded_python.py
@@ -122,7 +122,8 @@ class EPyBlock(Block):
self.label = blk_io.name or blk_io.cls
self.documentation = {'': blk_io.doc}
- self.module_name = "{}_{}".format(self.parent_flowgraph.get_option("id"), self.name)
+ self.module_name = "{}_{}".format(
+ self.parent_flowgraph.get_option("id"), self.name)
self.templates['imports'] = 'import {} as {} # embedded python block'.format(
self.module_name, self.name)
self.templates['make'] = '{mod}.{cls}({args})'.format(
@@ -131,7 +132,7 @@ class EPyBlock(Block):
args=', '.join('{0}=${{ {0} }}'.format(key) for key, _ in blk_io.params))
self.templates['callbacks'] = [
'{0} = ${{ {0} }}'.format(attr) for attr in blk_io.callbacks
- ]
+ ]
self._update_params(blk_io.params)
self._update_ports('in', self.sinks, blk_io.sinks, 'sink')
@@ -195,7 +196,8 @@ class EPyBlock(Block):
def validate(self):
super(EPyBlock, self).validate()
if self._epy_reload_error:
- self.params['_source_code'].add_error_message(str(self._epy_reload_error))
+ self.params['_source_code'].add_error_message(
+ str(self._epy_reload_error))
@register_build_in
@@ -240,6 +242,7 @@ class EPyModule(Block):
def rewrite(self):
super(EPyModule, self).rewrite()
- self.module_name = "{}_{}".format(self.parent_flowgraph.get_option("id"), self.name)
+ self.module_name = "{}_{}".format(
+ self.parent_flowgraph.get_option("id"), self.name)
self.templates['imports'] = 'import {} as {} # embedded python module'.format(
self.module_name, self.name)
diff --git a/grc/core/blocks/virtual.py b/grc/core/blocks/virtual.py
index 9d1387dbbb..34e0feb34b 100644
--- a/grc/core/blocks/virtual.py
+++ b/grc/core/blocks/virtual.py
@@ -21,7 +21,8 @@ class VirtualSink(Block):
flags.set('cpp')
parameters_data = build_params(
- params_raw=[dict(label='Stream ID', id='stream_id', dtype='stream_id')],
+ params_raw=[
+ dict(label='Stream ID', id='stream_id', dtype='stream_id')],
have_inputs=False, have_outputs=False, flags=flags, block_id=key
)
inputs_data = [dict(domain='stream', dtype='', direction='sink', id="0")]
@@ -45,10 +46,12 @@ class VirtualSource(Block):
flags.set('cpp')
parameters_data = build_params(
- params_raw=[dict(label='Stream ID', id='stream_id', dtype='stream_id')],
+ params_raw=[
+ dict(label='Stream ID', id='stream_id', dtype='stream_id')],
have_inputs=False, have_outputs=False, flags=flags, block_id=key
)
- outputs_data = [dict(domain='stream', dtype='', direction='source', id="0")]
+ outputs_data = [dict(domain='stream', dtype='',
+ direction='source', id="0")]
def __init__(self, parent, **kwargs):
super(VirtualSource, self).__init__(parent, **kwargs)
diff --git a/grc/core/cache.py b/grc/core/cache.py
index ab2cc4465b..59daa4b5ce 100644
--- a/grc/core/cache.py
+++ b/grc/core/cache.py
@@ -16,7 +16,7 @@ logger = logging.getLogger(__name__)
class Cache(object):
- def __init__(self, filename, version = None):
+ def __init__(self, filename, version=None):
self.cache_file = filename
self.version = version
self.cache = {}
@@ -57,7 +57,7 @@ class Cache(object):
if modtime <= self._converter_mtime:
try:
cached = self.cache[filename]
- if int(cached["cached-at"]+0.5) >= modtime:
+ if int(cached["cached-at"] + 0.5) >= modtime:
return cached["data"]
logger.info(f"Cache for {filename} outdated, loading yaml")
except KeyError:
diff --git a/grc/core/errors.py b/grc/core/errors.py
index 59f3e0c436..0b9aefccb7 100644
--- a/grc/core/errors.py
+++ b/grc/core/errors.py
@@ -5,7 +5,6 @@
#
-
class GRCError(Exception):
"""Generic error class"""
diff --git a/grc/core/generator/FlowGraphProxy.py b/grc/core/generator/FlowGraphProxy.py
index 38d44e5b13..dad36c9240 100644
--- a/grc/core/generator/FlowGraphProxy.py
+++ b/grc/core/generator/FlowGraphProxy.py
@@ -8,6 +8,7 @@
from ..utils import expr_utils
from operator import methodcaller, attrgetter
+
class FlowGraphProxy(object): # TODO: move this in a refactored Generator
def __init__(self, fg):
@@ -59,8 +60,8 @@ class FlowGraphProxy(object): # TODO: move this in a refactored Generator
'label': str(pad.params['label'].get_evaluated()),
'type': str(pad.params['type'].get_evaluated()),
'vlen': str(pad.params['vlen'].get_value()),
- 'size': type_param.options.attributes[type_param.get_value()]['size'],
- 'cpp_size': type_param.options.attributes[type_param.get_value()]['cpp_size'],
+ 'size': type_param.options.attributes[type_param.get_value()]['size'],
+ 'cpp_size': type_param.options.attributes[type_param.get_value()]['cpp_size'],
'optional': bool(pad.params['optional'].get_evaluated()),
}
num_ports = pad.params['num_streams'].get_evaluated()
@@ -127,7 +128,8 @@ class FlowGraphProxy(object): # TODO: move this in a refactored Generator
Returns:
a sorted list of variable blocks in order of dependency (indep -> dep)
"""
- variables = [block for block in self.iter_enabled_blocks() if block.is_variable]
+ variables = [block for block in self.iter_enabled_blocks()
+ if block.is_variable]
return expr_utils.sort_objects(variables, attrgetter('name'), methodcaller('get_cpp_var_make'))
def includes(self):
@@ -157,6 +159,7 @@ class FlowGraphProxy(object): # TODO: move this in a refactored Generator
"""
return [block.cpp_templates.render('packages') for block in self.iter_enabled_blocks() if not (block.is_virtual_sink() or block.is_virtual_source())]
+
def get_hier_block_io(flow_graph, direction, domain=None):
"""
Get a list of io ports for this flow graph.
@@ -172,7 +175,7 @@ def get_hier_block_io(flow_graph, direction, domain=None):
'label': str(pad.params['label'].get_evaluated()),
'type': str(pad.params['type'].get_evaluated()),
'vlen': str(pad.params['vlen'].get_value()),
- 'size': type_param.options.attributes[type_param.get_value()]['size'],
+ 'size': type_param.options.attributes[type_param.get_value()]['size'],
'optional': bool(pad.params['optional'].get_evaluated()),
}
num_ports = pad.params['num_streams'].get_evaluated()
diff --git a/grc/core/generator/Generator.py b/grc/core/generator/Generator.py
index 3f1831cc1b..8932419249 100644
--- a/grc/core/generator/Generator.py
+++ b/grc/core/generator/Generator.py
@@ -5,7 +5,6 @@
#
-
from .hier_block import HierBlockGenerator, QtHierBlockGenerator
from .top_block import TopBlockGenerator
from .cpp_top_block import CppTopBlockGenerator
diff --git a/grc/core/generator/cpp_hier_block.py b/grc/core/generator/cpp_hier_block.py
index 67f001568c..688af19348 100644
--- a/grc/core/generator/cpp_hier_block.py
+++ b/grc/core/generator/cpp_hier_block.py
@@ -8,6 +8,7 @@ from .cpp_top_block import CppTopBlockGenerator
from .. import Constants
from ..io import yaml
+
class CppHierBlockGenerator(CppTopBlockGenerator):
"""Extends the top block generator to also generate a block YML file"""
@@ -27,7 +28,8 @@ class CppHierBlockGenerator(CppTopBlockGenerator):
os.mkdir(hier_block_lib_dir)
self._mode = Constants.HIER_BLOCK_FILE_MODE
- self.file_path = os.path.join(hier_block_lib_dir, self._flow_graph.get_option('id'))
+ self.file_path = os.path.join(
+ hier_block_lib_dir, self._flow_graph.get_option('id'))
self.file_path_yml = self.file_path + '.block.yml'
def write(self):
@@ -55,7 +57,6 @@ class CppHierBlockGenerator(CppTopBlockGenerator):
# Windows only supports S_IREAD and S_IWRITE, other flags are ignored
os.chmod(self.file_path_yml, self._mode)
-
def _build_block_n_from_flow_graph_io(self):
"""
Generate a block YML nested data from the flow graph IO
@@ -136,7 +137,8 @@ class CppHierBlockGenerator(CppTopBlockGenerator):
t_cpp = data['cpp_templates'] = collections.OrderedDict()
t_cpp['includes'] = []
- t_cpp['includes'].append('#include "{id}/{id}.hpp"'.format(id=self._flow_graph.get_option('id')))
+ t_cpp['includes'].append(
+ '#include "{id}/{id}.hpp"'.format(id=self._flow_graph.get_option('id')))
# Make data
if parameters:
@@ -147,7 +149,8 @@ class CppHierBlockGenerator(CppTopBlockGenerator):
),
)
else:
- t_cpp['make'] = 'this->${{id}} = {cls}_sptr(make_{cls}());'.format(cls=block_id)
+ t_cpp['make'] = 'this->${{id}} = {cls}_sptr(make_{cls}());'.format(
+ cls=block_id)
t_cpp['declarations'] = '{cls}_sptr ${{id}};'.format(cls=block_id)
# Callback data
@@ -206,7 +209,8 @@ def get_hier_block_io(flow_graph, direction, domain=None):
Returns a list of dicts with: type, label, vlen, size, optional
"""
- pads = flow_graph.get_pad_sources() if direction == 'inputs' else flow_graph.get_pad_sinks()
+ pads = flow_graph.get_pad_sources(
+ ) if direction == 'inputs' else flow_graph.get_pad_sinks()
for pad in pads:
for port in (pad.sources if direction == 'inputs' else pad.sinks):
diff --git a/grc/core/generator/cpp_top_block.py b/grc/core/generator/cpp_top_block.py
index ee9dc1a314..3ee712553f 100644
--- a/grc/core/generator/cpp_top_block.py
+++ b/grc/core/generator/cpp_top_block.py
@@ -38,7 +38,8 @@ class CppTopBlockGenerator(object):
"""
self._flow_graph = FlowGraphProxy(flow_graph)
- self._generate_options = self._flow_graph.get_option('generate_options')
+ self._generate_options = self._flow_graph.get_option(
+ 'generate_options')
self._mode = TOP_BLOCK_FILE_MODE
# Handle the case where the directory is read-only
@@ -48,25 +49,26 @@ class CppTopBlockGenerator(object):
filename = self._flow_graph.get_option('id')
self.file_path = os.path.join(output_dir, filename)
self.output_dir = output_dir
-
+
def _warnings(self):
throttling_blocks = [b for b in self._flow_graph.get_enabled_blocks()
- if b.flags.throttle]
+ if b.flags.throttle]
if not throttling_blocks and not self._generate_options.startswith('hb'):
Messages.send_warning("This flow graph may not have flow control: "
- "no audio or RF hardware blocks found. "
- "Add a Misc->Throttle block to your flow "
- "graph to avoid CPU congestion.")
+ "no audio or RF hardware blocks found. "
+ "Add a Misc->Throttle block to your flow "
+ "graph to avoid CPU congestion.")
if len(throttling_blocks) > 1:
keys = set([b.key for b in throttling_blocks])
if len(keys) > 1 and 'blocks_throttle' in keys:
Messages.send_warning("This flow graph contains a throttle "
- "block and another rate limiting block, "
- "e.g. a hardware source or sink. "
- "This is usually undesired. Consider "
- "removing the throttle block.")
+ "block and another rate limiting block, "
+ "e.g. a hardware source or sink. "
+ "This is usually undesired. Consider "
+ "removing the throttle block.")
- deprecated_block_keys = {b.name for b in self._flow_graph.get_enabled_blocks() if b.flags.deprecated}
+ deprecated_block_keys = {
+ b.name for b in self._flow_graph.get_enabled_blocks() if b.flags.deprecated}
for key in deprecated_block_keys:
Messages.send_warning("The block {!r} is deprecated.".format(key))
@@ -76,7 +78,8 @@ class CppTopBlockGenerator(object):
fg = self._flow_graph
platform = fg.parent
- self.title = fg.get_option('title') or fg.get_option('id').replace('_', ' ').title()
+ self.title = fg.get_option('title') or fg.get_option(
+ 'id').replace('_', ' ').title()
variables = fg.get_cpp_variables()
parameters = fg.get_parameters()
monitors = fg.get_monitors()
@@ -119,7 +122,8 @@ class CppTopBlockGenerator(object):
Returns:
a string of C++ code
"""
- file_path = self.file_path + '/' + self._flow_graph.get_option('id') + '.cpp'
+ file_path = self.file_path + '/' + \
+ self._flow_graph.get_option('id') + '.cpp'
output = []
@@ -132,12 +136,12 @@ class CppTopBlockGenerator(object):
**self.namespace
)
# strip trailing white-space
- flow_graph_code = "\n".join(line.rstrip() for line in flow_graph_code.split("\n"))
+ flow_graph_code = "\n".join(line.rstrip()
+ for line in flow_graph_code.split("\n"))
output.append((file_path, flow_graph_code))
return output
-
def _build_cpp_header_code_from_template(self):
"""
Convert the flow graph to a C++ header file.
@@ -145,7 +149,8 @@ class CppTopBlockGenerator(object):
Returns:
a string of C++ code
"""
- file_path = self.file_path + '/' + self._flow_graph.get_option('id') + '.hpp'
+ file_path = self.file_path + '/' + \
+ self._flow_graph.get_option('id') + '.hpp'
output = []
@@ -158,7 +163,8 @@ class CppTopBlockGenerator(object):
**self.namespace
)
# strip trailing white-space
- flow_graph_code = "\n".join(line.rstrip() for line in flow_graph_code.split("\n"))
+ flow_graph_code = "\n".join(line.rstrip()
+ for line in flow_graph_code.split("\n"))
output.append((file_path, flow_graph_code))
return output
@@ -175,7 +181,7 @@ class CppTopBlockGenerator(object):
cmake_tuples = []
cmake_opt = self._flow_graph.get_option("cmake_opt")
- cmake_opt = " " + cmake_opt # To make sure we get rid of the "-D"s when splitting
+ cmake_opt = " " + cmake_opt # To make sure we get rid of the "-D"s when splitting
for opt_string in cmake_opt.split(" -D"):
opt_string = opt_string.strip()
@@ -196,7 +202,8 @@ class CppTopBlockGenerator(object):
**self.namespace
)
# strip trailing white-space
- flow_graph_code = "\n".join(line.rstrip() for line in flow_graph_code.split("\n"))
+ flow_graph_code = "\n".join(line.rstrip()
+ for line in flow_graph_code.split("\n"))
output.append((file_path, flow_graph_code))
return output
@@ -255,7 +262,8 @@ class CppTopBlockGenerator(object):
def _get_block_sort_text(block):
code = block.cpp_templates.render('declarations')
try:
- code += block.params['gui_hint'].get_value() # Newer gui markup w/ qtgui
+ # Newer gui markup w/ qtgui
+ code += block.params['gui_hint'].get_value()
except:
pass
return code
@@ -265,7 +273,8 @@ class CppTopBlockGenerator(object):
if b.enabled and not (b.get_bypassed() or b.is_import or b in parameters or b.key == 'options' or b.is_virtual_source() or b.is_virtual_sink())
]
- blocks = expr_utils.sort_objects(blocks, operator.attrgetter('name'), _get_block_sort_text)
+ blocks = expr_utils.sort_objects(
+ blocks, operator.attrgetter('name'), _get_block_sort_text)
blocks_make = []
for block in blocks:
translations = block.cpp_templates.render('translations')
@@ -279,7 +288,8 @@ class CppTopBlockGenerator(object):
{r"gr\.sizeof_([\w_]+)": r"sizeof(\1)"}
)
for key in translations:
- make = re.sub(key.replace("\\\\", "\\"), translations[key], make)
+ make = re.sub(key.replace("\\\\", "\\"),
+ translations[key], make)
declarations = declarations.replace(key, translations[key])
if make:
blocks_make.append((block, make, declarations))
@@ -293,7 +303,8 @@ class CppTopBlockGenerator(object):
fg = self._flow_graph
variables = fg.get_cpp_variables()
- type_translation = {'complex': 'gr_complex', 'real': 'double', 'float': 'float', 'int': 'int', 'complex_vector': 'std::vector<gr_complex>', 'real_vector': 'std::vector<double>', 'float_vector': 'std::vector<float>', 'int_vector': 'std::vector<int>', 'string': 'std::string', 'bool': 'bool'}
+ type_translation = {'complex': 'gr_complex', 'real': 'double', 'float': 'float', 'int': 'int', 'complex_vector': 'std::vector<gr_complex>',
+ 'real_vector': 'std::vector<double>', 'float_vector': 'std::vector<float>', 'int_vector': 'std::vector<int>', 'string': 'std::string', 'bool': 'bool'}
# If the type is explcitly specified, translate to the corresponding C++ type
for var in list(variables):
if var.params['value'].dtype != 'raw':
@@ -304,26 +315,28 @@ class CppTopBlockGenerator(object):
# Create an executable fragment of code containing all 'raw' variables in
# order to infer the lvalue types.
#
- # Note that this differs from using ast.literal_eval() as literal_eval evaluates one
- # variable at a time. The code fragment below evaluates all variables together which
+ # Note that this differs from using ast.literal_eval() as literal_eval evaluates one
+ # variable at a time. The code fragment below evaluates all variables together which
# allows the variables to reference each other (i.e. a = b * c).
prog = 'def get_decl_types():\n'
prog += '\tvar_types = {}\n'
for var in variables:
- prog += '\t' + str(var.params['id'].value) + '=' + str(var.params['value'].value) + '\n'
- prog += '\tvar_types = {}\n';
+ prog += '\t' + str(var.params['id'].value) + \
+ '=' + str(var.params['value'].value) + '\n'
+ prog += '\tvar_types = {}\n'
for var in variables:
- prog += '\tvar_types[\'' + str(var.params['id'].value) + '\'] = type(' + str(var.params['id'].value) + ')\n'
+ prog += '\tvar_types[\'' + str(var.params['id'].value) + \
+ '\'] = type(' + str(var.params['id'].value) + ')\n'
prog += '\treturn var_types'
# Execute the code fragment in a separate namespace and retrieve the lvalue types
var_types = {}
namespace = {}
try:
- exec(prog, namespace)
- var_types = namespace['get_decl_types']()
+ exec(prog, namespace)
+ var_types = namespace['get_decl_types']()
except Exception as excp:
- print('Failed to get parameter lvalue types: %s' %(excp))
+ print('Failed to get parameter lvalue types: %s' % (excp))
# Format the rvalue of each variable expression
for var in variables:
@@ -334,20 +347,22 @@ class CppTopBlockGenerator(object):
parameters = fg.get_parameters()
for param in parameters:
- type_translation = {'eng_float' : 'double', 'intx' : 'int', 'str' : 'std::string', 'complex': 'gr_complex'};
+ type_translation = {'eng_float': 'double', 'intx': 'int',
+ 'str': 'std::string', 'complex': 'gr_complex'}
param.vtype = type_translation[param.params['type'].value]
if param.vtype == 'gr_complex':
- evaluated = ast.literal_eval(param.params['value'].value.strip())
- cpp_cmplx = '{' + str(evaluated.real) + ', ' + str(evaluated.imag) + '}'
+ evaluated = ast.literal_eval(
+ param.params['value'].value.strip())
+ cpp_cmplx = '{' + str(evaluated.real) + \
+ ', ' + str(evaluated.imag) + '}'
# Update the 'var_make' entry in the cpp_templates dictionary
d = param.cpp_templates
cpp_expr = d['var_make'].replace('${value}', cpp_cmplx)
- d.update({'var_make':cpp_expr})
+ d.update({'var_make': cpp_expr})
param.cpp_templates = d
-
def _callbacks(self):
fg = self._flow_graph
variables = fg.get_cpp_variables()
@@ -361,16 +376,19 @@ class CppTopBlockGenerator(object):
callbacks_all = []
for block in fg.iter_enabled_blocks():
if not (block.is_virtual_sink() or block.is_virtual_source()):
- callbacks_all.extend(expr_utils.expr_replace(cb, replace_dict) for cb in block.get_cpp_callbacks())
+ callbacks_all.extend(expr_utils.expr_replace(
+ cb, replace_dict) for cb in block.get_cpp_callbacks())
# Map var id to callbacks
def uses_var_id(callback):
used = expr_utils.get_variable_dependencies(callback, [var_id])
- return used and ('this->' + var_id in callback) # callback might contain var_id itself
+ # callback might contain var_id itself
+ return used and ('this->' + var_id in callback)
callbacks = {}
for var_id in var_ids:
- callbacks[var_id] = [callback for callback in callbacks_all if uses_var_id(callback)]
+ callbacks[var_id] = [
+ callback for callback in callbacks_all if uses_var_id(callback)]
return callbacks
@@ -402,14 +420,17 @@ class CppTopBlockGenerator(object):
# Get the virtual blocks and resolve their connections
connection_factory = fg.parent_platform.Connection
- virtual_source_connections = [c for c in connections if isinstance(c.source_block, blocks.VirtualSource)]
+ virtual_source_connections = [c for c in connections if isinstance(
+ c.source_block, blocks.VirtualSource)]
for connection in virtual_source_connections:
sink = connection.sink_port
for source in connection.source_port.resolve_virtual_source():
- resolved = connection_factory(fg.orignal_flowgraph, source, sink)
+ resolved = connection_factory(
+ fg.orignal_flowgraph, source, sink)
connections.append(resolved)
- virtual_connections = [c for c in connections if (isinstance(c.source_block, blocks.VirtualSource) or isinstance(c.sink_block, blocks.VirtualSink))]
+ virtual_connections = [c for c in connections if (isinstance(
+ c.source_block, blocks.VirtualSource) or isinstance(c.sink_block, blocks.VirtualSink))]
for connection in virtual_connections:
# Remove the virtual connection
connections.remove(connection)
@@ -423,7 +444,8 @@ class CppTopBlockGenerator(object):
for block in bypassed_blocks:
# Get the upstream connection (off of the sink ports)
# Use *connections* not get_connections()
- source_connection = [c for c in connections if c.sink_port == block.sinks[0]]
+ source_connection = [
+ c for c in connections if c.sink_port == block.sinks[0]]
# The source connection should never have more than one element.
assert (len(source_connection) == 1)
@@ -435,7 +457,8 @@ class CppTopBlockGenerator(object):
if not sink.enabled:
# Ignore disabled connections
continue
- connection = connection_factory(fg.orignal_flowgraph, source_port, sink.sink_port)
+ connection = connection_factory(
+ fg.orignal_flowgraph, source_port, sink.sink_port)
connections.append(connection)
# Remove this sink connection
connections.remove(sink)
@@ -451,7 +474,8 @@ class CppTopBlockGenerator(object):
template = templates[con.type]
if con.source_port.dtype != 'bus':
- code = template.render(make_port_sig=make_port_sig, source=con.source_port, sink=con.sink_port)
+ code = template.render(
+ make_port_sig=make_port_sig, source=con.source_port, sink=con.sink_port)
if not self._generate_options.startswith('hb'):
code = 'this->tb->' + code
rendered.append(code)
@@ -470,7 +494,8 @@ class CppTopBlockGenerator(object):
hidden_portb = portb.parent.sinks[port_num]
connection = fg.parent_platform.Connection(
parent=self, source=hidden_porta, sink=hidden_portb)
- code = template.render(make_port_sig=make_port_sig, source=hidden_porta, sink=hidden_portb)
+ code = template.render(
+ make_port_sig=make_port_sig, source=hidden_porta, sink=hidden_portb)
if not self._generate_options.startswith('hb'):
code = 'this->tb->' + code
rendered.append(code)
diff --git a/grc/core/generator/hier_block.py b/grc/core/generator/hier_block.py
index d609a50ff9..0985437ed4 100644
--- a/grc/core/generator/hier_block.py
+++ b/grc/core/generator/hier_block.py
@@ -128,7 +128,6 @@ class HierBlockGenerator(TopBlockGenerator):
'set_{key}(${{ {key} }})'.format(key=param_block.name) for param_block in parameters
]
-
# Documentation
data['documentation'] = "\n".join(field for field in (
self._flow_graph.get_option('author'),
@@ -178,7 +177,8 @@ def get_hier_block_io(flow_graph, direction, domain=None):
Returns a list of blocks
"""
- pads = flow_graph.get_pad_sources() if direction == 'inputs' else flow_graph.get_pad_sinks()
+ pads = flow_graph.get_pad_sources(
+ ) if direction == 'inputs' else flow_graph.get_pad_sinks()
for pad in pads:
for port in (pad.sources if direction == 'inputs' else pad.sinks):
diff --git a/grc/core/generator/top_block.py b/grc/core/generator/top_block.py
index 275921da51..2abfd0fbb4 100644
--- a/grc/core/generator/top_block.py
+++ b/grc/core/generator/top_block.py
@@ -30,7 +30,8 @@ class TopBlockGenerator(object):
"""
self._flow_graph = FlowGraphProxy(flow_graph)
- self._generate_options = self._flow_graph.get_option('generate_options')
+ self._generate_options = self._flow_graph.get_option(
+ 'generate_options')
self._mode = TOP_BLOCK_FILE_MODE
# Handle the case where the directory is read-only
@@ -58,7 +59,8 @@ class TopBlockGenerator(object):
"This is usually undesired. Consider "
"removing the throttle block.")
- deprecated_block_keys = {b.name for b in self._flow_graph.get_enabled_blocks() if b.flags.deprecated}
+ deprecated_block_keys = {
+ b.name for b in self._flow_graph.get_enabled_blocks() if b.flags.deprecated}
for key in deprecated_block_keys:
Messages.send_warning("The block {!r} is deprecated.".format(key))
@@ -67,7 +69,8 @@ class TopBlockGenerator(object):
self._warnings()
fg = self._flow_graph
- self.title = fg.get_option('title') or fg.get_option('id').replace('_', ' ').title()
+ self.title = fg.get_option('title') or fg.get_option(
+ 'id').replace('_', ' ').title()
variables = fg.get_variables()
parameters = fg.get_parameters()
monitors = fg.get_monitors()
@@ -97,7 +100,8 @@ class TopBlockGenerator(object):
fg = self._flow_graph
platform = fg.parent
- title = fg.get_option('title') or fg.get_option('id').replace('_', ' ').title()
+ title = fg.get_option('title') or fg.get_option(
+ 'id').replace('_', ' ').title()
variables = fg.get_variables()
parameters = fg.get_parameters()
monitors = fg.get_monitors()
@@ -110,7 +114,8 @@ class TopBlockGenerator(object):
else:
continue
- file_path = os.path.join(self.output_dir, block.module_name + ".py")
+ file_path = os.path.join(
+ self.output_dir, block.module_name + ".py")
output.append((file_path, src))
self.namespace = {
@@ -131,7 +136,8 @@ class TopBlockGenerator(object):
**self.namespace
)
# strip trailing white-space
- flow_graph_code = "\n".join(line.rstrip() for line in flow_graph_code.split("\n"))
+ flow_graph_code = "\n".join(line.rstrip()
+ for line in flow_graph_code.split("\n"))
output.append((self.file_path, flow_graph_code))
return output
@@ -142,7 +148,8 @@ class TopBlockGenerator(object):
seen = set()
output = []
- need_path_hack = any(imp.endswith("# grc-generated hier_block") for imp in imports)
+ need_path_hack = any(imp.endswith(
+ "# grc-generated hier_block") for imp in imports)
if need_path_hack:
output.insert(0, textwrap.dedent("""\
import os
@@ -184,7 +191,8 @@ class TopBlockGenerator(object):
def _get_block_sort_text(block):
code = block.templates.render('make').replace(block.name, ' ')
try:
- code += block.params['gui_hint'].get_value() # Newer gui markup w/ qtgui
+ # Newer gui markup w/ qtgui
+ code += block.params['gui_hint'].get_value()
except KeyError:
# No gui hint
pass
@@ -195,7 +203,8 @@ class TopBlockGenerator(object):
if b.enabled and not (b.get_bypassed() or b.is_import or b.is_snippet or b in parameters or b.key == 'options')
]
- blocks = expr_utils.sort_objects(blocks, operator.attrgetter('name'), _get_block_sort_text)
+ blocks = expr_utils.sort_objects(
+ blocks, operator.attrgetter('name'), _get_block_sort_text)
blocks_make = []
for block in blocks:
make = block.templates.render('make')
@@ -217,16 +226,19 @@ class TopBlockGenerator(object):
callbacks_all = []
for block in fg.iter_enabled_blocks():
- callbacks_all.extend(expr_utils.expr_replace(cb, replace_dict) for cb in block.get_callbacks())
+ callbacks_all.extend(expr_utils.expr_replace(
+ cb, replace_dict) for cb in block.get_callbacks())
# Map var id to callbacks
def uses_var_id(callback):
used = expr_utils.get_variable_dependencies(callback, [var_id])
- return used and (('self.' + var_id in callback) or ('this->' + var_id in callback)) # callback might contain var_id itself
+ # callback might contain var_id itself
+ return used and (('self.' + var_id in callback) or ('this->' + var_id in callback))
callbacks = {}
for var_id in var_ids:
- callbacks[var_id] = [callback for callback in callbacks_all if uses_var_id(callback)]
+ callbacks[var_id] = [
+ callback for callback in callbacks_all if uses_var_id(callback)]
return callbacks
@@ -253,14 +265,17 @@ class TopBlockGenerator(object):
# Get the virtual blocks and resolve their connections
connection_factory = fg.parent_platform.Connection
- virtual_source_connections = [c for c in connections if isinstance(c.source_block, blocks.VirtualSource)]
+ virtual_source_connections = [c for c in connections if isinstance(
+ c.source_block, blocks.VirtualSource)]
for connection in virtual_source_connections:
sink = connection.sink_port
for source in connection.source_port.resolve_virtual_source():
- resolved = connection_factory(fg.orignal_flowgraph, source, sink)
+ resolved = connection_factory(
+ fg.orignal_flowgraph, source, sink)
connections.append(resolved)
- virtual_connections = [c for c in connections if (isinstance(c.source_block, blocks.VirtualSource) or isinstance(c.sink_block, blocks.VirtualSink))]
+ virtual_connections = [c for c in connections if (isinstance(
+ c.source_block, blocks.VirtualSource) or isinstance(c.sink_block, blocks.VirtualSink))]
for connection in virtual_connections:
# Remove the virtual connection
connections.remove(connection)
@@ -274,7 +289,8 @@ class TopBlockGenerator(object):
for block in bypassed_blocks:
# Get the upstream connection (off of the sink ports)
# Use *connections* not get_connections()
- source_connection = [c for c in connections if c.sink_port == block.sinks[0]]
+ source_connection = [
+ c for c in connections if c.sink_port == block.sinks[0]]
# The source connection should never have more than one element.
assert (len(source_connection) == 1)
@@ -286,7 +302,8 @@ class TopBlockGenerator(object):
if not sink.enabled:
# Ignore disabled connections
continue
- connection = connection_factory(fg.orignal_flowgraph, source_port, sink.sink_port)
+ connection = connection_factory(
+ fg.orignal_flowgraph, source_port, sink.sink_port)
connections.append(connection)
# Remove this sink connection
connections.remove(sink)
@@ -301,7 +318,8 @@ class TopBlockGenerator(object):
for con in sorted(connections, key=by_domain_and_blocks):
template = templates[con.type]
if con.source_port.dtype != 'bus':
- code = template.render(make_port_sig=make_port_sig, source=con.source_port, sink=con.sink_port)
+ code = template.render(
+ make_port_sig=make_port_sig, source=con.source_port, sink=con.sink_port)
rendered.append(code)
else:
# Bus ports need to iterate over the underlying connections and then render
@@ -318,10 +336,8 @@ class TopBlockGenerator(object):
hidden_portb = portb.parent.sinks[port_num_b]
connection = fg.parent_platform.Connection(
parent=self, source=hidden_porta, sink=hidden_portb)
- code = template.render(make_port_sig=make_port_sig, source=hidden_porta, sink=hidden_portb)
+ code = template.render(
+ make_port_sig=make_port_sig, source=hidden_porta, sink=hidden_portb)
rendered.append(code)
-
-
-
return rendered
diff --git a/grc/core/io/yaml.py b/grc/core/io/yaml.py
index d653dc5f77..3e10af55d1 100644
--- a/grc/core/io/yaml.py
+++ b/grc/core/io/yaml.py
@@ -11,6 +11,7 @@ import yaml
from ..params.param import attributed_str
+
class GRCDumper(yaml.SafeDumper):
@classmethod
def add(cls, data_type):
@@ -21,7 +22,8 @@ class GRCDumper(yaml.SafeDumper):
def represent_ordered_mapping(self, data):
value = []
- node = yaml.MappingNode(u'tag:yaml.org,2002:map', value, flow_style=False)
+ node = yaml.MappingNode(u'tag:yaml.org,2002:map',
+ value, flow_style=False)
if self.alias_key is not None:
self.represented_objects[self.alias_key] = node
@@ -62,7 +64,8 @@ class MultiLineString(str):
GRCDumper.add_representer(OrderedDict, GRCDumper.represent_ordered_mapping)
-GRCDumper.add_representer(OrderedDictFlowing, GRCDumper.represent_ordered_mapping_flowing)
+GRCDumper.add_representer(
+ OrderedDictFlowing, GRCDumper.represent_ordered_mapping_flowing)
GRCDumper.add_representer(ListFlowing, GRCDumper.represent_list_flowing)
GRCDumper.add_representer(tuple, GRCDumper.represent_list)
GRCDumper.add_representer(MultiLineString, GRCDumper.represent_ml_string)
@@ -71,7 +74,8 @@ GRCDumper.add_representer(attributed_str, GRCDumper.represent_str)
def dump(data, stream=None, **kwargs):
- config = dict(stream=stream, default_flow_style=False, indent=4, Dumper=GRCDumper)
+ config = dict(stream=stream, default_flow_style=False,
+ indent=4, Dumper=GRCDumper)
config.update(kwargs)
return yaml.dump_all([data], **config)
diff --git a/grc/core/params/dtypes.py b/grc/core/params/dtypes.py
index 1c851c4d2c..a582bcae85 100644
--- a/grc/core/params/dtypes.py
+++ b/grc/core/params/dtypes.py
@@ -16,7 +16,8 @@ from .. import Constants
ID_BLACKLIST = ['self', 'default'] + dir(builtins)
try:
from gnuradio import gr
- ID_BLACKLIST.extend(attr for attr in dir(gr.top_block()) if not attr.startswith('_'))
+ ID_BLACKLIST.extend(attr for attr in dir(
+ gr.top_block()) if not attr.startswith('_'))
except (ImportError, AttributeError):
pass
@@ -32,12 +33,13 @@ def validates(*dtypes):
return func
return decorator
+
class ValidateError(Exception):
"""Raised by validate functions"""
@validates('id')
-def validate_block_id(param,black_listed_ids):
+def validate_block_id(param, black_listed_ids):
value = param.value
# Can python use this as a variable?
@@ -45,10 +47,11 @@ def validate_block_id(param,black_listed_ids):
raise ValidateError('ID "{}" must begin with a letter and may contain letters, numbers, '
'and underscores.'.format(value))
if value in (black_listed_ids + ID_BLACKLIST) and \
- not getattr(param.parent_block, 'exempt_from_id_validation', False):
+ not getattr(param.parent_block, 'exempt_from_id_validation', False):
# Grant blacklist exemption to epy blocks and modules
raise ValidateError('ID "{}" is blacklisted.'.format(value))
- block_names = [block.name for block in param.parent_flowgraph.iter_enabled_blocks()]
+ block_names = [
+ block.name for block in param.parent_flowgraph.iter_enabled_blocks()]
# Id should only appear once, or zero times if block is disabled
if param.key == 'id' and block_names.count(value) > 1:
raise ValidateError('ID "{}" is not unique.'.format(value))
@@ -58,7 +61,7 @@ def validate_block_id(param,black_listed_ids):
@validates('name')
-def validate_name(param,black_listed_ids):
+def validate_name(param, black_listed_ids):
# Name of a function or other block that will be generated literally not as a string
value = param.value
@@ -71,7 +74,7 @@ def validate_name(param,black_listed_ids):
@validates('stream_id')
-def validate_stream_id(param,black_listed_ids):
+def validate_stream_id(param, black_listed_ids):
value = param.value
stream_ids = [
block.params['stream_id'].value
@@ -88,7 +91,7 @@ def validate_stream_id(param,black_listed_ids):
@validates('complex', 'real', 'float', 'int')
-def validate_scalar(param,black_listed_ids):
+def validate_scalar(param, black_listed_ids):
valid_types = Constants.PARAM_TYPE_MAP[param.dtype]
if not isinstance(param.get_evaluated(), valid_types):
raise ValidateError('Expression {!r} is invalid for type {!r}.'.format(
@@ -96,19 +99,21 @@ def validate_scalar(param,black_listed_ids):
@validates('complex_vector', 'real_vector', 'float_vector', 'int_vector')
-def validate_vector(param,black_listed_ids):
+def validate_vector(param, black_listed_ids):
# todo: check vector types
if param.get_evaluated() is None:
- raise ValidateError('Expression {!r} is invalid for type{!r}.'.format(param.get_evaluated(), param.dtype))
+ raise ValidateError('Expression {!r} is invalid for type{!r}.'.format(
+ param.get_evaluated(), param.dtype))
valid_types = Constants.PARAM_TYPE_MAP[param.dtype.split('_', 1)[0]]
if not all(isinstance(item, valid_types) for item in param.get_evaluated()):
raise ValidateError('Expression {!r} is invalid for type {!r}.'.format(
param.get_evaluated(), param.dtype))
+
@validates('gui_hint')
-def validate_gui_hint(param,black_listed_ids):
+def validate_gui_hint(param, black_listed_ids):
try:
param.parse_gui_hint(param.value)
except Exception as e:
diff --git a/grc/core/params/param.py b/grc/core/params/param.py
index 122480dfa2..2cde1facdb 100644
--- a/grc/core/params/param.py
+++ b/grc/core/params/param.py
@@ -18,6 +18,7 @@ from .template_arg import TemplateArg
attributed_str = type('attributed_str', (str,), {})
+
@setup_names
class Param(Element):
@@ -73,12 +74,14 @@ class Param(Element):
options.attributes = collections.defaultdict(dict)
padding = [''] * max(len(values), len(labels))
- attributes = {key: value + padding for key, value in attributes.items()}
+ attributes = {key: value + padding for key,
+ value in attributes.items()}
for i, option in enumerate(values):
# Test against repeated keys
if option in options:
- raise KeyError('Value "{}" already exists in options'.format(option))
+ raise KeyError(
+ 'Value "{}" already exists in options'.format(option))
# get label
try:
label = str(labels[i])
@@ -86,7 +89,8 @@ class Param(Element):
label = str(option)
# Store the option
options[option] = label
- options.attributes[option] = {attrib: values[i] for attrib, values in attributes.items()}
+ options.attributes[option] = {attrib: values[i]
+ for attrib, values in attributes.items()}
default = next(iter(options)) if options else ''
if not self.value:
@@ -151,12 +155,13 @@ class Param(Element):
"""
Element.validate(self)
if self.dtype not in Constants.PARAM_TYPE_NAMES:
- self.add_error_message('Type "{}" is not a possible type.'.format(self.dtype))
+ self.add_error_message(
+ 'Type "{}" is not a possible type.'.format(self.dtype))
validator = dtypes.validators.get(self.dtype, None)
if self._init and validator:
try:
- validator(self,self.parent_flowgraph.get_imported_names())
+ validator(self, self.parent_flowgraph.get_imported_names())
except dtypes.ValidateError as e:
self.add_error_message(str(e))
@@ -207,12 +212,14 @@ class Param(Element):
if expr:
try:
if isinstance(expr, str) and self.is_float(expr[:-1]):
- scale_factor = expr[-1:]
- if scale_factor in self.scale:
- expr = str(float(expr[:-1])*self.scale[scale_factor])
+ scale_factor = expr[-1:]
+ if scale_factor in self.scale:
+ expr = str(float(expr[:-1]) *
+ self.scale[scale_factor])
value = self.parent_flowgraph.evaluate(expr)
except Exception as e:
- raise Exception('Value "{}" cannot be evaluated:\n{}'.format(expr, e))
+ raise Exception(
+ 'Value "{}" cannot be evaluated:\n{}'.format(expr, e))
else:
value = None # No parameter value provided
if dtype == 'hex':
@@ -230,7 +237,8 @@ class Param(Element):
try:
value = self.parent.parent.evaluate(expr)
except Exception as value:
- raise Exception('Value "{}" cannot be evaluated:\n{}'.format(expr, value))
+ raise Exception(
+ 'Value "{}" cannot be evaluated:\n{}'.format(expr, value))
if not isinstance(value, Constants.VECTOR_TYPES):
self._lisitify_flag = True
value = [value]
@@ -339,7 +347,8 @@ class Param(Element):
e = self.parent_flowgraph.evaluate(pos)
if not isinstance(e, (list, tuple)) or len(e) not in (2, 4) or not all(isinstance(ei, int) for ei in e):
- raise Exception('Invalid GUI Hint entered: {e!r} (Must be a list of {{2,4}} non-negative integers).'.format(e=e))
+ raise Exception(
+ 'Invalid GUI Hint entered: {e!r} (Must be a list of {{2,4}} non-negative integers).'.format(e=e))
if len(e) == 2:
row, col = e
@@ -348,10 +357,12 @@ class Param(Element):
row, col, row_span, col_span = e
if (row < 0) or (col < 0):
- raise Exception('Invalid GUI Hint entered: {e!r} (non-negative integers only).'.format(e=e))
+ raise Exception(
+ 'Invalid GUI Hint entered: {e!r} (non-negative integers only).'.format(e=e))
if (row_span < 1) or (col_span < 1):
- raise Exception('Invalid GUI Hint entered: {e!r} (positive row/column span required).'.format(e=e))
+ raise Exception(
+ 'Invalid GUI Hint entered: {e!r} (positive row/column span required).'.format(e=e))
return row, col, row_span, col_span
@@ -360,7 +371,8 @@ class Param(Element):
if block.key == 'qtgui_tab_widget' and block.name == tab)
tab_block = next(iter(tabs), None)
if not tab_block:
- raise Exception('Invalid tab name entered: {tab} (Tab name not found).'.format(tab=tab))
+ raise Exception(
+ 'Invalid tab name entered: {tab} (Tab name not found).'.format(tab=tab))
tab_index_size = int(tab_block.params['num_tabs'].value)
if index >= tab_index_size:
@@ -369,7 +381,8 @@ class Param(Element):
# Collision Detection
def collision_detection(row, col, row_span, col_span):
- my_parent = '{tab}@{index}'.format(tab=tab, index=index) if tab else 'main'
+ my_parent = '{tab}@{index}'.format(tab=tab,
+ index=index) if tab else 'main'
# Calculate hostage cells
for r in range(row, row + row_span):
for c in range(col, col + col_span):
@@ -378,7 +391,8 @@ class Param(Element):
for other in self.get_all_params('gui_hint'):
if other is self:
continue
- collision = next(iter(self.hostage_cells & other.hostage_cells), None)
+ collision = next(
+ iter(self.hostage_cells & other.hostage_cells), None)
if collision:
raise Exception('Block {block!r} is also using parent {parent!r}, cell {cell!r}.'.format(
block=other.parent_block.name, parent=collision[0], cell=collision[1]
@@ -390,7 +404,8 @@ class Param(Element):
if not pos:
layout = '{tab}_layout_{index}'.format(tab=tab, index=index)
else:
- layout = '{tab}_grid_layout_{index}'.format(tab=tab, index=index)
+ layout = '{tab}_grid_layout_{index}'.format(
+ tab=tab, index=index)
else:
if not pos:
layout = 'top_layout'
@@ -412,8 +427,8 @@ class Param(Element):
self.{layout}.setColumnStretch(c, 1)
""".strip('\n')).format(
layout=layout, widget=widget,
- row=row, row_span=row_span, row_end=row+row_span,
- col=col, col_span=col_span, col_end=col+col_span,
+ row=row, row_span=row_span, row_end=row + row_span,
+ col=col, col_span=col_span, col_end=col + col_span,
)
elif self.parent_flowgraph.get_option('output_language') == 'cpp':
widget_str = textwrap.dedent("""
@@ -424,17 +439,19 @@ class Param(Element):
{layout}->setColumnStretch(c, 1);
""".strip('\n')).format(
layout=layout, widget=widget,
- row=row, row_span=row_span, row_end=row+row_span,
- col=col, col_span=col_span, col_end=col+col_span,
+ row=row, row_span=row_span, row_end=row + row_span,
+ col=col, col_span=col_span, col_end=col + col_span,
)
else:
widget_str = ''
else:
if self.parent_flowgraph.get_option('output_language') == 'python':
- widget_str = 'self.{layout}.addWidget({widget})'.format(layout=layout, widget=widget)
+ widget_str = 'self.{layout}.addWidget({widget})'.format(
+ layout=layout, widget=widget)
elif self.parent_flowgraph.get_option('output_language') == 'cpp':
- widget_str = '{layout}->addWidget({widget});'.format(layout=layout, widget=widget)
+ widget_str = '{layout}->addWidget({widget});'.format(
+ layout=layout, widget=widget)
else:
widget_str = ''
diff --git a/grc/core/params/template_arg.py b/grc/core/params/template_arg.py
index 7250a71827..53adb740d4 100644
--- a/grc/core/params/template_arg.py
+++ b/grc/core/params/template_arg.py
@@ -5,7 +5,6 @@
#
-
class TemplateArg(str):
"""
A cheetah template argument created from a param.
diff --git a/grc/core/platform.py b/grc/core/platform.py
index cc825ec953..7eeb192ece 100644
--- a/grc/core/platform.py
+++ b/grc/core/platform.py
@@ -36,7 +36,8 @@ class Platform(Element):
self.config = self.Config(*args, **kwargs)
self.block_docstrings = {}
- self.block_docstrings_loaded_callback = lambda: None # dummy to be replaced by BlockTreeWindow
+ # dummy to be replaced by BlockTreeWindow
+ self.block_docstrings_loaded_callback = lambda: None
self._docstring_extractor = utils.extract_docs.SubprocessLoader(
callback_query_result=self._save_docstring_extraction_result,
@@ -108,7 +109,8 @@ class Platform(Element):
Messages.send('>>> Generating: {}\n'.format(generator.file_path))
generator.write()
except Exception as e:
- Messages.send('>>> Generate Error: {}: {}\n'.format(file_path, str(e)))
+ Messages.send(
+ '>>> Generate Error: {}: {}\n'.format(file_path, str(e)))
return None, None
return flow_graph, generator.file_path
@@ -126,8 +128,8 @@ class Platform(Element):
self.connection_templates.clear()
self.cpp_connection_templates.clear()
self._block_categories.clear()
-
- with Cache(Constants.CACHE_FILE, version = self.config.version) as cache:
+
+ with Cache(Constants.CACHE_FILE, version=self.config.version) as cache:
for file_path in self._iter_files_in_block_path(path):
if file_path.endswith('.block.yml'):
@@ -147,9 +149,11 @@ class Platform(Element):
data = cache.get_or_load(file_path)
passed = checker.run(data)
for msg in checker.messages:
- logger.warning('{:<40s} {}'.format(os.path.basename(file_path), msg))
+ logger.warning('{:<40s} {}'.format(
+ os.path.basename(file_path), msg))
if not passed:
- logger.info('YAML schema check failed for: ' + file_path)
+ logger.info(
+ 'YAML schema check failed for: ' + file_path)
loader(data, file_path)
except Exception as error:
@@ -184,8 +188,8 @@ class Platform(Element):
raise RuntimeError(errstr)
else:
# might have some cleanup to do on the options block in particular
- utils.hide_bokeh_gui_options_if_not_installed(self.blocks['options'])
-
+ utils.hide_bokeh_gui_options_if_not_installed(
+ self.blocks['options'])
def _iter_files_in_block_path(self, path=None, ext='yml'):
"""Iterator for block descriptions and category trees"""
@@ -220,13 +224,15 @@ class Platform(Element):
# don't load future block format versions
file_format = data['file_format']
if file_format < 1 or file_format > Constants.BLOCK_DESCRIPTION_FILE_FORMAT_VERSION:
- log.error('Unknown format version %d in %s', file_format, file_path)
+ log.error('Unknown format version %d in %s',
+ file_format, file_path)
return
block_id = data['id'] = data['id'].rstrip('_')
if block_id in self.block_classes_build_in:
- log.warning('Not overwriting build-in block %s with %s', block_id, file_path)
+ log.warning('Not overwriting build-in block %s with %s',
+ block_id, file_path)
return
if block_id in self.blocks:
log.warning('Block with id "%s" loaded from\n %s\noverwritten by\n %s',
@@ -256,7 +262,8 @@ class Platform(Element):
try:
tuple(int(color[o:o + 2], 16) / 255.0 for o in range(1, 6, 2))
except ValueError:
- log.warning('Cannot parse color code "%s" in %s', color, file_path)
+ log.warning('Cannot parse color code "%s" in %s',
+ color, file_path)
return
self.domains[domain_id] = self.Domain(
@@ -272,8 +279,10 @@ class Platform(Element):
log.warn('Invalid connection template.')
continue
connection_id = str(source_id), str(sink_id)
- self.connection_templates[connection_id] = connection.get('connect', '')
- self.cpp_connection_templates[connection_id] = connection.get('cpp_connect', '')
+ self.connection_templates[connection_id] = connection.get(
+ 'connect', '')
+ self.cpp_connection_templates[connection_id] = connection.get(
+ 'cpp_connect', '')
def load_category_tree_description(self, data, file_path):
"""Parse category tree file and add it to list"""
@@ -326,7 +335,8 @@ class Platform(Element):
# todo: try
if not is_xml:
data = yaml.safe_load(fp)
- validator = schema_checker.Validator(schema_checker.FLOW_GRAPH_SCHEME)
+ validator = schema_checker.Validator(
+ schema_checker.FLOW_GRAPH_SCHEME)
validator.run(data)
if is_xml:
@@ -340,13 +350,15 @@ class Platform(Element):
data = flow_graph.export_data()
try:
- data['connections'] = [yaml.ListFlowing(i) for i in data['connections']]
+ data['connections'] = [yaml.ListFlowing(
+ i) for i in data['connections']]
except KeyError:
pass
try:
for d in chain([data['options']], data['blocks']):
- d['states']['coordinate'] = yaml.ListFlowing(d['states']['coordinate'])
+ d['states']['coordinate'] = yaml.ListFlowing(
+ d['states']['coordinate'])
except KeyError:
pass
@@ -393,7 +405,8 @@ class Platform(Element):
Connection = Connection
block_classes_build_in = blocks.build_ins
- block_classes = utils.backports.ChainMap({}, block_classes_build_in) # separates build-in from loaded blocks)
+ # separates build-in from loaded blocks)
+ block_classes = utils.backports.ChainMap({}, block_classes_build_in)
port_classes = {
None: ports.Port, # default
diff --git a/grc/core/ports/_virtual_connections.py b/grc/core/ports/_virtual_connections.py
index a0e7b05a81..a328531b1a 100644
--- a/grc/core/ports/_virtual_connections.py
+++ b/grc/core/ports/_virtual_connections.py
@@ -2,7 +2,7 @@
# This file is part of GNU Radio
#
# SPDX-License-Identifier: GPL-2.0-or-later
-#
+#
from itertools import chain
@@ -28,10 +28,12 @@ def _sources_from_virtual_sink_port(sink_port, _traversed=None):
"""
source_ports_per_virtual_connection = (
# there can be multiple ports per virtual connection
- _sources_from_virtual_source_port(c.source_port, _traversed) # type: list
+ _sources_from_virtual_source_port(
+ c.source_port, _traversed) # type: list
for c in sink_port.connections(enabled=True)
)
- return list(chain(*source_ports_per_virtual_connection)) # concatenate generated lists of ports
+ # concatenate generated lists of ports
+ return list(chain(*source_ports_per_virtual_connection))
def _sources_from_virtual_source_port(source_port, _traversed=None):
@@ -62,7 +64,8 @@ def _sources_from_virtual_source_port(source_port, _traversed=None):
_sources_from_virtual_sink_port(b.sinks[0], _traversed) # type: list
for b in connected_virtual_sink_blocks
)
- return list(chain(*source_ports_per_virtual_connection)) # concatenate generated lists of ports
+ # concatenate generated lists of ports
+ return list(chain(*source_ports_per_virtual_connection))
def downstream_ports(port):
@@ -82,7 +85,8 @@ def _sinks_from_virtual_source_port(source_port, _traversed=None):
_sinks_from_virtual_sink_port(c.sink_port, _traversed) # type: list
for c in source_port.connections(enabled=True)
)
- return list(chain(*sink_ports_per_virtual_connection)) # concatenate generated lists of ports
+ # concatenate generated lists of ports
+ return list(chain(*sink_ports_per_virtual_connection))
def _sinks_from_virtual_sink_port(sink_port, _traversed=None):
@@ -111,4 +115,5 @@ def _sinks_from_virtual_sink_port(sink_port, _traversed=None):
_sinks_from_virtual_source_port(b.sources[0], _traversed) # type: list
for b in connected_virtual_source_blocks
)
- return list(chain(*sink_ports_per_virtual_connection)) # concatenate generated lists of ports
+ # concatenate generated lists of ports
+ return list(chain(*sink_ports_per_virtual_connection))
diff --git a/grc/core/ports/port.py b/grc/core/ports/port.py
index ade961e296..534f2138e6 100644
--- a/grc/core/ports/port.py
+++ b/grc/core/ports/port.py
@@ -34,17 +34,21 @@ class Port(Element):
self._dir = direction
self.key = id
if not label:
- label = id if not id.isdigit() else {'sink': 'in', 'source': 'out'}[direction]
+ label = id if not id.isdigit() else {'sink': 'in', 'source': 'out'}[
+ direction]
if dtype == 'bus':
# Look for existing busses to give proper index
- busses = [p for p in self.parent.ports() if p._dir == self._dir and p.dtype == 'bus']
+ busses = [p for p in self.parent.ports() if p._dir ==
+ self._dir and p.dtype == 'bus']
bus_structure = self.parent.current_bus_structure[self._dir]
bus_index = len(busses)
if len(bus_structure) > bus_index:
- number = str(len(busses)) + '#' + str(len(bus_structure[bus_index]))
+ number = str(len(busses)) + '#' + \
+ str(len(bus_structure[bus_index]))
label = dtype + number
else:
- raise ValueError('Could not initialize bus port due to incompatible bus structure')
+ raise ValueError(
+ 'Could not initialize bus port due to incompatible bus structure')
self.name = self._base_name = label
@@ -102,7 +106,8 @@ class Port(Element):
self.add_error_message('Port is not connected.')
if self.dtype not in Constants.TYPE_TO_SIZEOF.keys():
- self.add_error_message('Type "{}" is not a possible type.'.format(self.dtype))
+ self.add_error_message(
+ 'Type "{}" is not a possible type.'.format(self.dtype))
try:
domain = platform.domains[self.domain]
@@ -113,7 +118,8 @@ class Port(Element):
self.add_error_message('Domain "{}" can have only one downstream block'
''.format(self.domain))
except KeyError:
- self.add_error_message('Domain key "{}" is not registered.'.format(self.domain))
+ self.add_error_message(
+ 'Domain key "{}" is not registered.'.format(self.domain))
def rewrite(self):
del self.vlen
@@ -150,9 +156,11 @@ class Port(Element):
try:
port = find_port(_virtual_connections.upstream_ports) or \
- find_port(_virtual_connections.downstream_ports)
- self.set_evaluated('dtype', port.dtype) # we don't want to override the template
- self.set_evaluated('vlen', port.vlen) # we don't want to override the template
+ find_port(_virtual_connections.downstream_ports)
+ # we don't want to override the template
+ self.set_evaluated('dtype', port.dtype)
+ # we don't want to override the template
+ self.set_evaluated('vlen', port.vlen)
self.domain = port.domain
except AttributeError:
self.domain = Constants.DEFAULT_DOMAIN
@@ -206,7 +214,7 @@ class Port(Element):
enabled: None for all, True for enabled only, False for disabled only
"""
for con in self.parent_flowgraph.connections:
- #TODO clean this up - but how to get past this validation
+ # TODO clean this up - but how to get past this validation
# things don't compare simply with an x in y because
# bus ports are created differently.
port_in_con = False
@@ -242,5 +250,6 @@ class Port(Element):
if bus_structure:
busses = [i for i in get_ports if i.dtype == 'bus']
bus_index = busses.index(self)
- ports = filter(lambda a: ports.index(a) in bus_structure[bus_index], ports)
+ ports = filter(lambda a: ports.index(
+ a) in bus_structure[bus_index], ports)
return ports
diff --git a/grc/core/schema_checker/block.py b/grc/core/schema_checker/block.py
index f336fc4fdb..801c68b906 100644
--- a/grc/core/schema_checker/block.py
+++ b/grc/core/schema_checker/block.py
@@ -12,7 +12,8 @@ PARAM_SCHEME = expand(
options=list,
option_labels=list,
- option_attributes=Spec(types=dict, required=False, item_scheme=(str, list)),
+ option_attributes=Spec(types=dict, required=False,
+ item_scheme=(str, list)),
hide=str,
)
@@ -59,7 +60,8 @@ BLOCK_SCHEME = expand(
value=str,
templates=Spec(types=dict, required=False, item_scheme=TEMPLATES_SCHEME),
- cpp_templates=Spec(types=dict, required=False, item_scheme=CPP_TEMPLATES_SCHEME),
+ cpp_templates=Spec(types=dict, required=False,
+ item_scheme=CPP_TEMPLATES_SCHEME),
documentation=str,
grc_source=str,
diff --git a/grc/core/utils/backports/chainmap.py b/grc/core/utils/backports/chainmap.py
index 1f4f4a96fb..a89c42cddd 100644
--- a/grc/core/utils/backports/chainmap.py
+++ b/grc/core/utils/backports/chainmap.py
@@ -30,16 +30,19 @@ class ChainMap(MutableMapping):
def __getitem__(self, key):
for mapping in self.maps:
try:
- return mapping[key] # can't use 'key in mapping' with defaultdict
+ # can't use 'key in mapping' with defaultdict
+ return mapping[key]
except KeyError:
pass
- return self.__missing__(key) # support subclasses that define __missing__
+ # support subclasses that define __missing__
+ return self.__missing__(key)
def get(self, key, default=None):
return self[key] if key in self else default
def __len__(self):
- return len(set().union(*self.maps)) # reuses stored hash values if possible
+ # reuses stored hash values if possible
+ return len(set().union(*self.maps))
def __iter__(self):
return iter(set().union(*self.maps))
@@ -85,7 +88,8 @@ class ChainMap(MutableMapping):
try:
del self.maps[0][key]
except KeyError:
- raise KeyError('Key not found in the first mapping: {!r}'.format(key))
+ raise KeyError(
+ 'Key not found in the first mapping: {!r}'.format(key))
def popitem(self):
"""Remove and return an item pair from maps[0]. Raise KeyError is maps[0] is empty."""
@@ -99,7 +103,8 @@ class ChainMap(MutableMapping):
try:
return self.maps[0].pop(key, *args)
except KeyError:
- raise KeyError('Key not found in the first mapping: {!r}'.format(key))
+ raise KeyError(
+ 'Key not found in the first mapping: {!r}'.format(key))
def clear(self):
"""Clear maps[0], leaving maps[1:] intact."""
diff --git a/grc/core/utils/descriptors/_lazy.py b/grc/core/utils/descriptors/_lazy.py
index 280b128365..7d5c2c49c0 100644
--- a/grc/core/utils/descriptors/_lazy.py
+++ b/grc/core/utils/descriptors/_lazy.py
@@ -23,6 +23,7 @@ class lazy_property(object):
def nop_write(prop):
"""Make this a property with a nop setter"""
+
def nop(self, value):
pass
return prop.setter(nop)
diff --git a/grc/core/utils/descriptors/evaluated.py b/grc/core/utils/descriptors/evaluated.py
index a9735fb861..e22ff5fc5b 100644
--- a/grc/core/utils/descriptors/evaluated.py
+++ b/grc/core/utils/descriptors/evaluated.py
@@ -23,7 +23,8 @@ class Evaluated(object):
value = instance.parent_block.evaluate(raw)
except Exception as error:
if raw:
- instance.add_error_message("Failed to eval '{}': {}".format(raw, error))
+ instance.add_error_message(
+ "Failed to eval '{}': {}".format(raw, error))
return self.default
if not isinstance(value, self.expected_type):
@@ -68,13 +69,15 @@ class EvaluatedEnum(Evaluated):
if isinstance(allowed_values, str):
allowed_values = set(allowed_values.split())
self.allowed_values = allowed_values
- default = default if default is not None else next(iter(self.allowed_values))
+ default = default if default is not None else next(
+ iter(self.allowed_values))
super(EvaluatedEnum, self).__init__(str, default, name)
def default_eval_func(self, instance):
value = super(EvaluatedEnum, self).default_eval_func(instance)
if value not in self.allowed_values:
- instance.add_error_message("Value '{}' not in allowed values".format(value))
+ instance.add_error_message(
+ "Value '{}' not in allowed values".format(value))
return self.default
return value
diff --git a/grc/core/utils/epy_block_io.py b/grc/core/utils/epy_block_io.py
index 58becc4f2b..9947fa4831 100644
--- a/grc/core/utils/epy_block_io.py
+++ b/grc/core/utils/epy_block_io.py
@@ -12,7 +12,8 @@ TYPE_MAP = {
'int8': 'byte', 'uint8': 'byte',
}
-BlockIO = collections.namedtuple('BlockIO', 'name cls params sinks sources doc callbacks')
+BlockIO = collections.namedtuple(
+ 'BlockIO', 'name cls params sinks sources doc callbacks')
def _ports(sigs, msgs):
@@ -72,11 +73,13 @@ def extract(cls):
def settable(attr):
try:
- return callable(getattr(cls, attr).fset) # check for a property with setter
+ # check for a property with setter
+ return callable(getattr(cls, attr).fset)
except AttributeError:
return attr in instance.__dict__ # not dir() - only the instance attribs
- callbacks = [attr for attr in dir(instance) if attr in init_args and settable(attr)]
+ callbacks = [attr for attr in dir(
+ instance) if attr in init_args and settable(attr)]
sinks = _ports(instance.in_sig(),
pmt.to_python(instance.message_ports_in()))
diff --git a/grc/core/utils/expr_utils.py b/grc/core/utils/expr_utils.py
index bc669cc7c8..cfb1274049 100644
--- a/grc/core/utils/expr_utils.py
+++ b/grc/core/utils/expr_utils.py
@@ -7,6 +7,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
"""
+import ast
import string
@@ -64,12 +65,10 @@ def sort_objects(objects, get_id, get_expr):
return [id2obj[id] for id in sorted_ids]
-import ast
-
-
def dependencies(expr, names=None):
node = ast.parse(expr, mode='eval')
- used_ids = frozenset([n.id for n in ast.walk(node) if isinstance(n, ast.Name)])
+ used_ids = frozenset(
+ [n.id for n in ast.walk(node) if isinstance(n, ast.Name)])
return used_ids & names if names else used_ids
@@ -93,8 +92,6 @@ def sort_objects2(objects, id_getter, expr_getter, check_circular=True):
return objects
-
-
VAR_CHARS = string.ascii_letters + string.digits + '_'
@@ -205,7 +202,8 @@ def _sort_variables(exprs):
# Determine dependency order
while var_graph.get_nodes():
# Get a list of nodes with no edges
- indep_vars = [var for var in var_graph.get_nodes() if not var_graph.get_edges(var)]
+ indep_vars = [var for var in var_graph.get_nodes()
+ if not var_graph.get_edges(var)]
if not indep_vars:
raise Exception('circular dependency caught in sort_variables')
# Add the indep vars to the end of the list
diff --git a/grc/core/utils/extract_docs.py b/grc/core/utils/extract_docs.py
index 09bcaeb7c7..a92ce1777e 100644
--- a/grc/core/utils/extract_docs.py
+++ b/grc/core/utils/extract_docs.py
@@ -55,7 +55,8 @@ def docstring_guess_from_key(key):
else:
return doc_strings
- pattern = re.compile('^' + init_name.replace('_', '_*').replace('x', r'\w') + r'\w*$')
+ pattern = re.compile(
+ '^' + init_name.replace('_', '_*').replace('x', r'\w') + r'\w*$')
for match in filter(pattern.match, dir(module)):
try:
doc_strings[match] = getattr(module, match).__doc__
@@ -135,7 +136,8 @@ class SubprocessLoader(object):
break
try:
self._worker = subprocess.Popen(
- args=(sys.executable, '-uc', self.BOOTSTRAP.format(__file__)),
+ args=(sys.executable, '-uc',
+ self.BOOTSTRAP.format(__file__)),
stdin=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
@@ -286,7 +288,8 @@ elif __name__ == '__main__':
# r.query('uhd_source')
r.query('expr_utils_graph')
r.query('blocks_add_cc')
- r.query('blocks_add_cc', ['import gnuradio.blocks'], 'gnuradio.blocks.add_cc(')
+ r.query('blocks_add_cc', ['import gnuradio.blocks'],
+ 'gnuradio.blocks.add_cc(')
# r.query('analog_feedforward_agc_cc')
# r.query('uhd_source')
# r.query('uhd_source')
diff --git a/grc/core/utils/flow_graph_complexity.py b/grc/core/utils/flow_graph_complexity.py
index e8962b0ae3..5731769a19 100644
--- a/grc/core/utils/flow_graph_complexity.py
+++ b/grc/core/utils/flow_graph_complexity.py
@@ -37,17 +37,20 @@ def calculate(flowgraph):
# Disabled multiplier
if enabled > 0:
- disabled_multi = 1 / (max(1 - ((blocks - enabled) / max(blocks, 1)), 0.05))
+ 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))
+ 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)
+ final = round(max((dbal - 1) * disabled_multi *
+ conn_multi * connections, 0.0) / 1000000, 6)
return final
except Exception: