~flimm/epidermis/icon-theme-bugfix

« back to all changes in this revision

Viewing changes to epidermis/shell.py

  • Committer: David D Lowe
  • Date: 2011-01-04 22:50:19 UTC
  • Revision ID: daviddlowe.flimm@gmail.com-20110104225019-uo31kb54cbxjt5vt
Tidy up code with better comments.
Deleted unused functions.

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
from gettext import gettext as _
18
18
import subprocess
19
19
import dbus
 
20
import handy
20
21
 
21
22
DEBUG_SHELL = True
22
23
if not const.DEBUG:
23
24
    DEBUG_SHELL = False
24
25
 
25
26
def bash_prepare(string): 
26
 
    """Prepares a string for bash by surrounding it with single quotes.
 
27
    """Prepare a string for bash by surrounding it with single quotes.
 
28
    
 
29
    Returns the formatted string.
 
30
    
27
31
    >>> shell.bash_prepare("two'words")
28
32
    "'two'\\''words'"
 
33
    >>> print shell.bash_prepare("two'words")
 
34
    'two'\''words'
 
35
    
29
36
    """ 
30
37
    return "'" + string.replace("'", r"'\''") + "'"
31
38
 
32
39
class Shell():
33
40
    """An object which can run commands
34
 
    This is an "abstract" class, only its subclasses should be used"""
 
41
    This is an "abstract" class, only its subclasses should be used.
 
42
    
 
43
    """
35
44
    def __init__(self):
36
45
        self.ready = False
37
46
    
38
47
    def prepare(self):
39
 
        """Prepares the shell, may ask user for password if necessary"""
40
 
        return self.ready
 
48
        """Prepare the shell, asking user for authentication if necessary"""
 
49
        handy.abstract()
41
50
    
42
51
    def do(self, command, intrShell=False, cwd=None):
43
 
        """Runs the command in this shell.
44
 
        If intrShell is True, allows the shell to interpret special characters
45
 
        such as *
46
 
        cwd: the current directory for the command"""
47
 
        pass
 
52
        """Run the command in this shell.
 
53
        
 
54
        Keyword arguments:
 
55
        command -- a list of command arguments
 
56
        intrShell -- if True, allow the shell to interpret special 
 
57
                     characters such as *
 
58
        cwd -- the current directory for the command
 
59
        
 
60
        """
 
61
        handy.abstract()
48
62
    
49
63
    def set_out_file(self, outfile):
50
 
        """Sets the file where stdout output is put"""
51
 
        pass
 
64
        """Set the file object where stdout output is put"""
 
65
        handy.abstract()
52
66
    
53
67
    def exit(self):
54
 
        """Exits the shell"""
55
 
        self.ready = False
 
68
        """Exit the shell"""
 
69
        handy.abstract()
56
70
 
57
71
class RootShell(Shell):
58
72
    """A shell that runs commands as root. It will automatically use
92
106
    
93
107
 
94
108
class BashRootShell(Shell):
95
 
    """The Shell object which has access to a bash terminal run as root
 
109
    """The Shell object which has access to a bash terminal run as root.
96
110
    It uses pexpect, and it runs sudo bash -i"""
 
111
    
97
112
    def __init__(self, prompt="epidermisbash:"):
 
113
        """Initialise this instance.
 
114
        
 
115
        Keyword arguments:
 
116
        prompt -- the prompt line of the command line (string)
 
117
        
 
118
        """
98
119
        Shell.__init__(self)
99
120
        self.prompt = prompt
100
121
        self.outfile = os.tmpfile()
101
122
        self.gksubash, self.gksued = None, None
102
123
        self.spawn = None
103
124
        self.ready = False
104
 
        import handy
105
125
        self.gksubash = handy.get_data_file("gksubash.sh")
106
126
        self.gksued = handy.get_data_file("gksued.sh")
107
127
        if not os.path.exists(self.gksubash):
110
130
            raise(Exception("Cannot find gksued.sh"))
111
131
        
112
132
    def prepare(self):
113
 
        """Initializes the bash shell as root, will ask user for 
114
 
        password graphically if necessary
115
 
        Will raise a ShellNotReadyException if it fails to prepare itself
 
133
        """Initialise the bash shell as root, asking user for 
 
134
        password graphically if necessary using gksu.
 
135
        
 
136
        This function raises a ShellNotReadyException if it fails to 
 
137
        prepare itself.
 
138
        
116
139
        # Unfortunately, due to bug #244930, gksu cannot run bash -i correctly
117
140
        # This workaround uses sudo, but still asks for the password
118
141
        # graphically, if required
119
 
        # See bug: https://bugs.launchpad.net/ubuntu/+source/gksu/+bug/244930"""
 
142
        # See bug: https://bugs.launchpad.net/ubuntu/+source/gksu/+bug/244930
 
