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

« back to all changes in this revision

Viewing changes to ivle/testfilespace.py

  • Committer: William Grant
  • Date: 2009-05-26 02:10:08 UTC
  • Revision ID: grantw@unimelb.edu.au-20090526021008-hnka598yacu5w6da
Always set isdir = False in the file browser template filling.

Previously we used os.path.isdir outside the jail, which was terribly
unreliable and prone to crashing. We should do it properly once we can get
server-side access to the jails.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# IVLE - Informatics Virtual Learning Environment
 
2
# Copyright (C) 2007-2008 The University of Melbourne
 
3
#
 
4
# This program is free software; you can redistribute it and/or modify
 
5
# it under the terms of the GNU General Public License as published by
 
6
# the Free Software Foundation; either version 2 of the License, or
 
7
# (at your option) any later version.
 
8
#
 
9
# This program is distributed in the hope that it will be useful,
 
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
# GNU General Public License for more details.
 
13
#
 
14
# You should have received a copy of the GNU General Public License
 
15
# along with this program; if not, write to the Free Software
 
16
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
17
 
 
18
# Module: TestFilespace
 
19
# Author: Dilshan Angampitiya
 
20
#         Steven Bird (revisions)
 
21
#         David Coles (revisions and moved to module)
 
22
# Date:   24/1/2008
 
23
 
 
24
import StringIO
 
25
 
 
26
class TestFilespace:
 
27
    """
 
28
    Our dummy file system which is accessed by code being tested.
 
29
    Implemented as a dictionary which maps filenames to strings
 
30
    """
 
31
    def __init__(self, files=None):
 
32
        "Initialise, optionally with filename-filedata pairs"
 
33
 
 
34
        if files == None:
 
35
            files = {}
 
36
 
 
37
        # dict mapping files to strings
 
38
        self._files = {}
 
39
        self._files.update(files)
 
40
        # set of file names
 
41
        self._modified_files = set([])
 
42
        # dict mapping files to stringIO objects
 
43
        self._open_files = {}
 
44
 
 
45
    def add_file(self, filename, data):
 
46
        " Add a file to the filespace "
 
47
        self._files[filename] = data
 
48
 
 
49
    def openfile(self, filename, mode='r'):
 
50
        """ Open a file from the filespace with the given mode.
 
51
        Return a StringIO subclass object with the file contents.
 
52
        """
 
53
        # currently very messy, needs to be cleaned up
 
54
        # Probably most of this should be in the initialiser to the TestStringIO
 
55
        
 
56
        import re
 
57
 
 
58
        if filename in self._open_files:
 
59
            raise IOError("File already open: %s" %filename)
 
60
 
 
61
        if not re.compile("[rwa][+b]{0,2}").match(mode):
 
62
            raise IOError("invalid mode %s" %mode)
 
63
        
 
64
        ## TODO: validate filename?
 
65
        
 
66
        mode.replace("b",'')
 
67
        
 
68
        # initialise the file properly (truncate/create if required)
 
69
        if mode[0] == 'w':
 
70
            self._files[filename] = ''
 
71
            self._modified_files.add(filename)
 
72
        elif filename not in self._files:
 
73
            if mode[0] == 'a':
 
74
                self._files[filename] = ''
 
75
                self._modified_files.add(filename)
 
76
            else:
 
77
                raise IOError(2, "Access to file denied: %s" %filename)
 
78
 
 
79
        # for append mode, remember the existing data
 
80
        if mode[0] == 'a':
 
81
            existing_data = self._files[filename]
 
82
        else:
 
83
            existing_data = ""
 
84
 
 
85
        # determine what operations are allowed
 
86
        reading_ok = (len(mode) == 2 or mode[0] == 'r')
 
87
        writing_ok = (len(mode) == 2 or mode[0] in 'wa')
 
88
 
 
89
        # for all writing modes, start off with blank file
 
90
        if mode[0] == 'w':
 
91
            initial_data = ''
 
92
        else:
 
93
            initial_data = self._files[filename]
 
94
 
 
95
        file_object = TestStringIO(initial_data, filename, self, reading_ok, writing_ok, existing_data)
 
96
        self._open_files[filename] = file_object
 
97
        
 
98
        return file_object
 
99
 
 
100
    def flush_all(self):
 
101
        """ Flush all open files
 
102
        """
 
103
        for file_object in self._open_files.values():
 
104
            file_object.flush()
 
105
 
 
106
    def updatefile(self,filename, data):
 
