summaryrefslogtreecommitdiff
path: root/grc/core/Param.py
diff options
context:
space:
mode:
Diffstat (limited to 'grc/core/Param.py')
-rw-r--r--grc/core/Param.py413
1 files changed, 0 insertions, 413 deletions
diff --git a/grc/core/Param.py b/grc/core/Param.py
deleted file mode 100644
index 56855908ea..0000000000
--- a/grc/core/Param.py
+++ /dev/null
@@ -1,413 +0,0 @@
-"""
-Copyright 2008-2015 Free Software Foundation, Inc.
-This file is part of GNU Radio
-
-GNU Radio Companion is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-GNU Radio Companion is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
-"""
-
-from __future__ import absolute_import
-
-import ast
-import numbers
-import re
-import collections
-
-import six
-from six.moves import builtins, filter, map, range, zip
-
-from . import Constants, blocks
-from .base import Element
-from .utils.descriptors import Evaluated, EvaluatedEnum, setup_names
-
-# Blacklist certain ids, its not complete, but should help
-ID_BLACKLIST = ['self', 'options', 'gr', 'math', 'firdes'] + dir(builtins)
-try:
- from gnuradio import gr
- ID_BLACKLIST.extend(attr for attr in dir(gr.top_block()) if not attr.startswith('_'))
-except (ImportError, AttributeError):
- pass
-
-
-class TemplateArg(str):
- """
- A cheetah template argument created from a param.
- The str of this class evaluates to the param's to code method.
- The use of this class as a dictionary (enum only) will reveal the enum opts.
- The __call__ or () method can return the param evaluated to a raw python data type.
- """
-
- def __new__(cls, param):
- value = param.to_code()
- instance = str.__new__(cls, value)
- setattr(instance, '_param', param)
- return instance
-
- def __getitem__(self, item):
- return str(self._param.get_opt(item)) if self._param.is_enum() else NotImplemented
-
- def __getattr__(self, item):
- if not self._param.is_enum():
- raise AttributeError()
- try:
- return str(self._param.get_opt(item))
- except KeyError:
- raise AttributeError()
-
- def __str__(self):
- return str(self._param.to_code())
-
- def __call__(self):
- return self._param.get_evaluated()
-
-
-@setup_names
-class Param(Element):
-
- is_param = True
-
- name = Evaluated(str, default='no name')
- dtype = EvaluatedEnum(Constants.PARAM_TYPE_NAMES, default='raw')
- hide = EvaluatedEnum('none all part')
-
- # region init
- def __init__(self, parent, id, label='', dtype='raw', default='',
- options=None, option_labels=None, option_attributes=None,
- category='', hide='none', **_):
- """Make a new param from nested data"""
- super(Param, self).__init__(parent)
- self.key = id
- self.name = label.strip() or id.title()
- self.category = category or Constants.DEFAULT_PARAM_TAB
-
- self.dtype = dtype
- self.value = self.default = str(default)
-
- self.options = self._init_options(options or [], option_labels or [],
- option_attributes or {})
- self.hide = hide or 'none'
- # end of args ########################################################
-
- self._evaluated = None
- self._stringify_flag = False
- self._lisitify_flag = False
- self._init = False
-
- @property
- def template_arg(self):
- return TemplateArg(self)
-
- def _init_options(self, values, labels, attributes):
- """parse option and option attributes"""
- options = collections.OrderedDict()
- options.attributes = collections.defaultdict(dict)
-
- padding = [''] * max(len(values), len(labels))
- attributes = {key: value + padding for key, value in six.iteritems(attributes)}
-
- for i, option in enumerate(values):
- # Test against repeated keys
- if option in options:
- raise KeyError('Value "{}" already exists in options'.format(option))
- # get label
- try:
- label = str(labels[i])
- except IndexError:
- label = str(option)
- # Store the option
- options[option] = label
- options.attributes[option] = {attrib: values[i] for attrib, values in six.iteritems(attributes)}
-
- default = next(iter(options)) if options else ''
- if not self.value:
- self.value = self.default = default
-
- if self.is_enum() and self.value not in options:
- self.value = self.default = default # TODO: warn
- # raise ValueError('The value {!r} is not in the possible values of {}.'
- # ''.format(self.get_value(), ', '.join(self.options)))
- return options
- # endregion
-
- def __str__(self):
- return 'Param - {}({})'.format(self.name, self.key)
-
- def __repr__(self):
- return '{!r}.param[{}]'.format(self.parent, self.key)
-
- def is_enum(self):
- return self.get_raw('dtype') == 'enum'
-
- def get_value(self):
- value = self.value
- if self.is_enum() and value not in self.options:
- value = self.default
- self.set_value(value)
- return value
-
- def set_value(self, value):
- # Must be a string
- self.value = str(value)
-
- def set_default(self, value):
- if self.default == self.value:
- self.set_value(value)
- self.default = str(value)
-
- def rewrite(self):
- Element.rewrite(self)
- del self.name
- del self.dtype
- del self.hide
-
- self._evaluated = None
- try:
- self._evaluated = self.evaluate()
- except Exception as e:
- self.add_error_message(str(e))
-
- def validate(self):
- """
- Validate the param.
- The value must be evaluated and type must a possible type.
- """
- 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))
-
- def get_evaluated(self):
- return self._evaluated
-
- def evaluate(self):
- """
- Evaluate the value.
-
- Returns:
- evaluated type
- """
- self._init = True
- self._lisitify_flag = False
- self._stringify_flag = False
- dtype = self.dtype
- expr = self.get_value()
-
- #########################
- # Enum Type
- #########################
- if self.is_enum():
- return expr
-
- #########################
- # Numeric Types
- #########################
- elif dtype in ('raw', 'complex', 'real', 'float', 'int', 'hex', 'bool'):
- # Raise exception if python cannot evaluate this value
- try:
- value = self.parent_flowgraph.evaluate(expr)
- except Exception as value:
- raise Exception('Value "{}" cannot be evaluated:\n{}'.format(expr, value))
- # Raise an exception if the data is invalid
- if dtype == 'raw':
- return value
- elif dtype == 'complex':
- if not isinstance(value, Constants.COMPLEX_TYPES):
- raise Exception('Expression "{}" is invalid for type complex.'.format(str(value)))
- return value
- elif dtype in ('real', 'float'):
- if not isinstance(value, Constants.REAL_TYPES):
- raise Exception('Expression "{}" is invalid for type float.'.format(str(value)))
- return value
- elif dtype == 'int':
- if not isinstance(value, Constants.INT_TYPES):
- raise Exception('Expression "{}" is invalid for type integer.'.format(str(value)))
- return value
- elif dtype == 'hex':
- return hex(value)
- elif dtype == 'bool':
- if not isinstance(value, bool):
- raise Exception('Expression "{}" is invalid for type bool.'.format(str(value)))
- return value
- else:
- raise TypeError('Type "{}" not handled'.format(dtype))
- #########################
- # Numeric Vector Types
- #########################
- elif dtype in ('complex_vector', 'real_vector', 'float_vector', 'int_vector'):
- default = []
-
- if not expr:
- return default # Turn a blank string into an empty list, so it will eval
-
- try:
- value = self.parent.parent.evaluate(expr)
- except Exception as value:
- raise Exception('Value "{}" cannot be evaluated:\n{}'.format(expr, value))
-
- if not isinstance(value, Constants.VECTOR_TYPES):
- self._lisitify_flag = True
- value = [value]
-
- # Raise an exception if the data is invalid
- if dtype == 'complex_vector' and not all(isinstance(item, numbers.Complex) for item in value):
- raise Exception('Expression "{}" is invalid for type complex vector.'.format(value))
- elif dtype in ('real_vector', 'float_vector') and not all(isinstance(item, numbers.Real) for item in value):
- raise Exception('Expression "{}" is invalid for type float vector.'.format(value))
- elif dtype == 'int_vector' and not all(isinstance(item, Constants.INT_TYPES) for item in value):
- raise Exception('Expression "{}" is invalid for type integer vector.'.format(str(value)))
- return value
- #########################
- # String Types
- #########################
- elif dtype in ('string', 'file_open', 'file_save', '_multiline', '_multiline_python_external'):
- # Do not check if file/directory exists, that is a runtime issue
- try:
- value = self.parent.parent.evaluate(expr)
- if not isinstance(value, str):
- raise Exception()
- except:
- self._stringify_flag = True
- value = str(expr)
- if dtype == '_multiline_python_external':
- ast.parse(value) # Raises SyntaxError
- return value
- #########################
- # Unique ID Type
- #########################
- elif dtype == 'id':
- self.validate_block_id()
- return expr
-
- #########################
- # Stream ID Type
- #########################
- elif dtype == 'stream_id':
- self.validate_stream_id()
- return expr
-
- #########################
- # GUI Position/Hint
- #########################
- elif dtype == 'gui_hint':
- if ':' in expr:
- tab, pos = expr.split(':')
- elif '@' in expr:
- tab, pos = expr, ''
- else:
- tab, pos = '', expr
-
- if '@' in tab:
- tab, index = tab.split('@')
- else:
- index = '?'
-
- # TODO: Problem with this code. Produces bad tabs
- widget_str = ({
- (True, True): 'self.%(tab)s_grid_layout_%(index)s.addWidget(%(widget)s, %(pos)s)',
- (True, False): 'self.%(tab)s_layout_%(index)s.addWidget(%(widget)s)',
- (False, True): 'self.top_grid_layout.addWidget(%(widget)s, %(pos)s)',
- (False, False): 'self.top_layout.addWidget(%(widget)s)',
- }[bool(tab), bool(pos)]) % {'tab': tab, 'index': index, 'widget': '%s', 'pos': pos}
-
- # FIXME: Move replace(...) into the make template of the qtgui blocks
- # Return a string here
- class GuiHint(object):
- def __init__(self, ws):
- self._ws = ws
-
- def __call__(self, w):
- return (self._ws.replace('addWidget', 'addLayout') if 'layout' in w else self._ws) % w
-
- def __str__(self):
- return self._ws
- return GuiHint(widget_str)
- #########################
- # Import Type
- #########################
- elif dtype == 'import':
- # New namespace
- n = dict()
- try:
- exec(expr, n)
- except ImportError:
- raise Exception('Import "{}" failed.'.format(expr))
- except Exception:
- raise Exception('Bad import syntax: "{}".'.format(expr))
- return [k for k in list(n.keys()) if str(k) != '__builtins__']
-
- #########################
- else:
- raise TypeError('Type "{}" not handled'.format(dtype))
-
- def validate_block_id(self):
- value = self.value
- # Can python use this as a variable?
- if not re.match(r'^[a-z|A-Z]\w*$', value):
- raise Exception('ID "{}" must begin with a letter and may contain letters, numbers, '
- 'and underscores.'.format(value))
- if value in ID_BLACKLIST:
- raise Exception('ID "{}" is blacklisted.'.format(value))
- block_names = [block.name for block in self.parent_flowgraph.iter_enabled_blocks()]
- # Id should only appear once, or zero times if block is disabled
- if self.key == 'id' and block_names.count(value) > 1:
- raise Exception('ID "{}" is not unique.'.format(value))
- elif value not in block_names:
- raise Exception('ID "{}" does not exist.'.format(value))
- return value
-
- def validate_stream_id(self):
- value = self.value
- stream_ids = [
- block.params['stream_id'].value
- for block in self.parent_flowgraph.iter_enabled_blocks()
- if isinstance(block, blocks.VirtualSink)
- ]
- # Check that the virtual sink's stream id is unique
- if isinstance(self.parent_block, blocks.VirtualSink) and stream_ids.count(value) >= 2:
- # Id should only appear once, or zero times if block is disabled
- raise Exception('Stream ID "{}" is not unique.'.format(value))
- # Check that the virtual source's steam id is found
- elif isinstance(self.parent_block, blocks.VirtualSource) and value not in stream_ids:
- raise Exception('Stream ID "{}" is not found.'.format(value))
-
- def to_code(self):
- """
- Convert the value to code.
- For string and list types, check the init flag, call evaluate().
- This ensures that evaluate() was called to set the xxxify_flags.
-
- Returns:
- a string representing the code
- """
- self._init = True
- v = self.get_value()
- t = self.dtype
- # String types
- if t in ('string', 'file_open', 'file_save', '_multiline', '_multiline_python_external'):
- if not self._init:
- self.evaluate()
- return repr(v) if self._stringify_flag else v
-
- # Vector types
- elif t in ('complex_vector', 'real_vector', 'float_vector', 'int_vector'):
- if not self._init:
- self.evaluate()
- if self._lisitify_flag:
- return '(%s, )' % v
- else:
- return '(%s)' % v
- else:
- return v
-
- def get_opt(self, item):
- return self.options.attributes[self.get_value()][item]