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

« back to all changes in this revision

Viewing changes to ivle/testfilespace.py

  • Committer: drtomc
  • Date: 2007-12-05 21:24:33 UTC
  • Revision ID: svn-v3-trunk0:2b9c9e99-6f39-0410-b283-7f802c844ae2:trunk:5
Fix a bunch of glitches that Ivo and I found yesterday.

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