diff options
Diffstat (limited to 'grc')
77 files changed, 999 insertions, 608 deletions
diff --git a/grc/compiler.py b/grc/compiler.py index 2478055daf..e0f51e51d3 100755 --- a/grc/compiler.py +++ b/grc/compiler.py @@ -38,7 +38,8 @@ def main(args=None): name='GNU Radio Companion Compiler', prefs=gr.prefs(), version=gr.version(), - version_parts=(gr.major_version(), gr.api_version(), gr.minor_version()) + version_parts=(gr.major_version(), + gr.api_version(), gr.minor_version()) ) platform.build_library() diff --git a/grc/converter/block.py b/grc/converter/block.py index 369e709286..ceddfc7615 100644 --- a/grc/converter/block.py +++ b/grc/converter/block.py @@ -94,7 +94,8 @@ def convert_block_xml(node): data['asserts'] = [converter.to_python_dec(check_node.text) for check_node in node.iterfind('check')] or no_value - data['templates'] = convert_templates(node, converter.to_mako, block_id) or no_value + data['templates'] = convert_templates( + node, converter.to_mako, block_id) or no_value docs = node.findtext('doc') if docs: @@ -103,7 +104,8 @@ def convert_block_xml(node): data['file_format'] = current_file_format - data = OrderedDict((key, value) for key, value in data.items() if value is not no_value) + data = OrderedDict((key, value) + for key, value in data.items() if value is not no_value) auto_hide_params_for_item_sizes(data) return data @@ -116,8 +118,10 @@ def auto_hide_params_for_item_sizes(data): for key in ['dtype', 'multiplicity']: item_size_templates.append(str(port.get(key, ''))) vlen_templates.append(str(port.get('vlen', ''))) - item_size_templates = ' '.join(value for value in item_size_templates if '${' in value) - vlen_templates = ' '.join(value for value in vlen_templates if '${' in value) + item_size_templates = ' '.join( + value for value in item_size_templates if '${' in value) + vlen_templates = ' '.join( + value for value in vlen_templates if '${' in value) for param in data.get('parameters', []): if param['id'] in item_size_templates: @@ -135,7 +139,8 @@ def convert_templates(node, convert, block_id=''): imports = yaml.MultiLineString(imports) templates['imports'] = imports or no_value - templates['var_make'] = convert(node.findtext('var_make') or '') or no_value + templates['var_make'] = convert( + node.findtext('var_make') or '') or no_value make = convert(node.findtext('make') or '') if make: @@ -160,8 +165,10 @@ def convert_param_xml(node, convert): param['dtype'] = convert(node.findtext('type') or '') param['default'] = node.findtext('value') or no_value - options = yaml.ListFlowing(on.findtext('key') for on in node.iterfind('option')) - option_labels = yaml.ListFlowing(on.findtext('name') for on in node.iterfind('option')) + options = yaml.ListFlowing(on.findtext('key') + for on in node.iterfind('option')) + option_labels = yaml.ListFlowing(on.findtext( + 'name') for on in node.iterfind('option')) param['options'] = options or no_value if not all(str(o).title() == l for o, l in zip(options, option_labels)): param['option_labels'] = option_labels @@ -192,7 +199,8 @@ def convert_port_xml(node, convert): else: port['dtype'] = dtype vlen = node.findtext('vlen') - port['vlen'] = int(vlen) if vlen and vlen.isdigit() else convert(vlen) or no_value + port['vlen'] = int(vlen) if vlen and vlen.isdigit( + ) else convert(vlen) or no_value port['multiplicity'] = convert(node.findtext('nports')) or no_value port['optional'] = bool(node.findtext('optional')) or no_value @@ -207,4 +215,5 @@ def check_mako_template(block_id, expr): try: Template(expr) except Exception as error: - print(block_id, expr, type(error), error, '', sep='\n', file=sys.stderr) + print(block_id, expr, type(error), error, + '', sep='\n', file=sys.stderr) diff --git a/grc/converter/cheetah_converter.py b/grc/converter/cheetah_converter.py index 62220812c6..778b9c9ac1 100644 --- a/grc/converter/cheetah_converter.py +++ b/grc/converter/cheetah_converter.py @@ -18,7 +18,8 @@ cheetah_substitution = re.compile( r'(?P<arg>[_a-zA-Z][_a-zA-Z0-9]*(?:\.[_a-zA-Z][_a-zA-Z0-9]*)?)(?P<eval>\(\))?' r'(?(d1)\)|(?(d2)\}|(?(d3)\]|)))$' ) -cheetah_inline_if = re.compile(r'#if (?P<cond>.*) then (?P<then>.*?) ?else (?P<else>.*?) ?(#|$)') +cheetah_inline_if = re.compile( + r'#if (?P<cond>.*) then (?P<then>.*?) ?else (?P<else>.*?) ?(#|$)') class Python(object): @@ -116,7 +117,8 @@ class Converter(object): return spec.type(out) def convert_hard(self, expr, spec=Python): - lines = '\n'.join(self.convert_hard_line(line, spec) for line in expr.split('\n')) + lines = '\n'.join(self.convert_hard_line(line, spec) + for line in expr.split('\n')) if spec == Mako: # no line-continuation before a mako control structure lines = re.sub(r'\\\n(\s*%)', r'\n\1', lines) @@ -220,7 +222,8 @@ class Converter(object): out.append(char) delim_to_find = False - elif delim_to_find and char in ')]}' and extra_close(): # end of substitution + # end of substitution + elif delim_to_find and char in ')]}' and extra_close(): out.append(spec.end) out.append(char) delim_to_find = False @@ -235,7 +238,8 @@ class Converter(object): out = ''.join(out) # fix: eval stuff - out = re.sub(r'(?P<arg>' + r'|'.join(self.extended) + r')\(\)', r'\g<arg>', out) + out = re.sub(r'(?P<arg>' + r'|'.join(self.extended) + + r')\(\)', r'\g<arg>', out) self.stats['hard'] += 1 return spec.type(out) diff --git a/grc/converter/main.py b/grc/converter/main.py index c5da997407..5eb80a504f 100644 --- a/grc/converter/main.py +++ b/grc/converter/main.py @@ -50,7 +50,8 @@ class Converter(object): self._force = force try: - logger.debug("Loading block cache from: {}".format(self.cache_file)) + logger.debug( + "Loading block cache from: {}".format(self.cache_file)) with open(self.cache_file, encoding='utf-8') as cache_file: self.cache = byteify(json.load(cache_file)) except (IOError, ValueError): @@ -108,7 +109,8 @@ class Converter(object): def load_category_tree_xml(self, xml_file): """Validate and parse category tree file and add it to list""" - module_name = path.basename(xml_file)[:-len('block_tree.xml')].rstrip('._-') + module_name = path.basename( + xml_file)[:-len('block_tree.xml')].rstrip('._-') yml_file = path.join(self.output_dir, module_name + '.tree.yml') if not self.needs_conversion(xml_file, yml_file): @@ -142,7 +144,8 @@ class Converter(object): if name.endswith(suffix): yield path.join(root, name) else: - logger.warning('Invalid entry in search path: {}'.format(block_path)) + logger.warning( + 'Invalid entry in search path: {}'.format(block_path)) def byteify(data): diff --git a/grc/converter/xml.py b/grc/converter/xml.py index a3c4cb457a..fab97f93bc 100644 --- a/grc/converter/xml.py +++ b/grc/converter/xml.py @@ -53,7 +53,7 @@ def load_stdlib(filename, document_type_def=None): if isinstance(filename, str): with open(filename, 'rb') as xml_file: data = xml_file.read().decode('utf-8') - else: # Already opened + else: # Already opened data = filename.read().decode('utf-8') try: 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: diff --git a/grc/gui/Actions.py b/grc/gui/Actions.py index 1d815cc533..3c312f6505 100644 --- a/grc/gui/Actions.py +++ b/grc/gui/Actions.py @@ -85,10 +85,10 @@ class Namespace(object): key = "{}.{}".format(prefix, name) if prefix == "app": pass - #self.app.add_action(action) + # self.app.add_action(action) elif prefix == "win": pass - #self.win.add_action(action) + # self.win.add_action(action) #log.debug("Registering action as '{}'".format(key)) self._actions[key] = action @@ -132,7 +132,7 @@ class Namespace(object): class Action(Gio.SimpleAction): # Change these to normal python properties. - #prefs_name + # prefs_name def __init__(self, name, @@ -295,7 +295,7 @@ FLOW_GRAPH_DUPLICATE = actions.register( "app.flowgraph.duplicate", label='_Duplicate', tooltip='Create a duplicate of current flow graph', - #stock_id=Gtk.STOCK_COPY, + # stock_id=Gtk.STOCK_COPY, keypresses=["<Ctrl><Shift>d"], ) FLOW_GRAPH_CLOSE = actions.register( @@ -433,26 +433,27 @@ BLOCK_BYPASS = actions.register( keypresses=["b"], ) ZOOM_IN = actions.register("win.zoom_in", - label='Zoom In', - tooltip='Increase the canvas zoom level', - keypresses=["<Ctrl>plus","<Ctrl>equal","<Ctrl>KP_Add"], -) + label='Zoom In', + tooltip='Increase the canvas zoom level', + keypresses=["<Ctrl>plus", + "<Ctrl>equal", "<Ctrl>KP_Add"], + ) ZOOM_OUT = actions.register("win.zoom_out", - label='Zoom Out', - tooltip='Decrease the canvas zoom level', - keypresses=["<Ctrl>minus","<Ctrl>KP_Subtract"], -) + label='Zoom Out', + tooltip='Decrease the canvas zoom level', + keypresses=["<Ctrl>minus", "<Ctrl>KP_Subtract"], + ) ZOOM_RESET = actions.register("win.zoom_reset", - label='Reset Zoom', - tooltip='Reset the canvas zoom level', - keypresses=["<Ctrl>0","<Ctrl>KP_0"], -) + label='Reset Zoom', + tooltip='Reset the canvas zoom level', + keypresses=["<Ctrl>0", "<Ctrl>KP_0"], + ) TOGGLE_SNAP_TO_GRID = actions.register("win.snap_to_grid", - label='_Snap to grid', - tooltip='Snap blocks to a grid for an easier connection alignment', - preference_name='snap_to_grid', - default=True, -) + label='_Snap to grid', + tooltip='Snap blocks to a grid for an easier connection alignment', + preference_name='snap_to_grid', + default=True, + ) TOGGLE_HIDE_DISABLED_BLOCKS = actions.register( "win.hide_disabled", label='Hide _Disabled Blocks', @@ -493,8 +494,7 @@ TOGGLE_SHOW_BLOCK_IDS = actions.register( TOGGLE_FLOW_GRAPH_VAR_EDITOR = actions.register( "win.toggle_variable_editor", label='Show _Variable Editor', - tooltip= - 'Show the variable editor. Modify variables and imports in this flow graph', + tooltip='Show the variable editor. Modify variables and imports in this flow graph', icon_name='accessories-text-editor', default=True, keypresses=["<Ctrl>e"], diff --git a/grc/gui/Application.py b/grc/gui/Application.py index 1996d66c1e..87c5cf0ed8 100644 --- a/grc/gui/Application.py +++ b/grc/gui/Application.py @@ -7,7 +7,6 @@ SPDX-License-Identifier: GPL-2.0-or-later """ - import logging import os import subprocess @@ -65,7 +64,8 @@ class Application(Gtk.Application): self.set_accels_for_action(x, keypress) # Initialize - self.init_file_paths = [os.path.abspath(file_path) for file_path in file_paths] + self.init_file_paths = [os.path.abspath( + file_path) for file_path in file_paths] self.init = False def do_startup(self): @@ -80,7 +80,7 @@ class Application(Gtk.Application): self.main_window.connect('delete-event', self._quit) self.get_focus_flag = self.main_window.get_focus_flag - #setup the messages + # setup the messages Messages.register_messenger(self.main_window.add_console_line) Messages.send_init(self.platform) @@ -117,7 +117,8 @@ class Application(Gtk.Application): file_path_to_show = self.config.file_open() for file_path in (self.init_file_paths or self.config.get_open_files()): if os.path.exists(file_path): - main.new_page(file_path, show=file_path_to_show == file_path) + main.new_page( + file_path, show=file_path_to_show == file_path) if not main.current_page: main.new_page() # ensure that at least a blank page exists @@ -190,9 +191,12 @@ class Application(Gtk.Application): action.load_from_preferences() # Hide the panels *IF* it's saved in preferences - main.update_panel_visibility(main.BLOCKS, Actions.TOGGLE_BLOCKS_WINDOW.get_active()) - main.update_panel_visibility(main.CONSOLE, Actions.TOGGLE_CONSOLE_WINDOW.get_active()) - main.update_panel_visibility(main.VARIABLES, Actions.TOGGLE_FLOW_GRAPH_VAR_EDITOR.get_active()) + main.update_panel_visibility( + main.BLOCKS, Actions.TOGGLE_BLOCKS_WINDOW.get_active()) + main.update_panel_visibility( + main.CONSOLE, Actions.TOGGLE_CONSOLE_WINDOW.get_active()) + main.update_panel_visibility( + main.VARIABLES, Actions.TOGGLE_FLOW_GRAPH_VAR_EDITOR.get_active()) # Force an update on the current page to match loaded preferences. # In the future, change the __init__ order to load preferences first @@ -210,7 +214,7 @@ class Application(Gtk.Application): # Selections ################################################## elif action == Actions.ELEMENT_SELECT: - pass #do nothing, update routines below + pass # do nothing, update routines below elif action == Actions.NOTHING_SELECT: flow_graph.unselect() elif action == Actions.SELECT_ALL: @@ -271,7 +275,6 @@ class Application(Gtk.Application): x_min = min(block.coordinate[0] for block in selected_blocks) y_min = min(block.coordinate[1] for block in selected_blocks) - for connection in flow_graph.connections: # Get id of connected blocks @@ -283,7 +286,8 @@ class Application(Gtk.Application): pads.append({ 'key': connection.sink_port.key, 'coord': source.coordinate, - 'block_index': selected_blocks.index(sink) + 1, # Ignore the options block + # Ignore the options block + 'block_index': selected_blocks.index(sink) + 1, 'direction': 'source' }) @@ -292,7 +296,8 @@ class Application(Gtk.Application): pads.append({ 'key': connection.source_port.key, 'coord': sink.coordinate, - 'block_index': selected_blocks.index(source) + 1, # Ignore the options block + # Ignore the options block + 'block_index': selected_blocks.index(source) + 1, 'direction': 'sink' }) @@ -335,7 +340,8 @@ class Application(Gtk.Application): pad_block = flow_graph.get_block(pad_id) pad_sink = pad_block.sinks[0] - source_block = flow_graph.get_block(flow_graph.blocks[pad['block_index']].name) + source_block = flow_graph.get_block( + flow_graph.blocks[pad['block_index']].name) source = source_block.get_source(pad['key']) # ensure the port types match @@ -350,13 +356,15 @@ class Application(Gtk.Application): new_connection = flow_graph.connect(source, pad_sink) elif pad['direction'] == 'source': - pad_id = flow_graph.add_new_block('pad_source', pad['coord']) + pad_id = flow_graph.add_new_block( + 'pad_source', pad['coord']) # setup the references to the sink and source pad_block = flow_graph.get_block(pad_id) pad_source = pad_block.sources[0] - sink_block = flow_graph.get_block(flow_graph.blocks[pad['block_index']].name) + sink_block = flow_graph.get_block( + flow_graph.blocks[pad['block_index']].name) sink = sink_block.get_sink(pad['key']) # ensure the port types match @@ -496,7 +504,8 @@ class Application(Gtk.Application): # to be visible. varedit = Actions.TOGGLE_FLOW_GRAPH_VAR_EDITOR if active: - log.debug("Variables are hidden. Forcing the variable panel to be visible.") + log.debug( + "Variables are hidden. Forcing the variable panel to be visible.") varedit.disable() else: varedit.enable() @@ -548,8 +557,9 @@ class Application(Gtk.Application): while response == Gtk.ResponseType.APPLY: # rerun the dialog if Apply was hit response = self.dialog.run() if response in (Gtk.ResponseType.APPLY, Gtk.ResponseType.ACCEPT): - page.state_cache.save_new_state(flow_graph.export_data()) - ### Following line forces a complete update of io ports + page.state_cache.save_new_state( + flow_graph.export_data()) + # Following line forces a complete update of io ports flow_graph_update() page.saved = False if response in (Gtk.ResponseType.REJECT, Gtk.ResponseType.ACCEPT): @@ -600,18 +610,21 @@ class Application(Gtk.Application): main.new_page() args = (GLib.Variant('s', 'qt_gui'),) flow_graph = main.current_page.flow_graph - flow_graph.options_block.params['generate_options'].set_value(str(args[0])[1:-1]) + flow_graph.options_block.params['generate_options'].set_value(str(args[0])[ + 1:-1]) flow_graph.options_block.params['author'].set_value(getuser()) flow_graph_update(flow_graph) elif action == Actions.FLOW_GRAPH_NEW_TYPE: main.new_page() if args: flow_graph = main.current_page.flow_graph - flow_graph.options_block.params['generate_options'].set_value(str(args[0])[1:-1]) + flow_graph.options_block.params['generate_options'].set_value(str(args[0])[ + 1:-1]) flow_graph_update(flow_graph) elif action == Actions.FLOW_GRAPH_OPEN: - file_paths = args[0] if args[0] else FileDialogs.OpenFlowGraph(main, page.file_path).run() - if file_paths: # Open a new page for each file, show only the first + file_paths = args[0] if args[0] else FileDialogs.OpenFlowGraph( + main, page.file_path).run() + if file_paths: # Open a new page for each file, show only the first for i, file_path in enumerate(file_paths): main.new_page(file_path, show=(i == 0)) self.config.add_recent_file(file_path) @@ -631,10 +644,10 @@ class Application(Gtk.Application): main.tool_bar.refresh_submenus() main.menu.refresh_submenus() elif action == Actions.FLOW_GRAPH_SAVE: - #read-only or undefined file path, do save-as + # read-only or undefined file path, do save-as if page.get_read_only() or not page.file_path: Actions.FLOW_GRAPH_SAVE_AS() - #otherwise try to save + # otherwise try to save else: try: self.platform.save_flow_graph(page.file_path, flow_graph) @@ -670,18 +683,25 @@ class Application(Gtk.Application): Actions.FLOW_GRAPH_SAVE_AS() else: dup_file_path = page.file_path - dup_file_name = '.'.join(dup_file_path.split('.')[:-1]) + "_copy" # Assuming .grc extension at the end of file_path + # Assuming .grc extension at the end of file_path + dup_file_name = '.'.join( + dup_file_path.split('.')[:-1]) + "_copy" dup_file_path_temp = dup_file_name + Constants.FILE_EXTENSION count = 1 while os.path.exists(dup_file_path_temp): - dup_file_path_temp = '{}({}){}'.format(dup_file_name, count, Constants.FILE_EXTENSION) + dup_file_path_temp = '{}({}){}'.format( + dup_file_name, count, Constants.FILE_EXTENSION) count += 1 - dup_file_path_user = FileDialogs.SaveFlowGraph(main, dup_file_path_temp).run() + dup_file_path_user = FileDialogs.SaveFlowGraph( + main, dup_file_path_temp).run() if dup_file_path_user is not None: - self.platform.save_flow_graph(dup_file_path_user, flow_graph) - Messages.send('Saved Copy to: "' + dup_file_path_user + '"\n') + self.platform.save_flow_graph( + dup_file_path_user, flow_graph) + Messages.send('Saved Copy to: "' + + dup_file_path_user + '"\n') except IOError: - Messages.send_fail_save("Can not create a copy of the flowgraph\n") + Messages.send_fail_save( + "Can not create a copy of the flowgraph\n") elif action == Actions.FLOW_GRAPH_DUPLICATE: previous = flow_graph # Create a new page @@ -694,10 +714,12 @@ class Application(Gtk.Application): page.state_cache.save_new_state(new_flow_graph.export_data()) page.saved = False elif action == Actions.FLOW_GRAPH_SCREEN_CAPTURE: - file_path, background_transparent = FileDialogs.SaveScreenShot(main, page.file_path).run() + file_path, background_transparent = FileDialogs.SaveScreenShot( + main, page.file_path).run() if file_path is not None: try: - Utils.make_screenshot(flow_graph, file_path, background_transparent) + Utils.make_screenshot( + flow_graph, file_path, background_transparent) except ValueError: Messages.send('Failed to generate screen shot\n') ################################################## @@ -717,7 +739,6 @@ class Application(Gtk.Application): except Exception as e: Messages.send_fail_gen(e) - elif action == Actions.FLOW_GRAPH_EXEC: if not page.process: Actions.FLOW_GRAPH_GEN() @@ -734,7 +755,7 @@ class Application(Gtk.Application): flow_graph_page=page, xterm_executable=xterm, callback=self.update_exec_stop - ) + ) elif action == Actions.FLOW_GRAPH_KILL: if page.process: try: @@ -748,7 +769,7 @@ class Application(Gtk.Application): self.platform.build_library() main.btwin.repopulate() - #todo: implement parser error dialog for YAML + # todo: implement parser error dialog for YAML # Force a redraw of the graph, by getting the current state and re-importing it main.update_pages() @@ -791,21 +812,21 @@ class Application(Gtk.Application): selected_blocks = list(flow_graph.selected_blocks()) selected_block = selected_blocks[0] if selected_blocks else None - #update general buttons + # update general buttons Actions.ERRORS_WINDOW_DISPLAY.set_enabled(not flow_graph.is_valid()) Actions.ELEMENT_DELETE.set_enabled(bool(flow_graph.selected_elements)) Actions.BLOCK_PARAM_MODIFY.set_enabled(bool(selected_block)) Actions.BLOCK_ROTATE_CCW.set_enabled(bool(selected_blocks)) Actions.BLOCK_ROTATE_CW.set_enabled(bool(selected_blocks)) - #update alignment options + # update alignment options for act in Actions.BLOCK_ALIGNMENTS: if act: act.set_enabled(len(selected_blocks) > 1) - #update cut/copy/paste + # update cut/copy/paste Actions.BLOCK_CUT.set_enabled(bool(selected_blocks)) Actions.BLOCK_COPY.set_enabled(bool(selected_blocks)) Actions.BLOCK_PASTE.set_enabled(bool(self.clipboard)) - #update enable/disable/bypass + # update enable/disable/bypass can_enable = any(block.state != 'enabled' for block in selected_blocks) can_disable = any(block.state != 'disabled' diff --git a/grc/gui/Bars.py b/grc/gui/Bars.py index 86eb3a5716..84867a8b4c 100644 --- a/grc/gui/Bars.py +++ b/grc/gui/Bars.py @@ -42,11 +42,14 @@ TOOLBAR_LIST = [ (Actions.FLOW_GRAPH_OPEN, 'flow_graph_recent'), Actions.FLOW_GRAPH_SAVE, Actions.FLOW_GRAPH_CLOSE], [Actions.TOGGLE_FLOW_GRAPH_VAR_EDITOR, Actions.FLOW_GRAPH_SCREEN_CAPTURE], - [Actions.BLOCK_CUT, Actions.BLOCK_COPY, Actions.BLOCK_PASTE, Actions.ELEMENT_DELETE], + [Actions.BLOCK_CUT, Actions.BLOCK_COPY, + Actions.BLOCK_PASTE, Actions.ELEMENT_DELETE], [Actions.FLOW_GRAPH_UNDO, Actions.FLOW_GRAPH_REDO], - [Actions.ERRORS_WINDOW_DISPLAY, Actions.FLOW_GRAPH_GEN, Actions.FLOW_GRAPH_EXEC, Actions.FLOW_GRAPH_KILL], + [Actions.ERRORS_WINDOW_DISPLAY, Actions.FLOW_GRAPH_GEN, + Actions.FLOW_GRAPH_EXEC, Actions.FLOW_GRAPH_KILL], [Actions.BLOCK_ROTATE_CCW, Actions.BLOCK_ROTATE_CW], - [Actions.BLOCK_ENABLE, Actions.BLOCK_DISABLE, Actions.BLOCK_BYPASS, Actions.TOGGLE_HIDE_DISABLED_BLOCKS], + [Actions.BLOCK_ENABLE, Actions.BLOCK_DISABLE, + Actions.BLOCK_BYPASS, Actions.TOGGLE_HIDE_DISABLED_BLOCKS], [Actions.FIND_BLOCKS, Actions.RELOAD_BLOCKS, Actions.OPEN_HIER] ] @@ -56,23 +59,28 @@ MENU_BAR_LIST = [ ('_File', [ [(Actions.FLOW_GRAPH_NEW, 'flow_graph_new_type'), Actions.FLOW_GRAPH_DUPLICATE, Actions.FLOW_GRAPH_OPEN, (Actions.FLOW_GRAPH_OPEN_RECENT, 'flow_graph_recent')], - [Actions.FLOW_GRAPH_SAVE, Actions.FLOW_GRAPH_SAVE_AS, Actions.FLOW_GRAPH_SAVE_COPY], + [Actions.FLOW_GRAPH_SAVE, Actions.FLOW_GRAPH_SAVE_AS, + Actions.FLOW_GRAPH_SAVE_COPY], [Actions.FLOW_GRAPH_SCREEN_CAPTURE], [Actions.FLOW_GRAPH_CLOSE, Actions.APPLICATION_QUIT] ]), ('_Edit', [ [Actions.FLOW_GRAPH_UNDO, Actions.FLOW_GRAPH_REDO], - [Actions.BLOCK_CUT, Actions.BLOCK_COPY, Actions.BLOCK_PASTE, Actions.ELEMENT_DELETE, Actions.SELECT_ALL], - [Actions.BLOCK_ROTATE_CCW, Actions.BLOCK_ROTATE_CW, ('_Align', Actions.BLOCK_ALIGNMENTS)], + [Actions.BLOCK_CUT, Actions.BLOCK_COPY, Actions.BLOCK_PASTE, + Actions.ELEMENT_DELETE, Actions.SELECT_ALL], + [Actions.BLOCK_ROTATE_CCW, Actions.BLOCK_ROTATE_CW, + ('_Align', Actions.BLOCK_ALIGNMENTS)], [Actions.BLOCK_ENABLE, Actions.BLOCK_DISABLE, Actions.BLOCK_BYPASS], [Actions.BLOCK_PARAM_MODIFY] ]), ('_View', [ [Actions.TOGGLE_BLOCKS_WINDOW], - [Actions.TOGGLE_CONSOLE_WINDOW, Actions.TOGGLE_SCROLL_LOCK, Actions.SAVE_CONSOLE, Actions.CLEAR_CONSOLE], + [Actions.TOGGLE_CONSOLE_WINDOW, Actions.TOGGLE_SCROLL_LOCK, + Actions.SAVE_CONSOLE, Actions.CLEAR_CONSOLE], [Actions.TOGGLE_HIDE_VARIABLES, Actions.TOGGLE_FLOW_GRAPH_VAR_EDITOR, Actions.TOGGLE_FLOW_GRAPH_VAR_EDITOR_SIDEBAR, Actions.TOGGLE_SHOW_PARAMETER_EXPRESSION, Actions.TOGGLE_SHOW_PARAMETER_EVALUATION], - [Actions.TOGGLE_HIDE_DISABLED_BLOCKS, Actions.TOGGLE_AUTO_HIDE_PORT_LABELS, Actions.TOGGLE_SNAP_TO_GRID, Actions.TOGGLE_SHOW_BLOCK_COMMENTS, Actions.TOGGLE_SHOW_BLOCK_IDS,], + [Actions.TOGGLE_HIDE_DISABLED_BLOCKS, Actions.TOGGLE_AUTO_HIDE_PORT_LABELS, + Actions.TOGGLE_SNAP_TO_GRID, Actions.TOGGLE_SHOW_BLOCK_COMMENTS, Actions.TOGGLE_SHOW_BLOCK_IDS, ], [Actions.TOGGLE_SHOW_CODE_PREVIEW_TAB], [Actions.ZOOM_IN], [Actions.ZOOM_OUT], @@ -87,15 +95,18 @@ MENU_BAR_LIST = [ [Actions.TOGGLE_SHOW_FLOWGRAPH_COMPLEXITY] ]), ('_Help', [ - [Actions.HELP_WINDOW_DISPLAY, Actions.TYPES_WINDOW_DISPLAY, Actions.KEYBOARD_SHORTCUTS_WINDOW_DISPLAY, Actions.XML_PARSER_ERRORS_DISPLAY], + [Actions.HELP_WINDOW_DISPLAY, Actions.TYPES_WINDOW_DISPLAY, + Actions.KEYBOARD_SHORTCUTS_WINDOW_DISPLAY, Actions.XML_PARSER_ERRORS_DISPLAY], [Actions.GET_INVOLVED_WINDOW_DISPLAY, Actions.ABOUT_WINDOW_DISPLAY] ])] # The list of actions for the context menu. CONTEXT_MENU_LIST = [ - [Actions.BLOCK_CUT, Actions.BLOCK_COPY, Actions.BLOCK_PASTE, Actions.ELEMENT_DELETE], - [Actions.BLOCK_ROTATE_CCW, Actions.BLOCK_ROTATE_CW, Actions.BLOCK_ENABLE, Actions.BLOCK_DISABLE, Actions.BLOCK_BYPASS], + [Actions.BLOCK_CUT, Actions.BLOCK_COPY, + Actions.BLOCK_PASTE, Actions.ELEMENT_DELETE], + [Actions.BLOCK_ROTATE_CCW, Actions.BLOCK_ROTATE_CW, + Actions.BLOCK_ENABLE, Actions.BLOCK_DISABLE, Actions.BLOCK_BYPASS], [("_More", [ [Actions.BLOCK_CREATE_HIER, Actions.OPEN_HIER], [Actions.BUSSIFY_SOURCES, Actions.BUSSIFY_SINKS] @@ -181,7 +192,8 @@ class MenuHelper(SubMenuHelper): target = "{}.{}".format(parent.prefix, parent.name) menuitem = Gio.MenuItem.new(label, None) if hasattr(parent, "icon_name"): - menuitem.set_icon(Gio.Icon.new_for_string(parent.icon_name)) + menuitem.set_icon( + Gio.Icon.new_for_string(parent.icon_name)) # Create the new submenu if isinstance(child, list): @@ -216,6 +228,7 @@ class MenuHelper(SubMenuHelper): parent_obj.remove(obj_idx) parent_obj.insert_item(obj_idx, obj) + class ToolbarHelper(SubMenuHelper): """ Builds a toolbar from a given list of actions. @@ -275,6 +288,7 @@ class ToolbarHelper(SubMenuHelper): create_func, parent_obj, _, obj, set_func = self.submenus[name] set_func(obj, create_func()) + class Menu(Gio.Menu, MenuHelper): """ Main Menu """ @@ -309,7 +323,7 @@ class Toolbar(Gtk.Toolbar, ToolbarHelper): ToolbarHelper.__init__(self) self.set_style(Gtk.ToolbarStyle.ICONS) - #self.get_style_context().add_class(Gtk.STYLE_CLASS_PRIMARY_TOOLBAR) + # self.get_style_context().add_class(Gtk.STYLE_CLASS_PRIMARY_TOOLBAR) - #SubMenuCreator.__init__(self) + # SubMenuCreator.__init__(self) self.build_toolbar(TOOLBAR_LIST, self) diff --git a/grc/gui/BlockTreeWindow.py b/grc/gui/BlockTreeWindow.py index 2f359f8c43..05341ec52b 100644 --- a/grc/gui/BlockTreeWindow.py +++ b/grc/gui/BlockTreeWindow.py @@ -34,7 +34,8 @@ def _format_doc(doc): def _format_cat_tooltip(category): - tooltip = '{}: {}'.format('Category' if len(category) > 1 else 'Module', category[-1]) + tooltip = '{}: {}'.format('Category' if len( + category) > 1 else 'Module', category[-1]) if category == ('Core',): tooltip += '\n\nThis subtree is meant for blocks included with GNU Radio (in-tree).' @@ -68,26 +69,33 @@ class BlockTreeWindow(Gtk.VBox): # search entry self.search_entry = Gtk.Entry() try: - self.search_entry.set_icon_from_icon_name(Gtk.EntryIconPosition.PRIMARY, 'edit-find') - self.search_entry.set_icon_activatable(Gtk.EntryIconPosition.PRIMARY, False) - self.search_entry.set_icon_from_icon_name(Gtk.EntryIconPosition.SECONDARY, 'window-close') + self.search_entry.set_icon_from_icon_name( + Gtk.EntryIconPosition.PRIMARY, 'edit-find') + self.search_entry.set_icon_activatable( + Gtk.EntryIconPosition.PRIMARY, False) + self.search_entry.set_icon_from_icon_name( + Gtk.EntryIconPosition.SECONDARY, 'window-close') self.search_entry.connect('icon-release', self._handle_icon_event) except AttributeError: pass # no icon for old pygtk self.search_entry.connect('changed', self._update_search_tree) - self.search_entry.connect('key-press-event', self._handle_search_key_press) + self.search_entry.connect( + 'key-press-event', self._handle_search_key_press) self.pack_start(self.search_entry, False, False, 0) # make the tree model for holding blocks and a temporary one for search results - self.treestore = Gtk.TreeStore(GObject.TYPE_STRING, GObject.TYPE_STRING, GObject.TYPE_STRING) - self.treestore_search = Gtk.TreeStore(GObject.TYPE_STRING, GObject.TYPE_STRING, GObject.TYPE_STRING) + self.treestore = Gtk.TreeStore( + GObject.TYPE_STRING, GObject.TYPE_STRING, GObject.TYPE_STRING) + self.treestore_search = Gtk.TreeStore( + GObject.TYPE_STRING, GObject.TYPE_STRING, GObject.TYPE_STRING) self.treeview = Gtk.TreeView(model=self.treestore) self.treeview.set_enable_search(False) # disable pop up search box self.treeview.set_search_column(-1) # really disable search self.treeview.set_headers_visible(False) self.treeview.add_events(Gdk.EventMask.BUTTON_PRESS_MASK) - self.treeview.connect('button-press-event', self._handle_mouse_button_press) + self.treeview.connect('button-press-event', + self._handle_mouse_button_press) self.treeview.connect('key-press-event', self._handle_search_key_press) self.treeview.get_selection().set_mode(Gtk.SelectionMode.SINGLE) @@ -99,13 +107,16 @@ class BlockTreeWindow(Gtk.VBox): column.set_sort_column_id(0) self.treestore.set_sort_column_id(0, Gtk.SortType.ASCENDING) # setup drag and drop - self.treeview.enable_model_drag_source(Gdk.ModifierType.BUTTON1_MASK, Constants.DND_TARGETS, Gdk.DragAction.COPY) + self.treeview.enable_model_drag_source( + Gdk.ModifierType.BUTTON1_MASK, Constants.DND_TARGETS, Gdk.DragAction.COPY) self.treeview.connect('drag-data-get', self._handle_drag_get_data) # make the scrolled window to hold the tree view scrolled_window = Gtk.ScrolledWindow() - scrolled_window.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) + scrolled_window.set_policy( + Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) scrolled_window.add(self.treeview) - scrolled_window.set_size_request(Constants.DEFAULT_BLOCKS_WINDOW_WIDTH, -1) + scrolled_window.set_size_request( + Constants.DEFAULT_BLOCKS_WINDOW_WIDTH, -1) self.pack_start(scrolled_window, True, True, 0) # map categories to iters, automatic mapping for root self._categories = {tuple(): None} @@ -128,10 +139,11 @@ class BlockTreeWindow(Gtk.VBox): self.treeview.collapse_all() core_module_iter = self._categories.get((module_name,)) if core_module_iter: - self.treeview.expand_row(self.treestore.get_path(core_module_iter), False) + self.treeview.expand_row( + self.treestore.get_path(core_module_iter), False) ############################################################ - ## Block Tree Methods + # Block Tree Methods ############################################################ def add_block(self, block, treestore=None, categories=None): """ @@ -144,16 +156,19 @@ class BlockTreeWindow(Gtk.VBox): treestore = treestore or self.treestore categories = categories or self._categories - category = tuple(filter(str, block.category)) # tuple is hashable, remove empty cats + # tuple is hashable, remove empty cats + category = tuple(filter(str, block.category)) # add category and all sub categories for level, parent_cat_name in enumerate(category, 1): parent_category = category[:level] if parent_category not in categories: - iter_ = treestore.insert_before(categories[parent_category[:-1]], None) + iter_ = treestore.insert_before( + categories[parent_category[:-1]], None) treestore.set_value(iter_, NAME_INDEX, parent_cat_name) treestore.set_value(iter_, KEY_INDEX, '') - treestore.set_value(iter_, DOC_INDEX, _format_cat_tooltip(parent_category)) + treestore.set_value( + iter_, DOC_INDEX, _format_cat_tooltip(parent_category)) categories[parent_category] = iter_ # add block iter_ = treestore.insert_before(categories[category], None) @@ -175,7 +190,7 @@ class BlockTreeWindow(Gtk.VBox): self.treestore_search.foreach(update_doc) ############################################################ - ## Helper Methods + # Helper Methods ############################################################ def _get_selected_block_key(self): """ @@ -195,7 +210,7 @@ class BlockTreeWindow(Gtk.VBox): self.treeview.expand_to_path(path) ############################################################ - ## Event Handlers + # Event Handlers ############################################################ def _handle_icon_event(self, widget, icon, event): if icon == Gtk.EntryIconPosition.PRIMARY: @@ -216,7 +231,8 @@ class BlockTreeWindow(Gtk.VBox): self.treestore_search.clear() self._categories_search = {tuple(): None} for block in matching_blocks: - self.add_block(block, self.treestore_search, self._categories_search) + self.add_block(block, self.treestore_search, + self._categories_search) self.treeview.set_model(self.treestore_search) self.treeview.expand_all() @@ -232,7 +248,8 @@ class BlockTreeWindow(Gtk.VBox): selected = self.treestore_search.iter_children(selected) if selected is not None: key = self.treestore_search.get_value(selected, KEY_INDEX) - if key: self.emit('create_new_block', key) + if key: + self.emit('create_new_block', key) elif widget == self.treeview: key = self._get_selected_block_key() if key: @@ -248,7 +265,7 @@ class BlockTreeWindow(Gtk.VBox): self.search_entry.hide() elif (event.get_state() & Gdk.ModifierType.CONTROL_MASK and event.keyval == Gdk.KEY_f) \ - or event.keyval == Gdk.KEY_slash: + or event.keyval == Gdk.KEY_slash: # propagation doesn't work although treeview search is disabled =( # manually trigger action... Actions.FIND_BLOCKS.activate() @@ -258,7 +275,7 @@ class BlockTreeWindow(Gtk.VBox): Actions.TOGGLE_BLOCKS_WINDOW.activate() else: - return False # propagate event + return False # propagate event return True diff --git a/grc/gui/Config.py b/grc/gui/Config.py index ee354ba54d..35d2eefcca 100644 --- a/grc/gui/Config.py +++ b/grc/gui/Config.py @@ -142,7 +142,8 @@ class Config(CoreConfig): def get_recent_files(self): """ Gets recent files, removes any that do not exist and re-saves it """ - files = list(filter(os.path.exists, self.get_file_list('files_recent'))) + files = list( + filter(os.path.exists, self.get_file_list('files_recent'))) self.set_recent_files(files) return files @@ -168,9 +169,9 @@ class Config(CoreConfig): # Figure out default if sidebar: _, h = self.main_window_size() - return self.entry('variable_editor_sidebar_position', pos, default=int(h*0.7)) + return self.entry('variable_editor_sidebar_position', pos, default=int(h * 0.7)) else: - return self.entry('variable_editor_position', pos, default=int(self.blocks_window_position()*0.5)) + return self.entry('variable_editor_position', pos, default=int(self.blocks_window_position() * 0.5)) def variable_editor_sidebar(self, pos=None): return self.entry('variable_editor_sidebar', pos, default=False) diff --git a/grc/gui/Console.py b/grc/gui/Console.py index 40345b9699..f88191cd88 100644 --- a/grc/gui/Console.py +++ b/grc/gui/Console.py @@ -7,17 +7,15 @@ SPDX-License-Identifier: GPL-2.0-or-later """ +from ..core import Messages +from .Dialogs import TextDisplay, MessageDialogWrapper +from .Constants import DEFAULT_CONSOLE_WINDOW_WIDTH +from gi.repository import Gtk, Gdk, GObject import os import logging import gi gi.require_version('Gtk', '3.0') -from gi.repository import Gtk, Gdk, GObject - -from .Constants import DEFAULT_CONSOLE_WINDOW_WIDTH -from .Dialogs import TextDisplay, MessageDialogWrapper - -from ..core import Messages log = logging.getLogger(__name__) diff --git a/grc/gui/Constants.py b/grc/gui/Constants.py index 2effc8c98c..dd74497468 100644 --- a/grc/gui/Constants.py +++ b/grc/gui/Constants.py @@ -91,7 +91,8 @@ and kindly ask to update their GRC Block Descriptions or Block Tree to include a # _SCREEN = Gdk.Screen.get_default() # _SCREEN_RESOLUTION = _SCREEN.get_resolution() if _SCREEN else -1 # DPI_SCALING = _SCREEN_RESOLUTION / 96.0 if _SCREEN_RESOLUTION > 0 else 1.0 -DPI_SCALING = 1.0 # todo: figure out the GTK3 way (maybe cairo does this for us +# todo: figure out the GTK3 way (maybe cairo does this for us +DPI_SCALING = 1.0 # Gtk-themes classified as dark GTK_DARK_THEMES = [ @@ -113,7 +114,10 @@ def update_font_size(font_size): PORT_FONT = BLOCK_FONT PARAM_FONT = "%s %f" % (FONT_FAMILY, font_size - 0.5) - PORT_SEPARATION = PORT_SPACING + 2 * PORT_LABEL_PADDING + int(1.5 * font_size) - PORT_SEPARATION += -PORT_SEPARATION % (2 * CANVAS_GRID_SIZE) # even multiple + PORT_SEPARATION = PORT_SPACING + 2 * \ + PORT_LABEL_PADDING + int(1.5 * font_size) + PORT_SEPARATION += - \ + PORT_SEPARATION % (2 * CANVAS_GRID_SIZE) # even multiple + update_font_size(DEFAULT_FONT_SIZE) diff --git a/grc/gui/Dialogs.py b/grc/gui/Dialogs.py index a51b1c44e7..7bdfb2aecb 100644 --- a/grc/gui/Dialogs.py +++ b/grc/gui/Dialogs.py @@ -237,7 +237,8 @@ class ErrorsDialog(Gtk.Dialog): aspect = "Connection to '{}'".format(element.sink_block.name) elif element.is_port: src = element.parent_block.name - aspect = "{} '{}'".format('Sink' if element.is_sink else 'Source', element.name) + aspect = "{} '{}'".format( + 'Sink' if element.is_sink else 'Source', element.name) elif element.is_param: src = element.parent_block.name aspect = "Param '{}'".format(element.name) @@ -279,7 +280,7 @@ def show_about(parent, config): except GLib.Error: Messages.send("Failed to set window logo\n") - #ad.set_comments("") + # ad.set_comments("") ad.set_copyright(config.license.splitlines()[0]) ad.set_website(config.website) @@ -311,6 +312,7 @@ def show_help(parent): parent, Gtk.MessageType.INFO, Gtk.ButtonsType.CLOSE, title='Help', markup=markup ).run_and_destroy() + def show_keyboard_shortcuts(parent): """ Display keyboard shortcut-keys. """ markup = textwrap.dedent("""\ @@ -371,7 +373,8 @@ def show_get_involved(parent): def show_types(parent): """ Display information about standard data types. """ - colors = [(name, color) for name, key, sizeof, color in Constants.CORE_TYPES] + colors = [(name, color) + for name, key, sizeof, color in Constants.CORE_TYPES] max_len = 10 + max(len(name) for name, code in colors) message = '\n'.join( @@ -424,7 +427,8 @@ def choose_editor(parent, config): file_dialog = Gtk.FileChooserDialog( 'Select an Editor...', None, Gtk.FileChooserAction.OPEN, - ('gtk-cancel', Gtk.ResponseType.CANCEL, 'gtk-open', Gtk.ResponseType.OK), + ('gtk-cancel', Gtk.ResponseType.CANCEL, + 'gtk-open', Gtk.ResponseType.OK), transient_for=parent ) file_dialog.set_select_multiple(False) @@ -449,7 +453,8 @@ def choose_editor(parent, config): # Save editor = config.editor = process except Exception: - Messages.send('>>> Unable to load the default editor. Please choose an editor.\n') + Messages.send( + '>>> Unable to load the default editor. Please choose an editor.\n') if editor == '': Messages.send('>>> No editor selected.\n') diff --git a/grc/gui/DrawingArea.py b/grc/gui/DrawingArea.py index 5295caedbb..d94a890272 100644 --- a/grc/gui/DrawingArea.py +++ b/grc/gui/DrawingArea.py @@ -79,10 +79,10 @@ class DrawingArea(Gtk.DrawingArea): self.set_can_focus(True) self.connect('focus-out-event', self._handle_focus_lost_event) - ########################################################################## # Handlers ########################################################################## + def _handle_drag_data_received(self, widget, drag_context, x, y, selection_data, info, time): """ Handle a drag and drop by adding a block at the given coordinate. @@ -96,7 +96,7 @@ class DrawingArea(Gtk.DrawingArea): self._set_zoom_factor(zoom_factor) def zoom_out(self): - change = 1/1.2 + change = 1 / 1.2 zoom_factor = max(self.zoom_factor * change, 0.1) self._set_zoom_factor(zoom_factor) diff --git a/grc/gui/Executor.py b/grc/gui/Executor.py index 4505ef0b37..78f91d93e2 100644 --- a/grc/gui/Executor.py +++ b/grc/gui/Executor.py @@ -80,7 +80,8 @@ class ExecFlowGraphThread(threading.Thread): Execute this C++ flow graph after generating and compiling it. """ generator = self.page.get_generator() - run_command = generator.file_path + '/build/' + self.flow_graph.get_option('id') + run_command = generator.file_path + \ + '/build/' + self.flow_graph.get_option('id') dirname = generator.file_path builddir = os.path.join(dirname, 'build') diff --git a/grc/gui/FileDialogs.py b/grc/gui/FileDialogs.py index acb2ed8610..ceca919531 100644 --- a/grc/gui/FileDialogs.py +++ b/grc/gui/FileDialogs.py @@ -41,7 +41,8 @@ class FileDialogHelper(Gtk.FileChooserDialog, object): Gtk.FileChooserDialog.__init__(self, title=self.title, action=self.action, transient_for=parent) - self.add_buttons('gtk-cancel', Gtk.ResponseType.CANCEL, ok_stock, Gtk.ResponseType.OK) + self.add_buttons('gtk-cancel', Gtk.ResponseType.CANCEL, + ok_stock, Gtk.ResponseType.OK) self.set_select_multiple(False) self.set_local_only(True) @@ -49,12 +50,14 @@ class FileDialogHelper(Gtk.FileChooserDialog, object): self.current_file_path = current_file_path or path.join( Constants.DEFAULT_FILE_PATH, Constants.NEW_FLOGRAPH_TITLE + Constants.FILE_EXTENSION) - self.set_current_folder(path.dirname(current_file_path)) # current directory + self.set_current_folder(path.dirname( + current_file_path)) # current directory self.setup_filters() def setup_filters(self, filters=None): set_default = True - filters = filters or ([(self.filter_label, self.filter_ext)] if self.filter_label else []) + filters = filters or ( + [(self.filter_label, self.filter_ext)] if self.filter_label else []) filters.append(('All Files', '')) for label, ext in filters: if not label: @@ -81,7 +84,8 @@ class SaveFileDialog(FileDialogHelper): def __init__(self, parent, current_file_path): super(SaveFileDialog, self).__init__(parent, current_file_path) - self.set_current_name(path.splitext(path.basename(self.current_file_path))[0] + self.filter_ext) + self.set_current_name(path.splitext(path.basename( + self.current_file_path))[0] + self.filter_ext) self.set_create_folders(True) self.set_do_overwrite_confirmation(True) @@ -94,7 +98,8 @@ class OpenFileDialog(FileDialogHelper): Dialogs.MessageDialogWrapper( self.parent, Gtk.MessageType.WARNING, Gtk.ButtonsType.CLOSE, 'Cannot Open!', - 'File <b>{filename}</b> Does not Exist!'.format(filename=Utils.encode(filename)), + 'File <b>{filename}</b> Does not Exist!'.format( + filename=Utils.encode(filename)), ).run_and_destroy() def get_filename(self): @@ -145,7 +150,8 @@ class SaveConsole(SaveFileDialog): class SaveScreenShot(SaveFileDialog): title = 'Save a Flow Graph Screen Shot...' - filters = [('PDF Files', '.pdf'), ('PNG Files', '.png'), ('SVG Files', '.svg')] + filters = [('PDF Files', '.pdf'), ('PNG Files', '.png'), + ('SVG Files', '.svg')] filter_ext = '.pdf' # the default def __init__(self, parent, current_file_path=''): @@ -154,7 +160,8 @@ class SaveScreenShot(SaveFileDialog): self.config = Gtk.Application.get_default().config self._button = button = Gtk.CheckButton(label='Background transparent') - self._button.set_active(self.config.screen_shot_background_transparent()) + self._button.set_active( + self.config.screen_shot_background_transparent()) self.set_extra_widget(button) def setup_filters(self, filters=None): @@ -164,7 +171,8 @@ class SaveScreenShot(SaveFileDialog): Dialogs.MessageDialogWrapper( self.parent, Gtk.MessageType.ERROR, Gtk.ButtonsType.CLOSE, 'Can not Save!', - 'File Extension of <b>{filename}</b> not supported!'.format(filename=Utils.encode(filename)), + 'File Extension of <b>{filename}</b> not supported!'.format( + filename=Utils.encode(filename)), ).run_and_destroy() def run(self): diff --git a/grc/gui/MainWindow.py b/grc/gui/MainWindow.py index 7e8462b3ef..5561c26419 100644 --- a/grc/gui/MainWindow.py +++ b/grc/gui/MainWindow.py @@ -43,7 +43,8 @@ class MainWindow(Gtk.ApplicationWindow): MainWindow constructor Setup the menu, toolbar, flow graph editor notebook, block selection window... """ - Gtk.ApplicationWindow.__init__(self, title="GNU Radio Companion", application=app) + Gtk.ApplicationWindow.__init__( + self, title="GNU Radio Companion", application=app) log.debug("__init__()") self._platform = platform @@ -63,7 +64,8 @@ class MainWindow(Gtk.ApplicationWindow): icon = icon_theme.lookup_icon("gnuradio-grc", 48, 0) if not icon: # Set default window icon - self.set_icon_from_file(os.path.dirname(os.path.abspath(__file__)) + "/icon.png") + self.set_icon_from_file(os.path.dirname( + os.path.abspath(__file__)) + "/icon.png") else: # Use gnuradio icon self.set_icon(icon.load_icon()) @@ -85,7 +87,7 @@ class MainWindow(Gtk.ApplicationWindow): vbox.pack_start(self.tool_bar, False, False, 0) # Main parent container for the different panels - self.main = Gtk.HPaned() #(orientation=Gtk.Orientation.HORIZONTAL) + self.main = Gtk.HPaned() # (orientation=Gtk.Orientation.HORIZONTAL) vbox.pack_start(self.main, True, True, 0) # Create the notebook @@ -99,15 +101,19 @@ class MainWindow(Gtk.ApplicationWindow): # Create the block tree and variable panels self.btwin = BlockTreeWindow(platform) - self.btwin.connect('create_new_block', self._add_block_to_current_flow_graph) + self.btwin.connect('create_new_block', + self._add_block_to_current_flow_graph) self.vars = VariableEditor() - self.vars.connect('create_new_block', self._add_block_to_current_flow_graph) - self.vars.connect('remove_block', self._remove_block_from_current_flow_graph) + self.vars.connect('create_new_block', + self._add_block_to_current_flow_graph) + self.vars.connect( + 'remove_block', self._remove_block_from_current_flow_graph) # Figure out which place to put the variable editor - self.left = Gtk.VPaned() #orientation=Gtk.Orientation.VERTICAL) - self.right = Gtk.VPaned() #orientation=Gtk.Orientation.VERTICAL) - self.left_subpanel = Gtk.HPaned() #orientation=Gtk.Orientation.HORIZONTAL) + self.left = Gtk.VPaned() # orientation=Gtk.Orientation.VERTICAL) + self.right = Gtk.VPaned() # orientation=Gtk.Orientation.VERTICAL) + # orientation=Gtk.Orientation.HORIZONTAL) + self.left_subpanel = Gtk.HPaned() self.variable_panel_sidebar = self.config.variable_editor_sidebar() if self.variable_panel_sidebar: @@ -133,9 +139,11 @@ class MainWindow(Gtk.ApplicationWindow): self.main.set_position(self.config.blocks_window_position()) self.left.set_position(self.config.console_window_position()) if self.variable_panel_sidebar: - self.right.set_position(self.config.variable_editor_position(sidebar=True)) + self.right.set_position( + self.config.variable_editor_position(sidebar=True)) else: - self.left_subpanel.set_position(self.config.variable_editor_position()) + self.left_subpanel.set_position( + self.config.variable_editor_position()) self.show_all() log.debug("Main window ready") @@ -238,16 +246,18 @@ class MainWindow(Gtk.ApplicationWindow): file_path: optional file to load into the flow graph show: true if the page should be shown after loading """ - #if the file is already open, show the open page and return - if file_path and file_path in self._get_files(): #already open - page = self.notebook.get_nth_page(self._get_files().index(file_path)) + # if the file is already open, show the open page and return + if file_path and file_path in self._get_files(): # already open + page = self.notebook.get_nth_page( + self._get_files().index(file_path)) self._set_page(page) return - try: #try to load from file - if file_path: Messages.send_start_load(file_path) + try: # try to load from file + if file_path: + Messages.send_start_load(file_path) flow_graph = self._platform.make_flow_graph() flow_graph.grc_file_path = file_path - #print flow_graph + # print flow_graph page = Page( self, flow_graph=flow_graph, @@ -260,18 +270,20 @@ class MainWindow(Gtk.ApplicationWindow): str(Messages.flowgraph_error) ) ) - if file_path: Messages.send_end_load() - except Exception as e: #return on failure + if file_path: + Messages.send_end_load() + except Exception as e: # return on failure Messages.send_fail_load(e) if isinstance(e, KeyError) and str(e) == "'options'": # This error is unrecoverable, so crash gracefully exit(-1) return - #add this page to the notebook + # add this page to the notebook self.notebook.append_page(page, page.tab) self.notebook.set_tab_reorderable(page, True) - #only show if blank or manual - if not file_path or show: self._set_page(page) + # only show if blank or manual + if not file_path or show: + self._set_page(page) def close_pages(self): """ @@ -280,25 +292,29 @@ class MainWindow(Gtk.ApplicationWindow): Returns: true if all closed """ - open_files = [file for file in self._get_files() if file] #filter blank files + open_files = [file for file in self._get_files() + if file] # filter blank files open_file = self.current_page.file_path - #close each page + # close each page for page in sorted(self.get_pages(), key=lambda p: p.saved): self.page_to_be_closed = page closed = self.close_page(False) if not closed: break - if self.notebook.get_n_pages(): return False - #save state before closing + if self.notebook.get_n_pages(): + return False + # save state before closing self.config.set_open_files(open_files) self.config.file_open(open_file) self.config.main_window_size(self.get_size()) self.config.console_window_position(self.left.get_position()) self.config.blocks_window_position(self.main.get_position()) if self.variable_panel_sidebar: - self.config.variable_editor_position(self.right.get_position(), sidebar=True) + self.config.variable_editor_position( + self.right.get_position(), sidebar=True) else: - self.config.variable_editor_position(self.left_subpanel.get_position()) + self.config.variable_editor_position( + self.left_subpanel.get_position()) self.config.save() return True @@ -311,29 +327,31 @@ class MainWindow(Gtk.ApplicationWindow): Args: ensure: boolean """ - if not self.page_to_be_closed: self.page_to_be_closed = self.current_page - #show the page if it has an executing flow graph or is unsaved + if not self.page_to_be_closed: + self.page_to_be_closed = self.current_page + # show the page if it has an executing flow graph or is unsaved if self.page_to_be_closed.process or not self.page_to_be_closed.saved: self._set_page(self.page_to_be_closed) - #unsaved? ask the user + # unsaved? ask the user if not self.page_to_be_closed.saved: - response = self._save_changes() # return value is either OK, CLOSE, or CANCEL + response = self._save_changes() # return value is either OK, CLOSE, or CANCEL if response == Gtk.ResponseType.OK: - Actions.FLOW_GRAPH_SAVE() #try to save - if not self.page_to_be_closed.saved: #still unsaved? - self.page_to_be_closed = None #set the page to be closed back to None + Actions.FLOW_GRAPH_SAVE() # try to save + if not self.page_to_be_closed.saved: # still unsaved? + self.page_to_be_closed = None # set the page to be closed back to None return False elif response == Gtk.ResponseType.CANCEL: self.page_to_be_closed = None return False - #stop the flow graph if executing + # stop the flow graph if executing if self.page_to_be_closed.process: Actions.FLOW_GRAPH_KILL() - #remove the page - self.notebook.remove_page(self.notebook.page_num(self.page_to_be_closed)) + # remove the page + self.notebook.remove_page( + self.notebook.page_num(self.page_to_be_closed)) if ensure and self.notebook.get_n_pages() == 0: - self.new_page() #no pages, make a new one - self.page_to_be_closed = None #set the page to be closed back to None + self.new_page() # no pages, make a new one + self.page_to_be_closed = None # set the page to be closed back to None return True ############################################################ @@ -405,7 +423,8 @@ class MainWindow(Gtk.ApplicationWindow): page: the page widget """ self.current_page = page - self.notebook.set_current_page(self.notebook.page_num(self.current_page)) + self.notebook.set_current_page( + self.notebook.page_num(self.current_page)) def _save_changes(self): """ diff --git a/grc/gui/Notebook.py b/grc/gui/Notebook.py index 02f27dc316..457e115d3f 100644 --- a/grc/gui/Notebook.py +++ b/grc/gui/Notebook.py @@ -118,9 +118,12 @@ class Page(Gtk.HBox): self.viewport.add(self.drawing_area) self.scrolled_window = Gtk.ScrolledWindow() - self.scrolled_window.set_size_request(MIN_WINDOW_WIDTH, MIN_WINDOW_HEIGHT) - self.scrolled_window.set_policy(Gtk.PolicyType.ALWAYS, Gtk.PolicyType.ALWAYS) - self.scrolled_window.connect('key-press-event', self._handle_scroll_window_key_press) + self.scrolled_window.set_size_request( + MIN_WINDOW_WIDTH, MIN_WINDOW_HEIGHT) + self.scrolled_window.set_policy( + Gtk.PolicyType.ALWAYS, Gtk.PolicyType.ALWAYS) + self.scrolled_window.connect( + 'key-press-event', self._handle_scroll_window_key_press) self.scrolled_window.add(self.viewport) self.pack_start(self.scrolled_window, True, True, 0) diff --git a/grc/gui/ParamWidgets.py b/grc/gui/ParamWidgets.py index 1cdfc34989..acb95b106f 100644 --- a/grc/gui/ParamWidgets.py +++ b/grc/gui/ParamWidgets.py @@ -42,6 +42,7 @@ def have_dark_theme(): return False return is_dark_theme(theme) + def add_style_provider(): """ Load GTK styles @@ -55,6 +56,8 @@ def add_style_provider(): style_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION ) + + add_style_provider() @@ -93,7 +96,8 @@ class InputParam(Gtk.HBox): """ Set the markup, color, tooltip, show/hide. """ - self.label.set_markup(self.param.format_label_markup(self._have_pending_changes)) + self.label.set_markup( + self.param.format_label_markup(self._have_pending_changes)) self.set_color('dtype_' + self.param.dtype) self.set_tooltip_text(self.param.format_tooltip_text()) @@ -117,14 +121,14 @@ class InputParam(Gtk.HBox): Handle a gui change by setting the new param value, calling the callback (if applicable), and updating. """ - #set the new value + # set the new value self.param.set_value(self.get_text()) - #call the callback + # call the callback if self._changed_callback: self._changed_callback(self, None) else: self.param.validate() - #gui update + # gui update self._have_pending_changes = False self._update_gui() @@ -205,7 +209,8 @@ class PythonEditorParam(InputParam): self.pack_start(button, True, True, True) def open_editor(self, widget=None): - self.param.parent_flowgraph.install_external_editor(self.param, parent=self._transient_for) + self.param.parent_flowgraph.install_external_editor( + self.param, parent=self._transient_for) def get_text(self): pass # we never update the value from here @@ -297,13 +302,15 @@ class FileParam(EntryParam): """ # get the paths file_path = self.param.is_valid() and self.param.get_evaluated() or '' - (dirname, basename) = os.path.isfile(file_path) and os.path.split(file_path) or (file_path, '') + (dirname, basename) = os.path.isfile( + file_path) and os.path.split(file_path) or (file_path, '') # check for qss theme default directory if self.param.key == 'qt_qss_theme': dirname = os.path.dirname(dirname) # trim filename if not os.path.exists(dirname): - config = self.param.parent_platform.config - dirname = os.path.join(config.install_prefix, '/share/gnuradio/themes') + config = self.param.parent_platform.config + dirname = os.path.join( + config.install_prefix, '/share/gnuradio/themes') if not os.path.exists(dirname): dirname = os.getcwd() # fix bad paths @@ -313,17 +320,20 @@ class FileParam(EntryParam): title='Open a Data File...', action=Gtk.FileChooserAction.OPEN, transient_for=self._transient_for, ) - file_dialog.add_buttons('gtk-cancel', Gtk.ResponseType.CANCEL, 'gtk-open', Gtk.ResponseType.OK) + file_dialog.add_buttons( + 'gtk-cancel', Gtk.ResponseType.CANCEL, 'gtk-open', Gtk.ResponseType.OK) elif self.param.dtype == 'file_save': file_dialog = Gtk.FileChooserDialog( title='Save a Data File...', action=Gtk.FileChooserAction.SAVE, transient_for=self._transient_for, ) - file_dialog.add_buttons('gtk-cancel', Gtk.ResponseType.CANCEL, 'gtk-save', Gtk.ResponseType.OK) + file_dialog.add_buttons( + 'gtk-cancel', Gtk.ResponseType.CANCEL, 'gtk-save', Gtk.ResponseType.OK) file_dialog.set_do_overwrite_confirmation(True) file_dialog.set_current_name(basename) # show the current filename else: - raise ValueError("Can't open file chooser dialog for type " + repr(self.param.dtype)) + raise ValueError( + "Can't open file chooser dialog for type " + repr(self.param.dtype)) file_dialog.set_current_folder(dirname) # current directory file_dialog.set_select_multiple(False) file_dialog.set_local_only(True) @@ -334,6 +344,7 @@ class FileParam(EntryParam): self._apply_change() file_dialog.destroy() # destroy the dialog + class DirectoryParam(FileParam): """Provide an entry box for a directory and a button to browse for it.""" @@ -344,23 +355,26 @@ class DirectoryParam(FileParam): """ dirname = self.param.get_evaluated() if self.param.is_valid() else '' - if not os.path.isdir(dirname): # Check if directory exists, if not fall back to workdir + # Check if directory exists, if not fall back to workdir + if not os.path.isdir(dirname): dirname = os.getcwd() - if self.param.dtype == "dir_select": # Setup directory selection dialog, and fail for unexpected dtype + if self.param.dtype == "dir_select": # Setup directory selection dialog, and fail for unexpected dtype dir_dialog = Gtk.FileChooserDialog( title='Select a Directory...', action=Gtk.FileChooserAction.SELECT_FOLDER, transient_for=self._transient_for ) else: - raise ValueError("Can't open directory chooser dialog for type " + repr(self.param.dtype)) + raise ValueError( + "Can't open directory chooser dialog for type " + repr(self.param.dtype)) # Set dialog properties - dir_dialog.add_buttons('gtk-cancel', Gtk.ResponseType.CANCEL, 'gtk-open', Gtk.ResponseType.OK) + dir_dialog.add_buttons( + 'gtk-cancel', Gtk.ResponseType.CANCEL, 'gtk-open', Gtk.ResponseType.OK) dir_dialog.set_current_folder(dirname) dir_dialog.set_local_only(True) dir_dialog.set_select_multiple(False) - + # Show dialog and update parameter on success if Gtk.ResponseType.OK == dir_dialog.run(): path = dir_dialog.get_filename() diff --git a/grc/gui/ParserErrorsDialog.py b/grc/gui/ParserErrorsDialog.py index 12f6f4c7a7..745dc47f0a 100644 --- a/grc/gui/ParserErrorsDialog.py +++ b/grc/gui/ParserErrorsDialog.py @@ -24,7 +24,8 @@ class ParserErrorsDialog(Gtk.Dialog): Args: block: a block instance """ - GObject.GObject.__init__(self, title='Parser Errors', buttons=(Gtk.STOCK_CLOSE, Gtk.ResponseType.ACCEPT)) + GObject.GObject.__init__(self, title='Parser Errors', buttons=( + Gtk.STOCK_CLOSE, Gtk.ResponseType.ACCEPT)) self._error_logs = None self.tree_store = Gtk.TreeStore(str) @@ -48,11 +49,12 @@ class ParserErrorsDialog(Gtk.Dialog): tree_view.expand_row(row.path, False) scrolled_window = Gtk.ScrolledWindow() - scrolled_window.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) + scrolled_window.set_policy( + Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) scrolled_window.add(tree_view) self.vbox.pack_start(scrolled_window, True) - self.set_size_request(2*MIN_DIALOG_WIDTH, MIN_DIALOG_HEIGHT) + self.set_size_request(2 * MIN_DIALOG_WIDTH, MIN_DIALOG_HEIGHT) self.show_all() def update_tree_store(self, error_logs): @@ -68,7 +70,8 @@ class ParserErrorsDialog(Gtk.Dialog): code = None for error in errors: # http://lxml.de/api/lxml.etree._LogEntry-class.html - em = self.tree_store.append(parent, ["Line {e.line}: {e.message}".format(e=error)]) + em = self.tree_store.append( + parent, ["Line {e.line}: {e.message}".format(e=error)]) if code: self.tree_store.append(em, ["\n".join( "{} {}{}".format(line, code[line - 1].replace("\t", " ").strip("\n"), diff --git a/grc/gui/PropsDialog.py b/grc/gui/PropsDialog.py index e7dd72edcf..570e6a4576 100644 --- a/grc/gui/PropsDialog.py +++ b/grc/gui/PropsDialog.py @@ -64,7 +64,8 @@ class PropsDialog(Gtk.Dialog): self._docs_text_display = doc_view = SimpleTextDisplay() doc_view.get_buffer().create_tag('b', weight=Pango.Weight.BOLD) self._docs_box = Gtk.ScrolledWindow() - self._docs_box.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) + self._docs_box.set_policy( + Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) self._docs_vbox = Gtk.VBox(homogeneous=False, spacing=0) self._docs_box.add(self._docs_vbox) self._docs_link = Gtk.Label(use_markup=True) @@ -81,7 +82,8 @@ class PropsDialog(Gtk.Dialog): # todo: set font size in non-deprecated way # code_view.override_font(Pango.FontDescription('monospace %d' % Constants.FONT_SIZE)) code_box = Gtk.ScrolledWindow() - code_box.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) + code_box.set_policy(Gtk.PolicyType.AUTOMATIC, + Gtk.PolicyType.AUTOMATIC) code_box.add(self._code_text_display) notebook.append_page(code_box, Gtk.Label(label="Generated Code")) else: @@ -90,7 +92,8 @@ class PropsDialog(Gtk.Dialog): # Error Messages for the block self._error_messages_text_display = SimpleTextDisplay() self._error_box = Gtk.ScrolledWindow() - self._error_box.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) + self._error_box.set_policy( + Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) self._error_box.add(self._error_messages_text_display) vpaned.pack2(self._error_box) vpaned.set_position(int(0.65 * Constants.MIN_DIALOG_HEIGHT)) @@ -117,7 +120,8 @@ class PropsDialog(Gtk.Dialog): label = Gtk.Label() vbox = Gtk.VBox() scroll_box = Gtk.ScrolledWindow() - scroll_box.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) + scroll_box.set_policy(Gtk.PolicyType.AUTOMATIC, + Gtk.PolicyType.AUTOMATIC) scroll_box.add(vbox) self.notebook.append_page(scroll_box, label) self._params_boxes.append((category, label, vbox)) @@ -232,7 +236,8 @@ class PropsDialog(Gtk.Dialog): buf.insert(pos, '\n') # if given the current parameters an exact match can be made - block_constructor = self._block.templates.render('make').rsplit('.', 2)[-1] + block_constructor = self._block.templates.render( + 'make').rsplit('.', 2)[-1] block_class = block_constructor.partition('(')[0].strip() if block_class in docstrings: docstrings = {block_class: docstrings[block_class]} diff --git a/grc/gui/StateCache.py b/grc/gui/StateCache.py index b3eb4e9232..fff261a29e 100644 --- a/grc/gui/StateCache.py +++ b/grc/gui/StateCache.py @@ -9,6 +9,7 @@ SPDX-License-Identifier: GPL-2.0-or-later from . import Actions from .Constants import STATE_CACHE_SIZE + class StateCache(object): """ The state cache is an interface to a list to record data/states and to revert to previous states. @@ -23,7 +24,7 @@ class StateCache(object): Args: initial_state: the initial state (nested data) """ - self.states = [None] * STATE_CACHE_SIZE #fill states + self.states = [None] * STATE_CACHE_SIZE # fill states self.current_state_index = 0 self.num_prev_states = 0 self.num_next_states = 0 @@ -38,10 +39,12 @@ class StateCache(object): Args: state: the new state """ - self.current_state_index = (self.current_state_index + 1)%STATE_CACHE_SIZE + self.current_state_index = ( + self.current_state_index + 1) % STATE_CACHE_SIZE self.states[self.current_state_index] = state self.num_prev_states = self.num_prev_states + 1 - if self.num_prev_states == STATE_CACHE_SIZE: self.num_prev_states = STATE_CACHE_SIZE - 1 + if self.num_prev_states == STATE_CACHE_SIZE: + self.num_prev_states = STATE_CACHE_SIZE - 1 self.num_next_states = 0 self.update_actions() @@ -63,7 +66,8 @@ class StateCache(object): the previous state or None """ if self.num_prev_states > 0: - self.current_state_index = (self.current_state_index + STATE_CACHE_SIZE -1)%STATE_CACHE_SIZE + self.current_state_index = ( + self.current_state_index + STATE_CACHE_SIZE - 1) % STATE_CACHE_SIZE self.num_next_states = self.num_next_states + 1 self.num_prev_states = self.num_prev_states - 1 return self.get_current_state() @@ -77,7 +81,8 @@ class StateCache(object): the next state or None """ if self.num_next_states > 0: - self.current_state_index = (self.current_state_index + 1)%STATE_CACHE_SIZE + self.current_state_index = ( + self.current_state_index + 1) % STATE_CACHE_SIZE self.num_next_states = self.num_next_states - 1 self.num_prev_states = self.num_prev_states + 1 return self.get_current_state() diff --git a/grc/gui/Utils.py b/grc/gui/Utils.py index 165537c383..5c643c9596 100644 --- a/grc/gui/Utils.py +++ b/grc/gui/Utils.py @@ -32,7 +32,7 @@ def get_rotated_coordinate(coor, rotation): # handles negative angles rotation = (rotation + 360) % 360 if rotation not in Constants.POSSIBLE_ROTATIONS: - raise ValueError('unusable rotation angle "%s"'%str(rotation)) + raise ValueError('unusable rotation angle "%s"' % str(rotation)) # determine the number of degrees to rotate cos_r, sin_r = { 0: (1, 0), 90: (0, 1), 180: (-1, 0), 270: (0, -1), @@ -76,7 +76,7 @@ def num_to_str(num): """Convert a number to a string in engineering notation. E.g., 5e-9 -> 5n""" template = '{:' + fmt + '}{}' magnitude = abs(value) - for exp, symbol in zip(range(9, -15-1, -3), 'GMk munpf'): + for exp, symbol in zip(range(9, -15 - 1, -3), 'GMk munpf'): factor = 10 ** exp if magnitude >= factor: return template.format(value / factor, symbol.strip()) @@ -87,7 +87,8 @@ def num_to_str(num): if num == 0: return '0' output = eng_notation(num.real) if num.real else '' - output += eng_notation(num.imag, '+g' if output else 'g') + 'j' if num.imag else '' + output += eng_notation(num.imag, '+g' if output else 'g') + \ + 'j' if num.imag else '' return output else: return str(num) @@ -144,6 +145,7 @@ def scale_scalar(coor, reverse=False): factor = Constants.DPI_SCALING if not reverse else 1 / Constants.DPI_SCALING return int(coor * factor) + def get_modifier_key(angle_brackets=False): """ Get the modifier key based on platform. @@ -167,9 +169,11 @@ def get_modifier_key(angle_brackets=False): _nproc = None + + def get_cmake_nproc(): """ Get number of cmake processes for C++ flowgraphs """ - global _nproc # Cached result + global _nproc # Cached result if _nproc: return _nproc try: @@ -180,5 +184,5 @@ def get_cmake_nproc(): if not _nproc: _nproc = 1 - _nproc = max(_nproc//2 - 1, 1) + _nproc = max(_nproc // 2 - 1, 1) return _nproc diff --git a/grc/gui/VariableEditor.py b/grc/gui/VariableEditor.py index c5090ba899..4cda5b2c6d 100644 --- a/grc/gui/VariableEditor.py +++ b/grc/gui/VariableEditor.py @@ -22,29 +22,35 @@ class VariableEditorContextMenu(Gtk.Menu): Gtk.Menu.__init__(self) self.imports = Gtk.MenuItem(label="Add _Import") - self.imports.connect('activate', var_edit.handle_action, var_edit.ADD_IMPORT) + self.imports.connect( + 'activate', var_edit.handle_action, var_edit.ADD_IMPORT) self.add(self.imports) self.variables = Gtk.MenuItem(label="Add _Variable") - self.variables.connect('activate', var_edit.handle_action, var_edit.ADD_VARIABLE) + self.variables.connect( + 'activate', var_edit.handle_action, var_edit.ADD_VARIABLE) self.add(self.variables) self.add(Gtk.SeparatorMenuItem()) self.enable = Gtk.MenuItem(label="_Enable") - self.enable.connect('activate', var_edit.handle_action, var_edit.ENABLE_BLOCK) + self.enable.connect( + 'activate', var_edit.handle_action, var_edit.ENABLE_BLOCK) self.disable = Gtk.MenuItem(label="_Disable") - self.disable.connect('activate', var_edit.handle_action, var_edit.DISABLE_BLOCK) + self.disable.connect( + 'activate', var_edit.handle_action, var_edit.DISABLE_BLOCK) self.add(self.enable) self.add(self.disable) self.add(Gtk.SeparatorMenuItem()) self.delete = Gtk.MenuItem(label="_Delete") - self.delete.connect('activate', var_edit.handle_action, var_edit.DELETE_BLOCK) + self.delete.connect( + 'activate', var_edit.handle_action, var_edit.DELETE_BLOCK) self.add(self.delete) self.add(Gtk.SeparatorMenuItem()) self.properties = Gtk.MenuItem(label="_Properties...") - self.properties.connect('activate', var_edit.handle_action, var_edit.OPEN_PROPERTIES) + self.properties.connect( + 'activate', var_edit.handle_action, var_edit.OPEN_PROPERTIES) self.add(self.properties) self.show_all() @@ -87,13 +93,16 @@ class VariableEditor(Gtk.VBox): self.treeview = Gtk.TreeView(model=self.treestore) self.treeview.set_enable_search(False) self.treeview.set_search_column(-1) - #self.treeview.set_enable_search(True) - #self.treeview.set_search_column(ID_INDEX) + # self.treeview.set_enable_search(True) + # self.treeview.set_search_column(ID_INDEX) self.treeview.get_selection().set_mode(Gtk.SelectionMode.SINGLE) self.treeview.set_headers_visible(True) - self.treeview.connect('button-press-event', self._handle_mouse_button_press) - self.treeview.connect('button-release-event', self._handle_mouse_button_release) - self.treeview.connect('motion-notify-event', self._handle_motion_notify) + self.treeview.connect('button-press-event', + self._handle_mouse_button_press) + self.treeview.connect('button-release-event', + self._handle_mouse_button_release) + self.treeview.connect('motion-notify-event', + self._handle_motion_notify) self.treeview.connect('key-press-event', self._handle_key_button_press) # Block Name or Category @@ -133,9 +142,11 @@ class VariableEditor(Gtk.VBox): # Make the scrolled window to hold the tree view scrolled_window = Gtk.ScrolledWindow() - scrolled_window.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) + scrolled_window.set_policy( + Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) scrolled_window.add(self.treeview) - scrolled_window.set_size_request(Constants.DEFAULT_BLOCKS_WINDOW_WIDTH, -1) + scrolled_window.set_size_request( + Constants.DEFAULT_BLOCKS_WINDOW_WIDTH, -1) self.pack_start(scrolled_window, True, True, 0) # Context menus @@ -215,9 +226,11 @@ class VariableEditor(Gtk.VBox): imports = self.treestore.append(None, [None, 'Imports']) variables = self.treestore.append(None, [None, 'Variables']) for block in self._imports: - self.treestore.append(imports, [block, block.params['id'].get_value()]) + self.treestore.append( + imports, [block, block.params['id'].get_value()]) for block in sorted(self._variables, key=lambda v: v.name): - self.treestore.append(variables, [block, block.params['id'].get_value()]) + self.treestore.append( + variables, [block, block.params['id'].get_value()]) def _handle_name_edited_cb(self, cell, path, new_text): block = self.treestore[path][BLOCK_INDEX] @@ -243,7 +256,7 @@ class VariableEditor(Gtk.VBox): self.emit('create_new_block', 'variable') elif key == self.OPEN_PROPERTIES: # TODO: This probably isn't working because the action doesn't expect a parameter - #Actions.BLOCK_PARAM_MODIFY() + # Actions.BLOCK_PARAM_MODIFY() pass elif key == self.DELETE_BLOCK: self.emit('remove_block', self._block.name) @@ -251,12 +264,15 @@ class VariableEditor(Gtk.VBox): if self._confirm_delete: # Create a context menu to confirm the delete operation confirmation_menu = Gtk.Menu() - block_id = self._block.params['id'].get_value().replace("_", "__") + block_id = self._block.params['id'].get_value().replace( + "_", "__") confirm = Gtk.MenuItem(label="Delete {}".format(block_id)) - confirm.connect('activate', self.handle_action, self.DELETE_BLOCK) + confirm.connect('activate', self.handle_action, + self.DELETE_BLOCK) confirmation_menu.add(confirm) confirmation_menu.show_all() - confirmation_menu.popup(None, None, None, None, event.button, event.time) + confirmation_menu.popup( + None, None, None, None, event.button, event.time) else: self.handle_action(None, self.DELETE_BLOCK, None) elif key == self.ENABLE_BLOCK: @@ -287,7 +303,8 @@ class VariableEditor(Gtk.VBox): if self._block and event.type == Gdk.EventType._2BUTTON_PRESS: # Open the advanced dialog if it is a gui variable if self._block.key not in ("variable", "import"): - self.handle_action(None, self.OPEN_PROPERTIES, event=event) + self.handle_action( + None, self.OPEN_PROPERTIES, event=event) return True if event.type == Gdk.EventType.BUTTON_PRESS: # User is adding/removing blocks @@ -295,19 +312,24 @@ class VariableEditor(Gtk.VBox): if path[2] > col.cell_get_position(self.action_cell)[0]: if row[1] == "Imports": # Add a new import block. - self.handle_action(None, self.ADD_IMPORT, event=event) + self.handle_action( + None, self.ADD_IMPORT, event=event) elif row[1] == "Variables": # Add a new variable block - self.handle_action(None, self.ADD_VARIABLE, event=event) + self.handle_action( + None, self.ADD_VARIABLE, event=event) else: - self.handle_action(None, self.DELETE_CONFIRM, event=event) + self.handle_action( + None, self.DELETE_CONFIRM, event=event) return True elif event.button == 3 and event.type == Gdk.EventType.BUTTON_PRESS: if self._block: - self._context_menu.update_sensitive(True, enabled=self._block.enabled) + self._context_menu.update_sensitive( + True, enabled=self._block.enabled) else: self._context_menu.update_sensitive(False) - self._context_menu.popup(None, None, None, None, event.button, event.time) + self._context_menu.popup( + None, None, None, None, event.button, event.time) # Null handler. Stops the treeview from handling double click events. if event.type == Gdk.EventType._2BUTTON_PRESS: diff --git a/grc/gui/__init__.py b/grc/gui/__init__.py index 8b13789179..e69de29bb2 100644 --- a/grc/gui/__init__.py +++ b/grc/gui/__init__.py @@ -1 +0,0 @@ - diff --git a/grc/gui/canvas/block.py b/grc/gui/canvas/block.py index a2964bd7e7..c80e2b8771 100644 --- a/grc/gui/canvas/block.py +++ b/grc/gui/canvas/block.py @@ -64,7 +64,8 @@ class Block(CoreBlock, Drawable): """ coor = Utils.scale(coor, reverse=True) if Actions.TOGGLE_SNAP_TO_GRID.get_active(): - offset_x, offset_y = (0, self.height / 2) if self.is_horizontal() else (self.height / 2, 0) + offset_x, offset_y = ( + 0, self.height / 2) if self.is_horizontal() else (self.height / 2, 0) coor = ( Utils.align_to_grid(coor[0] + offset_x) - offset_x, Utils.align_to_grid(coor[1] + offset_y) - offset_y @@ -137,8 +138,10 @@ class Block(CoreBlock, Drawable): for ports, has_busses in zip((self.active_sources, self.active_sinks), bussified): if not ports: continue - port_separation = Constants.PORT_SEPARATION if not has_busses else ports[0].height + Constants.PORT_SPACING - offset = (self.height - (len(ports) - 1) * port_separation - ports[0].height) / 2 + port_separation = Constants.PORT_SEPARATION if not has_busses else ports[ + 0].height + Constants.PORT_SPACING + offset = (self.height - (len(ports) - 1) * + port_separation - ports[0].height) / 2 for port in ports: port.create_shapes() port.coordinate = { @@ -148,7 +151,8 @@ class Block(CoreBlock, Drawable): 270: (offset, +self.width), }[port.connector_direction] - offset += Constants.PORT_SEPARATION if not has_busses else port.height + Constants.PORT_SPACING + offset += Constants.PORT_SEPARATION if not has_busses else port.height + \ + Constants.PORT_SPACING def create_labels(self, cr=None): """Create the labels for the signal block.""" @@ -178,7 +182,8 @@ class Block(CoreBlock, Drawable): markups = [param.format_block_surface_markup() for param in self.params.values() if (param.hide not in ('all', 'part') or (param.dtype == 'id' and force_show_id))] else: - markups = ['<span font_desc="{font}"><b>key: </b>{key}</span>'.format(font=Constants.PARAM_FONT, key=self.key)] + markups = ['<span font_desc="{font}"><b>key: </b>{key}</span>'.format( + font=Constants.PARAM_FONT, key=self.key)] params_layout.set_spacing(Constants.LABEL_SEPARATION * Pango.SCALE) params_layout.set_markup('\n'.join(markups)) @@ -197,12 +202,13 @@ class Block(CoreBlock, Drawable): self.create_port_labels() def get_min_height_for_ports(ports): - min_height = 2 * Constants.PORT_BORDER_SEPARATION + len(ports) * Constants.PORT_SEPARATION + min_height = 2 * Constants.PORT_BORDER_SEPARATION + \ + len(ports) * Constants.PORT_SEPARATION # If any of the ports are bus ports - make the min height larger if any([p.dtype == 'bus' for p in ports]): min_height = 2 * Constants.PORT_BORDER_SEPARATION + sum( port.height + Constants.PORT_SPACING for port in ports if port.dtype == 'bus' - ) - Constants.PORT_SPACING + ) - Constants.PORT_SPACING else: if ports: @@ -213,11 +219,13 @@ class Block(CoreBlock, Drawable): get_min_height_for_ports(self.active_sinks), get_min_height_for_ports(self.active_sources)) - self.width, self.height = width, height = Utils.align_to_grid((width, height)) + self.width, self.height = width, height = Utils.align_to_grid( + (width, height)) self._surface_layouts_offsets = [ (0, (height - label_height) / 2.0), - (0, (height - label_height) / 2.0 + Constants.LABEL_SEPARATION + title_height / Pango.SCALE) + (0, (height - label_height) / 2.0 + + Constants.LABEL_SEPARATION + title_height / Pango.SCALE) ] title_layout.set_width(width * Pango.SCALE) @@ -243,7 +251,8 @@ class Block(CoreBlock, Drawable): complexity = utils.flow_graph_complexity.calculate(self.parent) markups.append( '<span foreground="#444" size="medium" font_desc="{font}">' - '<b>Complexity: {num}bal</b></span>'.format(num=Utils.num_to_str(complexity), font=Constants.BLOCK_FONT) + '<b>Complexity: {num}bal</b></span>'.format( + num=Utils.num_to_str(complexity), font=Constants.BLOCK_FONT) ) comment = self.comment # Returns None if there are no comments if comment: @@ -303,7 +312,8 @@ class Block(CoreBlock, Drawable): for port in self.active_ports(): port_selected = port.what_is_selected( coor=[a - b for a, b in zip(coor, self.coordinate)], - coor_m=[a - b for a, b in zip(coor, self.coordinate)] if coor_m is not None else None + coor_m=[ + a - b for a, b in zip(coor, self.coordinate)] if coor_m is not None else None ) if port_selected: return port_selected @@ -359,7 +369,8 @@ class Block(CoreBlock, Drawable): true for change """ type_templates = ' '.join(p.dtype for p in self.params.values()) + ' ' - type_templates += ' '.join(p.get_raw('dtype') for p in (self.sinks + self.sources)) + type_templates += ' '.join(p.get_raw('dtype') + for p in (self.sinks + self.sources)) type_param = None for key, param in self.params.items(): if not param.is_enum(): @@ -396,7 +407,8 @@ class Block(CoreBlock, Drawable): """ changed = False # Concat the nports string from the private nports settings of all ports - nports_str = ' '.join(str(port.get_raw('multiplicity')) for port in self.ports()) + nports_str = ' '.join(str(port.get_raw('multiplicity')) + for port in self.ports()) # Modify all params whose keys appear in the nports string for key, param in self.params.items(): if param.is_enum() or param.key not in nports_str: diff --git a/grc/gui/canvas/colors.py b/grc/gui/canvas/colors.py index 2ab4933761..89f5025d0e 100644 --- a/grc/gui/canvas/colors.py +++ b/grc/gui/canvas/colors.py @@ -25,6 +25,7 @@ def get_color(color_code): # fg colors ################################################################################# + HIGHLIGHT_COLOR = get_color('#00FFFF') BORDER_COLOR = get_color('#616161') BORDER_COLOR_DISABLED = get_color('#888888') @@ -62,8 +63,10 @@ DEFAULT_DOMAIN_COLOR = get_color('#777777') # port colors ################################################################################# -PORT_TYPE_TO_COLOR = {key: get_color(color) for name, key, sizeof, color in Constants.CORE_TYPES} -PORT_TYPE_TO_COLOR.update((key, get_color(color)) for key, (_, color) in Constants.ALIAS_TYPES.items()) +PORT_TYPE_TO_COLOR = {key: get_color( + color) for name, key, sizeof, color in Constants.CORE_TYPES} +PORT_TYPE_TO_COLOR.update((key, get_color(color)) + for key, (_, color) in Constants.ALIAS_TYPES.items()) ################################################################################# @@ -109,4 +112,3 @@ LIGHT_THEME_STYLES = b""" #enum_custom { background-color: #EEEEEE; } """ - diff --git a/grc/gui/canvas/connection.py b/grc/gui/canvas/connection.py index 316ecbdd09..be5db73b65 100644 --- a/grc/gui/canvas/connection.py +++ b/grc/gui/canvas/connection.py @@ -73,11 +73,13 @@ class Connection(CoreConnection, Drawable): # first two components relative to source connector, rest relative to sink connector self._rel_points = [ - rotate((15, 0), source.rotation), # line from 0,0 to here, bezier curve start + # line from 0,0 to here, bezier curve start + rotate((15, 0), source.rotation), rotate((50, 0), source.rotation), # bezier curve control point 1 rotate((-50, 0), sink.rotation), # bezier curve control point 2 rotate((-15, 0), sink.rotation), # bezier curve end - rotate((-CONNECTOR_ARROW_HEIGHT, 0), sink.rotation), # line to arrow head + rotate((-CONNECTOR_ARROW_HEIGHT, 0), + sink.rotation), # line to arrow head ] self._current_coordinates = None # triggers _make_path() @@ -110,7 +112,8 @@ class Connection(CoreConnection, Drawable): # make rel_point all relative to source connector p0 = 0, 0 # x_start - x_pos, y_start - y_pos - p1, p2, (dx_e1, dy_e1), (dx_e2, dy_e2), (dx_e3, dy_e3) = self._rel_points + p1, p2, (dx_e1, dy_e1), (dx_e2, dy_e2), (dx_e3, + dy_e3) = self._rel_points p3 = x_e + dx_e1, y_e + dy_e1 p4 = x_e + dx_e2, y_e + dy_e2 p5 = x_e + dx_e3, y_e + dy_e3 @@ -137,7 +140,8 @@ class Connection(CoreConnection, Drawable): self.create_shapes() # triggers _make_path() call below self._current_port_rotations = port_rotations - new_coordinates = (source.parent_block.coordinate, sink.parent_block.coordinate) + new_coordinates = (source.parent_block.coordinate, + sink.parent_block.coordinate) if self._current_coordinates != new_coordinates: self._make_path(cr) self._current_coordinates = new_coordinates @@ -175,7 +179,7 @@ class Connection(CoreConnection, Drawable): cr.set_source_rgba(*color2) cr.rotate(self._arrow_rotation) cr.rel_move_to(CONNECTOR_ARROW_HEIGHT, 0) - cr.rel_line_to(-CONNECTOR_ARROW_HEIGHT, -CONNECTOR_ARROW_BASE/2) + cr.rel_line_to(-CONNECTOR_ARROW_HEIGHT, -CONNECTOR_ARROW_BASE / 2) cr.rel_line_to(0, CONNECTOR_ARROW_BASE) cr.close_path() cr.fill() @@ -238,4 +242,5 @@ class DummyCoreConnection(object): def has_real_sink(self): return self.sink_port is not self._dummy_port + DummyConnection = Connection.make_cls_with_base(DummyCoreConnection) diff --git a/grc/gui/canvas/flowgraph.py b/grc/gui/canvas/flowgraph.py index cb63f578ac..7c086f3641 100644 --- a/grc/gui/canvas/flowgraph.py +++ b/grc/gui/canvas/flowgraph.py @@ -125,7 +125,8 @@ class FlowGraph(CoreFlowgraph, Drawable): editor.open_editor() except Exception as e: # Problem launching the editor. Need to select a new editor. - Messages.send('>>> Error opening an external editor. Please select a different editor.\n') + Messages.send( + '>>> Error opening an external editor. Please select a different editor.\n') # Reset the editor to force the user to select a new one. self.parent_platform.config.editor = '' @@ -153,10 +154,13 @@ class FlowGraph(CoreFlowgraph, Drawable): # calculate the position coordinate h_adj = scroll_pane.get_hadjustment() v_adj = scroll_pane.get_vadjustment() - if coor is None: coor = ( - int(random.uniform(.25, .75)*h_adj.get_page_size() + h_adj.get_value()), - int(random.uniform(.25, .75)*v_adj.get_page_size() + v_adj.get_value()), - ) + if coor is None: + coor = ( + int(random.uniform(.25, .75) * + h_adj.get_page_size() + h_adj.get_value()), + int(random.uniform(.25, .75) * + v_adj.get_page_size() + v_adj.get_value()), + ) # get the new block block = self.new_block(key) block.coordinate = coor @@ -218,17 +222,17 @@ class FlowGraph(CoreFlowgraph, Drawable): Returns: the clipboard """ - #get selected blocks + # get selected blocks blocks = list(self.selected_blocks()) if not blocks: return None - #calc x and y min + # calc x and y min x_min, y_min = blocks[0].coordinate for block in blocks: x, y = block.coordinate x_min = min(x, x_min) y_min = min(y, y_min) - #get connections between selected blocks + # get connections between selected blocks connections = list(filter( lambda c: c.source_block in blocks and c.sink_block in blocks, self.connections, @@ -281,7 +285,8 @@ class FlowGraph(CoreFlowgraph, Drawable): block.move((x_off, y_off)) while any(Utils.align_to_grid(block.coordinate) == Utils.align_to_grid(other.coordinate) for other in self.blocks if other is not block): - block.move((Constants.CANVAS_GRID_SIZE, Constants.CANVAS_GRID_SIZE)) + block.move((Constants.CANVAS_GRID_SIZE, + Constants.CANVAS_GRID_SIZE)) # shift all following blocks x_off += Constants.CANVAS_GRID_SIZE y_off += Constants.CANVAS_GRID_SIZE @@ -353,15 +358,16 @@ class FlowGraph(CoreFlowgraph, Drawable): if not blocks: return - min_x, min_y = self.selected_block.coordinate + min_x, min_y = self.selected_block.coordinate for selected_block in blocks: x, y = selected_block.coordinate min_x, min_y = min(min_x, x), min(min_y, y) # Sanitize delta_coordinate so that blocks don't move to negative coordinate - delta_coordinate = max(delta_coordinate[0],-min_x), max(delta_coordinate[1], -min_y) + delta_coordinate = max( + delta_coordinate[0], -min_x), max(delta_coordinate[1], -min_y) - # Move selected blocks + # Move selected blocks for selected_block in blocks: selected_block.move(delta_coordinate) self.element_moved = True @@ -388,15 +394,15 @@ class FlowGraph(CoreFlowgraph, Drawable): x += selected_block.width y += selected_block.height max_x, max_y = max(max_x, x), max(max_y, y) - ctr_x, ctr_y = (max_x + min_x)/2, (max_y + min_y)/2 + ctr_x, ctr_y = (max_x + min_x) / 2, (max_y + min_y) / 2 # align the blocks as requested transform = { Actions.BLOCK_VALIGN_TOP: lambda x, y, w, h: (x, min_y), - Actions.BLOCK_VALIGN_MIDDLE: lambda x, y, w, h: (x, ctr_y - h/2), + Actions.BLOCK_VALIGN_MIDDLE: lambda x, y, w, h: (x, ctr_y - h / 2), Actions.BLOCK_VALIGN_BOTTOM: lambda x, y, w, h: (x, max_y - h), Actions.BLOCK_HALIGN_LEFT: lambda x, y, w, h: (min_x, y), - Actions.BLOCK_HALIGN_CENTER: lambda x, y, w, h: (ctr_x-w/2, y), + Actions.BLOCK_HALIGN_CENTER: lambda x, y, w, h: (ctr_x - w / 2, y), Actions.BLOCK_HALIGN_RIGHT: lambda x, y, w, h: (max_x - w, y), }.get(calling_action, lambda *args: args) @@ -419,21 +425,22 @@ class FlowGraph(CoreFlowgraph, Drawable): """ if not any(self.selected_blocks()): return False - #initialize min and max coordinates + # initialize min and max coordinates min_x, min_y = max_x, max_y = self.selected_block.coordinate # rotate each selected block, and find min/max coordinate for selected_block in self.selected_blocks(): selected_block.rotate(rotation) - #update the min/max coordinate + # update the min/max coordinate x, y = selected_block.coordinate min_x, min_y = min(min_x, x), min(min_y, y) max_x, max_y = max(max_x, x), max(max_y, y) - #calculate center point of selected blocks - ctr_x, ctr_y = (max_x + min_x)/2, (max_y + min_y)/2 - #rotate the blocks around the center point + # calculate center point of selected blocks + ctr_x, ctr_y = (max_x + min_x) / 2, (max_y + min_y) / 2 + # rotate the blocks around the center point for selected_block in self.selected_blocks(): x, y = selected_block.coordinate - x, y = Utils.get_rotated_coordinate((x - ctr_x, y - ctr_y), rotation) + x, y = Utils.get_rotated_coordinate( + (x - ctr_x, y - ctr_y), rotation) selected_block.coordinate = (x + ctr_x, y + ctr_y) return True @@ -496,7 +503,7 @@ class FlowGraph(CoreFlowgraph, Drawable): element.create_labels(cr) def create_shapes(self): - #TODO - this is a workaround for bus ports not having a proper coordinate + # TODO - this is a workaround for bus ports not having a proper coordinate # until the shape is drawn. The workaround is to draw blocks before connections for element in filter(lambda x: x.is_block, self._elements_to_draw): @@ -582,7 +589,8 @@ class FlowGraph(CoreFlowgraph, Drawable): else: # called from a mouse release if not self.element_moved and (not self.selected_elements or self.drawing_area.ctrl_mask) and not self._new_connection: - selected_elements = self.what_is_selected(self.coordinate, self.press_coor) + selected_elements = self.what_is_selected( + self.coordinate, self.press_coor) # this selection and the last were ports, try to connect them if self.make_connection(): @@ -635,7 +643,8 @@ class FlowGraph(CoreFlowgraph, Drawable): if selected_port and selected_port.is_source: selected.remove(selected_port.parent_block) - self._new_connection = DummyConnection(selected_port, coordinate=coor) + self._new_connection = DummyConnection( + selected_port, coordinate=coor) self.drawing_area.queue_draw() # update selected ports if selected_port is not self._new_selected_port: @@ -806,19 +815,21 @@ class FlowGraph(CoreFlowgraph, Drawable): dX, dY = x - X, y - Y if Actions.TOGGLE_SNAP_TO_GRID.get_active() or self.drawing_area.mod1_mask: - dX, dY = int(round(dX / Constants.CANVAS_GRID_SIZE)), int(round(dY / Constants.CANVAS_GRID_SIZE)) + dX, dY = int(round(dX / Constants.CANVAS_GRID_SIZE) + ), int(round(dY / Constants.CANVAS_GRID_SIZE)) dX, dY = dX * Constants.CANVAS_GRID_SIZE, dY * Constants.CANVAS_GRID_SIZE else: dX, dY = int(round(dX)), int(round(dY)) if dX != 0 or dY != 0: self.move_selected((dX, dY)) - self.coordinate = (X+dX, Y+dY) + self.coordinate = (X + dX, Y + dY) redraw = True return redraw def get_extents(self): show_comments = Actions.TOGGLE_SHOW_BLOCK_COMMENTS.get_active() + def sub_extents(): for element in self._elements_to_draw: yield element.get_extents() @@ -828,5 +839,6 @@ class FlowGraph(CoreFlowgraph, Drawable): extent = 10000000, 10000000, 0, 0 cmps = (min, min, max, max) for sub_extent in sub_extents(): - extent = [cmp(xy, e_xy) for cmp, xy, e_xy in zip(cmps, extent, sub_extent)] + extent = [cmp(xy, e_xy) + for cmp, xy, e_xy in zip(cmps, extent, sub_extent)] return tuple(extent) diff --git a/grc/gui/canvas/param.py b/grc/gui/canvas/param.py index 6b33ef223c..488ca7a5c3 100644 --- a/grc/gui/canvas/param.py +++ b/grc/gui/canvas/param.py @@ -86,20 +86,20 @@ class Param(CoreParam): tooltip_lines.extend(' * ' + msg for msg in errors) return '\n'.join(tooltip_lines) - - ################################################## # Truncate helper method ################################################## + def truncate(self, string, style=0): max_len = max(27 - len(self.name), 3) if len(string) > max_len: if style < 0: # Front truncate - string = '...' + string[3-max_len:] + string = '...' + string[3 - max_len:] elif style == 0: # Center truncate - string = string[:max_len//2 - 3] + '...' + string[-max_len//2:] + string = string[:max_len // 2 - 3] + \ + '...' + string[-max_len // 2:] elif style > 0: # Rear truncate - string = string[:max_len-3] + '...' + string = string[:max_len - 3] + '...' return string def pretty_print(self): @@ -183,5 +183,5 @@ class Param(CoreParam): display_value = expr_string return '<span {foreground} font_desc="{font}"><b>{label}:</b> {value}</span>'.format( - foreground='foreground="red"' if not self.is_valid() else '', font=Constants.PARAM_FONT, + foreground='foreground="red"' if not self.is_valid() else '', font=Constants.PARAM_FONT, label=Utils.encode(self.name), value=display_value) diff --git a/grc/gui/canvas/port.py b/grc/gui/canvas/port.py index d963964cdc..f78fd62179 100644 --- a/grc/gui/canvas/port.py +++ b/grc/gui/canvas/port.py @@ -68,9 +68,11 @@ class Port(CorePort, Drawable): color = colors.PORT_TYPE_TO_COLOR.get('message') else: self._font_color[-1] = 1.0 - color = colors.PORT_TYPE_TO_COLOR.get(self.dtype) or colors.PORT_TYPE_TO_COLOR.get('') + color = colors.PORT_TYPE_TO_COLOR.get( + self.dtype) or colors.PORT_TYPE_TO_COLOR.get('') if self.vlen > 1: - dark = (0, 0, 30 / 255.0, 50 / 255.0, 70 / 255.0)[min(4, self.vlen)] + dark = (0, 0, 30 / 255.0, 50 / 255.0, + 70 / 255.0)[min(4, self.vlen)] color = tuple(max(c - dark, 0) for c in color) self._bg_color = color self._border_color = tuple(max(c - 0.3, 0) for c in color) @@ -84,8 +86,8 @@ class Port(CorePort, Drawable): self.bounds_from_area(self._area) self._connector_coordinate = { - 0: (self.width, self.height / 2), - 90: (self.height / 2, 0), + 0: (self.width, self.height / 2), + 90: (self.height / 2, 0), 180: (0, self.height / 2), 270: (self.height / 2, self.width) }[self.connector_direction] @@ -112,7 +114,8 @@ class Port(CorePort, Drawable): label_width, label_height = self.label_layout.get_size() self.width = 2 * Constants.PORT_LABEL_PADDING + label_width / Pango.SCALE - self.height = (2 * Constants.PORT_LABEL_PADDING + label_height*(3 if self.dtype == 'bus' else 1)) / Pango.SCALE + self.height = (2 * Constants.PORT_LABEL_PADDING + label_height * + (3 if self.dtype == 'bus' else 1)) / Pango.SCALE self._label_layout_offsets = [0, Constants.PORT_LABEL_PADDING] self.height += self.height % 2 # uneven height diff --git a/grc/main.py b/grc/main.py index 06097ed58d..5362618840 100755 --- a/grc/main.py +++ b/grc/main.py @@ -4,12 +4,14 @@ # SPDX-License-Identifier: GPL-2.0-or-later # -import argparse, logging, sys +from gi.repository import Gtk +import argparse +import logging +import sys import gi gi.require_version('Gtk', '3.0') gi.require_version('PangoCairo', '1.0') -from gi.repository import Gtk VERSION_AND_DISCLAIMER_TEMPLATE = """\ @@ -34,7 +36,8 @@ def main(): parser = argparse.ArgumentParser( description=VERSION_AND_DISCLAIMER_TEMPLATE % gr.version()) parser.add_argument('flow_graphs', nargs='*') - parser.add_argument('--log', choices=['debug', 'info', 'warning', 'error', 'critical'], default='warning') + parser.add_argument( + '--log', choices=['debug', 'info', 'warning', 'error', 'critical'], default='warning') args = parser.parse_args() # Enable logging @@ -73,7 +76,8 @@ def main(): log.debug("Loading platform") platform = Platform( version=gr.version(), - version_parts=(gr.major_version(), gr.api_version(), gr.minor_version()), + version_parts=(gr.major_version(), gr.api_version(), + gr.minor_version()), prefs=gr.prefs(), install_prefix=gr.prefix() ) diff --git a/grc/scripts/gnuradio-companion b/grc/scripts/gnuradio-companion index 2f29974471..38a421f515 100755 --- a/grc/scripts/gnuradio-companion +++ b/grc/scripts/gnuradio-companion @@ -47,6 +47,7 @@ def die(error, message): print("The original error message follows.", file=sys.stderr) sys.exit(type(error).__name__ + '\n\n' + msg) + def check_gtk(): try: import gi diff --git a/grc/tests/test_block_templates.py b/grc/tests/test_block_templates.py index df9ab37550..bd3dd492eb 100644 --- a/grc/tests/test_block_templates.py +++ b/grc/tests/test_block_templates.py @@ -37,9 +37,11 @@ def test_list(): def test_parse_error(): with pytest.raises(TemplateError): - MakoTemplates(_bind_to=Block(num='123'), test='abc${num NOT CLOSING').render('test') + MakoTemplates(_bind_to=Block(num='123'), + test='abc${num NOT CLOSING').render('test') def test_parse_error2(): with pytest.raises(TemplateError): - MakoTemplates(_bind_to=Block(num='123'), test='abc${ WRONG_VAR }').render('test') + MakoTemplates(_bind_to=Block(num='123'), + test='abc${ WRONG_VAR }').render('test') diff --git a/grc/tests/test_cheetah_converter.py b/grc/tests/test_cheetah_converter.py index acb0ac402c..02944a31ee 100644 --- a/grc/tests/test_cheetah_converter.py +++ b/grc/tests/test_cheetah_converter.py @@ -39,7 +39,8 @@ def test_conditional(): def test_simple_format_string(): - convert = functools.partial(parser.Converter(names={'abc'}).convert_simple, spec=parser.FormatString) + convert = functools.partial(parser.Converter( + names={'abc'}).convert_simple, spec=parser.FormatString) assert '{abc}' == convert('$abc') assert '{abc:eval}' == convert('$abc()') assert '{abc}' == convert('$(abc)') @@ -50,7 +51,8 @@ def test_simple_format_string(): def test_hard_format_string(): names = {'abc': {'ff'}, 'param1': {}, 'param2': {}} - convert = functools.partial(parser.Converter(names).convert_hard, spec=parser.FormatString) + convert = functools.partial(parser.Converter( + names).convert_hard, spec=parser.FormatString) assert 'make_a_cool_block_{abc.ff}({param1}, {param2})' == \ convert('make_a_cool_block_${abc.ff}($param1, $param2)') @@ -66,7 +68,8 @@ def test_opts(): def test_nested(): - assert 'abc(abc) abc + abc abc[abc]' == c2p('$abc($abc) $(abc + $abc) ${abc[$abc]}') + assert 'abc(abc) abc + abc abc[abc]' == c2p( + '$abc($abc) $(abc + $abc) ${abc[$abc]}') assert '(abc_abc_)' == c2p('(abc_$(abc)_)') diff --git a/grc/tests/test_compiler.py b/grc/tests/test_compiler.py index fbdffd3e0f..4e0e262809 100644 --- a/grc/tests/test_compiler.py +++ b/grc/tests/test_compiler.py @@ -13,11 +13,13 @@ import tempfile from grc.compiler import main + def test_compiler(capsys): args = Namespace( output=tempfile.gettempdir(), user_lib_dir=False, - grc_files=[path.join(path.dirname(__file__), 'resources', 'test_compiler.grc')], + grc_files=[path.join(path.dirname(__file__), + 'resources', 'test_compiler.grc')], run=True ) diff --git a/grc/tests/test_cpp.py b/grc/tests/test_cpp.py index 52d977a31a..6f585a575f 100644 --- a/grc/tests/test_cpp.py +++ b/grc/tests/test_cpp.py @@ -13,11 +13,13 @@ import tempfile from grc.compiler import main + def test_cpp(capsys): args = Namespace( output=tempfile.gettempdir(), user_lib_dir=False, - grc_files=[path.join(path.dirname(__file__), 'resources', 'test_cpp.grc')], + grc_files=[path.join(path.dirname(__file__), + 'resources', 'test_cpp.grc')], run=True ) diff --git a/grc/tests/test_examples.py b/grc/tests/test_examples.py index 2b590a4a94..ecc37f0c98 100644 --- a/grc/tests/test_examples.py +++ b/grc/tests/test_examples.py @@ -14,12 +14,14 @@ except FileExistsError: # Gather blocks BLOCK_PATHS = [] ROOT = path.join(path.dirname(__file__), '../..') -BLOCK_PATHS = [path.join(path.dirname(__file__), '../../grc/blocks'), '../../build/gr-uhd/grc'] +BLOCK_PATHS = [path.join(path.dirname( + __file__), '../../grc/blocks'), '../../build/gr-uhd/grc'] for file_dir in os.scandir(ROOT): # If it is a module if path.isdir(file_dir) and file_dir.name.startswith("gr-"): BLOCK_PATHS.append(path.join(file_dir, "grc")) + def gather_examples(): global ROOT example_paths = [] @@ -39,11 +41,13 @@ def gather_examples(): continue return example_paths + def print_proper(element): if element.is_block: return element.name return f"{element.parent.name} - {element}" + @pytest.mark.examples @pytest.mark.parametrize("example", gather_examples()) def test_all_examples(example): @@ -62,7 +66,9 @@ def test_all_examples(example): flow_graph.rewrite() flow_graph.validate() - assert flow_graph.is_valid(), (example.name, [f"{print_proper(elem)}: {msg}" for elem, msg in flow_graph.iter_error_messages()]) + assert flow_graph.is_valid(), (example.name, [ + f"{print_proper(elem)}: {msg}" for elem, msg in flow_graph.iter_error_messages()]) - generator = platform.Generator(flow_graph, path.join(path.dirname(__file__), 'resources/tests')) + generator = platform.Generator(flow_graph, path.join( + path.dirname(__file__), 'resources/tests')) generator.write() diff --git a/grc/tests/test_generator.py b/grc/tests/test_generator.py index c6ae5b1109..931d3e9af3 100644 --- a/grc/tests/test_generator.py +++ b/grc/tests/test_generator.py @@ -15,7 +15,8 @@ from grc.core.platform import Platform def test_generator(): # c&p form compiler code. - grc_file = path.join(path.dirname(__file__), 'resources', 'test_compiler.grc') + grc_file = path.join(path.dirname(__file__), + 'resources', 'test_compiler.grc') out_dir = tempfile.gettempdir() block_paths = [ path.join(path.dirname(__file__), '../../grc/blocks'), @@ -35,5 +36,6 @@ def test_generator(): assert flow_graph.is_valid() - generator = platform.Generator(flow_graph, path.join(path.dirname(__file__), 'resources')) + generator = platform.Generator( + flow_graph, path.join(path.dirname(__file__), 'resources')) generator.write() diff --git a/grc/tests/test_xml_parser.py b/grc/tests/test_xml_parser.py index 0fd5a94b3d..28ec770cf6 100644 --- a/grc/tests/test_xml_parser.py +++ b/grc/tests/test_xml_parser.py @@ -11,7 +11,8 @@ from grc.converter import flow_graph def test_flow_graph_converter(): - filename = path.join(path.dirname(__file__), 'resources', 'test_compiler.grc') + filename = path.join(path.dirname(__file__), + 'resources', 'test_compiler.grc') data = flow_graph.from_xml(filename) @@ -19,7 +20,8 @@ def test_flow_graph_converter(): def test_flow_graph_converter_with_fp(): - filename = path.join(path.dirname(__file__), 'resources', 'test_compiler.grc') + filename = path.join(path.dirname(__file__), + 'resources', 'test_compiler.grc') with open(filename, 'rb') as fp: data = flow_graph.from_xml(fp) diff --git a/grc/tests/test_yaml_checker.py b/grc/tests/test_yaml_checker.py index 0b658a1087..87f8e5ffe7 100644 --- a/grc/tests/test_yaml_checker.py +++ b/grc/tests/test_yaml_checker.py @@ -58,7 +58,8 @@ def test_min(): def test_extra_keys(): checker = Validator(BLOCK_SCHEME) assert checker.run({'id': 'test', 'abcdefg': 'nonsense', 'file_format': 1}) - assert checker.messages == [('block', 'warn', "Ignoring extra key 'abcdefg'")] + assert checker.messages == [ + ('block', 'warn', "Ignoring extra key 'abcdefg'")] def test_checker(): |