~ubuntu-branches/ubuntu/natty/moin/natty-updates

« back to all changes in this revision

Viewing changes to MoinMoin/support/werkzeug/_internal.py

  • Committer: Bazaar Package Importer
  • Author(s): Jonas Smedegaard
  • Date: 2008-06-22 21:17:13 UTC
  • mto: This revision was merged to the branch mainline in revision 18.
  • Revision ID: james.westby@ubuntu.com-20080622211713-inlv5k4eifxckelr
ImportĀ upstreamĀ versionĀ 1.7.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# -*- coding: utf-8 -*-
2
 
"""
3
 
    werkzeug._internal
4
 
    ~~~~~~~~~~~~~~~~~~
5
 
 
6
 
    This module provides internally used helpers and constants.
7
 
 
8
 
    :copyright: (c) 2009 by the Werkzeug Team, see AUTHORS for more details.
9
 
    :license: BSD, see LICENSE for more details.
10
 
"""
11
 
import inspect
12
 
from weakref import WeakKeyDictionary
13
 
from cStringIO import StringIO
14
 
from Cookie import BaseCookie, Morsel, CookieError
15
 
from time import gmtime
16
 
from datetime import datetime
17
 
 
18
 
 
19
 
_logger = None
20
 
_empty_stream = StringIO('')
21
 
_signature_cache = WeakKeyDictionary()
22
 
 
23
 
 
24
 
HTTP_STATUS_CODES = {
25
 
    100:    'Continue',
26
 
    101:    'Switching Protocols',
27
 
    102:    'Processing',
28
 
    200:    'OK',
29
 
    201:    'Created',
30
 
    202:    'Accepted',
31
 
    203:    'Non Authoritative Information',
32
 
    204:    'No Content',
33
 
    205:    'Reset Content',
34
 
    206:    'Partial Content',
35
 
    207:    'Multi Status',
36
 
    226:    'IM Used',              # see RFC 3229
37
 
    300:    'Multiple Choices',
38
 
    301:    'Moved Permanently',
39
 
    302:    'Found',
40
 
    303:    'See Other',
41
 
    304:    'Not Modified',
42
 
    305:    'Use Proxy',
43
 
    307:    'Temporary Redirect',
44
 
    400:    'Bad Request',
45
 
    401:    'Unauthorized',
46
 
    402:    'Payment Required',     # unused
47
 
    403:    'Forbidden',
48
 
    404:    'Not Found',
49
 
    405:    'Method Not Allowed',
50
 
    406:    'Not Acceptable',
51
 
    407:    'Proxy Authentication Required',
52
 
    408:    'Request Timeout',
53
 
    409:    'Conflict',
54
 
    410:    'Gone',
55
 
    411:    'Length Required',
56
 
    412:    'Precondition Failed',
57
 
    413:    'Request Entity Too Large',
58
 
    414:    'Request URI Too Long',
59
 
    415:    'Unsupported Media Type',
60
 
    416:    'Requested Range Not Satisfiable',
61
 
    417:    'Expectation Failed',
62
 
    418:    'I\'m a teapot',        # see RFC 2324
63
 
    422:    'Unprocessable Entity',
64
 
    423:    'Locked',
65
 
    424:    'Failed Dependency',
66
 
    426:    'Upgrade Required',
67
 
    449:    'Retry With',           # propritary MS extension
68
 
    500:    'Internal Server Error',
69
 
    501:    'Not Implemented',
70
 
    502:    'Bad Gateway',
71
 
    503:    'Service Unavailable',
72
 
    504:    'Gateway Timeout',
73
 
    505:    'HTTP Version Not Supported',
74
 
    507:    'Insufficient Storage',
75
 
    510:    'Not Extended'
76
 
}
77
 
 
78
 
 
79
 
class _Missing(object):
80
 
 
81
 
    def __repr__(self):
82
 
        return 'no value'
83
 
 
84
 
    def __reduce__(self):
85
 
        return '_missing'
86
 
 
87
 
_missing = _Missing()
88
 
 
89
 
 
90
 
def _proxy_repr(cls):
91
 
    def proxy_repr(self):
92
 
        return '%s(%s)' % (self.__class__.__name__, cls.__repr__(self))
