Ticket #5682: patch_django_5682.20080309.diff

File patch_django_5682.20080309.diff, 15.5 KB (added by David Larlet, 16 years ago)

Patch against r7207, no improvements yet

  • django/http/__init__.py

     
    11import os
    22from Cookie import SimpleCookie
    33from pprint import pformat
    4 from urllib import urlencode
     4from urllib import urlencode, unquote
    55from urlparse import urljoin
    66try:
    77    # The mod_python version is more efficient, so try importing it first.
     
    2323class HttpRequest(object):
    2424    """A basic HTTP request."""
    2525
    26     # The encoding used in GET/POST dicts. None means use default setting.
     26    # The encoding used in GET/POST/PUT dicts. None means use default setting.
    2727    _encoding = None
    2828
    2929    def __init__(self):
    30         self.GET, self.POST, self.COOKIES, self.META, self.FILES = {}, {}, {}, {}, {}
     30        self.GET, self.POST, self.PUT, self.COOKIES, self.META, self.DATA, self.FILES = {}, {}, {}, {}, {}, {}, {}
    3131        self.path = ''
    3232        self.method = None
    3333
    3434    def __repr__(self):
    35         return '<HttpRequest\nGET:%s,\nPOST:%s,\nCOOKIES:%s,\nMETA:%s>' % \
    36             (pformat(self.GET), pformat(self.POST), pformat(self.COOKIES),
    37             pformat(self.META))
     35        return '<HttpRequest\nGET:%s,\nPOST:%s,\nPUT:%s,\nCOOKIES:%s,\nMETA:%s>' % \
     36            (pformat(self.GET), pformat(self.POST), pformat(self.PUT),
     37            pformat(self.COOKIES), pformat(self.META))
    3838
    3939    def __getitem__(self, key):
    40         for d in (self.POST, self.GET):
     40        for d in (self.POST, self.GET, self.PUT):
    4141            if key in d:
    4242                return d[key]
    43         raise KeyError, "%s not found in either POST or GET" % key
     43        raise KeyError, "%s not found in either POST, GET or PUT" % key
    4444
    4545    def has_key(self, key):
    46         return key in self.GET or key in self.POST
     46        return key in self.GET or key in self.POST or key in self.PUT
    4747
    4848    __contains__ = has_key
    4949
     
    8484
    8585    def _set_encoding(self, val):
    8686        """
    87         Sets the encoding used for GET/POST accesses. If the GET or POST
     87        Sets the encoding used for GET/POST/PUT accesses. If the GET, POST or PUT
    8888        dictionary has already been created, it is removed and recreated on the
    8989        next access (so that it is decoded correctly).
    9090        """
     
    9393            del self._get
    9494        if hasattr(self, '_post'):
    9595            del self._post
     96        if hasattr(self, '_put'):
     97            del self._put
    9698
    9799    def _get_encoding(self):
    98100        return self._encoding
     
    100102    encoding = property(_get_encoding, _set_encoding)
    101103
    102104def parse_file_upload(header_dict, post_data):
    103     """Returns a tuple of (POST QueryDict, FILES MultiValueDict)."""
     105    """Returns a tuple of (DATA QueryDict, FILES MultiValueDict)."""
    104106    import email, email.Message
    105107    from cgi import parse_header
    106108    raw_message = '\r\n'.join(['%s:%s' % pair for pair in header_dict.items()])
    107109    raw_message += '\r\n\r\n' + post_data
    108110    msg = email.message_from_string(raw_message)
    109     POST = QueryDict('', mutable=True)
     111    DATA = QueryDict('', mutable=True)
    110112    FILES = MultiValueDict()
    111113    for submessage in msg.get_payload():
    112114        if submessage and isinstance(submessage, email.Message.Message):
     
    129131                    'content': submessage.get_payload(),
    130132                }))
    131133            else:
    132                 POST.appendlist(name_dict['name'], submessage.get_payload())
    133     return POST, FILES
     134                DATA.appendlist(name_dict['name'], submessage.get_payload())
     135    return DATA, FILES
    134136
    135137
    136138class QueryDict(MultiValueDict):
     
    198200    def appendlist(self, key, value):
    199201        self._assert_mutable()
    200202        key = str_to_unicode(key, self.encoding)
     203        if key == u'text': # restrict unquoting for sms
     204            value = unquote(value)
    201205        value = str_to_unicode(value, self.encoding)
    202206        MultiValueDict.appendlist(self, key, value)
    203207
  • django/test/client.py

     
    216216
    217217        return self.request(**r)
    218218
     219    def delete(self, path, data={}, **extra):
     220        "Request a response from the server using DELETE."
     221        r = {
     222            'CONTENT_LENGTH':  None,
     223            'CONTENT_TYPE':    'text/html; charset=utf-8',
     224            'PATH_INFO':       path,
     225            'QUERY_STRING':    urlencode(data, doseq=True),
     226            'REQUEST_METHOD': 'DELETE',
     227        }
     228        r.update(extra)
     229
     230        return self.request(**r)
     231
     232    def delete(self, path, data={}, **extra):
     233        "Request a response from the server using DELETE."
     234        r = {
     235            'CONTENT_LENGTH':  None,
     236            'CONTENT_TYPE':    'text/html; charset=utf-8',
     237            'PATH_INFO':       path,
     238            'QUERY_STRING':    urlencode(data, doseq=True),
     239            'REQUEST_METHOD': 'DELETE',
     240        }
     241        r.update(extra)
     242
     243        return self.request(**r)
     244
    219245    def post(self, path, data={}, content_type=MULTIPART_CONTENT, **extra):
    220246        "Request a response from the server using POST."
    221247
     
    235261
    236262        return self.request(**r)
    237263
     264    def put(self, path, data={}, content_type=MULTIPART_CONTENT, **extra):
     265        "Request a response from the server using PUT."
     266
     267        if content_type is MULTIPART_CONTENT:
     268            put_data = encode_multipart(BOUNDARY, data)
     269        else:
     270            put_data = data
     271
     272        r = {
     273            'CONTENT_LENGTH': len(put_data),
     274            'CONTENT_TYPE':   content_type,
     275            'PATH_INFO':      path,
     276            'REQUEST_METHOD': 'PUT',
     277            'wsgi.input':     StringIO(put_data),
     278        }
     279        r.update(extra)
     280
     281        return self.request(**r)
     282
     283    def put(self, path, data={}, content_type=MULTIPART_CONTENT, **extra):
     284        "Request a response from the server using PUT."
     285
     286        if content_type is MULTIPART_CONTENT:
     287            put_data = encode_multipart(BOUNDARY, data)
     288        else:
     289            put_data = data
     290
     291        r = {
     292            'CONTENT_LENGTH': len(put_data),
     293            'CONTENT_TYPE':   content_type,
     294            'PATH_INFO':      path,
     295            'REQUEST_METHOD': 'PUT',
     296            'wsgi.input':     StringIO(put_data),
     297        }
     298        r.update(extra)
     299
     300        return self.request(**r)
     301
    238302    def login(self, **credentials):
    239303        """Set the Client to appear as if it has sucessfully logged into a site.
    240304
  • django/core/handlers/wsgi.py

     
    9191        except:
    9292            post = '<could not parse>'
    9393        try:
     94            put = pformat(self.PUT)
     95        except:
     96            put = '<could not parse>'
     97        try:
    9498            cookies = pformat(self.COOKIES)
    9599        except:
    96100            cookies = '<could not parse>'
     
    98102            meta = pformat(self.META)
    99103        except:
    100104            meta = '<could not parse>'
    101         return '<WSGIRequest\nGET:%s,\nPOST:%s,\nCOOKIES:%s,\nMETA:%s>' % \
    102             (get, post, cookies, meta)
     105        return '<WSGIRequest\nGET:%s,\nPOST:%s,\nPUT:%s,\nCOOKIES:%s,\nMETA:%s>' % \
     106            (get, post, put, cookies, meta)
    103107
    104108    def get_full_path(self):
    105109        return '%s%s' % (self.path, self.environ.get('QUERY_STRING', '') and ('?' + self.environ.get('QUERY_STRING', '')) or '')
     
    108112        return 'wsgi.url_scheme' in self.environ \
    109113            and self.environ['wsgi.url_scheme'] == 'https'
    110114
    111     def _load_post_and_files(self):
    112         # Populates self._post and self._files
    113         if self.method == 'POST':
     115    def _load_data_and_files(self):
     116        # Populates self._data and self._files
     117        if self.method in ('POST', 'PUT'):
    114118            if self.environ.get('CONTENT_TYPE', '').startswith('multipart'):
    115119                header_dict = dict([(k, v) for k, v in self.environ.items() if k.startswith('HTTP_')])
    116120                header_dict['Content-Type'] = self.environ.get('CONTENT_TYPE', '')
    117                 self._post, self._files = http.parse_file_upload(header_dict, self.raw_post_data)
     121                self._data, self._files = http.parse_file_upload(header_dict, self.raw_post_data)
    118122            else:
    119                 self._post, self._files = http.QueryDict(self.raw_post_data, encoding=self._encoding), datastructures.MultiValueDict()
     123                self._data, self._files = http.QueryDict(self.raw_post_data, encoding=self._encoding), datastructures.MultiValueDict()
    120124        else:
    121             self._post, self._files = http.QueryDict('', encoding=self._encoding), datastructures.MultiValueDict()
     125            self._data, self._files = http.QueryDict('', encoding=self._encoding), datastructures.MultiValueDict()
    122126
     127    def _load_post_and_files(self):
     128        # Populates self._post, preserve backward compatibility.
     129        if not hasattr(self, '_data'):
     130            self._load_data_and_files()
     131        self._post = self._data
     132
    123133    def _get_request(self):
    124134        if not hasattr(self, '_request'):
    125             self._request = datastructures.MergeDict(self.POST, self.GET)
     135            self._request = datastructures.MergeDict(self.POST, self.PUT, self.GET)
    126136        return self._request
    127137
    128138    def _get_get(self):
    129139        if not hasattr(self, '_get'):
    130140            # The WSGI spec says 'QUERY_STRING' may be absent.
    131             self._get = http.QueryDict(self.environ.get('QUERY_STRING', ''), encoding=self._encoding)
     141            query_string = self.environ.get('QUERY_STRING', '')
     142            if 'charset' in query_string: # for sms
     143                self._encoding = query_string.split('charset=', 1)[1].split('&', 1)[0].lower()
     144            self._get = http.QueryDict(query_string, encoding=self._encoding)
    132145        return self._get
    133146
    134147    def _set_get(self, get):
     
    136149
    137150    def _get_post(self):
    138151        if not hasattr(self, '_post'):
    139             self._load_post_and_files()
     152            self._post = self.DATA
    140153        return self._post
    141154
    142155    def _set_post(self, post):
    143156        self._post = post
    144157
     158    def _get_put(self):
     159        if not hasattr(self, '_put'):
     160            self._put = self.DATA
     161        return self._put
     162
     163    def _set_put(self, put):
     164        self._put = put
     165
    145166    def _get_cookies(self):
    146167        if not hasattr(self, '_cookies'):
    147168            self._cookies = http.parse_cookie(self.environ.get('HTTP_COOKIE', ''))
     
    152173
    153174    def _get_files(self):
    154175        if not hasattr(self, '_files'):
    155             self._load_post_and_files()
     176            self._load_data_and_files()
    156177        return self._files
    157178
     179    def _get_data(self):
     180        if not hasattr(self, '_data'):
     181            self._load_data_and_files()
     182        return self._data
     183
    158184    def _get_raw_post_data(self):
    159185        try:
    160186            return self._raw_post_data
     
    174200
    175201    GET = property(_get_get, _set_get)
    176202    POST = property(_get_post, _set_post)
     203    PUT = property(_get_put, _set_put)
    177204    COOKIES = property(_get_cookies, _set_cookies)
    178205    FILES = property(_get_files)
     206    DATA = property(_get_data)
    179207    REQUEST = property(_get_request)
    180208    raw_post_data = property(_get_raw_post_data)
    181209
     210
    182211class WSGIHandler(BaseHandler):
    183212    initLock = Lock()
    184213    request_class = WSGIRequest
  • django/core/handlers/modpython.py

     
    2929        except:
    3030            post = '<could not parse>'
    3131        try:
     32            put = pformat(self.PUT)
     33        except:
     34            put = '<could not parse>'
     35        try:
    3236            cookies = pformat(self.COOKIES)
    3337        except:
    3438            cookies = '<could not parse>'
     
    3640            meta = pformat(self.META)
    3741        except:
    3842            meta = '<could not parse>'
    39         return smart_str(u'<ModPythonRequest\npath:%s,\nGET:%s,\nPOST:%s,\nCOOKIES:%s,\nMETA:%s>' %
     43        return smart_str(u'<ModPythonRequest\npath:%s,\nGET:%s,\nPOST:%s,\nPUT:%s,\nCOOKIES:%s,\nMETA:%s>' %
    4044                         (self.path, unicode(get), unicode(post),
    41                           unicode(cookies), unicode(meta)))
     45                          unicode(put), unicode(cookies), unicode(meta)))
    4246
    4347    def get_full_path(self):
    4448        return '%s%s' % (self.path, self._req.args and ('?' + self._req.args) or '')
     
    5054            # mod_python < 3.2.10 doesn't have req.is_https().
    5155            return self._req.subprocess_env.get('HTTPS', '').lower() in ('on', '1')
    5256
    53     def _load_post_and_files(self):
     57    def _load_data_and_files(self):
    5458        "Populates self._post and self._files"
    5559        if 'content-type' in self._req.headers_in and self._req.headers_in['content-type'].startswith('multipart'):
    56             self._post, self._files = http.parse_file_upload(self._req.headers_in, self.raw_post_data)
     60            self._data, self._files = http.parse_file_upload(self._req.headers_in, self.raw_post_data)
    5761        else:
    58             self._post, self._files = http.QueryDict(self.raw_post_data, encoding=self._encoding), datastructures.MultiValueDict()
     62            self._data, self._files = http.QueryDict(self.raw_post_data, encoding=self._encoding), datastructures.MultiValueDict()
    5963
     64    def _load_post_and_files(self):
     65        # Populates self._post, preserve backward compatibility.
     66        if not hasattr(self, '_data'):
     67            self._load_data_and_files()
     68        self._post = self._data
     69
    6070    def _get_request(self):
    6171        if not hasattr(self, '_request'):
    62             self._request = datastructures.MergeDict(self.POST, self.GET)
     72            self._request = datastructures.MergeDict(self.POST, self.PUT, self.GET)
    6373        return self._request
    6474
    6575    def _get_get(self):
    6676        if not hasattr(self, '_get'):
     77            if self._req.args is not None and 'charset' in self._req.args: # for sms
     78                self._encoding = self._req.args.split('charset=', 1)[1].split('&', 1)[0].lower()
    6779            self._get = http.QueryDict(self._req.args, encoding=self._encoding)
    6880        return self._get
    6981
     
    7284
    7385    def _get_post(self):
    7486        if not hasattr(self, '_post'):
    75             self._load_post_and_files()
     87            self._post = self.DATA
    7688        return self._post
    7789
    7890    def _set_post(self, post):
    7991        self._post = post
    8092
     93    def _get_put(self):
     94        if not hasattr(self, '_put'):
     95            self._put = self.DATA
     96        return self._put
     97
     98    def _set_put(self, put):
     99        self._put = put
     100
    81101    def _get_cookies(self):
    82102        if not hasattr(self, '_cookies'):
    83103            self._cookies = http.parse_cookie(self._req.headers_in.get('cookie', ''))
     
    86106    def _set_cookies(self, cookies):
    87107        self._cookies = cookies
    88108
     109    def _get_data(self):
     110        if not hasattr(self, '_data'):
     111            self._load_data_and_files()
     112        return self._data
     113
    89114    def _get_files(self):
    90115        if not hasattr(self, '_files'):
    91             self._load_post_and_files()
     116            self._load_data_and_files()
    92117        return self._files
    93118
    94119    def _get_meta(self):
     
    130155
    131156    GET = property(_get_get, _set_get)
    132157    POST = property(_get_post, _set_post)
     158    PUT = property(_get_put, _set_put)
    133159    COOKIES = property(_get_cookies, _set_cookies)
    134160    FILES = property(_get_files)
     161    DATA = property(_get_data)
    135162    META = property(_get_meta)
    136163    REQUEST = property(_get_request)
    137164    raw_post_data = property(_get_raw_post_data)
Back to Top