Codebase list python-werkzeug / 800cd87
Imported Upstream version 0.3.1 SVN-Git Migration 8 years ago
39 changed file(s) with 38 addition(s) and 340 deletion(s). Raw diff Collapse all Expand all
11 ==================
22
33
4 Version 0.3.1
5 -------------
6 (released on June 24th 2008)
7
8 - fixed a security problem with `werkzeug.contrib.SecureCookie`.
9 More details available in the `release announcement`_.
10
11 .. _release announcement: http://lucumr.pocoo.org/cogitations/2008/06/24/werkzeug-031-released/
12
413 Version 0.3
514 -----------
6 (codename to be selected, release date somewhere around May 2008)
15 (codename EUR325CAT6, released on June 14th 2008)
716
817 - added support for redirecting in url routing.
918 - added `Authorization` and `AuthorizationMixin`
00 Metadata-Version: 1.0
11 Name: Werkzeug
2 Version: 0.3
2 Version: 0.3.1
33 Summary: The Swiss Army knife of Python web development
44 Home-page: http://werkzeug.pocoo.org/
55 Author: Armin Ronacher
00 Metadata-Version: 1.0
11 Name: Werkzeug
2 Version: 0.3
2 Version: 0.3.1
33 Summary: The Swiss Army knife of Python web development
44 Home-page: http://werkzeug.pocoo.org/
55 Author: Armin Ronacher
3737 docs/build/test.html
3838 docs/build/tutorial.html
3939 docs/build/tutorial_de.html
40 docs/build/unicode.html
4140 docs/build/utils.html
4241 docs/build/werkzeug.png
4342 docs/build/wrappers.html
7372 examples/manage-shorty.py
7473 examples/manage-simplewiki.py
7574 examples/manage-webpylike.py
76 examples/objectapp.py
7775 examples/upload.py
7876 examples/contrib/README
7977 examples/contrib/securecookie.py
9694 examples/couchy/utils.py
9795 examples/couchy/views.py
9896 examples/couchy/static/style.css
99 examples/couchy/templates/.DS_Store
10097 examples/couchy/templates/display.html
10198 examples/couchy/templates/layout.html
10299 examples/couchy/templates/list.html
103100 examples/couchy/templates/new.html
104101 examples/couchy/templates/not_found.html
105102 examples/cupoftee/__init__.py
106 examples/cupoftee/__init__.pyc
107103 examples/cupoftee/application.py
108 examples/cupoftee/application.pyc
109104 examples/cupoftee/db.py
110 examples/cupoftee/db.pyc
111105 examples/cupoftee/network.py
112 examples/cupoftee/network.pyc
113106 examples/cupoftee/pages.py
114 examples/cupoftee/pages.pyc
115107 examples/cupoftee/utils.py
116 examples/cupoftee/utils.pyc
117108 examples/cupoftee/shared/content.png
118109 examples/cupoftee/shared/down.png
119110 examples/cupoftee/shared/favicon.ico
137128 examples/partial/README
138129 examples/partial/complex_routing.py
139130 examples/plnt/__init__.py
140 examples/plnt/__init__.pyc
141131 examples/plnt/database.py
142 examples/plnt/database.pyc
143132 examples/plnt/sync.py
144133 examples/plnt/utils.py
145 examples/plnt/utils.pyc
146134 examples/plnt/views.py
147 examples/plnt/views.pyc
148135 examples/plnt/webapp.py
149 examples/plnt/webapp.pyc
150136 examples/plnt/shared/style.css
151137 examples/plnt/templates/about.html
152138 examples/plnt/templates/index.html
153139 examples/plnt/templates/layout.html
154140 examples/shorty/__init__.py
155 examples/shorty/__init__.pyc
156141 examples/shorty/application.py
157 examples/shorty/application.pyc
158142 examples/shorty/models.py
159 examples/shorty/models.pyc
160143 examples/shorty/utils.py
161 examples/shorty/utils.pyc
162144 examples/shorty/views.py
163 examples/shorty/views.pyc
164145 examples/shorty/static/style.css
165146 examples/shorty/templates/display.html
166147 examples/shorty/templates/layout.html
168149 examples/shorty/templates/new.html
169150 examples/shorty/templates/not_found.html
170151 examples/simplewiki/__init__.py
171 examples/simplewiki/__init__.pyc
172152 examples/simplewiki/actions.py
173 examples/simplewiki/actions.pyc
174153 examples/simplewiki/application.py
175 examples/simplewiki/application.pyc
176154 examples/simplewiki/database.py
177 examples/simplewiki/database.pyc
178155 examples/simplewiki/specialpages.py
179 examples/simplewiki/specialpages.pyc
180156 examples/simplewiki/utils.py
181 examples/simplewiki/utils.pyc
182157 examples/simplewiki/shared/style.css
183158 examples/simplewiki/templates/action_diff.html
184159 examples/simplewiki/templates/action_edit.html
195170 examples/webpylike/webpylike.py
196171 tests/conftest.py
197172 tests/test_http.py
198 tests/test_http.pyc
199173 tests/test_routing.py
200 tests/test_routing.pyc
201174 tests/test_templates.py
202 tests/test_templates.pyc
203175 tests/test_utils.py
204 tests/test_utils.pyc
205176 tests/test_wrappers.py
206 tests/test_wrappers.pyc
207177 tests/contrib/test_testtools.py
208 tests/contrib/test_testtools.pyc
209178 tests/res/test.txt
210179 werkzeug/__init__.py
211180 werkzeug/_internal.py
+0
-150
docs/build/unicode.html less more
0 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
1 <html>
2 <head>
3 <title>Unicode // Werkzeug Documentation</title>
4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
5 <link rel="stylesheet" type="text/css" href="style.css">
6 <link rel="stylesheet" type="text/css" href="pygments.css">
7 <link rel="stylesheet" type="text/css" media="print" href="print.css">
8 <link rel="shortcut icon" type="image/x-icon" href="favicon.ico">
9 </head>
10 <body>
11 <div class="page">
12 <div class="header">
13 <h1><a href="index.html"><span>Werkzeug</span></a></h1>
14 <p><span>The Swiss Army Knife For Python Web Developers</span></p>
15 </div>
16 <div class="body">
17 <h2>Unicode</h2>
18
19 <div class="toc">
20 <h4>Table of Contents</h4>
21 <ul><li><a class="reference" href="#unicode-in-python" id="id1" name="id1">Unicode in Python</a></li>
22 <li><a class="reference" href="#unicode-in-http" id="id2" name="id2">Unicode in HTTP</a></li>
23 <li><a class="reference" href="#error-handling" id="id3" name="id3">Error Handling</a></li>
24 <li><a class="reference" href="#request-and-response-objects" id="id4" name="id4">Request and Response Objects</a></li>
25 </ul>
26 </div>
27
28 <p>Since early Python 2 days unicode was part of all default Python builds. It
29 allows developers to write applications that deal with non-ASCII characters
30 in a straightforward way. But working with unicode requires a basic knowledge
31 about that matter, especially when working with libraries that do not support
32 it.</p>
33 <p>Werkzeug uses unicode internally everywhere text data is assumed, even if the
34 HTTP standard is not unicode aware as it. Basically all incoming data is
35 decoded from the charset specified (per default <cite>utf-8</cite>) so that you don&#8217;t
36 operate on bytestrings any more. Outgoing unicode data is then encoded into
37 the target charset again.</p>
38 <div class="section">
39 <h3 id="unicode-in-python">Unicode in Python</h3>
40 <p>In Python 2 there are two basic string types: <cite>str</cite> and <cite>unicode</cite>. <cite>str</cite> may
41 carry encoded unicode data but it&#8217;s always represented in bytes whereas the
42 <cite>unicode</cite> type does not contain bytes but charpoints. What does this mean?
43 Imagine you have the German Umlaut <cite>ö</cite>. In ASCII you cannot represent that
44 character, but in the <cite>latin-1</cite> and <cite>utf-8</cite> character sets you can represent
45 it, but they look differently when encoded:</p>
46 <div class="syntax"><pre><span class="gp">&gt;&gt;&gt; </span><span class="s">u&#39;ö&#39;</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s">&#39;latin1&#39;</span><span class="p">)</span>
47 <span class="go">&#39;\xf6&#39;</span>
48 <span class="gp">&gt;&gt;&gt; </span><span class="s">u&#39;ö&#39;</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s">&#39;utf-8&#39;</span><span class="p">)</span>
49 <span class="go">&#39;\xc3\xb6&#39;</span>
50 </pre></div>
51 <p>So an <cite>ö</cite> might look totally different depending on the encoding which makes
52 it hard to work with it. The solution is using the <cite>unicode</cite> type (as we did
53 above, note the <cite>u</cite> prefix before the string). The unicode type does not
54 store the bytes for <cite>ö</cite> but the information, that this is a
55 <tt class="docutils literal"><span class="pre">LATIN</span> <span class="pre">SMALL</span> <span class="pre">LETTER</span> <span class="pre">O</span> <span class="pre">WITH</span> <span class="pre">DIAERESIS</span></tt>.</p>
56 <p>Doing <tt class="docutils literal"><span class="pre">len(u'ö')</span></tt> will always give us the expected &#8220;1&#8221; but <tt class="docutils literal"><span class="pre">len('ö')</span></tt>
57 might give different results depending on the encoding of <tt class="docutils literal"><span class="pre">'ö'</span></tt>.</p>
58 </div>
59 <div class="section">
60 <h3 id="unicode-in-http">Unicode in HTTP</h3>
61 <p>The problem with unicode is that HTTP does not know what unicode is. HTTP
62 is limited to bytes but this is not a big problem as Werkzeug decodes and
63 encodes for us automatically all incoming and outgoing data. Basically what
64 this means is that data sent from the browser to the web application is per
65 default decoded from an utf-8 bytestring into a <cite>unicode</cite> string. Data sent
66 from the application back to the browser that is not yet a bytestring is then
67 encoded back to utf-8.</p>
68 <p>Usually this &#8220;just works&#8221; and we don&#8217;t have to worry about it, but there are
69 situations where this behavior is problematic. For example the Python 2 IO
70 layer is not unicode aware. This means that whenever you work with data from
71 the file system you have to properly decode it. The correct way to load
72 a text file from the file system looks like this:</p>
73 <div class="syntax"><pre><span class="n">f</span> <span class="o">=</span> <span class="nb">file</span><span class="p">(</span><span class="s">&#39;/path/to/the_file.txt&#39;</span><span class="p">,</span> <span class="s">&#39;r&#39;</span><span class="p">)</span>
74 <span class="k">try</span><span class="p">:</span>
75 <span class="n">text</span> <span class="o">=</span> <span class="n">f</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s">&#39;utf-8&#39;</span><span class="p">)</span> <span class="c"># assuming the file is utf-8 encoded</span>
76 <span class="k">finally</span><span class="p">:</span>
77 <span class="n">f</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
78 </pre></div>
79 <p>There is also the codecs module which provides an open function that decodes
80 automatically from the given encoding.</p>
81 </div>
82 <div class="section">
83 <h3 id="error-handling">Error Handling</h3>
84 <p>With Werkzeug 0.3 onwards you can further control the way Werkzeug works with
85 unicode. In the past Werkzeug ignored encoding errors silently on incoming
86 data. This decision was made to avoid internal server errors if the user
87 tampered with the submitted data. However there are situations where you
88 want to abort with a <cite>400 BAD REQUEST</cite> instead of silently ignoring the error.</p>
89 <p>All the functions that do internal decoding now accept an <cite>errors</cite> keyword
90 argument that behaves like the <cite>errors</cite> parameter of the builtin string method
91 <cite>decode</cite>. The following values are possible:</p>
92 <dl>
93 <dt><cite>ignore</cite></dt>
94 <dd>This is the default behavior and tells the codec to ignore characters that
95 it doesn&#8217;t understand silently.</dd>
96 <dt><cite>replace</cite></dt>
97 <dd>The codec will replace unknown characters with a replacement character
98 (<cite>U+FFFD</cite> <tt class="docutils literal"><span class="pre">REPLACEMENT</span> <span class="pre">CHARACTER</span></tt>)</dd>
99 <dt><cite>strict</cite></dt>
100 <dd>Raise an exception if decoding fails.</dd>
101 </dl>
102 <p>Unlike the regular python decoding Werkzeug does not raise an
103 <cite>UnicodeDecodeError</cite> if the decoding failed but an <cite>HTTPUnicodeError</cite> which
104 is a direct subclass of <cite>UnicodeError</cite> and the <cite>BadRequest</cite> HTTP exception.
105 The reason is that if this exception is not caught by the application but
106 a catch-all for HTTP exceptions exists a default <cite>400 BAD REQUEST</cite> error
107 page is displayed.</p>
108 <p>There is additional error handling available which is a Werkzeug extension
109 to the regular codec error handling which is called <cite>fallback</cite>. Often you
110 want to use utf-8 but support latin1 as legacy encoding too if decoding
111 failed. For this case you can use the <cite>fallback</cite> error handling. For
112 example you can specify <tt class="docutils literal"><span class="pre">'fallback:iso-8859-15'</span></tt> to tell Werkzeug it should
113 try with <cite>iso-8859-15</cite> if <cite>utf-8</cite> failed. If this decoding fails too (which
114 should not happen for most legacy charsets such as <cite>iso-8859-15</cite>) the error
115 is silently ignored as if the error handling was <cite>ignore</cite>.</p>
116 <p>Further details are available as part of the API documentation of the concrete
117 implementations of the functions or classes working with unicode.</p>
118 </div>
119 <div class="section">
120 <h3 id="request-and-response-objects">Request and Response Objects</h3>
121 <p>As request and response objects usually are the central entities of Werkzeug
122 powered applications you can change the default encoding Werkzeug operates on
123 by subclassing these two classes. For example you can easily set the
124 application to utf-7 and strict error handling:</p>
125 <div class="syntax"><pre><span class="k">from</span> <span class="nn">werkzeug</span> <span class="k">import</span> <span class="n">BaseRequest</span><span class="p">,</span> <span class="n">BaseResponse</span>
126
127 <span class="k">class</span> <span class="nc">Request</span><span class="p">(</span><span class="n">BaseRequest</span><span class="p">):</span>
128 <span class="n">charset</span> <span class="o">=</span> <span class="s">&#39;utf-7&#39;</span>
129 <span class="n">encoding_errors</span> <span class="o">=</span> <span class="s">&#39;strict&#39;</span>
130
131 <span class="k">class</span> <span class="nc">Response</span><span class="p">(</span><span class="n">BaseResponse</span><span class="p">):</span>
132 <span class="n">charset</span> <span class="o">=</span> <span class="s">&#39;utf-7&#39;</span>
133 </pre></div>
134 <p>Keep in mind that the error handling is only customizable for all decoding
135 but not encoding. If Werkzeug encounters an encoding error it will raise a
136 <cite>UnicodeEncodeError</cite>. It&#8217;s your responsibility to not create data that is
137 not present in the target charset (a non issue with all unicode encodings
138 such as utf-8).</p>
139 </div>
140
141 <div style="clear:both"></div>
142 </div>
143 <div class="footer">
144 Werkzeug is a <a href="http://pocoo.org/">Pocoo</a> project licensed under the
145 BSD license.
146 </div>
147 </div>
148 </body>
149 </html>
examples/couchy/templates/.DS_Store less more
Binary diff not shown
examples/couchy/templates/._.DS_Store less more
Binary diff not shown
examples/cupoftee/__init__.pyc less more
Binary diff not shown
examples/cupoftee/application.pyc less more
Binary diff not shown
examples/cupoftee/db.pyc less more
Binary diff not shown
examples/cupoftee/network.pyc less more
Binary diff not shown
examples/cupoftee/pages.pyc less more
Binary diff not shown
examples/cupoftee/utils.pyc less more
Binary diff not shown
+0
-132
examples/objectapp.py less more
0 # -*- coding: utf-8 -*-
1 """
2 Object Based Dispatching
3 ~~~~~~~~~~~~~~~~~~~~~~~~
4
5 Colubrid inspired object based dispatching.
6
7 :copyright: Copyright 2008 by Armin Ronacher.
8 :license: GNU GPL.
9 """
10 import inspect
11 from werkzeug import Request, Response, responder, redirect
12 from werkzeug.exceptions import HTTPException, NotFound
13
14
15 def fix_slash(request, is_container):
16 path = request.path
17 new_path = None
18 ends_with_slash = path.endswith('/')
19 if ends_with_slash and not is_container:
20 new_path = path.rstrip('/')
21 elif not ends_with_slash and is_container:
22 new_path = path + '/'
23 if new_path is not None:
24 qs = request.environ.get('QUERY_STRING')
25 if qs:
26 new_path += '?' + qs
27 return redirect(new_path)
28
29
30 class Controller(object):
31
32 def __init__(self, request):
33 self.request = request
34
35
36 class ObjectApplication(object):
37
38 root = None
39
40 def dispatch_request(self, request):
41 handler = self.root
42 container = None
43 args = []
44 for part in request.path.strip('/').split('/'):
45 if part.startswith('_'):
46 raise NotFound()
47 node = getattr(handler, part, None)
48 if node is None:
49 if part:
50 args.append(part)
51 else:
52 handler = node
53
54 if inspect.ismethod(handler):
55 if handler.__name__ == 'index':
56 container = False
57 else:
58 index = getattr(handler, 'index', None)
59 if index is not None:
60 if not hasattr(index, '_is_container'):
61 container = True
62 handler = index
63 else:
64 raise NotFound()
65
66 if container is None and hasattr(handler, '_is_container'):
67 container = handler._is_container
68
69 handler_args, varargs, _, defaults = inspect.getargspec(handler)
70 if defaults is None:
71 defaults = 0
72 else:
73 defaults = len(defaults)
74
75 max_len = len(handler_args) - 1
76 min_len = max_len - defaults
77 cur_len = len(args)
78 if varargs:
79 max_len = -1
80
81 # check if the number of arguments fits our handler
82 if max_len < 0:
83 if cur_len < min_len:
84 raise NotFound()
85 elif min_len <= cur_len <= max_len:
86 if container is None:
87 container = cur_len < max_len
88 else:
89 raise NotFound()
90
91 # redirect if necessary
92 response = fix_slash(request, container)
93 if response is not None:
94 return response
95
96 # call handler
97 return handler(handler.im_class(request), *args)
98
99 @responder
100 def __call__(self, environ, start_response):
101 request = Request(environ)
102 try:
103 rv = self.dispatch_request(request)
104 if isinstance(rv, basestring):
105 rv = Response(rv, mimetype='text/html')
106 return rv
107 except HTTPException, e:
108 return e
109
110
111 class BlogController(Controller):
112
113 def index(self):
114 return 'Hello World'
115
116
117 class AdminController(Controller):
118
119 def hello(self, name='World'):
120 times = self.request.args['times']
121 return 'Hello %s (%s times)!' % (name, times)
122
123
124 application = ObjectApplication()
125 application.root = BlogController
126 application.root.admin = AdminController
127
128
129 if __name__ == '__main__':
130 from werkzeug import run_simple
131 run_simple('localhost', 4000, application, use_reloader=True)
examples/plnt/__init__.pyc less more
Binary diff not shown
examples/plnt/database.pyc less more
Binary diff not shown
examples/plnt/utils.pyc less more
Binary diff not shown
examples/plnt/views.pyc less more
Binary diff not shown
examples/plnt/webapp.pyc less more
Binary diff not shown
examples/shorty/__init__.pyc less more
Binary diff not shown
examples/shorty/application.pyc less more
Binary diff not shown
examples/shorty/models.pyc less more
Binary diff not shown
examples/shorty/utils.pyc less more
Binary diff not shown
examples/shorty/views.pyc less more
Binary diff not shown
examples/simplewiki/._actions.py less more
Binary diff not shown
examples/simplewiki/__init__.pyc less more
Binary diff not shown
examples/simplewiki/actions.pyc less more
Binary diff not shown
examples/simplewiki/application.pyc less more
Binary diff not shown
examples/simplewiki/database.pyc less more
Binary diff not shown
examples/simplewiki/specialpages.pyc less more
Binary diff not shown
examples/simplewiki/utils.pyc less more
Binary diff not shown
7070
7171 setup(
7272 name='Werkzeug',
73 version='0.3',
73 version='0.3.1',
7474 url='http://werkzeug.pocoo.org/',
7575 license='BSD',
7676 author='Armin Ronacher',
tests/contrib/test_testtools.pyc less more
Binary diff not shown
tests/test_http.pyc less more
Binary diff not shown
tests/test_routing.pyc less more
Binary diff not shown
tests/test_templates.pyc less more
Binary diff not shown
tests/test_utils.pyc less more
Binary diff not shown
tests/test_wrappers.pyc less more
Binary diff not shown
7373 try:
7474 from hashlib import sha1
7575 except ImportError:
76 from sha import new as sha1
77 from binascii import Error as BinASCIIError
76 import sha as sha1
77 from hmac import new as hmac
7878 from datetime import datetime
7979 from time import time, mktime, gmtime
8080 from random import Random
109109
110110 class SecureCookie(ModificationTrackingDict):
111111 """Represents a secure cookie. You can subclass this class and provide
112 an alternative hash method. The import thing is that the hash method
112 an alternative mac method. The import thing is that the mac method
113113 is a function with a similar interface to the hashlib. Required
114114 methods are update() and digest().
115115 """
116 __slots__ = ModificationTrackingDict.__slots__ + ('secret_key', 'new')
117
116
117 # the hash method to use. In python 2.5 and higher this is a callable
118 # that returns a new hashlib object or a module with a new method that
119 # creates such an object. In python 2.4 and earlier only the module
120 # is supported.
118121 hash_method = sha1
119122
120123 def __init__(self, data=None, secret_key=None, new=True):
133136 """True if the session should be saved."""
134137 return self.modified
135138 should_save = property(should_save)
136
137 def new_salt(self, secret_key):
138 """Return a new salt Return value must be 4 bytes long."""
139 return generate_key()[:4]
140139
141140 def serialize(self, expires=None):
142141 """Serialize the secure cookie into a string.
154153 expires = gmtime(expires)
155154 self['_expires'] = int(mktime(expires))
156155 result = []
157 salt = self.new_salt(self.secret_key)
158 hash = self.hash_method(self.secret_key + salt)
156 mac = hmac(self.secret_key, None, self.hash_method)
159157 for key, value in self.iteritems():
160158 result.append('%s=%s' % (
161159 url_quote_plus(key),
162160 pickle_quote(value)
163161 ))
164 hash.update('|' + result[-1])
165 return '%s%s?%s' % (
166 salt,
167 hash.digest().encode('base64').strip(),
162 mac.update('|' + result[-1])
163 return '%s?%s' % (
164 mac.digest().encode('base64').strip(),
168165 '&'.join(result)
169166 )
170167
172169 """Load the secure cookie from a serialized string."""
173170 if isinstance(string, unicode):
174171 string = string.encode('utf-8', 'ignore')
175 salt = string[:4]
176172 try:
177 base64_hash, data = string[4:].split('?', 1)
173 base64_hash, data = string.split('?', 1)
178174 except (ValueError, IndexError):
179175 items = ()
180176 else:
181177 items = {}
182 hash = sha1(secret_key + salt)
178 mac = hmac(secret_key, None, cls.hash_method)
183179 for item in data.split('&'):
184 hash.update('|' + item)
180 mac.update('|' + item)
185181 if not '=' in item:
186182 items = None
187183 break
188184 key, value = item.split('=', 1)
189 items[url_unquote_plus(key)] = value
190
191 # no parsing error and the hash looks okay, we can now
185 # try to make the key a string
186 key = url_unquote_plus(key)
187 try:
188 key = str(key)
189 except UnicodeError:
190 pass
191 items[key] = value
192
193 # no parsing error and the mac looks okay, we can now
192194 # sercurely unpickle our cookie.
193195 try:
194196 client_hash = base64_hash.decode('base64')
195197 except Exception:
196198 items = client_hash = None
197 if items is not None and client_hash == hash.digest():
199 if items is not None and client_hash == mac.digest():
198200 try:
199201 for key, value in items.iteritems():
200202 items[key] = pickle_unquote(value)