Commits

Sergey Schetinin committed 32a4120 Merge

merge

Comments (0)

Files changed (7)

 .. comment:
 
     >>> from dtopt import ELLIPSIS
-   
+
 
 Status & License
 ================
 <http://pythonpaste.org/>`_.  It is under active development.
 Discussion should happen on the `Paste mailing lists
 <http://pythonpaste.org/community/>`_, and bugs can go on the `Paste
-trac instance <http://trac.pythonpaste.org/>`_.
+trac instance <http://trac.pythonpaste.org/>`_.  It was originally
+written by `Ian Bicking <http://ianbicking.org/>`, and the primary
+maintainer is now `Sergey Schetinin <http://self.maluke.com/>`.
 
 WebOb is released under an `MIT-style license <license.html>`_.
 
 ``req.POST``:
     A `dictionary-like object`_ with all the variables in the request
     body.  This only has variables if the request was a ``POST`` and
-    it is a form submission.  
+    it is a form submission.
 
 ``req.params``:
     A `dictionary-like object`_ with a combination of everything in
 Instantiating the Response
 --------------------------
 
-Of course most of the time you just want to *make* a response.  
+Of course most of the time you just want to *make* a response.
 Generally any attribute of the response can be passed in as a keyword
 argument to the class; e.g.:
 
 <comment-example.html>`_ shows middleware.  For applications it's more
 reasonable to use WebOb in the context of a larger framework.  `Pylons
 <http://pylonshq.com>`_ uses WebOb in 0.9.7+.
-
-
     keywords='wsgi request web http',
     author='Ian Bicking',
     author_email='ianb@colorstudy.com',
+    maintainer='Sergey Schetinin',
+    maintainer_email='sergey@maluke.com',
     url='http://pythonpaste.org/webob/',
     license='MIT',
     packages=['webob'],

tests/test_request.py

     assert req.body_file is old_body_file
 
 class UnseekableInputWithSeek(UnseekableInput):
-    def seek(self, pos):
+    def seek(self, pos, rel=0):
         raise IOError("Invalid seek!")
 
 def test_broken_seek():

tests/test_response.txt

     >>> tuple(result.content_range)
     (5, 10, 10)
 
+    >>> req_head = req.copy()
+    >>> req_head.method = 'HEAD'
+    >>> print req_head.get_response(res)
+    206 Partial Content
+    Content-Length: 5
+    Content-Range: bytes 5-9/10
+    Content-Type: text/html; charset=UTF-8
+
 And an invalid requested range:
 
     >>> req.range = (10, 20)
     >>> str(result.content_range)
     'bytes */10'
 
+    >>> req_head = req.copy()
+    >>> req_head.method = 'HEAD'
+    >>> print req_head.get_response(res)
+    416 Requested Range Not Satisfiable
+    Content-Length: 44
+    Content-Range: bytes */10
+    Content-Type: text/plain
+
     >>> Request.blank('/', range=(1,2)).get_response(
     ...     Response('0123456789', conditional_response=True)).content_length
     1

webob/descriptors.py

 
 def upath_property(key):
     def fget(req):
-        return req.environ[key].decode('UTF8', req.unicode_errors)
+        return req.environ.get(key, '').decode('UTF8', req.unicode_errors)
     def fset(req, val):
         req.environ[key] = val.encode('UTF8', req.unicode_errors)
     return property(fget, fset, doc='upath_property(%r)' % key)
 
     scheme = environ_getter('wsgi.url_scheme')
     method = environ_getter('REQUEST_METHOD')
-    script_name = environ_getter('SCRIPT_NAME')
+    script_name = environ_getter('SCRIPT_NAME', '')
     path_info = environ_getter('PATH_INFO')
     content_length = converter(
         environ_getter('CONTENT_LENGTH', None, '14.13'),
         clen = self.content_length
         if clen is None:
             clen = -1
-        r = self.body_file.read(clen)
-        self.body_file.seek(0)
+        f = self.environ['wsgi.input']
+        r = f.read(clen)
+        f.seek(0)
         return r
 
     def _body__set(self, value):
 
         This only does a shallow copy, except of wsgi.input
         """
+        self.make_body_seekable()
         env = self.environ.copy()
         new_req = self.__class__(env)
         new_req.copy_body()
         or a temporary file.
         """
         length = self.content_length
-        if length:
+        if length is not None:
             did_copy = self._copy_body_tempfile()
             if not did_copy:
                 self.body = self.body_file.read(length)
         assert isinstance(length, int)
         if not tempfile_limit or length <= tempfile_limit:
             return False
-        fileobj = tempfile.TemporaryFile()
+        fileobj = self.make_tempfile()
         input = self.body_file
         while length:
             data = input.read(min(length, 65536))
         self.environ['wsgi.input'] = fileobj
         return True
 
+    def make_tempfile(self):
+        """
+            Create a tempfile to store big request body
+        """
+        return tempfile.TemporaryFile()
+
 
     def remove_conditional_headers(self, remove_encoding=True, remove_range=True,
                                         remove_match=True, remove_modified=True):

webob/response.py

         params = []
         for k, v in sorted(value_dict.items()):
             if not _OK_PARAM_RE.search(v):
-                ## FIXME: I'm not sure what to do with "'s in the parameter value
-                ## I think it might be simply illegal
                 v = '"%s"' % v.replace('"', '\\"')
             params.append('; %s=%s' % (k, v))
         ct = self.headers.pop('Content-Type', '').split(';', 1)[0]
         if status304:
             start_response('304 Not Modified', filter_headers(headerlist))
             return EmptyResponse(self.app_iter)
-        if req.method == 'HEAD':
-            start_response(self.status, headerlist)
-            return EmptyResponse(self.app_iter)
-        # FIXME: we should handle HEAD requests with Range
         if (req.range and req.if_range.match_response(self)
             and self.content_range is None
-            and req.method == 'GET'
+            and req.method in ('HEAD', 'GET')
             and self.status_int == 200
             and self.content_length is not None
         ):
                     ('Content-Type', 'text/plain'),
                 ] + filter_headers(headerlist)
                 start_response('416 Requested Range Not Satisfiable', headerlist)
+                if req.method == 'HEAD':
+                    return ()
                 return [body]
             else:
                 app_iter = self.app_iter_range(content_range.start, content_range.stop)
                         ('Content-Range', str(content_range)),
                     ] + filter_headers(headerlist, ('content-length',))
                     start_response('206 Partial Content', headerlist)
+                    if req.method == 'HEAD':
+                        return EmptyResponse(app_iter)
                     return app_iter
 
         start_response(self.status, headerlist)
+        if req.method == 'HEAD':
+            return EmptyResponse(self.app_iter)
         return self.app_iter
 
     def app_iter_range(self, start, stop):