Skip to content

Commit eb7073c

Browse files
committed
Merge pull request #525 from KeepSafe/resp_prepare
Resp prepare
2 parents ef94077 + 22c42c4 commit eb7073c

15 files changed

+244
-111
lines changed

CHANGES.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ CHANGES
22
=======
33

44
0.18.0a0 (XX-XX-XXXX)
5-
-------------------
5+
---------------------
66

77
- Use errors.HttpProcessingError.message as HTTP error reason and
88
message #459

aiohttp/web.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ def handle_request(self, message, payload):
9292
except HTTPException as exc:
9393
resp = exc
9494

95-
resp_msg = resp.start(request)
95+
resp_msg = yield from resp.prepare(request)
9696
yield from resp.write_eof()
9797

9898
# notify server about keep-alive

aiohttp/web_reqrep.py

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -425,9 +425,14 @@ def _copy_cookies(self):
425425
self.headers.add(hdrs.SET_COOKIE, value)
426426

427427
@property
428-
def started(self):
428+
def prepared(self):
429429
return self._resp_impl is not None
430430

431+
@property
432+
def started(self):
433+
warnings.warn('use Response.prepared instead', DeprecationWarning)
434+
return self.prepared
435+
431436
@property
432437
def status(self):
433438
return self._status
@@ -612,27 +617,39 @@ def _start_pre_check(self, request):
612617
return None
613618

614619
def _start_compression(self, request):
615-
def start(coding):
620+
def _start(coding):
616621
if coding != ContentCoding.identity:
617622
self.headers[hdrs.CONTENT_ENCODING] = coding.value
618623
self._resp_impl.add_compression_filter(coding.value)
619624
self.content_length = None
620625

621626
if self._compression_force:
622-
start(self._compression_force)
627+
_start(self._compression_force)
623628
else:
624629
accept_encoding = request.headers.get(
625630
hdrs.ACCEPT_ENCODING, '').lower()
626631
for coding in ContentCoding:
627632
if coding.value in accept_encoding:
628-
start(coding)
633+
_start(coding)
629634
return
630635

631636
def start(self, request):
637+
warnings.warn('use .prepare(request) instead', DeprecationWarning)
632638
resp_impl = self._start_pre_check(request)
633639
if resp_impl is not None:
634640
return resp_impl
635641

642+
return self._start(request)
643+
644+
@asyncio.coroutine
645+
def prepare(self, request):
646+
resp_impl = self._start_pre_check(request)
647+
if resp_impl is not None:
648+
return resp_impl
649+
650+
return self._start(request)
651+
652+
def _start(self, request):
636653
self._req = request
637654
keep_alive = self._keep_alive
638655
if keep_alive is None:

aiohttp/web_urldispatcher.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ def handle(self, request):
281281
file_size = st.st_size
282282

283283
resp.content_length = file_size
284-
resp.start(request)
284+
yield from resp.prepare(request)
285285

286286
with open(filepath, 'rb') as f:
287287
yield from self._sendfile(request, resp, f, file_size)

