mirror of
https://github.com/gnuradio/gnuradio-companion.git
synced 2025-12-10 17:46:12 -06:00
All of the removed `from __future__ import` were needed in older versions of Python (mostly 2.5.x and below) but later became mandatory in most versions of Python 3 hence are not necessary anymore. More specifically, according to __future__.py[1]: - unicode_literals is part of Python since versions 2.6.0 and 3.0.0; - print_function is part of Python since versions 2.6.0 and 3.0.0; - absolute_import is part of Python since versions 2.5.0 and 3.0.0; - division is part of Python since versions 2.2.0 and 3.0.0; Get rid of those unnecessary imports to slightly clean up the codebase. [1] https://github.com/python/cpython/blob/master/Lib/__future__.py
211 lines
7.3 KiB
Python
211 lines
7.3 KiB
Python
# Copyright 2016 Free Software Foundation, Inc.
|
|
# This file is part of GNU Radio
|
|
#
|
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
|
#
|
|
"""
|
|
Converter for legacy block definitions in XML format
|
|
|
|
- Cheetah expressions that can not be converted are passed to Cheetah for now
|
|
- Instead of generating a Block subclass directly a string representation is
|
|
used and evaluated. This is slower / lamer but allows us to show the user
|
|
how a converted definition would look like
|
|
"""
|
|
|
|
|
|
from collections import OrderedDict, defaultdict
|
|
from itertools import chain
|
|
|
|
from ..core.io import yaml
|
|
from . import cheetah_converter, xml
|
|
|
|
current_file_format = 1
|
|
reserved_block_keys = ('import', ) # todo: add more keys
|
|
|
|
|
|
def from_xml(filename):
|
|
"""Load block description from xml file"""
|
|
element, version_info = xml.load(filename, 'block.dtd')
|
|
|
|
try:
|
|
data = convert_block_xml(element)
|
|
except NameError:
|
|
raise ValueError('Conversion failed', filename)
|
|
|
|
return data
|
|
|
|
|
|
def dump(data, stream):
|
|
out = yaml.dump(data)
|
|
|
|
replace = [
|
|
('parameters:', '\nparameters:'),
|
|
('inputs:', '\ninputs:'),
|
|
('outputs:', '\noutputs:'),
|
|
('templates:', '\ntemplates:'),
|
|
('documentation:', '\ndocumentation:'),
|
|
('file_format:', '\nfile_format:'),
|
|
]
|
|
for r in replace:
|
|
out = out.replace(*r)
|
|
prefix = '# auto-generated by grc.converter\n\n'
|
|
stream.write(prefix + out)
|
|
|
|
|
|
no_value = object()
|
|
dummy = cheetah_converter.DummyConverter()
|
|
|
|
|
|
def convert_block_xml(node):
|
|
converter = cheetah_converter.Converter(names={
|
|
param_node.findtext('key'): {
|
|
opt_node.text.split(':')[0]
|
|
for opt_node in next(param_node.iterfind('option'), param_node).iterfind('opt')
|
|
} for param_node in node.iterfind('param')
|
|
})
|
|
|
|
block_id = node.findtext('key')
|
|
if block_id in reserved_block_keys:
|
|
block_id += '_'
|
|
|
|
data = OrderedDict()
|
|
data['id'] = block_id
|
|
data['label'] = node.findtext('name') or no_value
|
|
data['category'] = node.findtext('category') or no_value
|
|
data['flags'] = [n.text for n in node.findall('flags')]
|
|
data['flags'] += ['show_id'] if block_id.startswith('variable') else []
|
|
if not data['flags']:
|
|
data['flags'] = no_value
|
|
|
|
data['parameters'] = [convert_param_xml(param_node, converter.to_python_dec)
|
|
for param_node in node.iterfind('param')] or no_value
|
|
# data['params'] = {p.pop('key'): p for p in data['params']}
|
|
|
|
data['inputs'] = [convert_port_xml(port_node, converter.to_python_dec)
|
|
for port_node in node.iterfind('sink')] or no_value
|
|
|
|
data['outputs'] = [convert_port_xml(port_node, converter.to_python_dec)
|
|
for port_node in node.iterfind('source')] or no_value
|
|
data['value'] = (
|
|
converter.to_python_dec(node.findtext('var_value')) or
|
|
('${ value }' if block_id.startswith('variable') else no_value)
|
|
)
|
|
|
|
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
|
|
|
|
docs = node.findtext('doc')
|
|
if docs:
|
|
docs = docs.strip().replace('\\\n', '')
|
|
data['documentation'] = yaml.MultiLineString(docs)
|
|
|
|
data['file_format'] = current_file_format
|
|
|
|
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
|
|
|
|
|
|
def auto_hide_params_for_item_sizes(data):
|
|
item_size_templates = []
|
|
vlen_templates = []
|
|
for port in chain(*[data.get(direction, []) for direction in ['inputs', 'outputs']]):
|
|
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)
|
|
|
|
for param in data.get('parameters', []):
|
|
if param['id'] in item_size_templates:
|
|
param.setdefault('hide', 'part')
|
|
if param['id'] in vlen_templates:
|
|
param.setdefault('hide', "${ 'part' if vlen == 1 else 'none' }")
|
|
|
|
|
|
def convert_templates(node, convert, block_id=''):
|
|
templates = OrderedDict()
|
|
|
|
imports = '\n'.join(convert(import_node.text)
|
|
for import_node in node.iterfind('import'))
|
|
if '\n' in imports:
|
|
imports = yaml.MultiLineString(imports)
|
|
templates['imports'] = imports or no_value
|
|
|
|
templates['var_make'] = convert(node.findtext('var_make') or '') or no_value
|
|
|
|
make = convert(node.findtext('make') or '')
|
|
if make:
|
|
check_mako_template(block_id, make)
|
|
if '\n' in make:
|
|
make = yaml.MultiLineString(make)
|
|
templates['make'] = make or no_value
|
|
|
|
templates['callbacks'] = [
|
|
convert(cb_node.text) for cb_node in node.iterfind('callback')
|
|
] or no_value
|
|
|
|
return OrderedDict((key, value) for key, value in templates.items() if value is not no_value)
|
|
|
|
|
|
def convert_param_xml(node, convert):
|
|
param = OrderedDict()
|
|
param['id'] = node.findtext('key').strip()
|
|
param['label'] = node.findtext('name').strip()
|
|
param['category'] = node.findtext('tab') or no_value
|
|
|
|
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'))
|
|
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
|
|
|
|
attributes = defaultdict(yaml.ListFlowing)
|
|
for option_n in node.iterfind('option'):
|
|
for opt_n in option_n.iterfind('opt'):
|
|
key, value = opt_n.text.split(':', 2)
|
|
attributes[key].append(value)
|
|
param['option_attributes'] = dict(attributes) or no_value
|
|
|
|
param['hide'] = convert(node.findtext('hide')) or no_value
|
|
|
|
return OrderedDict((key, value) for key, value in param.items() if value is not no_value)
|
|
|
|
|
|
def convert_port_xml(node, convert):
|
|
port = OrderedDict()
|
|
label = node.findtext('name')
|
|
# default values:
|
|
port['label'] = label if label not in ('in', 'out') else no_value
|
|
|
|
dtype = convert(node.findtext('type'))
|
|
# TODO: detect dyn message ports
|
|
port['domain'] = domain = 'message' if dtype == 'message' else 'stream'
|
|
if domain == 'message':
|
|
port['id'], port['label'] = label, no_value
|
|
else:
|
|
port['dtype'] = dtype
|
|
vlen = node.findtext('vlen')
|
|
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
|
|
port['hide'] = convert(node.findtext('hide')) or no_value
|
|
|
|
return OrderedDict((key, value) for key, value in port.items() if value is not no_value)
|
|
|
|
|
|
def check_mako_template(block_id, expr):
|
|
import sys
|
|
from mako.template import Template
|
|
try:
|
|
Template(expr)
|
|
except Exception as error:
|
|
print(block_id, expr, type(error), error, '', sep='\n', file=sys.stderr)
|