93
 
    return proxy_repr
94
 
 
95
 
 
96
 
def _log(type, message, *args, **kwargs):
97
 
    """Log into the internal werkzeug logger."""
98
 
    global _logger
99
 
    if _logger is None:
100
 
        import logging
101
 
        _logger = logging.getLogger('werkzeug')
102
 
        if _logger.level == logging.NOTSET:
103
 
            _logger.setLevel(logging.INFO)
104
 
            handler = logging.StreamHandler()
105
 
            _logger.addHandler(handler)
106
 
    getattr(_logger, type)(message.rstrip(), *args, **kwargs)
107
 
 
108
 
 
109
 
def _parse_signature(func):
110
 
    """Return a signature object for the function."""
111
 
    if hasattr(func, 'im_func'):
112
 
        func = func.im_func
113
 
 
114
 
    # if we have a cached validator for this function, return it
115
 
    parse = _signature_cache.get(func)
116
 
    if parse is not None:
117
 
        return parse
118
 
 
119
 
    # inspect the function signature and collect all the information
120
 
    positional, vararg_var, kwarg_var, defaults = inspect.getargspec(func)
121
 
    defaults = defaults or ()
122
 
    arg_count = len(positional)
123
 
    arguments = []
124
 
    for idx, name in enumerate(positional):
125
 
        if isinstance(name, list):
126
 
            raise TypeError('cannot parse functions that unpack tuples '
127
 
                            'in the function signature')
128
 
        try:
129
 
            default = defaults[idx - arg_count]
130
 
        except IndexError:
131
 
            param = (name, False, None)
132
 
        else:
133
 
            param = (name, True, default)
134
 
        arguments.append(param)
135
 
    arguments = tuple(arguments)
136
 
 
137
 
    def parse(args, kwargs):
138
 
        new_args = []
139
 
        missing = []
140
 
        extra = {}
141
 
 
142
 
        # consume as many arguments as positional as possible
143
 
        for idx, (name, has_default, default) in enumerate(arguments):
144
 
            try:
145
 
                new_args.append(args[idx])
146
 
            except IndexError:
147
 
                try:
148
 
                    new_args.append(kwargs.pop(name))
149
 
                except KeyError:
150
 
                    if has_default:
151
 
                        new_args.append(default)
152
 
                    else:
153
 
                        missing.append(name)
154
 
            else:
155
 
                if name in kwargs:
156
 
                    extra[name] = kwargs.pop(name)
157
 
 
158
 
        # handle extra arguments
159
 
        extra_positional = args[arg_count:]
160
 
        if vararg_var is not None:
161
 
            new_args.extend(extra_positional)
162
 
            extra_positional = ()
163
 
        if kwargs and not kwarg_var is not None:
164
 
            extra.update(kwargs)
165
 
            kwargs = {}
166
 
 
167
 
        return new_args, kwargs, missing, extra, extra_positional, \
168
 
               arguments, vararg_var, kwarg_var
169
 
    _signature_cache[func] = parse
170
 
    return parse
171
 
 
172
 
 
173
 
def _patch_wrapper(old, new):
174
 
    """Helper function that forwards all the function details to the
175
 
    decorated function."""
176
 
    try:
177
 
        new.__name__ = old.__name__
178
 
        new.__module__ = old.__module__
179
 
        new.__doc__ = old.__doc__
180
 
        new.__dict__ = old.__dict__
181
 
    except:
182
 
        pass
183
 
    return new
184
 
 
185
 
 
186
 
def _decode_unicode(value, charset, errors):
187
 
    """Like the regular decode function but this one raises an
188
 
    `HTTPUnicodeError` if errors is `strict`."""
189
 
    fallback = None
190
 
    if errors.startswith('fallback:'):
191
 
        fallback = errors[9:]
192
 
        errors = 'strict'
193
 
    try:
194
 
        return value.decode(charset, errors)
195
 
    except UnicodeError, e:
196
 
        if fallback is not None:
197
 
            return value.decode(fallback, 'ignore')
198
 
        from werkzeug.exceptions import HTTPUnicodeError
199
 
        raise HTTPUnicodeError(str(e))
200
 
 
201
 
 
202
 
