53
53
reify ,
54
54
set_result ,
55
55
)
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
+ )
57
63
from .log import client_logger
58
64
from .streams import StreamReader
59
65
from .typedefs import (
@@ -241,7 +247,7 @@ class ClientRequest:
241
247
auth = None
242
248
response = None
243
249
244
- _writer = None # async task for streaming data
250
+ __writer = None # async task for streaming data
245
251
_continue = None # waiter future for '100 Continue' response
246
252
247
253
# N.B.
@@ -332,6 +338,21 @@ def __init__(
332
338
traces = []
333
339
self ._traces = traces
334
340
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
+
335
356
def is_ssl (self ) -> bool :
336
357
return self .url .scheme in ("https" , "wss" )
337
358
@@ -625,8 +646,6 @@ async def write_bytes(
625
646
else :
626
647
await writer .write_eof ()
627
648
protocol .start_timeout ()
628
- finally :
629
- self ._writer = None
630
649
631
650
async def send (self , conn : "Connection" ) -> "ClientResponse" :
632
651
# Specify request target:
@@ -711,16 +730,14 @@ async def send(self, conn: "Connection") -> "ClientResponse":
711
730
712
731
async def close (self ) -> None :
713
732
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
719
735
720
736
def terminate (self ) -> None :
721
737
if self ._writer is not None :
722
738
if not self .loop .is_closed ():
723
739
self ._writer .cancel ()
740
+ self ._writer .remove_done_callback (self .__reset_writer )
724
741
self ._writer = None
725
742
726
743
async def _on_chunk_request_sent (self , method : str , url : URL , chunk : bytes ) -> None :
@@ -740,9 +757,9 @@ class ClientResponse(HeadersMixin):
740
757
# but will be set by the start() method.
741
758
# As the end user will likely never see the None values, we cheat the types below.
742
759
# 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
746
763
747
764
content : StreamReader = None # type: ignore[assignment] # Payload stream
748
765
_headers : CIMultiDictProxy [str ] = None # type: ignore[assignment]
@@ -754,6 +771,7 @@ class ClientResponse(HeadersMixin):
754
771
# post-init stage allows to not change ctor signature
755
772
_closed = True # to allow __del__ for non-initialized properly response
756
773
_released = False
774
+ __writer = None
757
775
758
776
def __init__ (
759
777
self ,
@@ -799,6 +817,21 @@ def __init__(
799
817
if loop .get_debug ():
800
818
self ._source_traceback = traceback .extract_stack (sys ._getframe (1 ))
801
819
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
+
802
835
@reify
803
836
def url (self ) -> URL :
804
837
return self ._url
@@ -863,7 +896,7 @@ def __repr__(self) -> str:
863
896
"ascii" , "backslashreplace"
864
897
).decode ("ascii" )
865
898
else :
866
- ascii_encodable_reason = self . reason
899
+ ascii_encodable_reason = "None"
867
900
print (
868
901
"<ClientResponse({}) [{} {}]>" .format (
869
902
ascii_encodable_url , self .status , ascii_encodable_reason
@@ -1044,18 +1077,12 @@ def _release_connection(self) -> None:
1044
1077
1045
1078
async def _wait_released (self ) -> None :
1046
1079
if self ._writer is not None :
1047
- try :
1048
- await self ._writer
1049
- finally :
1050
- self ._writer = None
1080
+ await self ._writer
1051
1081
self ._release_connection ()
1052
1082
1053
1083
def _cleanup_writer (self ) -> None :
1054
1084
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 ()
1059
1086
self ._session = None
1060
1087
1061
1088
def _notify_content (self ) -> None :
@@ -1066,10 +1093,7 @@ def _notify_content(self) -> None:
1066
1093
1067
1094
async def wait_for_close (self ) -> None :
1068
1095
if self ._writer is not None :
1069
- try :
1070
- await self ._writer
1071
- finally :
1072
- self ._writer = None
1096
+ await self ._writer
1073
1097
self .release ()
1074
1098
1075
1099
async def read (self ) -> bytes :
0 commit comments