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

« back to all changes in this revision

Viewing changes to ivle/util.py

  • Committer: William Grant
  • Date: 2009-04-28 06:02:41 UTC
  • Revision ID: grantw@unimelb.edu.au-20090428060241-t4gnwl35maukfvfg
Move ivle.conf.mimetypes to ivle.mimetypes, and rename things in it.

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: util
 
19
# Author: Matt Giuca
 
20
# Date: 12/12/2007
 
21
 
 
22
# Contains common utility functions.
 
23
 
 
24
import os
 
25
import datetime
 
26
 
 
27
import ivle.conf
 
28
 
 
29
class IVLEError(Exception):
 
30
    """
 
31
    This is the "standard" exception class for IVLE errors.
 
32
    It is the ONLY exception which should propagate to the top - it will then
 
33
    be displayed to the user as an HTTP error with the given code.
 
34
 
 
35
    All other exceptions are considered IVLE bugs and should not occur
 
36
    (they will display a traceback).
 
37
 
 
38
    This error should not be raised directly. Call req.throw_error.
 
39
    """
 
40
    def __init__(self, httpcode, message=None):
 
41
        self.httpcode = httpcode
 
42
        self.message = message
 
43
        self.args = (httpcode, message)
 
44
 
 
45
class IVLEJailError(Exception):
 
46
    """
 
47
    This exception indicates an error that occurred inside an IVLE CGI script
 
48
    inside the jail. It should never be raised directly - only by the 
 
49
    interpreter.
 
50
 
 
51
    Information will be retrieved from it, and then treated as a normal
 
52
    error.
 
53
    """
 
54
    def __init__(self, type_str, message, info):
 
55
        self.type_str = type_str
 
56
        self.message = message
 
57
        self.info = info
 
58
 
 
59
class FakeObject(object):
 
60
    """ A representation of an object that can't be Pickled """
 
61
    def __init__(self, type, name, attrib={}):
 
62
        self.type = type
 
63
        self.name = name
 
64
        self.attrib = attrib
 
65
 
 
66
    def __repr__(self):
 
67
        return "<Fake %s %s>"%(self.type, self.name)
 
68
 
 
69
def make_path(path):
 
70
    """Given a path relative to the IVLE root, makes the path relative to the
 
71
    site root using ivle.conf.root_dir. This path can be used in URLs sent to
 
72
    the client."""
 
73
    return os.path.join(ivle.conf.root_dir, path)
 
74
 
 
75
def unmake_path(path):
 
76
    """Given a path relative to the site root, makes the path relative to the
 
77
    IVLE root by removing ivle.conf.root_dir if it appears at the beginning. If
 
78
    it does not appear at the beginning, returns path unchanged. Also
 
79
    normalises the path."""
 
80
    path = os.path.normpath(path)
 
81
    root = os.path.normpath(ivle.conf.root_dir)
 
82
 
 
83
    if path.startswith(root):
 
84
        path = path[len(root):]
 
85
        # Take out the slash as well
 
86
        if len(path) > 0 and path[0] == os.sep:
 
87
            path = path[1:]
 
88
 
 
89
    return path
 
90
 
 
91
def split_path(path):
 
92
    """Given a path, returns a tuple consisting of the top-level directory in
 
93
    the path, and the rest of the path. Note that both items in the tuple will
 
94
    NOT begin with a slash, regardless of whether the original path did. Also
 
95
    normalises the path.
 
96
 
 
97
    Always returns a pair of strings, except for one special case, in which
 
98
    the path is completely empty (or just a single slash). In this case the
 
99
    return value will be (None, ''). But still always returns a pair.
 
100
 
 
101
    Examples:
 
102
 
 
103
    >>> split_path("")
 
104
    (None, '')
 
105
    >>> split_path("/")
 
106
    (None, '')
 
107
    >>> split_path("home")
 
108
    ('home', '')
 
109
    >>> split_path("home/docs/files")
 
110
    ('home', 'docs/files')
 
111
    >>> split_path("//home/docs/files")
 
112
    ('', 'home/docs/files')
 
113
    """
 
