5353 reify ,
5454 set_result ,
5555)
56- from .http import SERVER_SOFTWARE , HttpVersion10 , HttpVersion11 , StreamWriter
56+ from .http import (
57+ SERVER_SOFTWARE ,
58+ HttpVersion ,
59+ HttpVersion10 ,
60+ HttpVersion11 ,
61+ StreamWriter ,
62+ )
5763from .log import client_logger
5864from .streams import StreamReader
5965from .typedefs import (
@@ -241,7 +247,7 @@ class ClientRequest:
241247 auth = None
242248 response = None
243249
244- _writer = None # async task for streaming data
250+ __writer = None # async task for streaming data
245251 _continue = None # waiter future for '100 Continue' response
246252
247253 # N.B.
@@ -332,6 +338,21 @@ def __init__(
332338 traces = []
333339 self ._traces = traces
334340
341+ def __reset_writer (self , _ : object = None ) -> None :
342+ self .__writer = None
343+
344+ @property
345+ def _writer (self ) -> Optional ["asyncio.Task[None]" ]:
346+ return self .__writer
347+
348+ @_writer .setter
349+ def _writer (self , writer : Optional ["asyncio.Task[None]" ]) -> None :
350+ if self .__writer is not None :
351+ self .__writer .remove_done_callback (self .__reset_writer )
352+ self .__writer = writer
353+ if writer is not None :
354+ writer .add_done_callback (self .__reset_writer )
355+
335356 def is_ssl (self ) -> bool :
336357 return self .url .scheme in ("https" , "wss" )
337358
@@ -625,8 +646,6 @@ async def write_bytes(
625646 else :
626647 await writer .write_eof ()
627648 protocol .start_timeout ()
628- finally :
629- self ._writer = None
630649
631650 async def send (self , conn : "Connection" ) -> "ClientResponse" :
632651 # Specify request target:
@@ -711,16 +730,14 @@ async def send(self, conn: "Connection") -> "ClientResponse":
711730
712731 async def close (self ) -> None :
713732 if self ._writer is not None :
714- try :
715- with contextlib .suppress (asyncio .CancelledError ):
716- await self ._writer
717- finally :
718- self ._writer = None
733+ with contextlib .suppress (asyncio .CancelledError ):
734+ await self ._writer
719735
720736 def terminate (self ) -> None :
721737 if self ._writer is not None :
722738 if not self .loop .is_closed ():
723739 self ._writer .cancel ()
740+ self ._writer .remove_done_callback (self .__reset_writer )
724741 self ._writer = None
725742
726743 async def _on_chunk_request_sent (self , method : str , url : URL , chunk : bytes ) -> None :
@@ -740,9 +757,9 @@ class ClientResponse(HeadersMixin):
740757 # but will be set by the start() method.
741758 # As the end user will likely never see the None values, we cheat the types below.
742759 # from the Status-Line of the response
743- version = None # HTTP-Version
744- status : int = None # type: ignore[assignment] # Status-Code
745- reason = None # Reason-Phrase
760+ version : Optional [ HttpVersion ] = None # HTTP-Version
761+ status : int = None # type: ignore[assignment] # Status-Code
762+ reason : Optional [ str ] = None # Reason-Phrase
746763
747764 content : StreamReader = None # type: ignore[assignment] # Payload stream
748765 _headers : CIMultiDictProxy [str ] = None # type: ignore[assignment]
@@ -754,6 +771,7 @@ class ClientResponse(HeadersMixin):
754771 # post-init stage allows to not change ctor signature
755772 _closed = True # to allow __del__ for non-initialized properly response
756773 _released = False
774+ __writer = None
757775
758776 def __init__ (
759777 self ,
@@ -799,6 +817,21 @@ def __init__(
799817 if loop .get_debug ():
800818 self ._source_traceback = traceback .extract_stack (sys ._getframe (1 ))
801819
820+ def __reset_writer (self , _ : object = None ) -> None :
821+ self .__writer = None
822+
823+ @property
824+ def _writer (self ) -> Optional ["asyncio.Task[None]" ]:
825+ return self .__writer
826+
827+ @_writer .setter
828+ def _writer (self , writer : Optional ["asyncio.Task[None]" ]) -> None :
829+ if self .__writer is not None :
830+ self .__writer .remove_done_callback (self .__reset_writer )
831+ self .__writer = writer
832+ if writer is not None :
833+ writer .add_done_callback (self .__reset_writer )
834+
802835 @reify
803836 def url (self ) -> URL :
804837 return self ._url
@@ -863,7 +896,7 @@ def __repr__(self) -> str:
863896 "ascii" , "backslashreplace"
864897 ).decode ("ascii" )
865898 else :
866- ascii_encodable_reason = self . reason
899+ ascii_encodable_reason = "None"
867900 print (
868901 "<ClientResponse({}) [{} {}]>" .format (
869902 ascii_encodable_url , self .status , ascii_encodable_reason
@@ -1044,18 +1077,12 @@ def _release_connection(self) -> None:
10441077
10451078 async def _wait_released (self ) -> None :
10461079 if self ._writer is not None :
1047- try :
1048- await self ._writer
1049- finally :
1050- self ._writer = None
1080+ await self ._writer
10511081 self ._release_connection ()
10521082
10531083 def _cleanup_writer (self ) -> None :
10541084 if self ._writer is not None :
1055- if self ._writer .done ():
1056- self ._writer = None
1057- else :
1058- self ._writer .cancel ()
1085+ self ._writer .cancel ()
10591086 self ._session = None
10601087
10611088 def _notify_content (self ) -> None :
@@ -1066,10 +1093,7 @@ def _notify_content(self) -> None:
10661093
10671094 async def wait_for_close (self ) -> None :
10681095 if self ._writer is not None :
1069- try :
1070- await self ._writer
1071- finally :
1072- self ._writer = None
1096+ await self ._writer
10731097 self .release ()
10741098
10751099 async def read (self ) -> bytes :
0 commit comments