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