aiohttp/web_ws.py

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,19 @@ def __init__(self, *,
3535
self._autoclose = autoclose
3636
self._autoping = autoping
3737

38-
def start(self, request):
38+
@asyncio.coroutine
39+
def prepare(self, request):
3940
# make pre-check to don't hide it by do_handshake() exceptions
4041
resp_impl = self._start_pre_check(request)
4142
if resp_impl is not None:
4243
return resp_impl
4344

45+
parser, protocol, writer = self._pre_start(request)
46+
resp_impl = yield from super().prepare(request)
47+
self._post_start(request, parser, protocol, writer)
48+
return resp_impl
49+
50+
def _pre_start(self, request):
4451
try:
4552
status, headers, parser, writer, protocol = do_handshake(
4653
request.method, request.headers, request.transport,
@@ -59,17 +66,27 @@ def start(self, request):
5966
for k, v in headers:
6067
self.headers[k] = v
6168
self.force_close()
69+
return parser, protocol, writer
6270

63-
resp_impl = super().start(request)
64-
71+
def _post_start(self, request, parser, protocol, writer):
6572
self._reader = request._reader.set_parser(parser)
6673
self._writer = writer
6774
self._protocol = protocol
6875
self._loop = request.app.loop
6976

77+
def start(self, request):
78+
warnings.warn('use .prepare(request) instead', DeprecationWarning)
79+
# make pre-check to don't hide it by do_handshake() exceptions
80+
resp_impl = self._start_pre_check(request)
81+
if resp_impl is not None:
82+
return resp_impl
83+
84+
parser, protocol, writer = self._pre_start(request)
85+
resp_impl = super().start(request)
86+
self._post_start(request, parser, protocol, writer)
7087
return resp_impl
7188

72-
def can_start(self, request):
89+
def can_prepare(self, request):
7390
if self._writer is not None:
7491
raise RuntimeError('Already started')
7592
try:
@@ -81,6 +98,10 @@ def can_start(self, request):
8198
else:
8299
return True, protocol
83100

101+
def can_start(self, request):
102+
warnings.warn('use .can_prepare(request) instead', DeprecationWarning)
103+
return self.can_prepare(request)
104+
84105
@property
85106
def closed(self):
86107
return self._closed
@@ -98,22 +119,22 @@ def exception(self):
98119

99120
def ping(self, message='b'):
100121
if self._writer is None:
101-
raise RuntimeError('Call .start() first')
122+
raise RuntimeError('Call .prepare() first')
102123
if self._closed:
103124
raise RuntimeError('websocket connection is closing')
104125
self._writer.ping(message)
105126

106127
def pong(self, message='b'):
107128
# unsolicited pong
108129
if self._writer is None:
109-
raise RuntimeError('Call .start() first')
130+
raise RuntimeError('Call .prepare() first')
110131
if self._closed:
111132
raise RuntimeError('websocket connection is closing')
112133
self._writer.pong(message)
113134

114135
def send_str(self, data):
115136
if self._writer is None:
116-
raise RuntimeError('Call .start() first')
137+
raise RuntimeError('Call .prepare() first')
117138
if self._closed:
118139
raise RuntimeError('websocket connection is closing')
119140
if not isinstance(data, str):
@@ -122,7 +143,7 @@ def send_str(self, data):
122143

123144
def send_bytes(self, data):
124145
if self._writer is None:
125-
raise RuntimeError('Call .start() first')
146+
raise RuntimeError('Call .prepare() first')
126147
if self._closed:
127148
raise RuntimeError('websocket connection is closing')
128149
if not isinstance(data, (bytes, bytearray, memoryview)):
@@ -151,7 +172,7 @@ def write_eof(self):
151172
@asyncio.coroutine
152173
def close(self, *, code=1000, message=b''):
153174
if self._writer is None:
154-
raise RuntimeError('Call .start() first')
175+
raise RuntimeError('Call .prepare() first')
155176

156177
if not self._closed:
157178
self._closed = True
@@ -190,7 +211,7 @@ def close(self, *, code=1000, message=b''):
190211
@asyncio.coroutine
191212
def receive(self):
192213
if self._reader is None:
193-
raise RuntimeError('Call .start() first')
214+
raise RuntimeError('Call .prepare() first')
194215
if self._waiting:
195216
raise RuntimeError('Concurrent call to receive() is not allowed')
196217

@@ -239,7 +260,7 @@ def receive(self):
239260
self._waiting = False
240261

241262
@asyncio.coroutine
242-
def receive_msg(self): # pragma: no cover
263+
def receive_msg(self):
243264
warnings.warn(
244265
'receive_msg() coroutine is deprecated. use receive() instead',
245266
DeprecationWarning)

docs/web.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,7 @@ using response's methods:
407407
def websocket_handler(request):
408408
409409
ws = web.WebSocketResponse()
410-
ws.start(request)
410+
yield from ws.prepare(request)
411411
412412
while True:
413413
msg = yield from ws.receive()

docs/web_reference.rst

Lines changed: 55 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -339,11 +339,10 @@ StreamResponse
339339
The most important thing you should know about *response* --- it
340340
is *Finite State Machine*.
341341

342-
That means you can do any manipulations with *headers*,
343-
*cookies* and *status code* only before :meth:`start`
344-
called.
342+
That means you can do any manipulations with *headers*, *cookies*
343+
and *status code* only before :meth:`prepare` coroutine is called.
345344

346-
Once you call :meth:`start` any change of
345+
Once you call :meth:`prepare` any change of
347346
the *HTTP header* part will raise :exc:`RuntimeError` exception.
348347

349348
Any :meth:`write` call after :meth:`write_eof` is also forbidden.
@@ -355,11 +354,19 @@ StreamResponse
355354
parameter. Otherwise pass :class:`str` with
356355
arbitrary *status* explanation..
357356

358-
.. attribute:: started
357+
.. attribute:: prepared
359358

360-
Read-only :class:`bool` property, ``True`` if :meth:`start` has
359+
Read-only :class:`bool` property, ``True`` if :meth:`prepare` has
361360
been called, ``False`` otherwise.
362361

362+
.. versionadded:: 0.18
363+
364+
.. attribute:: started
365+
366+
Deprecated alias for :attr:`prepared`.
367+
368+
.. deprecated:: 0.18
369+
363370
.. attribute:: status
364371

365372
Read-only property for *HTTP response status code*, :class:`int`.
@@ -550,16 +557,30 @@ StreamResponse
550557
Send *HTTP header*. You should not change any header data after
551558
calling this method.
552559

560+
.. deprecated:: 0.18
561+
562+
Use :meth:`prepare` instead.
563+
564+
.. coroutinemethod:: prepare(request)
565+
566+
:param aiohttp.web.Request request: HTTP request object, that the
567+
response answers.
568+
569+
Send *HTTP header*. You should not change any header data after
570+
calling this method.
571+
572+
.. versionadded:: 0.18
573+
553574
.. method:: write(data)
554575

555576
Send byte-ish data as the part of *response BODY*.
556577

557-
:meth:`start` must be called before.
578+
:meth:`prepare` must be called before.
558579

559580
Raises :exc:`TypeError` if data is not :class:`bytes`,
560581
:class:`bytearray` or :class:`memoryview` instance.
561582

562-
Raises :exc:`RuntimeError` if :meth:`start` has not been called.
583+
Raises :exc:`RuntimeError` if :meth:`prepare` has not been called.
563584

564585
Raises :exc:`RuntimeError` if :meth:`write_eof` has been called.
565586

@@ -651,11 +672,23 @@ WebSocketResponse
651672

652673
Class for handling server-side websockets.
653674

654-
After starting (by :meth:`start` call) the response you
675+
After starting (by :meth:`prepare` call) the response you
655676
cannot use :meth:`~StreamResponse.write` method but should to
656677
communicate with websocket client by :meth:`send_str`,
657678
:meth:`receive` and others.
658679

680+
.. coroutinemethod:: prepare(request)
681+
682+
Starts websocket. After the call you can use websocket methods.
683+
684+
:param aiohttp.web.Request request: HTTP request object, that the
685+
response answers.
686+
687+
688+
:raises HTTPException: if websocket handshake has failed.
689+
690+
.. versionadded:: 0.18
691+
659692
.. method:: start(request)
660693

661694
Starts websocket. After the call you can use websocket methods.
@@ -666,12 +699,17 @@ WebSocketResponse
666699

667700
:raises HTTPException: if websocket handshake has failed.
668701

669-
.. method:: can_start(request)
702+
.. deprecated:: 0.18
703+
704+
Use :meth:`prepare` instead.
705+
706+
.. method:: can_prepare(request)
670707

671708
Performs checks for *request* data to figure out if websocket
672709
can be started on the request.
673710

674-
If :meth:`can_start` call is success then :meth:`start` will success too.
711+
If :meth:`can_prepare` call is success then :meth:`prepare` will
712+
success too.
675713

676714
:param aiohttp.web.Request request: HTTP request object, that the
677715
response answers.
@@ -684,6 +722,12 @@ WebSocketResponse
684722

685723
.. note:: The method never raises exception.
686724

725+
.. method:: can_start(request)
726+
727+
Deprecated alias for :meth:`can_prepare`
728+
729+
.. deprecated:: 0.18
730+
687731
.. attribute:: closed
688732

689733
Read-only property, ``True`` if connection has been closed or in process

examples/web_srv.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ def intro(request):
1515
binary = txt.encode('utf8')
1616
resp = StreamResponse()
1717
resp.content_length = len(binary)
18-
resp.start(request)
18+
yield from resp.prepare(request)
1919
resp.write(binary)
2020
return resp
2121

@@ -36,7 +36,7 @@ def hello(request):
3636
name = request.match_info.get('name', 'Anonymous')
3737
answer = ('Hello, ' + name).encode('utf8')
3838
resp.content_length = len(answer)
39-
resp.start(request)
39+
yield from resp.prepare(request)
4040
resp.write(answer)
4141
yield from resp.write_eof()
4242
return resp

examples/web_ws.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ def wshandler(request):
1717
with open(WS_FILE, 'rb') as fp:
1818
return Response(body=fp.read(), content_type='text/html')
1919

20-
resp.start(request)
20+
yield from resp.prepare(request)
2121
print('Someone joined.')
2222
for ws in request.app['sockets']:
2323
ws.send_str('Someone joined')

tests/autobahn/server.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ def wshandler(request):
1212
if not ok:
1313
return web.HTTPBadRequest()
1414

15-
ws.start(request)
15+
yield from ws.prepare(request)
1616

1717
while True:
1818
msg = yield from ws.receive()

0 commit comments

Comments
 (0)