56
56
reify ,
57
57
set_result ,
58
58
)
59
- from .http import SERVER_SOFTWARE , HttpVersion10 , HttpVersion11 , StreamWriter
59
+ from .http import (
60
+ SERVER_SOFTWARE ,
61
+ HttpVersion ,
62
+ HttpVersion10 ,
63
+ HttpVersion11 ,
64
+ StreamWriter ,
65
+ )
60
66
from .log import client_logger
61
67
from .streams import StreamReader
62
68
from .typedefs import (
@@ -178,7 +184,7 @@ class ClientRequest:
178
184
auth = None
179
185
response = None
180
186
181
- _writer = None # async task for streaming data
187
+ __writer = None # async task for streaming data
182
188
_continue = None # waiter future for '100 Continue' response
183
189
184
190
# N.B.
@@ -265,6 +271,21 @@ def __init__(
265
271
traces = []
266
272
self ._traces = traces
267
273
274
+ def __reset_writer (self , _ : object = None ) -> None :
275
+ self .__writer = None
276
+
277
+ @property
278
+ def _writer (self ) -> Optional ["asyncio.Task[None]" ]:
279
+ return self .__writer
280
+
281
+ @_writer .setter
282
+ def _writer (self , writer : Optional ["asyncio.Task[None]" ]) -> None :
283
+ if self .__writer is not None :
284
+ self .__writer .remove_done_callback (self .__reset_writer )
285
+ self .__writer = writer
286
+ if writer is not None :
287
+ writer .add_done_callback (self .__reset_writer )
288
+
268
289
def is_ssl (self ) -> bool :
269
290
return self .url .scheme in ("https" , "wss" )
270
291
@@ -563,8 +584,6 @@ async def write_bytes(
563
584
else :
564
585
await writer .write_eof ()
565
586
protocol .start_timeout ()
566
- finally :
567
- self ._writer = None
568
587
569
588
async def send (self , conn : "Connection" ) -> "ClientResponse" :
570
589
# Specify request target:
@@ -649,16 +668,14 @@ async def send(self, conn: "Connection") -> "ClientResponse":
649
668
650
669
async def close (self ) -> None :
651
670
if self ._writer is not None :
652
- try :
653
- with contextlib .suppress (asyncio .CancelledError ):
654
- await self ._writer
655
- finally :
656
- self ._writer = None
671
+ with contextlib .suppress (asyncio .CancelledError ):
672
+ await self ._writer
657
673
658
674
def terminate (self ) -> None :
659
675
if self ._writer is not None :
660
676
if not self .loop .is_closed ():
661
677
self ._writer .cancel ()
678
+ self ._writer .remove_done_callback (self .__reset_writer )
662
679
self ._writer = None
663
680
664
681
async def _on_chunk_request_sent (self , method : str , url : URL , chunk : bytes ) -> None :
@@ -677,9 +694,9 @@ class ClientResponse(HeadersMixin):
677
694
# but will be set by the start() method.
678
695
# As the end user will likely never see the None values, we cheat the types below.
679
696
# from the Status-Line of the response
680
- version = None # HTTP-Version
697
+ version : Optional [ HttpVersion ] = None # HTTP-Version
681
698
status : int = None # type: ignore[assignment] # Status-Code
682
- reason = None # Reason-Phrase
699
+ reason : Optional [ str ] = None # Reason-Phrase
683
700
684
701
content : StreamReader = None # type: ignore[assignment] # Payload stream
685
702
_headers : CIMultiDictProxy [str ] = None # type: ignore[assignment]
@@ -691,6 +708,7 @@ class ClientResponse(HeadersMixin):
691
708
# post-init stage allows to not change ctor signature
692
709
_closed = True # to allow __del__ for non-initialized properly response
693
710
_released = False
711
+ __writer = None
694
712
695
713
def __init__ (
696
714
self ,
@@ -737,6 +755,21 @@ def __init__(
737
755
if loop .get_debug ():
738
756
self ._source_traceback = traceback .extract_stack (sys ._getframe (1 ))
739
757
758
+ def __reset_writer (self , _ : object = None ) -> None :
759
+ self .__writer = None
760
+
761
+ @property
762
+ def _writer (self ) -> Optional ["asyncio.Task[None]" ]:
763
+ return self .__writer
764
+
765
+ @_writer .setter
766
+ def _writer (self , writer : Optional ["asyncio.Task[None]" ]) -> None :
767
+ if self .__writer is not None :
768
+ self .__writer .remove_done_callback (self .__reset_writer )
769
+ self .__writer = writer
770
+ if writer is not None :
771
+ writer .add_done_callback (self .__reset_writer )
772
+
740
773
@reify
741
774
def url (self ) -> URL :
742
775
return self ._url
@@ -797,7 +830,7 @@ def __repr__(self) -> str:
797
830
"ascii" , "backslashreplace"
798
831
).decode ("ascii" )
799
832
else :
800
- ascii_encodable_reason = self . reason
833
+ ascii_encodable_reason = "None"
801
834
print (
802
835
"<ClientResponse({}) [{} {}]>" .format (
803
836
ascii_encodable_url , self .status , ascii_encodable_reason
@@ -978,18 +1011,12 @@ def _release_connection(self) -> None:
978
1011
979
1012
async def _wait_released (self ) -> None :
980
1013
if self ._writer is not None :
981
- try :
982
- await self ._writer
983
- finally :
984
- self ._writer = None
1014
+ await self ._writer
985
1015
self ._release_connection ()
986
1016
987
1017
def _cleanup_writer (self ) -> None :
988
1018
if self ._writer is not None :
989
- if self ._writer .done ():
990
- self ._writer = None
991
- else :
992
- self ._writer .cancel ()
1019
+ self ._writer .cancel ()
993
1020
self ._session = None
994
1021
995
1022
def _notify_content (self ) -> None :
@@ -1001,10 +1028,7 @@ def _notify_content(self) -> None:
1001
1028
1002
1029
async def wait_for_close (self ) -> None :
1003
1030
if self ._writer is not None :
1004
- try :
1005
- await self ._writer
1006
- finally :
1007
- self ._writer = None
1031
+ await self ._writer
1008
1032
self .release ()
1009
1033
1010
1034
async def read (self ) -> bytes :
0 commit comments