107
        """ Callback function used by an open file to inform when it has been updated.
 
108
        """
 
109
        if filename in self._open_files:
 
110
            self._files[filename] = data
 
111
            if self._open_files[filename].is_modified():
 
112
                self._modified_files.add(filename)
 
113
        else:
 
114
            raise IOError(2, "Access to file denied: %s" %filename)
 
115
 
 
116
    def closefile(self, filename):
 
117
        """ Callback function used by an open file to inform when it has been closed.
 
118
        """
 
119
        if filename in self._open_files:
 
120
            del self._open_files[filename]
 
121
 
 
122
    def get_modified_files(self):
 
123
        """" A subset of the filespace containing only those files which have been
 
124
        modified
 
125
        """
 
126
        modified_files = {}
 
127
        for filename in self._modified_files:
 
128
            modified_files[filename] = self._files[filename]
 
129
 
 
130
        return modified_files
 
131
 
 
132
    def get_open_files(self):
 
133
        " Return the names of all open files "
 
134
        return self._open_files.keys()
 
135
            
 
136
    def copy(self):
 
137
        """ Return a copy of the current filespace.
 
138
        Only the files are copied, not the modified or open file lists.
 
139
        """
 
140
        self.flush_all()
 
141
        return TestFilespace(self._files)
 
142
 
 
143
class TestStringIO(StringIO.StringIO):
 
144
    """
 
145
    A subclass of StringIO which acts as a file in our dummy file system
 
146
    """
 
147
    def __init__(self, string, filename, filespace, reading_ok, writing_ok, existing_data):
 
148
        """ Initialise with the filedata, file name and infomation on what ops are
 
149
        acceptable """
 
150
        StringIO.StringIO.__init__(self, string)
 
151
        self._filename = filename
 
152
        self._filespace = filespace
 
153
        self._reading_ok = reading_ok
 
154
        self._writing_ok = writing_ok
 
155
        self._existing_data = existing_data
 
156
        self._modified = False
 
157
        self._open = True
 
158
 
 
159
    # Override all standard file ops. Make sure that they are valid with the given
 
160
    # permissions and if so then call the corresponding method in StringIO
 
161
    
 
162
    def read(self, *args):
 
163
        if not self._reading_ok:
 
164
            raise IOError(9, "Bad file descriptor")
 
165
        else:
 
166
            return StringIO.StringIO.read(self, *args)
 
167
 
 
168
    def readline(self, *args):
 
169
        if not self._reading_ok:
 
170
            raise IOError(9, "Bad file descriptor")
 
171
        else:
 
172
            return StringIO.StringIO.readline(self, *args)
 
173
 
 
174
    def readlines(self, *args):
 
175
        if not self._reading_ok:
 
176
            raise IOError(9, "Bad file descriptor")
 
177
        else:
 
178
            return StringIO.StringIO.readlines(self, *args)
 
179
 
 
180
    def seek(self, *args):
 
181
        if not self._reading_ok:
 
182
            raise IOError(9, "Bad file descriptor")
 
183
        else:
 
184
            return StringIO.StringIO.seek(self, *args)
 
185
 
 
186
    def truncate(self, *args):
 
187
        self._modified = True
 
188
        if not self._writing_ok:
 
189
            raise IOError(9, "Bad file descriptor")
 
190
        else:
 
191
            return StringIO.StringIO.truncate(self, *args)
 
192
        
 
193
    def write(self, *args):
 
194
        self._modified = True
 
195
        if not self._writing_ok:
 
196
            raise IOError(9, "Bad file descriptor")
 
197
        else:
 
198
            return StringIO.StringIO.write(self, *args)
 
199
 
 
200
    def writelines(self, *args):
 
201
        self._modified = True
 
202
        if not self._writing_ok:
 
203
            raise IOError(9, "Bad file descriptor")
 
204
        else:
 
205
            return StringIO.StringIO.writelines(self, *args)
 
206
 
 
207
    def is_modified(self):
 
208
        " Return true if the file has been written to, or truncated"
 
209
        return self._modified
 
210
        
 
211
    def flush(self):
 
212
        " Update the contents of the filespace with the new data "
 
213
        self._filespace.updatefile(self._filename, self._existing_data+self.getvalue())
 
214
        return StringIO.StringIO.flush(self)
 
215
 
 
216
    def close(self):
 
217
        " Flush the file and close it "
 
218
        self.flush()
 
219
        self._filespace.closefile(self._filename)
 
220
        return StringIO.StringIO.close(self)
 
221