def _iter_modules(path):
203
 
    """Iterate over all modules in a package."""
204
 
    import os
205
 
    import pkgutil
206
 
    if hasattr(pkgutil, 'iter_modules'):
207
 
        for importer, modname, ispkg in pkgutil.iter_modules(path):
208
 
            yield modname, ispkg
209
 
        return
210
 
    from inspect import getmodulename
211
 
    from pydoc import ispackage
212
 
    found = set()
213
 
    for path in path:
214
 
        for filename in os.listdir(path):
215
 
            p = os.path.join(path, filename)
216
 
            modname = getmodulename(filename)
217
 
            if modname and modname != '__init__':
218
 
                if modname not in found:
219
 
                    found.add(modname)
220
 
                    yield modname, ispackage(modname)
221
 
 
222
 
 
223
 
def _dump_date(d, delim):
224
 
    """Used for `http_date` and `cookie_date`."""
225
 
    if d is None:
226
 
        d = gmtime()
227
 
    elif isinstance(d, datetime):
228
 
        d = d.utctimetuple()
229
 
    elif isinstance(d, (int, long, float)):
230
 
        d = gmtime(d)
231
 
    return '%s, %02d%s%s%s%s %02d:%02d:%02d GMT' % (
232
 
        ('Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun')[d.tm_wday],
233
 
        d.tm_mday, delim,
234
 
        ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
235
 
         'Oct', 'Nov', 'Dec')[d.tm_mon - 1],
236
 
        delim, str(d.tm_year), d.tm_hour, d.tm_min, d.tm_sec
237
 
    )
238
 
 
239
 
 
240
 
_timegm = None
241
 
def _date_to_unix(arg):
242
 
    """Converts a timetuple, integer or datetime object into the seconds from
243
 
    epoch in utc.
244
 
    """
245
 
    global _timegm
246
 
    if isinstance(arg, datetime):
247
 
        arg = arg.utctimetuple()
248
 
    elif isinstance(arg, (int, long, float)):
249
 
        return int(arg)
250
 
    if _timegm is None:
251
 
        from calendar import timegm as _timegm
252
 
    return _timegm(arg)
253
 
 
254
 
 
255
 
class _ExtendedMorsel(Morsel):
256
 
    _reserved = {'httponly': 'HttpOnly'}
257
 
    _reserved.update(Morsel._reserved)
258
 
 
259
 
    def __init__(self, name=None, value=None):
260
 
        Morsel.__init__(self)
261
 
        if name is not None:
262
 
            self.set(name, value, value)
263
 
 
264
 
    def OutputString(self, attrs=None):
265
 
        httponly = self.pop('httponly', False)
266
 
        result = Morsel.OutputString(self, attrs).rstrip('\t ;')
267
 
        if httponly:
268
 
            result += '; HttpOnly'
269
 
        return result
270
 
 
271
 
 
272
 
class _ExtendedCookie(BaseCookie):
273
 
    """Form of the base cookie that doesn't raise a `CookieError` for
274
 
    malformed keys.  This has the advantage that broken cookies submitted
275
 
    by nonstandard browsers don't cause the cookie to be empty.
276
 
    """
277
 
 
278
 
    def _BaseCookie__set(self, key, real_value, coded_value):
279
 
        morsel = self.get(key, _ExtendedMorsel())
280
 
        try:
281
 
            morsel.set(key, real_value, coded_value)
282
 
        except CookieError:
283
 
            pass
284
 
        dict.__setitem__(self, key, morsel)
285
 
 
286
 
 
287
 
class _DictAccessorProperty(object):
288
 
    """Baseclass for `environ_property` and `header_property`."""
289
 
    read_only = False
290
 
 
291
 
    def __init__(self, name, default=None, load_func=None, dump_func=None,
292
 
                 read_only=None, doc=None):
293
 
        self.name = name
294
 
        self.default = default
295
 
        self.load_func = load_func
296
 
        self.dump_func = dump_func
297
 
        if read_only is not None:
298
 
            self.read_only = read_only
299
 
        self.__doc__ = doc
300
 
 
301
 
    def __get__(self, obj, type=None):
302
 
        if obj is None:
303
 
            return self
304
 
        storage = self.lookup(obj)
