5656 reify ,
5757 set_result ,
5858)
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+ )
6066from .log import client_logger
6167from .streams import StreamReader
6268from .typedefs import (
@@ -178,7 +184,7 @@ class ClientRequest:
178184 auth = None
179185 response = None
180186
181- _writer = None # async task for streaming data
187+ __writer = None # async task for streaming data
182188 _continue = None # waiter future for '100 Continue' response
183189
184190 # N.B.
@@ -265,6 +271,21 @@ def __init__(
265271 traces = []
266272 self ._traces = traces
267273
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+
268289 def is_ssl (self ) -> bool :
269290 return self .url .scheme in ("https" , "wss" )
270291
@@ -563,8 +584,6 @@ async def write_bytes(
563584 else :
564585 await writer .write_eof ()
565586 protocol .start_timeout ()
566- finally :
567- self ._writer = None
568587
569588 async def send (self , conn : "Connection" ) -> "ClientResponse" :
570589 # Specify request target:
@@ -649,16 +668,14 @@ async def send(self, conn: "Connection") -> "ClientResponse":
649668
650669 async def close (self ) -> None :
651670 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
657673
658674 def terminate (self ) -> None :
659675 if self ._writer is not None :
660676 if not self .loop .is_closed ():
661677 self ._writer .cancel ()
678+ self ._writer .remove_done_callback (self .__reset_writer )
662679 self ._writer = None
663680
664681 async def _on_chunk_request_sent (self , method : str , url : URL , chunk : bytes ) -> None :
@@ -677,9 +694,9 @@ class ClientResponse(HeadersMixin):
677694 # but will be set by the start() method.
678695 # As the end user will likely never see the None values, we cheat the types below.
679696 # from the Status-Line of the response
680- version = None # HTTP-Version
697+ version : Optional [ HttpVersion ] = None # HTTP-Version
681698 status : int = None # type: ignore[assignment] # Status-Code
682- reason = None # Reason-Phrase
699+ reason : Optional [ str ] = None # Reason-Phrase
683700
684701 content : StreamReader = None # type: ignore[assignment] # Payload stream
685702 _headers : CIMultiDictProxy [str ] = None # type: ignore[assignment]
@@ -691,6 +708,7 @@ class ClientResponse(HeadersMixin):
691708 # post-init stage allows to not change ctor signature
692709 _closed = True # to allow __del__ for non-initialized properly response
693710 _released = False
711+ __writer = None
694712
695713 def __init__ (
696714 self ,
@@ -737,6 +755,21 @@ def __init__(
737755 if loop .get_debug ():
738756 self ._source_traceback = traceback .extract_stack (sys ._getframe (1 ))
739757
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+
740773 @reify
741774 def url (self ) -> URL :
742775 return self ._url
@@ -797,7 +830,7 @@ def __repr__(self) -> str:
797830 "ascii" , "backslashreplace"
798831 ).decode ("ascii" )
799832 else :
800- ascii_encodable_reason = self . reason
833+ ascii_encodable_reason = "None"
801834 print (
802835 "<ClientResponse({}) [{} {}]>" .format (
803836 ascii_encodable_url , self .status , ascii_encodable_reason
@@ -978,18 +1011,12 @@ def _release_connection(self) -> None:
9781011
9791012 async def _wait_released (self ) -> None :
9801013 if self ._writer is not None :
981- try :
982- await self ._writer
983- finally :
984- self ._writer = None
1014+ await self ._writer
9851015 self ._release_connection ()
9861016
9871017 def _cleanup_writer (self ) -> None :
9881018 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 ()
9931020 self ._session = None
9941021
9951022 def _notify_content (self ) -> None :
@@ -1001,10 +1028,7 @@ def _notify_content(self) -> None:
10011028
10021029 async def wait_for_close (self ) -> None :
10031030 if self ._writer is not None :
1004- try :
1005- await self ._writer
1006- finally :
1007- self ._writer = None
1031+ await self ._writer
10081032 self .release ()
10091033
10101034 async def read (self ) -> bytes :
0 commit comments