1515from . import client_exceptions , client_reqrep , hdrs , http
1616from .client_exceptions import * # noqa
1717from .client_exceptions import (ClientError , ClientOSError ,
18- ClientResponseError , WSServerHandshakeError )
18+ ClientResponseError , ServerTimeoutError ,
19+ WSServerHandshakeError )
1920from .client_reqrep import * # noqa
2021from .client_reqrep import ClientRequest , ClientResponse
2122from .client_ws import ClientWebSocketResponse
2223from .connector import * # noqa
2324from .connector import TCPConnector
2425from .cookiejar import CookieJar
25- from .helpers import PY_35 , TimeService , noop
26+ from .helpers import PY_35 , CeilTimeout , TimeoutHandle , noop
2627from .http import WS_KEY , WebSocketReader , WebSocketWriter
2728from .streams import FlowControlDataQueue
2829
@@ -48,8 +49,8 @@ def __init__(self, *, connector=None, loop=None, cookies=None,
4849 response_class = ClientResponse ,
4950 ws_response_class = ClientWebSocketResponse ,
5051 version = http .HttpVersion11 ,
51- cookie_jar = None , read_timeout = None , time_service = None ,
52- connector_owner = True ):
52+ cookie_jar = None , connector_owner = True ,
53+ read_timeout = None , conn_timeout = None ):
5354
5455 implicit_loop = False
5556 if loop is None :
@@ -93,6 +94,7 @@ def __init__(self, *, connector=None, loop=None, cookies=None,
9394 self ._default_auth = auth
9495 self ._version = version
9596 self ._read_timeout = read_timeout
97+ self ._conn_timeout = conn_timeout
9698
9799 # Convert to list of tuples
98100 if headers :
@@ -110,12 +112,6 @@ def __init__(self, *, connector=None, loop=None, cookies=None,
110112 self ._response_class = response_class
111113 self ._ws_response_class = ws_response_class
112114
113- self ._time_service_owner = time_service is None
114- if time_service is None :
115- time_service = TimeService (self ._loop )
116-
117- self ._time_service = time_service
118-
119115 def __del__ (self , _warnings = warnings ):
120116 if not self .closed :
121117 self .close ()
@@ -128,10 +124,6 @@ def __del__(self, _warnings=warnings):
128124 context ['source_traceback' ] = self ._source_traceback
129125 self ._loop .call_exception_handler (context )
130126
131- @property
132- def time_service (self ):
133- return self ._time_service
134-
135127 def request (self , method , url , ** kwargs ):
136128 """Perform HTTP request."""
137129 return _RequestContextManager (self ._request (method , url , ** kwargs ))
@@ -195,22 +187,16 @@ def _request(self, method, url, *,
195187 if proxy is not None :
196188 proxy = URL (proxy )
197189
198- # request timeout
199- if timeout is None :
200- timeout = self ._read_timeout
201- if timeout is None :
202- timeout = self ._connector .conn_timeout
203- elif self ._connector .conn_timeout is not None :
204- timeout = max (timeout , self ._connector .conn_timeout )
205-
206190 # timeout is cumulative for all request operations
207191 # (request, redirects, responses, data consuming)
208- timer = self ._time_service .timeout (timeout )
192+ tm = TimeoutHandle (
193+ self ._loop , timeout if timeout is not None else self ._read_timeout )
194+ handle = tm .start ()
209195
196+ timer = tm .timer ()
210197 with timer :
211198 while True :
212199 url = URL (url ).with_fragment (None )
213-
214200 cookies = self ._cookie_jar .filter_cookies (url )
215201
216202 req = self ._request_class (
@@ -221,7 +207,14 @@ def _request(self, method, url, *,
221207 loop = self ._loop , response_class = self ._response_class ,
222208 proxy = proxy , proxy_auth = proxy_auth , timer = timer )
223209
224- conn = yield from self ._connector .connect (req )
210+ # connection timeout
211+ try :
212+ with CeilTimeout (self ._conn_timeout , loop = self ._loop ):
213+ conn = yield from self ._connector .connect (req )
214+ except asyncio .TimeoutError as exc :
215+ raise ServerTimeoutError (
216+ 'Connection timeout to host {0}' .format (url )) from exc
217+
225218 conn .writer .set_tcp_nodelay (True )
226219 try :
227220 resp = req .send (conn )
@@ -285,6 +278,13 @@ def _request(self, method, url, *,
285278
286279 break
287280
281+ # register connection
282+ if handle is not None :
283+ if resp .connection is not None :
284+ resp .connection .add_callback (handle .cancel )
285+ else :
286+ handle .cancel ()
287+
288288 resp ._history = tuple (history )
289289 return resp
290290
@@ -417,7 +417,6 @@ def _ws_connect(self, url, *,
417417 autoclose ,
418418 autoping ,
419419 self ._loop ,
420- time_service = self .time_service ,
421420 receive_timeout = receive_timeout ,
422421 heartbeat = heartbeat )
423422
@@ -496,9 +495,6 @@ def close(self):
496495 self ._connector .close ()
497496 self ._connector = None
498497
499- if self ._time_service_owner :
500- self ._time_service .close ()
501-
502498 return noop ()
503499
504500 @property
0 commit comments