6693f6f86bbaa6d35a18ee611d34ce3a22bf8177
[debian/gnuradio] / grc / python / Block.py
1 """
2 Copyright 2008, 2009 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 .. base.Block import Block as _Block
21 import extract_docs
22 import extract_category
23
24 class Block(_Block):
25
26         ##for make source to keep track of indexes
27         _source_count = 0
28         ##for make sink to keep track of indexes
29         _sink_count = 0
30
31         def __init__(self, flow_graph, n):
32                 """
33                 Make a new block from nested data.
34                 @param flow graph the parent element
35                 @param n the nested odict
36                 @return block a new block
37                 """
38                 #grab the data
39                 self._doc = n.find('doc') or ''
40                 self._imports = map(lambda i: i.strip(), n.findall('import'))
41                 self._make = n.find('make')
42                 self._var_make = n.find('var_make')
43                 self._checks = n.findall('check')
44                 self._callbacks = n.findall('callback')
45                 #build the block
46                 _Block.__init__(
47                         self,
48                         flow_graph=flow_graph,
49                         n=n,
50                 )
51
52         def validate(self):
53                 """
54                 Validate this block.
55                 Call the base class validate.
56                 Evaluate the checks: each check must evaluate to True.
57                 Adjust the nports.
58                 """
59                 _Block.validate(self)
60                 #evaluate the checks
61                 for check in self._checks:
62                         check_res = self.resolve_dependencies(check)
63                         try:
64                                 check_eval = self.get_parent().evaluate(check_res)
65                                 try: assert check_eval
66                                 except AssertionError: self.add_error_message('Check "%s" failed.'%check)
67                         except: self.add_error_message('Check "%s" did not evaluate.'%check)
68                 #adjust nports
69                 for ports, Port in (
70                         (self._sources, self.get_parent().get_parent().Source),
71                         (self._sinks, self.get_parent().get_parent().Sink),
72                 ):
73                         #TODO #FIXME we want to filter out msg ports and run the regular code below this line
74                         if any([port.get_type() == 'msg' for port in ports.values()]): continue
75                         #how many ports?
76                         num_ports = len(ports)
77                         #do nothing for 0 ports
78                         if not num_ports: continue
79                         #get the nports setting
80                         port0 = ports[str(0)]
81                         nports = port0.get_nports()
82                         #do nothing for no nports
83                         if not nports: continue
84                         #do nothing if nports is already num ports
85                         if nports == num_ports: continue
86                         #remove excess ports and connections
87                         if nports < num_ports:
88                                 #remove the connections
89                                 for key in map(str, range(nports, num_ports)):
90                                         port = ports[key]
91                                         for connection in port.get_connections():
92                                                 self.get_parent().remove_element(connection)
93                                 #remove the ports
94                                 for key in map(str, range(nports, num_ports)): ports.pop(key)
95                                 continue
96                         #add more ports
97                         if nports > num_ports:
98                                 for key in map(str, range(num_ports, nports)):
99                                         n = port0._n
100                                         n['key'] = key
101                                         port = Port(self, n)
102                                         ports[key] = port
103                                 continue
104
105         def port_controller_modify(self, direction):
106                 """
107                 Change the port controller.
108                 @param direction +1 or -1
109                 @return true for change
110                 """
111                 changed = False
112                 #concat the nports string from the private nports settings of both port0
113                 nports_str = \
114                         (self.get_sinks() and self.get_sinks()[0]._nports or '') + \
115                         (self.get_sources() and self.get_sources()[0]._nports or '')
116                 #modify all params whose keys appear in the nports string
117                 for param in self.get_params():
118                         if param.is_enum() or param.get_key() not in nports_str: continue
119                         #try to increment the port controller by direction
120                         try:
121                                 value = param.get_evaluated()
122                                 value = value + direction
123                                 assert 0 < value
124                                 param.set_value(value)
125                                 changed = True
126                         except: pass
127                 return changed
128
129         def get_doc(self):
130                 doc = self._doc.strip('\n').replace('\\\n', '')
131                 #merge custom doc with doxygen docs
132                 return '\n'.join([doc, extract_docs.extract(self.get_key())]).strip('\n')
133
134         def get_category(self):
135                 category = extract_category.extract(self.get_key())
136                 #if category: return category
137                 return _Block.get_category(self)
138
139         def get_imports(self):
140                 """
141                 Resolve all import statements.
142                 Split each import statement at newlines.
143                 Combine all import statments into a list.
144                 Filter empty imports.
145                 @return a list of import statements
146                 """
147                 return filter(lambda i: i, sum(map(lambda i: self.resolve_dependencies(i).split('\n'), self._imports), []))
148
149         def get_make(self): return self.resolve_dependencies(self._make)
150         def get_var_make(self): return self.resolve_dependencies(self._var_make)
151
152         def get_callbacks(self):
153                 """
154                 Get a list of function callbacks for this block.
155                 @return a list of strings
156                 """
157                 def make_callback(callback):
158                         callback = self.resolve_dependencies(callback)
159                         if 'self.' in callback: return callback
160                         return 'self.%s.%s'%(self.get_id(), callback)
161                 return map(make_callback, self._callbacks)