Merged r9481:9518 on jblum/grc_reorganize into trunk. Reorganized grc source under...
[debian/gnuradio] / grc / src / platforms / base / 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 ... import utils
21 from ... utils import odict
22 from Element import Element
23
24 class Option(Element):
25
26         def __init__(self, param, name, key, opts):
27                 Element.__init__(self, param)
28                 self._name = name
29                 self._key = key
30                 self._opts = dict()
31                 for opt in opts:
32                         #separate the key:value
33                         try: key, value = opt.split(':')
34                         except: self._exit_with_error('Error separating "%s" into key:value'%opt)
35                         #test against repeated keys
36                         try: assert(not self._opts.has_key(key))
37                         except AssertionError: self._exit_with_error('Key "%s" already exists in option'%key)
38                         #store the option
39                         self._opts[key] = value
40
41         def __str__(self): return 'Option %s(%s)'%(self.get_name(), self.get_key())
42
43         def get_name(self): return self._name
44
45         def get_key(self): return self._key
46
47         ##############################################
48         # Access Opts
49         ##############################################
50         def get_opt_keys(self): return self._opts.keys()
51         def get_opt(self, key): return self._opts[key]
52         def get_opts(self): return self._opts.values()
53
54         ##############################################
55         ## Static Make Methods
56         ##############################################
57         def make_option_from_n(param, n):
58                 """
59                 Make a new option from nested data.
60                 @param param the parent element
61                 @param n the nested odict
62                 @return a new option
63                 """
64                 #grab the data
65                 name = n['name']
66                 key = n['key']
67                 opts = utils.listify(n, 'opt')
68                 #build the option
69                 return Option(
70                         param=param,
71                         name=name,
72                         key=key,
73                         opts=opts,
74                 )
75         make_option_from_n = staticmethod(make_option_from_n)
76
77 class Param(Element):
78
79         ##possible param types
80         TYPES = ['enum', 'raw']
81
82         def __init__(self, block, n):
83                 """
84                 Make a new param from nested data.
85                 @param block the parent element
86                 @param n the nested odict
87                 @return a new param
88                 """
89                 #grab the data
90                 name = n['name']
91                 key = n['key']
92                 value = utils.exists_or_else(n, 'value', '')
93                 type = n['type']
94                 hide = utils.exists_or_else(n, 'hide', '')
95                 options = utils.listify(n, 'option')
96                 #build the param
97                 Element.__init__(self, block)
98                 self._name = name
99                 self._key = key
100                 self._type = type
101                 self._hide = hide
102                 #create the Option objects from the n data
103                 self._options = odict()
104                 for option in map(lambda o: Option.make_option_from_n(self, o), options):
105                         key = option.get_key()
106                         #test against repeated keys
107                         try: assert(key not in self.get_option_keys())
108                         except AssertionError: self._exit_with_error('Key "%s" already exists in options'%key)
109                         #store the option
110                         self._options[key] = option
111                 #test the enum options
112                 if self._options or self.is_enum():
113                         #test against bad combos of type and enum
114                         try: assert(self._options)
115                         except AssertionError: self._exit_with_error('At least one option must exist when type "enum" is set.')
116                         try: assert(self.is_enum())
117                         except AssertionError: self._exit_with_error('Type "enum" must be set when options are present.')
118                         #test against options with identical keys
119                         try: assert(len(set(self.get_option_keys())) == len(self._options))
120                         except AssertionError: self._exit_with_error('Options keys "%s" are not unique.'%self.get_option_keys())
121                         #test against inconsistent keys in options
122                         opt_keys = self._options.values()[0].get_opt_keys()
123                         for option in self._options.values():
124                                 try: assert(set(opt_keys) == set(option.get_opt_keys()))
125                                 except AssertionError: self._exit_with_error('Opt keys "%s" are not identical across all options.'%opt_keys)
126                         #if a value is specified, it must be in the options keys
127                         self._value = value or self.get_option_keys()[0]
128                         try: assert(self.get_value() in self.get_option_keys())
129                         except AssertionError: self._exit_with_error('The value "%s" is not in the possible values of "%s".'%(self.get_value(), self.get_option_keys()))
130                 else: self._value = value or ''
131
132         def test(self):
133                 """
134                 call test on all children
135                 """
136                 map(lambda c: c.test(), self.get_options())
137
138         def validate(self):
139                 """
140                 Validate the param.
141                 The value must be evaluated and type must a possible type.
142                 """
143                 try:
144                         assert(self.get_type() in self.TYPES)
145                         try: self.evaluate()
146                         except:
147                                 #if the evaluate failed but added no error messages, add the generic one below
148                                 if not self.get_error_messages():
149                                         self._add_error_message('Value "%s" cannot be evaluated.'%self.get_value())
150                 except AssertionError: self._add_error_message('Type "%s" is not a possible type.'%self.get_type())
151
152         def evaluate(self):
153                 """
154                 Evaluate the value of this param.
155                 @throw NotImplementedError
156                 """
157                 raise NotImplementedError
158
159         def to_code(self):
160                 """
161                 Convert the value to code.
162                 @throw NotImplementedError
163                 """
164                 raise NotImplementedError
165
166         def __str__(self): return 'Param - %s(%s)'%(self.get_name(), self.get_key())
167
168         def is_param(self): return True
169
170         def get_name(self): return self._name
171
172         def get_key(self): return self._key
173
174         def get_hide(self): return self.get_parent().resolve_dependencies(self._hide)
175
176         def get_value(self):
177                 value = self._value
178                 if self.is_enum() and value not in self.get_option_keys():
179                         value = self.get_option_keys()[0]
180                         self.set_value(value)
181                 return value
182
183         def set_value(self, value):
184                 self.flag()
185                 self._value = str(value) #must be a string
186
187         def get_type(self): return self.get_parent().resolve_dependencies(self._type)
188
189         def is_enum(self): return self._type == 'enum'
190
191         def is_type_dependent(self): return '$' in self._type
192
193         ##############################################
194         # Access Options
195         ##############################################
196         def get_option_keys(self): return self._options.keys()
197         def get_option(self, key): return self._options[key]
198         def get_options(self): return self._options.values()
199
200         ##############################################
201         # Access Opts
202         ##############################################
203         def get_opt_keys(self): return self._options[self.get_value()].get_opt_keys()
204         def get_opt(self, key): return self._options[self.get_value()].get_opt(key)
205         def get_opts(self): return self._options[self.get_value()].get_opts()
206
207         ##############################################
208         ## Import/Export Methods
209         ##############################################
210         def export_data(self):
211                 """
212                 Export this param's key/value.
213                 @return a nested data odict
214                 """
215                 n = odict()
216                 n['key'] = self.get_key()
217                 n['value'] = self.get_value()
218                 return n