~azzar1/unity/add-show-desktop-key

« back to all changes in this revision

Viewing changes to ivle/console.py

  • Committer: David Coles
  • Date: 2010-08-30 03:26:13 UTC
  • Revision ID: coles.david@gmail.com-20100830032613-d14vng0jkelniu3l
python-console: Fix globals broken with new JSON library.

simplejson always returns unicode strings. cJSON would return ordinary strings 
if possible. cPickle.loads() only accepts strings. At present we use pickle 
version 0 so they should all works as ASCII strings. Higher versions of pickle 
are not plain ASCII and are likely to break this and so this should be fixed 
at some point.

Also replaced unconditional exception with one that catches Pickle errors. Not 
sure the best way to report failures of these functions.

Show diffs side-by-side

added added

removed removed

Lines of Context:
30
30
import StringIO
31
31
import uuid
32
32
 
33
 
import cjson
34
 
 
35
 
from ivle import chat
 
33
from ivle import chat, interpret
36
34
 
37
35
class ConsoleError(Exception):
38
36
    """ The console failed in some way. This is bad. """
39
 
    def __init__(self, value):
40
 
        self.value = value
41
 
    def __str__(self):
42
 
        return repr(self.value)
 
37
    pass
43
38
 
44
39
class ConsoleException(Exception):
45
40
    """ The code being exectuted on the console returned an exception. 
46
41
    """
47
 
    def __init__(self, value):
48
 
        self.value = value
49
 
    def __str__(self):
50
 
        return repr(self.value)
 
42
    pass
51
43
 
52
44
class TruncateStringIO(StringIO.StringIO):
53
45
    """ A class that wraps around StringIO and truncates the buffer when the 
114
106
class Console(object):
115
107
    """ Provides a nice python interface to the console
116
108
    """
117
 
    def __init__(self, config, uid, jail_path, working_dir):
 
109
    def __init__(self, config, user, jail_path, working_dir):
118
110
        """Starts up a console service for user uid, inside chroot jail 
119
111
        jail_path with work directory of working_dir
120
112
        """
121
113
        super(Console, self).__init__()
122
114
 
123
115
        self.config = config
124
 
        self.uid = uid
 
116
        self.user = user
125
117
        self.jail_path = jail_path
126
118
        self.working_dir = working_dir
127
119
 
158
150
        # is (k / N) ** t (e.g. 3.2*10e-9).
159
151
 
160
152
        tries = 0
 
153
        error = None
161
154
        while tries < 5:
162
155
            self.port = int(random.uniform(3000, 8000))
163
156
 
164
 
            trampoline_path = os.path.join(self.config['paths']['lib'],
165
 
                                           "trampoline")
166
 
 
167
 
            # Start the console server (port, magic)
168
 
            # trampoline usage: tramp uid jail_dir working_dir script_path args
169
 
            # console usage:    python-console port magic
170
 
            res = os.spawnv(os.P_WAIT, trampoline_path, [
171
 
                trampoline_path,
172
 
                str(self.uid),
173
 
                self.config['paths']['jails']['mounts'],
174
 
                self.config['paths']['jails']['src'],
175
 
                self.config['paths']['jails']['template'],
176
 
                self.jail_path,
177
 
                os.path.join(self.config['paths']['share'], 'services'),
178
 
                "/usr/bin/python",
179
 
                os.path.join(self.config['paths']['share'],
180
 
                             'services/python-console'),
181
 
                str(self.port),
182
 
                str(self.magic),
183
 
                self.working_dir
184
 
                ])
185
 
 
186
 
            if res == 0:
 
157
            python_console = os.path.join(self.config['paths']['share'],
 
158
                        'services/python-console')
 
159
            args = [python_console, str(self.port), str(self.magic)]
 
160
 
 
161
            try:
 
162
                interpret.execute_raw(self.config, self.user, self.jail_path,
 
163
                        self.working_dir, "/usr/bin/python", args)
187
164
                # success
188
 
                break;
189
 
 
190
 
            tries += 1
191
 
 
192
 
        # If we can't start the console after 5 attemps (can't find a free port 
193
 
        # during random probing, syntax errors, segfaults) throw an exception.
 
165
                break
 
166
            except interpret.ExecutionError, e:
 
167
                tries += 1
 
168
                error = e.message
 
169
 
 
170
        # If we can't start the console after 5 attemps (can't find a free 
 
171
        # port during random probing, syntax errors, segfaults) throw an 
 
172
        # exception.
194
173
        if tries == 5:
195
 
            raise ConsoleError("Unable to start console service!")
 
174
            raise ConsoleError('Unable to start console service: %s'%error)
196
175
 
197
176
    def __chat(self, cmd, args):
198
177
        """ A wrapper around chat.chat to comunicate directly with the 
209
188
            else:
210
189
                # Some other error - probably serious
211
190
                raise socket.error, (enumber, estring)
212
 
        except cjson.DecodeError:
 
191
        except ValueError:
213
192
            # Couldn't decode the JSON
214
193
            raise ConsoleError(
215
194
                "Could not understand the python console response")
 
195
        except chat.ProtocolError, e:
 
196
            raise ConsoleError(*e.args)
216
197
 
217
198
        return response
218
199
 
266
247
 
267
248
        # Unpickle the globals
268
249
        for g in globals['globals']:
269
 
            globals['globals'][g] = cPickle.loads(globals['globals'][g])
 
250
            globals['globals'][g] = cPickle.loads(str(globals['globals'][g]))
270
251
 
271
252
        return globals['globals']
272
253
        
285
266
        # Unpickle any exceptions
286
267
        if 'exception' in call:
287
268
            call['exception']['except'] = \
288
 
                cPickle.loads(call['exception']['except'])
 
269
                cPickle.loads(str(call['exception']['except']))
289
270
 
290
271
        return call
291
272
 
297
278
              
298
279
        # Unpickle any exceptions
299
280
        if 'exception' in execute:
300
 
            return cPickle.loads(execute['exception'])
301
 
        else:
302
 
            return execute
 
281
            execute['exception'] = cPickle.loads(str(execute['exception']))
 
282
        return execute
303
283
 
304
284
 
305
285
    def set_vars(self, variables):