305
 
        if self.name not in storage:
306
 
            return self.default
307
 
        rv = storage[self.name]
308
 
        if self.load_func is not None:
309
 
            try:
310
 
                rv = self.load_func(rv)
311
 
            except (ValueError, TypeError):
312
 
                rv = self.default
313
 
        return rv
314
 
 
315
 
    def __set__(self, obj, value):
316
 
        if self.read_only:
317
 
            raise AttributeError('read only property')
318
 
        if self.dump_func is not None:
319
 
            value = self.dump_func(value)
320
 
        self.lookup(obj)[self.name] = value
321
 
 
322
 
    def __delete__(self, obj):
323
 
        if self.read_only:
324
 
            raise AttributeError('read only property')
325
 
        self.lookup(obj).pop(self.name, None)
326
 
 
327
 
    def __repr__(self):
328
 
        return '<%s %s>' % (
329
 
            self.__class__.__name__,
330
 
            self.name
331
 
        )
332
 
 
333
 
 
334
 
def _easteregg(app):
335
 
    """Like the name says.  But who knows how it works?"""
336
 
    gyver = '\n'.join([x + (77 - len(x)) * ' ' for x in '''
337
 
eJyFlzuOJDkMRP06xRjymKgDJCDQStBYT8BCgK4gTwfQ2fcFs2a2FzvZk+hvlcRvRJD148efHt9m
338
 
9Xz94dRY5hGt1nrYcXx7us9qlcP9HHNh28rz8dZj+q4rynVFFPdlY4zH873NKCexrDM6zxxRymzz
339
 
4QIxzK4bth1PV7+uHn6WXZ5C4ka/+prFzx3zWLMHAVZb8RRUxtFXI5DTQ2n3Hi2sNI+HK43AOWSY
340
 
jmEzE4naFp58PdzhPMdslLVWHTGUVpSxImw+pS/D+JhzLfdS1j7PzUMxij+mc2U0I9zcbZ/HcZxc
341
 
q1QjvvcThMYFnp93agEx392ZdLJWXbi/Ca4Oivl4h/Y1ErEqP+lrg7Xa4qnUKu5UE9UUA4xeqLJ5
342
 
jWlPKJvR2yhRI7xFPdzPuc6adXu6ovwXwRPXXnZHxlPtkSkqWHilsOrGrvcVWXgGP3daXomCj317
343
 
8P2UOw/NnA0OOikZyFf3zZ76eN9QXNwYdD8f8/LdBRFg0BO3bB+Pe/+G8er8tDJv83XTkj7WeMBJ
344
 
v/rnAfdO51d6sFglfi8U7zbnr0u9tyJHhFZNXYfH8Iafv2Oa+DT6l8u9UYlajV/hcEgk1x8E8L/r
345
 
XJXl2SK+GJCxtnyhVKv6GFCEB1OO3f9YWAIEbwcRWv/6RPpsEzOkXURMN37J0PoCSYeBnJQd9Giu
346
 
LxYQJNlYPSo/iTQwgaihbART7Fcyem2tTSCcwNCs85MOOpJtXhXDe0E7zgZJkcxWTar/zEjdIVCk
347
 
iXy87FW6j5aGZhttDBoAZ3vnmlkx4q4mMmCdLtnHkBXFMCReqthSGkQ+MDXLLCpXwBs0t+sIhsDI
348
 
tjBB8MwqYQpLygZ56rRHHpw+OAVyGgaGRHWy2QfXez+ZQQTTBkmRXdV/A9LwH6XGZpEAZU8rs4pE
349
 
1R4FQ3Uwt8RKEtRc0/CrANUoes3EzM6WYcFyskGZ6UTHJWenBDS7h163Eo2bpzqxNE9aVgEM2CqI
350
 
GAJe9Yra4P5qKmta27VjzYdR04Vc7KHeY4vs61C0nbywFmcSXYjzBHdiEjraS7PGG2jHHTpJUMxN
351
 
Jlxr3pUuFvlBWLJGE3GcA1/1xxLcHmlO+LAXbhrXah1tD6Ze+uqFGdZa5FM+3eHcKNaEarutAQ0A
352
 
QMAZHV+ve6LxAwWnXbbSXEG2DmCX5ijeLCKj5lhVFBrMm+ryOttCAeFpUdZyQLAQkA06RLs56rzG
353
 
8MID55vqr/g64Qr/wqwlE0TVxgoiZhHrbY2h1iuuyUVg1nlkpDrQ7Vm1xIkI5XRKLedN9EjzVchu
354
 
jQhXcVkjVdgP2O99QShpdvXWoSwkp5uMwyjt3jiWCqWGSiaaPAzohjPanXVLbM3x0dNskJsaCEyz
355
 
DTKIs+7WKJD4ZcJGfMhLFBf6hlbnNkLEePF8Cx2o2kwmYF4+MzAxa6i+6xIQkswOqGO+3x9NaZX8
356
 
MrZRaFZpLeVTYI9F/djY6DDVVs340nZGmwrDqTCiiqD5luj3OzwpmQCiQhdRYowUYEA3i1WWGwL4
357
 
GCtSoO4XbIPFeKGU13XPkDf5IdimLpAvi2kVDVQbzOOa4KAXMFlpi/hV8F6IDe0Y2reg3PuNKT3i
358
 
RYhZqtkQZqSB2Qm0SGtjAw7RDwaM1roESC8HWiPxkoOy0lLTRFG39kvbLZbU9gFKFRvixDZBJmpi
359
 
Xyq3RE5lW00EJjaqwp/v3EByMSpVZYsEIJ4APaHmVtpGSieV5CALOtNUAzTBiw81GLgC0quyzf6c
360
 
NlWknzJeCsJ5fup2R4d8CYGN77mu5vnO1UqbfElZ9E6cR6zbHjgsr9ly18fXjZoPeDjPuzlWbFwS
361
 
pdvPkhntFvkc13qb9094LL5NrA3NIq3r9eNnop9DizWOqCEbyRBFJTHn6Tt3CG1o8a4HevYh0XiJ
362
 
sR0AVVHuGuMOIfbuQ/OKBkGRC6NJ4u7sbPX8bG/n5sNIOQ6/Y/BX3IwRlTSabtZpYLB85lYtkkgm
363
 
p1qXK3Du2mnr5INXmT/78KI12n11EFBkJHHp0wJyLe9MvPNUGYsf+170maayRoy2lURGHAIapSpQ
364
 
krEDuNoJCHNlZYhKpvw4mspVWxqo415n8cD62N9+EfHrAvqQnINStetek7RY2Urv8nxsnGaZfRr/
365
 
nhXbJ6m/yl1LzYqscDZA9QHLNbdaSTTr+kFg3bC0iYbX/eQy0Bv3h4B50/SGYzKAXkCeOLI3bcAt
366
 
mj2Z/FM1vQWgDynsRwNvrWnJHlespkrp8+vO1jNaibm+PhqXPPv30YwDZ6jApe3wUjFQobghvW9p
367
 
7f2zLkGNv8b191cD/3vs9Q833z8t'''.decode('base64').decode('zlib').splitlines()])
368
 
    def easteregged(environ, start_response):
369
 
        def injecting_start_response(status, headers, exc_info=None):
370
 
            headers.append(('X-Powered-By', 'Werkzeug'))
371
 
            return start_response(status, headers, exc_info)
372
 
        if environ.get('QUERY_STRING') != 'macgybarchakku':
373
 
            return app(environ, injecting_start_response)
374
 
        injecting_start_response('200 OK', [('Content-Type', 'text/html')])
375
 
        return ['''<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
376
 
<title>About Werkzeug</>
377
 
<style type="text/css">
378
 
  body { font: 15px Georgia, serif; text-align: center; }
379
 
  a { color: #333; text-decoration: none; }
380
 
  h1 { font-size: 30px; margin: 20px 0 10px 0; }
381
 
  p { margin: 0 0 30px 0; }
382
 
  pre { font: 11px 'Consolas', 'Monaco', monospace; line-height: 0.95; }
383
 
</style>
384
 
<h1><a href="http://werkzeug.pocoo.org/">Werkzeug</a></h1>
385
 
<p>the Swiss Army knife of Python web development.
386
 
<pre>%s\n\n\n</>''' % gyver]
387
 
    return easteregged