Skip to content

Commit

Permalink
Adapt istr (#1015)
Browse files Browse the repository at this point in the history
* Work on adapting istr

* Fix response tests

* Fix request tests

* Fix proxy tests

* Fix web exceptions tests

* Fix server tests

* Fix web response tests

* Fix web request tests

* Fix protocol tests

* Fix multipart tests

* Fix http parser tests

* Fix helpers tests

* Fix fuctional test

* Don't perform extra conversions
  • Loading branch information
asvetlov authored Jul 29, 2016
1 parent 67649c5 commit 8145024
Show file tree
Hide file tree
Showing 19 changed files with 205 additions and 213 deletions.
7 changes: 3 additions & 4 deletions aiohttp/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import warnings
import urllib.parse

from multidict import MultiDictProxy, MultiDict, CIMultiDict, upstr
from multidict import MultiDictProxy, MultiDict, CIMultiDict, istr

import aiohttp
from .client_reqrep import ClientRequest, ClientResponse
Expand Down Expand Up @@ -70,7 +70,7 @@ def __init__(self, *, connector=None, loop=None, cookies=None,
headers = CIMultiDict()
self._default_headers = headers
if skip_auto_headers is not None:
self._skip_auto_headers = frozenset([upstr(i)
self._skip_auto_headers = frozenset([istr(i)
for i in skip_auto_headers])
else:
self._skip_auto_headers = frozenset()
Expand Down Expand Up @@ -158,7 +158,6 @@ def _request(self, method, url, *,

redirects = 0
history = []
method = upstr(method)

# Merge with default headers and transform to CIMultiDict
headers = self._prepare_headers(headers)
Expand All @@ -175,7 +174,7 @@ def _request(self, method, url, *,
skip_headers = set(self._skip_auto_headers)
if skip_auto_headers is not None:
for i in skip_auto_headers:
skip_headers.add(upstr(i))
skip_headers.add(istr(i))

while True:

Expand Down
168 changes: 84 additions & 84 deletions aiohttp/hdrs.py
Original file line number Diff line number Diff line change
@@ -1,91 +1,91 @@
"""HTTP Headers constants."""
from multidict import upstr
from multidict import istr

METH_ANY = upstr('*')
METH_CONNECT = upstr('CONNECT')
METH_HEAD = upstr('HEAD')
METH_GET = upstr('GET')
METH_DELETE = upstr('DELETE')
METH_OPTIONS = upstr('OPTIONS')
METH_PATCH = upstr('PATCH')
METH_POST = upstr('POST')
METH_PUT = upstr('PUT')
METH_TRACE = upstr('TRACE')
METH_ANY = '*'
METH_CONNECT = 'CONNECT'
METH_HEAD = 'HEAD'
METH_GET = 'GET'
METH_DELETE = 'DELETE'
METH_OPTIONS = 'OPTIONS'
METH_PATCH = 'PATCH'
METH_POST = 'POST'
METH_PUT = 'PUT'
METH_TRACE = 'TRACE'

METH_ALL = {METH_CONNECT, METH_HEAD, METH_GET, METH_DELETE,
METH_OPTIONS, METH_PATCH, METH_POST, METH_PUT, METH_TRACE}


ACCEPT = upstr('ACCEPT')
ACCEPT_CHARSET = upstr('ACCEPT-CHARSET')
ACCEPT_ENCODING = upstr('ACCEPT-ENCODING')
ACCEPT_LANGUAGE = upstr('ACCEPT-LANGUAGE')
ACCEPT_RANGES = upstr('ACCEPT-RANGES')
ACCESS_CONTROL_MAX_AGE = upstr('ACCESS-CONTROL-MAX-AGE')
ACCESS_CONTROL_ALLOW_CREDENTIALS = upstr('ACCESS-CONTROL-ALLOW-CREDENTIALS')
ACCESS_CONTROL_ALLOW_HEADERS = upstr('ACCESS-CONTROL-ALLOW-HEADERS')
ACCESS_CONTROL_ALLOW_METHODS = upstr('ACCESS-CONTROL-ALLOW-METHODS')
ACCESS_CONTROL_ALLOW_ORIGIN = upstr('ACCESS-CONTROL-ALLOW-ORIGIN')
ACCESS_CONTROL_EXPOSE_HEADERS = upstr('ACCESS-CONTROL-EXPOSE-HEADERS')
ACCESS_CONTROL_REQUEST_HEADERS = upstr('ACCESS-CONTROL-REQUEST-HEADERS')
ACCESS_CONTROL_REQUEST_METHOD = upstr('ACCESS-CONTROL-REQUEST-METHOD')
AGE = upstr('AGE')
ALLOW = upstr('ALLOW')
AUTHORIZATION = upstr('AUTHORIZATION')
CACHE_CONTROL = upstr('CACHE-CONTROL')
CONNECTION = upstr('CONNECTION')
CONTENT_DISPOSITION = upstr('CONTENT-DISPOSITION')
CONTENT_ENCODING = upstr('CONTENT-ENCODING')
CONTENT_LANGUAGE = upstr('CONTENT-LANGUAGE')
CONTENT_LENGTH = upstr('CONTENT-LENGTH')
CONTENT_LOCATION = upstr('CONTENT-LOCATION')
CONTENT_MD5 = upstr('CONTENT-MD5')
CONTENT_RANGE = upstr('CONTENT-RANGE')
CONTENT_TRANSFER_ENCODING = upstr('CONTENT-TRANSFER-ENCODING')
CONTENT_TYPE = upstr('CONTENT-TYPE')
COOKIE = upstr('COOKIE')
DATE = upstr('DATE')
DESTINATION = upstr('DESTINATION')
DIGEST = upstr('DIGEST')
ETAG = upstr('ETAG')
EXPECT = upstr('EXPECT')
EXPIRES = upstr('EXPIRES')
FROM = upstr('FROM')
HOST = upstr('HOST')
IF_MATCH = upstr('IF-MATCH')
IF_MODIFIED_SINCE = upstr('IF-MODIFIED-SINCE')
IF_NONE_MATCH = upstr('IF-NONE-MATCH')
IF_RANGE = upstr('IF-RANGE')
IF_UNMODIFIED_SINCE = upstr('IF-UNMODIFIED-SINCE')
KEEP_ALIVE = upstr('KEEP-ALIVE')
LAST_EVENT_ID = upstr('LAST-EVENT-ID')
LAST_MODIFIED = upstr('LAST-MODIFIED')
LINK = upstr('LINK')
LOCATION = upstr('LOCATION')
MAX_FORWARDS = upstr('MAX-FORWARDS')
ORIGIN = upstr('ORIGIN')
PRAGMA = upstr('PRAGMA')
PROXY_AUTHENTICATE = upstr('PROXY_AUTHENTICATE')
PROXY_AUTHORIZATION = upstr('PROXY-AUTHORIZATION')
RANGE = upstr('RANGE')
REFERER = upstr('REFERER')
RETRY_AFTER = upstr('RETRY-AFTER')
SEC_WEBSOCKET_ACCEPT = upstr('SEC-WEBSOCKET-ACCEPT')
SEC_WEBSOCKET_VERSION = upstr('SEC-WEBSOCKET-VERSION')
SEC_WEBSOCKET_PROTOCOL = upstr('SEC-WEBSOCKET-PROTOCOL')
SEC_WEBSOCKET_KEY = upstr('SEC-WEBSOCKET-KEY')
SEC_WEBSOCKET_KEY1 = upstr('SEC-WEBSOCKET-KEY1')
SERVER = upstr('SERVER')
SET_COOKIE = upstr('SET-COOKIE')
TE = upstr('TE')
TRAILER = upstr('TRAILER')
TRANSFER_ENCODING = upstr('TRANSFER-ENCODING')
UPGRADE = upstr('UPGRADE')
WEBSOCKET = upstr('WEBSOCKET')
URI = upstr('URI')
USER_AGENT = upstr('USER-AGENT')
VARY = upstr('VARY')
VIA = upstr('VIA')
WANT_DIGEST = upstr('WANT-DIGEST')
WARNING = upstr('WARNING')
WWW_AUTHENTICATE = upstr('WWW-AUTHENTICATE')
ACCEPT = istr('ACCEPT')
ACCEPT_CHARSET = istr('ACCEPT-CHARSET')
ACCEPT_ENCODING = istr('ACCEPT-ENCODING')
ACCEPT_LANGUAGE = istr('ACCEPT-LANGUAGE')
ACCEPT_RANGES = istr('ACCEPT-RANGES')
ACCESS_CONTROL_MAX_AGE = istr('ACCESS-CONTROL-MAX-AGE')
ACCESS_CONTROL_ALLOW_CREDENTIALS = istr('ACCESS-CONTROL-ALLOW-CREDENTIALS')
ACCESS_CONTROL_ALLOW_HEADERS = istr('ACCESS-CONTROL-ALLOW-HEADERS')
ACCESS_CONTROL_ALLOW_METHODS = istr('ACCESS-CONTROL-ALLOW-METHODS')
ACCESS_CONTROL_ALLOW_ORIGIN = istr('ACCESS-CONTROL-ALLOW-ORIGIN')
ACCESS_CONTROL_EXPOSE_HEADERS = istr('ACCESS-CONTROL-EXPOSE-HEADERS')
ACCESS_CONTROL_REQUEST_HEADERS = istr('ACCESS-CONTROL-REQUEST-HEADERS')
ACCESS_CONTROL_REQUEST_METHOD = istr('ACCESS-CONTROL-REQUEST-METHOD')
AGE = istr('AGE')
ALLOW = istr('ALLOW')
AUTHORIZATION = istr('AUTHORIZATION')
CACHE_CONTROL = istr('CACHE-CONTROL')
CONNECTION = istr('CONNECTION')
CONTENT_DISPOSITION = istr('CONTENT-DISPOSITION')
CONTENT_ENCODING = istr('CONTENT-ENCODING')
CONTENT_LANGUAGE = istr('CONTENT-LANGUAGE')
CONTENT_LENGTH = istr('CONTENT-LENGTH')
CONTENT_LOCATION = istr('CONTENT-LOCATION')
CONTENT_MD5 = istr('CONTENT-MD5')
CONTENT_RANGE = istr('CONTENT-RANGE')
CONTENT_TRANSFER_ENCODING = istr('CONTENT-TRANSFER-ENCODING')
CONTENT_TYPE = istr('CONTENT-TYPE')
COOKIE = istr('COOKIE')
DATE = istr('DATE')
DESTINATION = istr('DESTINATION')
DIGEST = istr('DIGEST')
ETAG = istr('ETAG')
EXPECT = istr('EXPECT')
EXPIRES = istr('EXPIRES')
FROM = istr('FROM')
HOST = istr('HOST')
IF_MATCH = istr('IF-MATCH')
IF_MODIFIED_SINCE = istr('IF-MODIFIED-SINCE')
IF_NONE_MATCH = istr('IF-NONE-MATCH')
IF_RANGE = istr('IF-RANGE')
IF_UNMODIFIED_SINCE = istr('IF-UNMODIFIED-SINCE')
KEEP_ALIVE = istr('KEEP-ALIVE')
LAST_EVENT_ID = istr('LAST-EVENT-ID')
LAST_MODIFIED = istr('LAST-MODIFIED')
LINK = istr('LINK')
LOCATION = istr('LOCATION')
MAX_FORWARDS = istr('MAX-FORWARDS')
ORIGIN = istr('ORIGIN')
PRAGMA = istr('PRAGMA')
PROXY_AUTHENTICATE = istr('PROXY_AUTHENTICATE')
PROXY_AUTHORIZATION = istr('PROXY-AUTHORIZATION')
RANGE = istr('RANGE')
REFERER = istr('REFERER')
RETRY_AFTER = istr('RETRY-AFTER')
SEC_WEBSOCKET_ACCEPT = istr('SEC-WEBSOCKET-ACCEPT')
SEC_WEBSOCKET_VERSION = istr('SEC-WEBSOCKET-VERSION')
SEC_WEBSOCKET_PROTOCOL = istr('SEC-WEBSOCKET-PROTOCOL')
SEC_WEBSOCKET_KEY = istr('SEC-WEBSOCKET-KEY')
SEC_WEBSOCKET_KEY1 = istr('SEC-WEBSOCKET-KEY1')
SERVER = istr('SERVER')
SET_COOKIE = istr('SET-COOKIE')
TE = istr('TE')
TRAILER = istr('TRAILER')
TRANSFER_ENCODING = istr('TRANSFER-ENCODING')
UPGRADE = istr('UPGRADE')
WEBSOCKET = istr('WEBSOCKET')
URI = istr('URI')
USER_AGENT = istr('USER-AGENT')
VARY = istr('VARY')
VIA = istr('VIA')
WANT_DIGEST = istr('WANT-DIGEST')
WARNING = istr('WARNING')
WWW_AUTHENTICATE = istr('WWW-AUTHENTICATE')
16 changes: 8 additions & 8 deletions aiohttp/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from pathlib import Path
from urllib.parse import quote, urlencode, urlsplit

import multidict
from multidict import MultiDict, MultiDictProxy

from . import hdrs
from .abc import AbstractCookieJar
Expand Down Expand Up @@ -119,7 +119,7 @@ def add_field(self, name, value, *, content_type=None, filename=None,
if filename is None and content_transfer_encoding is None:
filename = name

type_options = multidict.MultiDict({'name': name})
type_options = MultiDict({'name': name})
if filename is not None and not isinstance(filename, str):
raise TypeError('filename must be an instance of str. '
'Got: %s' % filename)
Expand Down Expand Up @@ -155,9 +155,7 @@ def add_fields(self, *fields):
k = guess_filename(rec, 'unknown')
self.add_field(k, rec)

elif isinstance(rec,
(multidict.MultiDictProxy,
multidict.MultiDict)):
elif isinstance(rec, (MultiDictProxy, MultiDict)):
to_add.extend(rec.items())

elif isinstance(rec, (list, tuple)) and len(rec) == 2:
Expand Down Expand Up @@ -331,17 +329,19 @@ def compile_format(self, log_format):

@staticmethod
def _format_e(key, args):
return (args[1] or {}).get(multidict.upstr(key), '-')
return (args[1] or {}).get(key, '-')

@staticmethod
def _format_i(key, args):
if not args[0]:
return '(no headers)'
return args[0].headers.get(multidict.upstr(key), '-')
# suboptimal, make istr(key) once
return args[0].headers.get(key, '-')

@staticmethod
def _format_o(key, args):
return args[2].headers.get(multidict.upstr(key), '-')
# suboptimal, make istr(key) once
return args[2].headers.get(key, '-')

@staticmethod
def _format_a(args):
Expand Down
6 changes: 3 additions & 3 deletions aiohttp/protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import zlib
from abc import abstractmethod, ABC
from wsgiref.handlers import format_date_time
from multidict import CIMultiDict, upstr
from multidict import CIMultiDict, istr

import aiohttp
from . import errors, hdrs
Expand Down Expand Up @@ -115,7 +115,7 @@ def parse_headers(self, lines):

bvalue = bvalue.strip()

name = bname.decode('utf-8', 'surrogateescape')
name = istr(bname.decode('utf-8', 'surrogateescape'))
value = bvalue.decode('utf-8', 'surrogateescape')

# keep-alive and encoding
Expand Down Expand Up @@ -608,7 +608,7 @@ def add_header(self, name, value):
'Header {!r} should have string value, got {!r}'.format(
name, value)

name = upstr(name)
name = istr(name)
value = value.strip()

if name == hdrs.CONTENT_LENGTH:
Expand Down
2 changes: 1 addition & 1 deletion aiohttp/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ def handle_request(self, message, payload):
return

for hdr, val in message.headers.items():
if (hdr == 'EXPECT') and (val == '100-continue'):
if (hdr.upper() == 'EXPECT') and (val == '100-continue'):
self.transport.write(b'HTTP/1.0 100 Continue\r\n\r\n')
break

Expand Down
14 changes: 6 additions & 8 deletions aiohttp/web_urldispatcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@
from urllib.parse import urlencode, unquote
from types import MappingProxyType

from multidict import upstr

from . import hdrs
from .abc import AbstractRouter, AbstractMatchInfo, AbstractView
from .file_sender import FileSender
Expand Down Expand Up @@ -80,7 +78,7 @@ def __init__(self, method, handler, *,
assert asyncio.iscoroutinefunction(expect_handler), \
'Coroutine is expected, got {!r}'.format(expect_handler)

method = upstr(method)
method = method.upper()
if method not in self.METHODS:
raise ValueError("{} is not allowed HTTP method".format(method))

Expand Down Expand Up @@ -743,28 +741,28 @@ def add_get(self, *args, **kwargs):
"""
Shortcut for add_route with method GET
"""
return self.add_route('GET', *args, **kwargs)
return self.add_route(hdrs.METH_GET, *args, **kwargs)

def add_post(self, *args, **kwargs):
"""
Shortcut for add_route with method POST
"""
return self.add_route('POST', *args, **kwargs)
return self.add_route(hdrs.METH_POST, *args, **kwargs)

def add_put(self, *args, **kwargs):
"""
Shortcut for add_route with method PUT
"""
return self.add_route('PUT', *args, **kwargs)
return self.add_route(hdrs.METH_PUT, *args, **kwargs)

def add_patch(self, *args, **kwargs):
"""
Shortcut for add_route with method PATCH
"""
return self.add_route('PATCH', *args, **kwargs)
return self.add_route(hdrs.METH_PATCH, *args, **kwargs)

def add_delete(self, *args, **kwargs):
"""
Shortcut for add_route with method DELETE
"""
return self.add_route('DELETE', *args, **kwargs)
return self.add_route(hdrs.METH_DELETE, *args, **kwargs)
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def build_extension(self, ext):
raise RuntimeError('Unable to determine version.')


install_requires = ['chardet', 'multidict>=1.1.0,<2']
install_requires = ['chardet', 'multidict>=2.0']

if sys.version_info < (3, 4, 1):
raise RuntimeError("aiohttp requires Python 3.4.1+")
Expand Down
6 changes: 3 additions & 3 deletions tests/test_client_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -458,23 +458,23 @@ def test_content_type_auto_header_bytes(self):

def test_content_type_skip_auto_header_bytes(self):
req = ClientRequest('post', 'http://python.org', data=b'hey you',
skip_auto_headers={'CONTENT-TYPE'},
skip_auto_headers={'Content-Type'},
loop=self.loop)
resp = req.send(self.transport, self.protocol)
self.assertNotIn('CONTENT-TYPE', req.headers)
resp.close()

def test_content_type_skip_auto_header_form(self):
req = ClientRequest('post', 'http://python.org', data={'hey': 'you'},
loop=self.loop, skip_auto_headers={'CONTENT-TYPE'})
loop=self.loop, skip_auto_headers={'Content-Type'})
resp = req.send(self.transport, self.protocol)
self.assertNotIn('CONTENT-TYPE', req.headers)
resp.close()

def test_content_type_auto_header_content_length_no_skip(self):
req = ClientRequest('get', 'http://python.org',
data=io.BytesIO(b'hey'),
skip_auto_headers={'CONTENT-LENGTH'},
skip_auto_headers={'Content-Length'},
loop=self.loop)
resp = req.send(self.transport, self.protocol)
self.assertEqual(req.headers.get('CONTENT-LENGTH'), '3')
Expand Down
Loading

0 comments on commit 8145024

Please sign in to comment.