1f5b967a6eec924102da8afafed7418f6960b812
[debian/gnuradio] / grc / src / grc_gnuradio / Param.py
1 """
2 Copyright 2008 Free Software Foundation, Inc.
3 This file is part of GNU Radio
4
5 GNU Radio Companion is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
9
10 GNU Radio Companion is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
18 """
19 ##@package grc_gnuradio.Param
20 #Flow graph block parameters.
21
22 from utils import expr_utils
23 from grc.elements.Param import Param as _Param
24 import os
25
26 class Param(_Param):
27
28         _init = False
29         _hostage_cells = list()
30
31         ##possible param types
32         TYPES = _Param.TYPES + [
33                 'complex', 'real', 'int',
34                 'complex_vector', 'real_vector', 'int_vector',
35                 'hex', 'string',
36                 'file_open', 'file_save',
37                 'id',
38                 'grid_pos', 'import',
39         ]
40
41         def get_hide(self):
42                 """!
43                 Get the hide value from the base class.
44                 If hide was empty, and this is a type controller, set hide to part.
45                 If hide was empty, and this is an id of a non variable, set hide to part.
46                 @return hide the hide property string
47                 """
48                 hide = _Param.get_hide(self)
49                 #hide IO controlling params
50                 if not hide and self.get_key() in (
51                         'type', 'vlen', 'num_inputs', 'num_outputs'
52                 ): hide = 'part'
53                 #hide ID in non variable blocks
54                 elif not hide and self.get_key() == 'id' and self.get_parent().get_key() not in (
55                         'variable', 'variable_slider', 'variable_chooser', 'variable_text_box', 'parameter', 'options'
56                 ): hide = 'part'
57                 return hide
58
59         def evaluate(self):
60                 """!
61                 Evaluate the value.
62                 @return evaluated type
63                 """
64                 self._lisitify_flag = False
65                 self._stringify_flag = False
66                 self._hostage_cells = list()
67                 def eval_string(v):
68                         try:
69                                 e = self.get_parent().get_parent().evaluate(v)
70                                 assert(isinstance(e, str))
71                                 return e
72                         except:
73                                 self._stringify_flag = True
74                                 return v
75                 t = self.get_type()
76                 v = self.get_value()
77                 #########################
78                 # Enum Type
79                 #########################
80                 if self.is_enum(): return self.get_value()
81                 #########################
82                 # Numeric Types
83                 #########################
84                 elif t in ('raw', 'complex', 'real', 'int', 'complex_vector', 'real_vector', 'int_vector', 'hex'):
85                         #raise exception if python cannot evaluate this value
86                         try: e = self.get_parent().get_parent().evaluate(v)
87                         except:
88                                 self._add_error_message('Value "%s" cannot be evaluated.'%v)
89                                 raise Exception
90                         #raise an exception if the data is invalid
91                         if t == 'raw': return e
92                         elif t == 'complex':
93                                 try: assert(isinstance(e, (complex, float, int, long)))
94                                 except AssertionError:
95                                         self._add_error_message('Expression "%s" is invalid for type complex.'%str(e))
96                                         raise Exception
97                                 return e
98                         elif t == 'real':
99                                 try: assert(isinstance(e, (float, int, long)))
100                                 except AssertionError:
101                                         self._add_error_message('Expression "%s" is invalid for type real.'%str(e))
102                                         raise Exception
103                                 return e
104                         elif t == 'int':
105                                 try: assert(isinstance(e, (int, long)))
106                                 except AssertionError:
107                                         self._add_error_message('Expression "%s" is invalid for type integer.'%str(e))
108                                         raise Exception
109                                 return e
110                         elif t == 'complex_vector':
111                                 if not isinstance(e, (tuple, list, set)):
112                                         self._lisitify_flag = True
113                                         e = [e]
114                                 try:
115                                         for ei in e:
116                                                 assert(isinstance(ei, (complex, float, int, long)))
117                                 except AssertionError:
118                                         self._add_error_message('Expression "%s" is invalid for type complex vector.'%str(e))
119                                         raise Exception
120                                 return e
121                         elif t == 'real_vector':
122                                 if not isinstance(e, (tuple, list, set)):
123                                         self._lisitify_flag = True
124                                         e = [e]
125                                 try:
126                                         for ei in e:
127                                                 assert(isinstance(ei, (float, int, long)))
128                                 except AssertionError:
129                                         self._add_error_message('Expression "%s" is invalid for type real vector.'%str(e))
130                                         raise Exception
131                                 return e
132                         elif t == 'int_vector':
133                                 if not isinstance(e, (tuple, list, set)):
134                                         self._lisitify_flag = True
135                                         e = [e]
136                                 try:
137                                         for ei in e:
138                                                 assert(isinstance(ei, (int, long)))
139                                 except AssertionError:
140                                         self._add_error_message('Expression "%s" is invalid for type integer vector.'%str(e))
141                                         raise Exception
142                                 return e
143                         elif t == 'hex':
144                                 return hex(e)
145                         else: raise TypeError, 'Type "%s" not handled'%t
146                 #########################
147                 # String Types
148                 #########################
149                 elif t in ('string', 'file_open', 'file_save'):
150                         #do not check if file/directory exists, that is a runtime issue
151                         e = eval_string(v)
152                         return str(e)
153                 #########################
154                 # Unique ID Type
155                 #########################
156                 elif t == 'id':
157                         #can python use this as a variable?
158                         try:
159                                 assert(len(v) > 0)
160                                 assert(v[0].isalpha())
161                                 for c in v: assert(c.isalnum() or c in ('_',))
162                         except AssertionError:
163                                 self._add_error_message('ID "%s" must be alpha-numeric or underscored, and begin with a letter.'%v)
164                                 raise Exception
165                         params = self.get_all_params('id')
166                         keys = [param.get_value() for param in params]
167                         try: assert(len(keys) == len(set(keys)))
168                         except:
169                                 self._add_error_message('ID "%s" is not unique.'%v)
170                                 raise Exception
171                         return v
172                 #########################
173                 # Grid Position Type
174                 #########################
175                 elif t == 'grid_pos':
176                         if not v: return '' #allow for empty grid pos
177                         e = self.get_parent().get_parent().evaluate(v)
178                         try:
179                                 assert(isinstance(e, (list, tuple)) and len(e) == 4)
180                                 for ei in e: assert(isinstance(ei, int))
181                         except AssertionError:
182                                 self._add_error_message('A grid position must be a list of 4 integers.')
183                                 raise Exception
184                         row, col, row_span, col_span = e
185                         #check row, col
186                         try: assert(row >= 0 and col >= 0)
187                         except AssertionError:
188                                 self._add_error_message('Row and column must be non-negative.')
189                                 raise Exception
190                         #check row span, col span
191                         try: assert(row_span > 0 and col_span > 0)
192                         except AssertionError:
193                                 self._add_error_message('Row and column span must be greater than zero.')
194                                 raise Exception
195                         #calculate hostage cells
196                         for r in range(row_span):
197                                 for c in range(col_span):
198                                         self._hostage_cells.append((row+r, col+c))
199                         #avoid collisions
200                         params = filter(lambda p: p is not self, self.get_all_params('grid_pos'))
201                         for param in params:
202                                 for cell in param._hostage_cells:
203                                         if cell in self._hostage_cells:
204                                                 self._add_error_message('Another graphical element is using cell "%s".'%str(cell))
205                                                 raise Exception
206                         return e
207                 #########################
208                 # Import Type
209                 #########################
210                 elif t == 'import':
211                         n = dict() #new namespace
212                         try: exec v in n
213                         except ImportError:
214                                 self._add_error_message('Import "%s" failed.'%v)
215                                 raise Exception
216                         except Exception:
217                                 self._add_error_message('Bad import syntax: "%s".'%v)
218                                 raise Exception
219                         return filter(lambda k: str(k) != '__builtins__', n.keys())
220                 #########################
221                 else: raise TypeError, 'Type "%s" not handled'%t
222
223         def to_code(self):
224                 """!
225                 Convert the value to code.
226                 @return a string representing the code
227                 """
228                 #run init tasks in evaluate
229                 #such as setting flags
230                 if not self._init:
231                         self.evaluate()
232                         self._init = True
233                 v = self.get_value()
234                 t = self.get_type()
235                 if t in ('string', 'file_open', 'file_save'): #string types
236                         if self._stringify_flag:
237                                 return '"%s"'%v.replace('"', '\"')
238                         else:
239                                 return v
240                 elif t in ('complex_vector', 'real_vector', 'int_vector'): #vector types
241                         if self._lisitify_flag:
242                                 return '(%s, )'%v
243                         else:
244                                 return '(%s)'%v
245                 else:
246                         return v
247
248         def get_all_params(self, type):
249                 """!
250                 Get all the params from the flowgraph that have the given type.
251                 @param type the specified type
252                 @return a list of params
253                 """
254                 return sum([filter(lambda p: p.get_type() == type, block.get_params()) for block in self.get_parent().get_parent().get_blocks()], [])
255