143
        
 
144
        """
120
145
        self.spawn = pexpect.spawn("sh", [self.gksubash, self.gksued])
121
146
        self.spawn.logfile = self.outfile
122
147
        res = self.spawn.expect(["EPIDERMIS_PASS", "EPIDERMIS_SUDO_RUN_SUCCESSFULLY", \
169
194
            return True
170
195
    
171
196
    def set_out_file(self, outfile):
172
 
        """sets where the bash should print to, by default, no where
173
 
        outfile: file like object"""
174
197
        if not self.spawn is None:
175
198
            Sfile = outfile
176
199
        self.outfile = outfile
177
200
    
178
201
    
179
202
    def do(self, command, intrShell=False, cwd=None, expectStr=None, expectNum=1 ):
180
 
        """Runs the command
181
 
        command: the command string as bash would expect, or a list of command
182
 
        arguments
183
 
        expectStr: the string to stop execution at, if not specified, Shell will
184
 
        stop at bash prompt
185
 
        cwd: the current directory for the command run
186
 
        expectNum: if expectStr is specified, this number indicates the number
187
 
        of times do must expect expectStr
188
 
        intrShell: if False, do will automatically prepare bash on each of the
189
 
        command's list's items. Currently has no effect if command is str"""
 
203
        """Run the command
 
204
        
 
205
        Keyword arguments:
 
206
        command -- a list of command arguments
 
207
        intrShell -- if False, do() will automatically bash_prepare on 
 
208
                     each of the command's list's items. Currently has 
 
209
                     no effect if command is str
 
210
        cwd -- the current directory for the command run (string)
 
211
        expectStr -- the string to stop execution at, if not specified, Shell will
 
212
                     stop at bash prompt
 
213
        expectNum -- if expectStr is specified, this number indicates the number
 
214
                     of times do() must expect expectStr
 
215
 
 
216
        
 
217
        """
190
218
        
191
219
        if not self.ready:
192
220
            raise(ShellNotReadyException())
234
262
            return False
235
263
    
236
264
    def exit(self):
237
 
        """exits the bash shell, terminates it if necessary"""
238
265
        if self.spawn.isalive():
239
266
            self.do("exit", expectStr="exit")
240
267
        
246
273
 
247
274
class PolicyKitShell(Shell):
248
275
    """An object which can run commands using a DBus service and 
249
 
    PolicyKit authentication"""
 
276
    PolicyKit authentication
 
277
    
 
278
    """
 
279
    
250
280
    def __init__(self):
251
281
        self.ready = False
252
282
        self.outFile, self.errFile = None, None
269
299
        self.errFile = errfile
270
300
    
271
301
    def do(self, command, intrShell=False, cwd=None):
272
 
        """Runs the command.
273
 
        command: can only be a list
274
 
        If intrShell is True, allows the shell to interpret special characters
275
 
        such as *
276
 
        cwd: current directory"""
 
302
        """Run the command.
 
303
        
 
304
        Keyword arguments:
 
305
        command -- can only be a list
 
306
        intrShell -- If intrShell is True, allows the shell to interpret
 
307
                     special characters such as *
 
308
        cwd -- current directory (string)
 
309
        
 
310
        """
277
311
        if not isinstance(command, list):
278
312
            raise(Exception("Not list"))
279
313
        global DEBUG_SHELL
308
342
        self.errFile = sys.stderr
309
343
    
310
344
    def prepare(self):
311
 
        """Prepares the shell"""
 
345
        """Prepare the shell"""
312
346
        self.ready = True
313
347
        self.outFile = sys.stdout
314
348
        return self.ready
315
349
    
316
350
    def do(self, command, intrShell=False, cwd=None):
317
 
        """Runs the command.
318
 
        command: can only be a list
319
 
        If intrShell is True, allows the shell to interpret special characters
320
 
        such as *
321
 
        cwd: current directory"""
322
351
        if not isinstance(command, list):
323
352
            raise(Exception("Not list"))
324
353
        global DEBUG_SHELL
348
377
        return "Shell has not been prepared"
349
378
 
350
379
def testshell():
351
 
    """A function that tries some of BashRootShell's and PolicyKitShell's
352
 
    functionality"""
 
380
    """Test some of BashRootShell's and PolicyKitShell's
 
381
    functionality
 
382
    
 
383
    """
353
384
    bashShell = BashRootShell()
354
385
    bashShell.set_out_file(sys.stdout)
355
386
    bashShell.prepare()
392
423
        print >> sys.stderr, "There is no __file__ variable. Please contact the author."
393
424
        sys.exit (1)
394
425
        raise(ee)
395
 
 
396
 
 
397
 
if __name__ == "__main__":
398
 
    print >> sys.stderr, "do not run"
399
 
    sys.exit(1)