114
    path = os.path.normpath(path)
 
115
    # Ignore the opening slash
 
116
    if path.startswith(os.sep):
 
117
        path = path[len(os.sep):]
 
118
    if path == '' or path == '.':
 
119
        return (None, '')
 
120
    splitpath = path.split(os.sep, 1)
 
121
    if len(splitpath) == 1:
 
122
        return (splitpath[0], '')
 
123
    else:
 
124
        return tuple(splitpath)
 
125
 
 
126
def incomplete_utf8_sequence(byteseq):
 
127
    """
 
128
    str -> int
 
129
    Given a UTF-8-encoded byte sequence (str), returns the number of bytes at
 
130
    the end of the string which comprise an incomplete UTF-8 character
 
131
    sequence.
 
132
 
 
133
    If the string is empty or ends with a complete character OR INVALID
 
134
    sequence, returns 0.
 
135
    Otherwise, returns 1-3 indicating the number of bytes in the final
 
136
    incomplete (but valid) character sequence.
 
137
 
 
138
    Does not check any bytes before the final sequence for correctness.
 
139
 
 
140
    >>> incomplete_utf8_sequence("")
 
141
    0
 
142
    >>> incomplete_utf8_sequence("xy")
 
143
    0
 
144
    >>> incomplete_utf8_sequence("xy\xc3\xbc")
 
145
    0
 
146
    >>> incomplete_utf8_sequence("\xc3")
 
147
    1
 
148
    >>> incomplete_utf8_sequence("\xbc\xc3")
 
149
    1
 
150
    >>> incomplete_utf8_sequence("xy\xbc\xc3")
 
151
    1
 
152
    >>> incomplete_utf8_sequence("xy\xe0\xa0")
 
153
    2
 
154
    >>> incomplete_utf8_sequence("xy\xf4")
 
155
    1
 
156
    >>> incomplete_utf8_sequence("xy\xf4\x8f")
 
157
    2
 
158
    >>> incomplete_utf8_sequence("xy\xf4\x8f\xa0")
 
159
    3
 
160
    """
 
161
    count = 0
 
162
    expect = None
 
163
    for b in byteseq[::-1]:
 
164
        b = ord(b)
 
165
        count += 1
 
166
        if b & 0x80 == 0x0:
 
167
            # 0xxxxxxx (single-byte character)
 
168
            expect = 1
 
169
            break
 
170
        elif b & 0xc0 == 0x80:
 
171
            # 10xxxxxx (subsequent byte)
 
172
            pass
 
173
        elif b & 0xe0 == 0xc0:
 
174
            # 110xxxxx (start of 2-byte sequence)
 
175
            expect = 2
 
176
            break
 
177
        elif b & 0xf0 == 0xe0:
 
178
            # 1110xxxx (start of 3-byte sequence)
 
179
            expect = 3
 
180
            break
 
181
        elif b & 0xf8 == 0xf0:
 
182
            # 11110xxx (start of 4-byte sequence)
 
183
            expect = 4
 
184
            break
 
185
        else:
 
186
            # Invalid byte
 
187
            return 0
 
188
 
 
189
        if count >= 4:
 
190
            # Seen too many "subsequent bytes", invalid
 
191
            return 0
 
192
 
 
193
    if expect is None:
 
194
        # We never saw a "first byte", invalid
 
195
        return 0
 
196
 
 
197
    # We now know expect and count
 
198
    if count >= expect:
 
199
        # Complete, or we saw an invalid sequence
 
200
        return 0
 
201
    elif count < expect:
 
202
        # Incomplete
 
203
        return count
 
204
 
 
205
def object_to_dict(attrnames, obj):
 
206
    """
 
207
    Convert an object into a dictionary. This takes a shallow copy of the
 
208
    object.
 
209
    attrnames: Set (or iterable) of names of attributes to be copied into the
 
210
        dictionary. (We don't auto-lookup, because this function needs to be
 
211
        used on magical objects).
 
212
    """
 
213
    return dict((k, getattr(obj, k))
 
214
        for k in attrnames if not k.startswith('_'))