Skip to content

Commit

Permalink
Deprecated BaseRequest.has_body, replaced with 2 new attributes (aio-…
Browse files Browse the repository at this point in the history
…libs#2005) (aio-libs#2169)

* Deprecated BaseRequest.has_body, replaced with 2 new attributes

* Test obsolete BaseRequest.has_body attr
  • Loading branch information
David Poirier authored and arthurdarcet committed Aug 8, 2017
1 parent bdd862b commit 22c0fed
Show file tree
Hide file tree
Showing 5 changed files with 151 additions and 4 deletions.
16 changes: 15 additions & 1 deletion aiohttp/web_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

from . import hdrs, multipart
from .helpers import HeadersMixin, SimpleCookie, reify, sentinel
from .streams import EmptyStreamReader
from .web_exceptions import HTTPRequestEntityTooLarge


Expand Down Expand Up @@ -457,9 +458,22 @@ def content(self):

@property
def has_body(self):
"""Return True if request has HTTP BODY, False otherwise."""
"""Return True if request's HTTP BODY can be read, False otherwise."""
warnings.warn(
"Deprecated, use .can_read_body #2005",
DeprecationWarning, stacklevel=2)
return not self._payload.at_eof()

@property
def can_read_body(self):
"""Return True if request's HTTP BODY can be read, False otherwise."""
return not self._payload.at_eof()

@property
def body_exists(self):
"""Return True if request has HTTP BODY, False otherwise."""
return type(self._payload) is not EmptyStreamReader

@asyncio.coroutine
def release(self):
"""Release request.
Expand Down
3 changes: 3 additions & 0 deletions changes/2005.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
- Deprecated BaseRequest.has_body in favour of BaseRequest.can_read_body
- Added BaseRequest.body_exists attribute that stays static for the lifetime
of the request
24 changes: 21 additions & 3 deletions docs/web_reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -230,15 +230,33 @@ and :ref:`aiohttp-web-signals` handlers.

Read-only property.

.. attribute:: has_body
.. attribute:: body_exists

Return ``True`` if request has *HTTP BODY*, ``False`` otherwise.

Read-only :class:`bool` property.

.. versionadded:: 0.16
.. versionadded:: 2.3

.. attribute:: can_read_body

.. attribute:: content_type
Return ``True`` if request's *HTTP BODY* can be read, ``False`` otherwise.

Read-only :class:`bool` property.

.. versionadded:: 2.3

.. attribute:: has_body

Return ``True`` if request's *HTTP BODY* can be read, ``False`` otherwise.

Read-only :class:`bool` property.

.. deprecated:: 2.3

Use :meth:`can_read_body` instead.

.. attribute:: content_type

Read-only property with *content* part of *Content-Type* header.

Expand Down
4 changes: 4 additions & 0 deletions tests/test_web_functional.py
Original file line number Diff line number Diff line change
Expand Up @@ -694,6 +694,8 @@ def test_empty_content_for_query_without_body(loop, test_client):

@asyncio.coroutine
def handler(request):
assert not request.body_exists
assert not request.can_read_body
assert not request.has_body
return web.Response()

Expand All @@ -710,6 +712,8 @@ def test_empty_content_for_query_with_body(loop, test_client):

@asyncio.coroutine
def handler(request):
assert request.body_exists
assert request.can_read_body
assert request.has_body
body = yield from request.read()
return web.Response(body=body)
Expand Down
108 changes: 108 additions & 0 deletions tools/bench-asyncio-write.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import asyncio
import atexit
import csv
import math
import os
import signal

PORT = 8888

server = os.fork()
if server == 0:
loop = asyncio.get_event_loop()
coro = asyncio.start_server(lambda *_: None, port=PORT)
loop.run_until_complete(coro)
loop.run_forever()
else:
atexit.register(os.kill, server, signal.SIGTERM)


async def write_joined_bytearray(writer, chunks):
body = bytearray(chunks[0])
for c in chunks[1:]:
body += c
writer.write(body)

async def write_joined_list(writer, chunks):
body = b''.join(chunks)
writer.write(body)

async def write_separately(writer, chunks):
for c in chunks:
writer.write(c)


def fm_size(s, _fms=('', 'K', 'M', 'G')):
i = 0
while s > 1024:
s /= 1024
i += 1
return '{:.1f}{}B'.format(s, _fms[i])

writes = {
'Join the chunks in a bytearray then write': write_joined_bytearray,
'Join the chunks with a list then write': write_joined_list,
'Write the chunks separately': write_separately,
}

bodies = (
[],
[2 ** 7],
[2 ** 17],
[2 ** 27],
[2 ** 30],
[1000 * 2 ** 0 for _ in range(1)],
[ 100 * 2 ** 0 for _ in range(10)],
[ 10 * 2 ** 0 for _ in range(100)],
[ 2 ** 0 for _ in range(1000)],
[1000 * 2 ** 10 for _ in range(1)],
[ 100 * 2 ** 10 for _ in range(10)],
[ 10 * 2 ** 10 for _ in range(100)],
[ 2 ** 10 for _ in range(1000)],
[1000 * 2 ** 20 for _ in range(1)],
[ 100 * 2 ** 20 for _ in range(10)],
[ 10 * 2 ** 20 for _ in range(100)],
[ 2 ** 20 for _ in range(1000)],
)

jobs = [(
# always start with a 256B headers chunk
'{} in {} chunks'.format(fm_size(sum(j) if j else 0), len(j)),
[b'0' * s for s in [256] + list(j)],
) for j in bodies]

async def time(loop, fn, *args):
spent = []
while len(spent) < 10000 and (not spent or sum(spent) < .2):
s = loop.time()
await fn(*args)
e = loop.time()
spent.append(e - s)
mean = sum(spent) / len(spent)
sd = sum((x - mean) ** 2 for x in spent) / len(spent)
return len(spent), mean, math.sqrt(sd)

async def main(loop):
_, writer = await asyncio.open_connection(port=PORT)
res = []
for t, c in jobs:
print(t)
for k, v in writes.items():
print('{:<42}: '.format(k), end='')
coro = time(loop, v, writer, c)
try:
it, mean, sd = await asyncio.wait_for(coro, 2)
except asyncio.TimeoutError:
print('timed out')
else:
print('{:.6f}ms per loop (stdev: {:.3f}ms, {} iterations)'.format(mean * 1000, sd * 1000, it))
res.append([t, k, mean, sd, it])
print('--')
with open('bench.csv', 'w', newline='') as f:
w = csv.writer(f)
w.writerow(['Job', 'Writer', 'Mean', 'St dev', 'Iterations'])
for r in res:
w.writerow(r)

loop = asyncio.get_event_loop()
loop.run_until_complete(main(loop))

0 comments on commit 22c0fed

Please sign in to comment.