Imported Upstream version 0.9.3+dfsg
SVN-Git Migration
8 years ago
0 | 0 | Werkzeug Changelog |
1 | 1 | ================== |
2 | ||
3 | Version 0.9.3 | |
4 | ------------- | |
5 | ||
6 | (bugfix release, released on July 25th 2013) | |
7 | ||
8 | - Restored beahvior of the ``data`` descriptor of the request class to pre 0.9 | |
9 | behavior. This now also means that ``.data`` and ``.get_data()`` have | |
10 | different behavior. New code should use ``.get_data()`` always. | |
11 | ||
12 | In addition to that there is now a flag for the ``.get_data()`` method that | |
13 | controls what should happen with form data parsing and the form parser will | |
14 | honor cached data. This makes dealing with custom form data more consistent. | |
2 | 15 | |
3 | 16 | Version 0.9.2 |
4 | 17 | ------------- |
0 | 0 | Metadata-Version: 1.0 |
1 | 1 | Name: Werkzeug |
2 | Version: 0.9.2 | |
2 | Version: 0.9.3 | |
3 | 3 | Summary: The Swiss Army knife of Python web development |
4 | 4 | Home-page: http://werkzeug.pocoo.org/ |
5 | 5 | Author: Armin Ronacher |
0 | 0 | Metadata-Version: 1.0 |
1 | 1 | Name: Werkzeug |
2 | Version: 0.9.2 | |
2 | Version: 0.9.3 | |
3 | 3 | Summary: The Swiss Army knife of Python web development |
4 | 4 | Home-page: http://werkzeug.pocoo.org/ |
5 | 5 | Author: Armin Ronacher |
60 | 60 | |
61 | 61 | setup( |
62 | 62 | name='Werkzeug', |
63 | version='0.9.2', | |
63 | version='0.9.3', | |
64 | 64 | url='http://werkzeug.pocoo.org/', |
65 | 65 | license='BSD', |
66 | 66 | author='Armin Ronacher', |
19 | 19 | from werkzeug._compat import iteritems |
20 | 20 | |
21 | 21 | # the version. Usually set automatically by a script. |
22 | __version__ = '0.9.2' | |
22 | __version__ = '0.9.3' | |
23 | 23 | |
24 | 24 | |
25 | 25 | # This import magic raises concerns quite often which is why the implementation |
366 | 366 | req.stream = LowercasingStream(req.stream) |
367 | 367 | self.assert_equal(req.form['foo'], 'hello world') |
368 | 368 | |
369 | def test_data_descriptor_triggers_parsing(self): | |
370 | data = b'foo=Hello+World' | |
371 | req = wrappers.Request.from_values('/', method='POST', data=data, | |
372 | content_type='application/x-www-form-urlencoded') | |
373 | ||
374 | self.assert_equal(req.data, b'') | |
375 | self.assert_equal(req.form['foo'], u'Hello World') | |
376 | ||
377 | def test_get_data_method_parsing_caching_behavior(self): | |
378 | data = b'foo=Hello+World' | |
379 | req = wrappers.Request.from_values('/', method='POST', data=data, | |
380 | content_type='application/x-www-form-urlencoded') | |
381 | ||
382 | # get_data() caches, so form stays available | |
383 | self.assert_equal(req.get_data(), data) | |
384 | self.assert_equal(req.form['foo'], u'Hello World') | |
385 | self.assert_equal(req.get_data(), data) | |
386 | ||
387 | # here we access the form data first, caching is bypassed | |
388 | req = wrappers.Request.from_values('/', method='POST', data=data, | |
389 | content_type='application/x-www-form-urlencoded') | |
390 | self.assert_equal(req.form['foo'], u'Hello World') | |
391 | self.assert_equal(req.get_data(), b'') | |
392 | ||
393 | # Another case is uncached get data which trashes everything | |
394 | req = wrappers.Request.from_values('/', method='POST', data=data, | |
395 | content_type='application/x-www-form-urlencoded') | |
396 | self.assert_equal(req.get_data(cache=False), data) | |
397 | self.assert_equal(req.get_data(cache=False), b'') | |
398 | self.assert_equal(req.form, {}) | |
399 | ||
400 | # Or we can implicitly start the form parser which is similar to | |
401 | # the old .data behavior | |
402 | req = wrappers.Request.from_values('/', method='POST', data=data, | |
403 | content_type='application/x-www-form-urlencoded') | |
404 | self.assert_equal(req.get_data(parse_form_data=True), b'') | |
405 | self.assert_equal(req.form['foo'], u'Hello World') | |
406 | ||
369 | 407 | def test_etag_response_mixin(self): |
370 | 408 | response = wrappers.Response('Hello World') |
371 | 409 | self.assert_equal(response.get_etag(), (None, None)) |
44 | 44 | from werkzeug._internal import _get_environ |
45 | 45 | from werkzeug._compat import to_bytes, string_types, text_type, \ |
46 | 46 | integer_types, wsgi_decoding_dance, wsgi_get_bytes, \ |
47 | to_unicode, to_native | |
47 | to_unicode, to_native, BytesIO | |
48 | 48 | |
49 | 49 | |
50 | 50 | def _run_wsgi_app(*args): |
334 | 334 | """Method used internally to retrieve submitted data. After calling |
335 | 335 | this sets `form` and `files` on the request object to multi dicts |
336 | 336 | filled with the incoming form data. As a matter of fact the input |
337 | stream will be empty afterwards. | |
337 | stream will be empty afterwards. You can also call this method to | |
338 | force the parsing of the form data. | |
338 | 339 | |
339 | 340 | .. versionadded:: 0.8 |
340 | 341 | """ |
349 | 350 | content_length = get_content_length(self.environ) |
350 | 351 | mimetype, options = parse_options_header(content_type) |
351 | 352 | parser = self.make_form_data_parser() |
352 | data = parser.parse(self.stream, mimetype, | |
353 | content_length, options) | |
353 | data = parser.parse(self._get_stream_for_parsing(), | |
354 | mimetype, content_length, options) | |
354 | 355 | else: |
355 | 356 | data = (self.stream, self.parameter_storage_class(), |
356 | 357 | self.parameter_storage_class()) |
359 | 360 | # our cached_property non-data descriptor. |
360 | 361 | d = self.__dict__ |
361 | 362 | d['stream'], d['form'], d['files'] = data |
363 | ||
364 | def _get_stream_for_parsing(self): | |
365 | """This is the same as accessing :attr:`stream` with the difference | |
366 | that if it finds cached data from calling :meth:`get_data` first it | |
367 | will create a new stream out of the cached data. | |
368 | ||
369 | .. versionadded:: 0.9.3 | |
370 | """ | |
371 | cached_data = getattr(self, '_cached_data', None) | |
372 | if cached_data is not None: | |
373 | return BytesIO(cached_data) | |
374 | return self.stream | |
362 | 375 | |
363 | 376 | def close(self): |
364 | 377 | """Closes associated resources of this request object. This |
414 | 427 | if self.disable_data_descriptor: |
415 | 428 | raise AttributeError('data descriptor is disabled') |
416 | 429 | # XXX: this should eventually be deprecated. |
417 | return self.get_data() | |
418 | ||
419 | def get_data(self, cache=True, as_text=False): | |
430 | ||
431 | # We trigger form data parsing first which means that the descriptor | |
432 | # will not cache the data that would otherwise be .form or .files | |
433 | # data. This restores the behavior that was there in Werkzeug | |
434 | # before 0.9. New code should use :meth:`get_data` explicitly as | |
435 | # this will make behavior explicit. | |
436 | return self.get_data(parse_form_data=True) | |
437 | ||
438 | def get_data(self, cache=True, as_text=False, parse_form_data=False): | |
420 | 439 | """This reads the buffered incoming data from the client into one |
421 | 440 | bytestring. By default this is cached but that behavior can be |
422 | 441 | changed by setting `cache` to `False`. |
425 | 444 | content length first as a client could send dozens of megabytes or more |
426 | 445 | to cause memory problems on the server. |
427 | 446 | |
447 | Note that if the form data was already parsed this method will not | |
448 | return anything as form data parsing does not cache the data like | |
449 | this method does. To implicitly invoke form data parsing function | |
450 | set `parse_form_data` to `True`. When this is done the return value | |
451 | of this method will be an empty string if the form parser handles | |
452 | the data. This generally is not necessary as if the whole data is | |
453 | cached (which is the default) the form parser will used the cached | |
454 | data to parse the form data. Please be generally aware of checking | |
455 | the content length first in any case before calling this method | |
456 | to avoid exhausting server memory. | |
457 | ||
428 | 458 | If `as_text` is set to `True` the return value will be a decoded |
429 | 459 | unicode string. |
430 | 460 | |
432 | 462 | """ |
433 | 463 | rv = getattr(self, '_cached_data', None) |
434 | 464 | if rv is None: |
465 | if parse_form_data: | |
466 | self._load_form_data() | |
435 | 467 | rv = self.stream.read() |
436 | 468 | if cache: |
437 | 469 | self._cached_data = rv |