| 1 | n/a | """Event loop and event loop policy.""" |
|---|
| 2 | n/a | |
|---|
| 3 | n/a | __all__ = ['AbstractEventLoopPolicy', |
|---|
| 4 | n/a | 'AbstractEventLoop', 'AbstractServer', |
|---|
| 5 | n/a | 'Handle', 'TimerHandle', |
|---|
| 6 | n/a | 'get_event_loop_policy', 'set_event_loop_policy', |
|---|
| 7 | n/a | 'get_event_loop', 'set_event_loop', 'new_event_loop', |
|---|
| 8 | n/a | 'get_child_watcher', 'set_child_watcher', |
|---|
| 9 | n/a | '_set_running_loop', '_get_running_loop', |
|---|
| 10 | n/a | ] |
|---|
| 11 | n/a | |
|---|
| 12 | n/a | import functools |
|---|
| 13 | n/a | import inspect |
|---|
| 14 | n/a | import reprlib |
|---|
| 15 | n/a | import socket |
|---|
| 16 | n/a | import subprocess |
|---|
| 17 | n/a | import sys |
|---|
| 18 | n/a | import threading |
|---|
| 19 | n/a | import traceback |
|---|
| 20 | n/a | |
|---|
| 21 | n/a | from asyncio import compat |
|---|
| 22 | n/a | |
|---|
| 23 | n/a | |
|---|
| 24 | n/a | def _get_function_source(func): |
|---|
| 25 | n/a | if compat.PY34: |
|---|
| 26 | n/a | func = inspect.unwrap(func) |
|---|
| 27 | n/a | elif hasattr(func, '__wrapped__'): |
|---|
| 28 | n/a | func = func.__wrapped__ |
|---|
| 29 | n/a | if inspect.isfunction(func): |
|---|
| 30 | n/a | code = func.__code__ |
|---|
| 31 | n/a | return (code.co_filename, code.co_firstlineno) |
|---|
| 32 | n/a | if isinstance(func, functools.partial): |
|---|
| 33 | n/a | return _get_function_source(func.func) |
|---|
| 34 | n/a | if compat.PY34 and isinstance(func, functools.partialmethod): |
|---|
| 35 | n/a | return _get_function_source(func.func) |
|---|
| 36 | n/a | return None |
|---|
| 37 | n/a | |
|---|
| 38 | n/a | |
|---|
| 39 | n/a | def _format_args_and_kwargs(args, kwargs): |
|---|
| 40 | n/a | """Format function arguments and keyword arguments. |
|---|
| 41 | n/a | |
|---|
| 42 | n/a | Special case for a single parameter: ('hello',) is formatted as ('hello'). |
|---|
| 43 | n/a | """ |
|---|
| 44 | n/a | # use reprlib to limit the length of the output |
|---|
| 45 | n/a | items = [] |
|---|
| 46 | n/a | if args: |
|---|
| 47 | n/a | items.extend(reprlib.repr(arg) for arg in args) |
|---|
| 48 | n/a | if kwargs: |
|---|
| 49 | n/a | items.extend('{}={}'.format(k, reprlib.repr(v)) |
|---|
| 50 | n/a | for k, v in kwargs.items()) |
|---|
| 51 | n/a | return '(' + ', '.join(items) + ')' |
|---|
| 52 | n/a | |
|---|
| 53 | n/a | |
|---|
| 54 | n/a | def _format_callback(func, args, kwargs, suffix=''): |
|---|
| 55 | n/a | if isinstance(func, functools.partial): |
|---|
| 56 | n/a | suffix = _format_args_and_kwargs(args, kwargs) + suffix |
|---|
| 57 | n/a | return _format_callback(func.func, func.args, func.keywords, suffix) |
|---|
| 58 | n/a | |
|---|
| 59 | n/a | if hasattr(func, '__qualname__'): |
|---|
| 60 | n/a | func_repr = getattr(func, '__qualname__') |
|---|
| 61 | n/a | elif hasattr(func, '__name__'): |
|---|
| 62 | n/a | func_repr = getattr(func, '__name__') |
|---|
| 63 | n/a | else: |
|---|
| 64 | n/a | func_repr = repr(func) |
|---|
| 65 | n/a | |
|---|
| 66 | n/a | func_repr += _format_args_and_kwargs(args, kwargs) |
|---|
| 67 | n/a | if suffix: |
|---|
| 68 | n/a | func_repr += suffix |
|---|
| 69 | n/a | return func_repr |
|---|
| 70 | n/a | |
|---|
| 71 | n/a | def _format_callback_source(func, args): |
|---|
| 72 | n/a | func_repr = _format_callback(func, args, None) |
|---|
| 73 | n/a | source = _get_function_source(func) |
|---|
| 74 | n/a | if source: |
|---|
| 75 | n/a | func_repr += ' at %s:%s' % source |
|---|
| 76 | n/a | return func_repr |
|---|
| 77 | n/a | |
|---|
| 78 | n/a | |
|---|
| 79 | n/a | class Handle: |
|---|
| 80 | n/a | """Object returned by callback registration methods.""" |
|---|
| 81 | n/a | |
|---|
| 82 | n/a | __slots__ = ('_callback', '_args', '_cancelled', '_loop', |
|---|
| 83 | n/a | '_source_traceback', '_repr', '__weakref__') |
|---|
| 84 | n/a | |
|---|
| 85 | n/a | def __init__(self, callback, args, loop): |
|---|
| 86 | n/a | self._loop = loop |
|---|
| 87 | n/a | self._callback = callback |
|---|
| 88 | n/a | self._args = args |
|---|
| 89 | n/a | self._cancelled = False |
|---|
| 90 | n/a | self._repr = None |
|---|
| 91 | n/a | if self._loop.get_debug(): |
|---|
| 92 | n/a | self._source_traceback = traceback.extract_stack(sys._getframe(1)) |
|---|
| 93 | n/a | else: |
|---|
| 94 | n/a | self._source_traceback = None |
|---|
| 95 | n/a | |
|---|
| 96 | n/a | def _repr_info(self): |
|---|
| 97 | n/a | info = [self.__class__.__name__] |
|---|
| 98 | n/a | if self._cancelled: |
|---|
| 99 | n/a | info.append('cancelled') |
|---|
| 100 | n/a | if self._callback is not None: |
|---|
| 101 | n/a | info.append(_format_callback_source(self._callback, self._args)) |
|---|
| 102 | n/a | if self._source_traceback: |
|---|
| 103 | n/a | frame = self._source_traceback[-1] |
|---|
| 104 | n/a | info.append('created at %s:%s' % (frame[0], frame[1])) |
|---|
| 105 | n/a | return info |
|---|
| 106 | n/a | |
|---|
| 107 | n/a | def __repr__(self): |
|---|
| 108 | n/a | if self._repr is not None: |
|---|
| 109 | n/a | return self._repr |
|---|
| 110 | n/a | info = self._repr_info() |
|---|
| 111 | n/a | return '<%s>' % ' '.join(info) |
|---|
| 112 | n/a | |
|---|
| 113 | n/a | def cancel(self): |
|---|
| 114 | n/a | if not self._cancelled: |
|---|
| 115 | n/a | self._cancelled = True |
|---|
| 116 | n/a | if self._loop.get_debug(): |
|---|
| 117 | n/a | # Keep a representation in debug mode to keep callback and |
|---|
| 118 | n/a | # parameters. For example, to log the warning |
|---|
| 119 | n/a | # "Executing <Handle...> took 2.5 second" |
|---|
| 120 | n/a | self._repr = repr(self) |
|---|
| 121 | n/a | self._callback = None |
|---|
| 122 | n/a | self._args = None |
|---|
| 123 | n/a | |
|---|
| 124 | n/a | def _run(self): |
|---|
| 125 | n/a | try: |
|---|
| 126 | n/a | self._callback(*self._args) |
|---|
| 127 | n/a | except Exception as exc: |
|---|
| 128 | n/a | cb = _format_callback_source(self._callback, self._args) |
|---|
| 129 | n/a | msg = 'Exception in callback {}'.format(cb) |
|---|
| 130 | n/a | context = { |
|---|
| 131 | n/a | 'message': msg, |
|---|
| 132 | n/a | 'exception': exc, |
|---|
| 133 | n/a | 'handle': self, |
|---|
| 134 | n/a | } |
|---|
| 135 | n/a | if self._source_traceback: |
|---|
| 136 | n/a | context['source_traceback'] = self._source_traceback |
|---|
| 137 | n/a | self._loop.call_exception_handler(context) |
|---|
| 138 | n/a | self = None # Needed to break cycles when an exception occurs. |
|---|
| 139 | n/a | |
|---|
| 140 | n/a | |
|---|
| 141 | n/a | class TimerHandle(Handle): |
|---|
| 142 | n/a | """Object returned by timed callback registration methods.""" |
|---|
| 143 | n/a | |
|---|
| 144 | n/a | __slots__ = ['_scheduled', '_when'] |
|---|
| 145 | n/a | |
|---|
| 146 | n/a | def __init__(self, when, callback, args, loop): |
|---|
| 147 | n/a | assert when is not None |
|---|
| 148 | n/a | super().__init__(callback, args, loop) |
|---|
| 149 | n/a | if self._source_traceback: |
|---|
| 150 | n/a | del self._source_traceback[-1] |
|---|
| 151 | n/a | self._when = when |
|---|
| 152 | n/a | self._scheduled = False |
|---|
| 153 | n/a | |
|---|
| 154 | n/a | def _repr_info(self): |
|---|
| 155 | n/a | info = super()._repr_info() |
|---|
| 156 | n/a | pos = 2 if self._cancelled else 1 |
|---|
| 157 | n/a | info.insert(pos, 'when=%s' % self._when) |
|---|
| 158 | n/a | return info |
|---|
| 159 | n/a | |
|---|
| 160 | n/a | def __hash__(self): |
|---|
| 161 | n/a | return hash(self._when) |
|---|
| 162 | n/a | |
|---|
| 163 | n/a | def __lt__(self, other): |
|---|
| 164 | n/a | return self._when < other._when |
|---|
| 165 | n/a | |
|---|
| 166 | n/a | def __le__(self, other): |
|---|
| 167 | n/a | if self._when < other._when: |
|---|
| 168 | n/a | return True |
|---|
| 169 | n/a | return self.__eq__(other) |
|---|
| 170 | n/a | |
|---|
| 171 | n/a | def __gt__(self, other): |
|---|
| 172 | n/a | return self._when > other._when |
|---|
| 173 | n/a | |
|---|
| 174 | n/a | def __ge__(self, other): |
|---|
| 175 | n/a | if self._when > other._when: |
|---|
| 176 | n/a | return True |
|---|
| 177 | n/a | return self.__eq__(other) |
|---|
| 178 | n/a | |
|---|
| 179 | n/a | def __eq__(self, other): |
|---|
| 180 | n/a | if isinstance(other, TimerHandle): |
|---|
| 181 | n/a | return (self._when == other._when and |
|---|
| 182 | n/a | self._callback == other._callback and |
|---|
| 183 | n/a | self._args == other._args and |
|---|
| 184 | n/a | self._cancelled == other._cancelled) |
|---|
| 185 | n/a | return NotImplemented |
|---|
| 186 | n/a | |
|---|
| 187 | n/a | def __ne__(self, other): |
|---|
| 188 | n/a | equal = self.__eq__(other) |
|---|
| 189 | n/a | return NotImplemented if equal is NotImplemented else not equal |
|---|
| 190 | n/a | |
|---|
| 191 | n/a | def cancel(self): |
|---|
| 192 | n/a | if not self._cancelled: |
|---|
| 193 | n/a | self._loop._timer_handle_cancelled(self) |
|---|
| 194 | n/a | super().cancel() |
|---|
| 195 | n/a | |
|---|
| 196 | n/a | |
|---|
| 197 | n/a | class AbstractServer: |
|---|
| 198 | n/a | """Abstract server returned by create_server().""" |
|---|
| 199 | n/a | |
|---|
| 200 | n/a | def close(self): |
|---|
| 201 | n/a | """Stop serving. This leaves existing connections open.""" |
|---|
| 202 | n/a | return NotImplemented |
|---|
| 203 | n/a | |
|---|
| 204 | n/a | def wait_closed(self): |
|---|
| 205 | n/a | """Coroutine to wait until service is closed.""" |
|---|
| 206 | n/a | return NotImplemented |
|---|
| 207 | n/a | |
|---|
| 208 | n/a | |
|---|
| 209 | n/a | class AbstractEventLoop: |
|---|
| 210 | n/a | """Abstract event loop.""" |
|---|
| 211 | n/a | |
|---|
| 212 | n/a | # Running and stopping the event loop. |
|---|
| 213 | n/a | |
|---|
| 214 | n/a | def run_forever(self): |
|---|
| 215 | n/a | """Run the event loop until stop() is called.""" |
|---|
| 216 | n/a | raise NotImplementedError |
|---|
| 217 | n/a | |
|---|
| 218 | n/a | def run_until_complete(self, future): |
|---|
| 219 | n/a | """Run the event loop until a Future is done. |
|---|
| 220 | n/a | |
|---|
| 221 | n/a | Return the Future's result, or raise its exception. |
|---|
| 222 | n/a | """ |
|---|
| 223 | n/a | raise NotImplementedError |
|---|
| 224 | n/a | |
|---|
| 225 | n/a | def stop(self): |
|---|
| 226 | n/a | """Stop the event loop as soon as reasonable. |
|---|
| 227 | n/a | |
|---|
| 228 | n/a | Exactly how soon that is may depend on the implementation, but |
|---|
| 229 | n/a | no more I/O callbacks should be scheduled. |
|---|
| 230 | n/a | """ |
|---|
| 231 | n/a | raise NotImplementedError |
|---|
| 232 | n/a | |
|---|
| 233 | n/a | def is_running(self): |
|---|
| 234 | n/a | """Return whether the event loop is currently running.""" |
|---|
| 235 | n/a | raise NotImplementedError |
|---|
| 236 | n/a | |
|---|
| 237 | n/a | def is_closed(self): |
|---|
| 238 | n/a | """Returns True if the event loop was closed.""" |
|---|
| 239 | n/a | raise NotImplementedError |
|---|
| 240 | n/a | |
|---|
| 241 | n/a | def close(self): |
|---|
| 242 | n/a | """Close the loop. |
|---|
| 243 | n/a | |
|---|
| 244 | n/a | The loop should not be running. |
|---|
| 245 | n/a | |
|---|
| 246 | n/a | This is idempotent and irreversible. |
|---|
| 247 | n/a | |
|---|
| 248 | n/a | No other methods should be called after this one. |
|---|
| 249 | n/a | """ |
|---|
| 250 | n/a | raise NotImplementedError |
|---|
| 251 | n/a | |
|---|
| 252 | n/a | def shutdown_asyncgens(self): |
|---|
| 253 | n/a | """Shutdown all active asynchronous generators.""" |
|---|
| 254 | n/a | raise NotImplementedError |
|---|
| 255 | n/a | |
|---|
| 256 | n/a | # Methods scheduling callbacks. All these return Handles. |
|---|
| 257 | n/a | |
|---|
| 258 | n/a | def _timer_handle_cancelled(self, handle): |
|---|
| 259 | n/a | """Notification that a TimerHandle has been cancelled.""" |
|---|
| 260 | n/a | raise NotImplementedError |
|---|
| 261 | n/a | |
|---|
| 262 | n/a | def call_soon(self, callback, *args): |
|---|
| 263 | n/a | return self.call_later(0, callback, *args) |
|---|
| 264 | n/a | |
|---|
| 265 | n/a | def call_later(self, delay, callback, *args): |
|---|
| 266 | n/a | raise NotImplementedError |
|---|
| 267 | n/a | |
|---|
| 268 | n/a | def call_at(self, when, callback, *args): |
|---|
| 269 | n/a | raise NotImplementedError |
|---|
| 270 | n/a | |
|---|
| 271 | n/a | def time(self): |
|---|
| 272 | n/a | raise NotImplementedError |
|---|
| 273 | n/a | |
|---|
| 274 | n/a | def create_future(self): |
|---|
| 275 | n/a | raise NotImplementedError |
|---|
| 276 | n/a | |
|---|
| 277 | n/a | # Method scheduling a coroutine object: create a task. |
|---|
| 278 | n/a | |
|---|
| 279 | n/a | def create_task(self, coro): |
|---|
| 280 | n/a | raise NotImplementedError |
|---|
| 281 | n/a | |
|---|
| 282 | n/a | # Methods for interacting with threads. |
|---|
| 283 | n/a | |
|---|
| 284 | n/a | def call_soon_threadsafe(self, callback, *args): |
|---|
| 285 | n/a | raise NotImplementedError |
|---|
| 286 | n/a | |
|---|
| 287 | n/a | def run_in_executor(self, executor, func, *args): |
|---|
| 288 | n/a | raise NotImplementedError |
|---|
| 289 | n/a | |
|---|
| 290 | n/a | def set_default_executor(self, executor): |
|---|
| 291 | n/a | raise NotImplementedError |
|---|
| 292 | n/a | |
|---|
| 293 | n/a | # Network I/O methods returning Futures. |
|---|
| 294 | n/a | |
|---|
| 295 | n/a | def getaddrinfo(self, host, port, *, family=0, type=0, proto=0, flags=0): |
|---|
| 296 | n/a | raise NotImplementedError |
|---|
| 297 | n/a | |
|---|
| 298 | n/a | def getnameinfo(self, sockaddr, flags=0): |
|---|
| 299 | n/a | raise NotImplementedError |
|---|
| 300 | n/a | |
|---|
| 301 | n/a | def create_connection(self, protocol_factory, host=None, port=None, *, |
|---|
| 302 | n/a | ssl=None, family=0, proto=0, flags=0, sock=None, |
|---|
| 303 | n/a | local_addr=None, server_hostname=None): |
|---|
| 304 | n/a | raise NotImplementedError |
|---|
| 305 | n/a | |
|---|
| 306 | n/a | def create_server(self, protocol_factory, host=None, port=None, *, |
|---|
| 307 | n/a | family=socket.AF_UNSPEC, flags=socket.AI_PASSIVE, |
|---|
| 308 | n/a | sock=None, backlog=100, ssl=None, reuse_address=None, |
|---|
| 309 | n/a | reuse_port=None): |
|---|
| 310 | n/a | """A coroutine which creates a TCP server bound to host and port. |
|---|
| 311 | n/a | |
|---|
| 312 | n/a | The return value is a Server object which can be used to stop |
|---|
| 313 | n/a | the service. |
|---|
| 314 | n/a | |
|---|
| 315 | n/a | If host is an empty string or None all interfaces are assumed |
|---|
| 316 | n/a | and a list of multiple sockets will be returned (most likely |
|---|
| 317 | n/a | one for IPv4 and another one for IPv6). The host parameter can also be a |
|---|
| 318 | n/a | sequence (e.g. list) of hosts to bind to. |
|---|
| 319 | n/a | |
|---|
| 320 | n/a | family can be set to either AF_INET or AF_INET6 to force the |
|---|
| 321 | n/a | socket to use IPv4 or IPv6. If not set it will be determined |
|---|
| 322 | n/a | from host (defaults to AF_UNSPEC). |
|---|
| 323 | n/a | |
|---|
| 324 | n/a | flags is a bitmask for getaddrinfo(). |
|---|
| 325 | n/a | |
|---|
| 326 | n/a | sock can optionally be specified in order to use a preexisting |
|---|
| 327 | n/a | socket object. |
|---|
| 328 | n/a | |
|---|
| 329 | n/a | backlog is the maximum number of queued connections passed to |
|---|
| 330 | n/a | listen() (defaults to 100). |
|---|
| 331 | n/a | |
|---|
| 332 | n/a | ssl can be set to an SSLContext to enable SSL over the |
|---|
| 333 | n/a | accepted connections. |
|---|
| 334 | n/a | |
|---|
| 335 | n/a | reuse_address tells the kernel to reuse a local socket in |
|---|
| 336 | n/a | TIME_WAIT state, without waiting for its natural timeout to |
|---|
| 337 | n/a | expire. If not specified will automatically be set to True on |
|---|
| 338 | n/a | UNIX. |
|---|
| 339 | n/a | |
|---|
| 340 | n/a | reuse_port tells the kernel to allow this endpoint to be bound to |
|---|
| 341 | n/a | the same port as other existing endpoints are bound to, so long as |
|---|
| 342 | n/a | they all set this flag when being created. This option is not |
|---|
| 343 | n/a | supported on Windows. |
|---|
| 344 | n/a | """ |
|---|
| 345 | n/a | raise NotImplementedError |
|---|
| 346 | n/a | |
|---|
| 347 | n/a | def create_unix_connection(self, protocol_factory, path, *, |
|---|
| 348 | n/a | ssl=None, sock=None, |
|---|
| 349 | n/a | server_hostname=None): |
|---|
| 350 | n/a | raise NotImplementedError |
|---|
| 351 | n/a | |
|---|
| 352 | n/a | def create_unix_server(self, protocol_factory, path, *, |
|---|
| 353 | n/a | sock=None, backlog=100, ssl=None): |
|---|
| 354 | n/a | """A coroutine which creates a UNIX Domain Socket server. |
|---|
| 355 | n/a | |
|---|
| 356 | n/a | The return value is a Server object, which can be used to stop |
|---|
| 357 | n/a | the service. |
|---|
| 358 | n/a | |
|---|
| 359 | n/a | path is a str, representing a file systsem path to bind the |
|---|
| 360 | n/a | server socket to. |
|---|
| 361 | n/a | |
|---|
| 362 | n/a | sock can optionally be specified in order to use a preexisting |
|---|
| 363 | n/a | socket object. |
|---|
| 364 | n/a | |
|---|
| 365 | n/a | backlog is the maximum number of queued connections passed to |
|---|
| 366 | n/a | listen() (defaults to 100). |
|---|
| 367 | n/a | |
|---|
| 368 | n/a | ssl can be set to an SSLContext to enable SSL over the |
|---|
| 369 | n/a | accepted connections. |
|---|
| 370 | n/a | """ |
|---|
| 371 | n/a | raise NotImplementedError |
|---|
| 372 | n/a | |
|---|
| 373 | n/a | def create_datagram_endpoint(self, protocol_factory, |
|---|
| 374 | n/a | local_addr=None, remote_addr=None, *, |
|---|
| 375 | n/a | family=0, proto=0, flags=0, |
|---|
| 376 | n/a | reuse_address=None, reuse_port=None, |
|---|
| 377 | n/a | allow_broadcast=None, sock=None): |
|---|
| 378 | n/a | """A coroutine which creates a datagram endpoint. |
|---|
| 379 | n/a | |
|---|
| 380 | n/a | This method will try to establish the endpoint in the background. |
|---|
| 381 | n/a | When successful, the coroutine returns a (transport, protocol) pair. |
|---|
| 382 | n/a | |
|---|
| 383 | n/a | protocol_factory must be a callable returning a protocol instance. |
|---|
| 384 | n/a | |
|---|
| 385 | n/a | socket family AF_INET or socket.AF_INET6 depending on host (or |
|---|
| 386 | n/a | family if specified), socket type SOCK_DGRAM. |
|---|
| 387 | n/a | |
|---|
| 388 | n/a | reuse_address tells the kernel to reuse a local socket in |
|---|
| 389 | n/a | TIME_WAIT state, without waiting for its natural timeout to |
|---|
| 390 | n/a | expire. If not specified it will automatically be set to True on |
|---|
| 391 | n/a | UNIX. |
|---|
| 392 | n/a | |
|---|
| 393 | n/a | reuse_port tells the kernel to allow this endpoint to be bound to |
|---|
| 394 | n/a | the same port as other existing endpoints are bound to, so long as |
|---|
| 395 | n/a | they all set this flag when being created. This option is not |
|---|
| 396 | n/a | supported on Windows and some UNIX's. If the |
|---|
| 397 | n/a | :py:data:`~socket.SO_REUSEPORT` constant is not defined then this |
|---|
| 398 | n/a | capability is unsupported. |
|---|
| 399 | n/a | |
|---|
| 400 | n/a | allow_broadcast tells the kernel to allow this endpoint to send |
|---|
| 401 | n/a | messages to the broadcast address. |
|---|
| 402 | n/a | |
|---|
| 403 | n/a | sock can optionally be specified in order to use a preexisting |
|---|
| 404 | n/a | socket object. |
|---|
| 405 | n/a | """ |
|---|
| 406 | n/a | raise NotImplementedError |
|---|
| 407 | n/a | |
|---|
| 408 | n/a | # Pipes and subprocesses. |
|---|
| 409 | n/a | |
|---|
| 410 | n/a | def connect_read_pipe(self, protocol_factory, pipe): |
|---|
| 411 | n/a | """Register read pipe in event loop. Set the pipe to non-blocking mode. |
|---|
| 412 | n/a | |
|---|
| 413 | n/a | protocol_factory should instantiate object with Protocol interface. |
|---|
| 414 | n/a | pipe is a file-like object. |
|---|
| 415 | n/a | Return pair (transport, protocol), where transport supports the |
|---|
| 416 | n/a | ReadTransport interface.""" |
|---|
| 417 | n/a | # The reason to accept file-like object instead of just file descriptor |
|---|
| 418 | n/a | # is: we need to own pipe and close it at transport finishing |
|---|
| 419 | n/a | # Can got complicated errors if pass f.fileno(), |
|---|
| 420 | n/a | # close fd in pipe transport then close f and vise versa. |
|---|
| 421 | n/a | raise NotImplementedError |
|---|
| 422 | n/a | |
|---|
| 423 | n/a | def connect_write_pipe(self, protocol_factory, pipe): |
|---|
| 424 | n/a | """Register write pipe in event loop. |
|---|
| 425 | n/a | |
|---|
| 426 | n/a | protocol_factory should instantiate object with BaseProtocol interface. |
|---|
| 427 | n/a | Pipe is file-like object already switched to nonblocking. |
|---|
| 428 | n/a | Return pair (transport, protocol), where transport support |
|---|
| 429 | n/a | WriteTransport interface.""" |
|---|
| 430 | n/a | # The reason to accept file-like object instead of just file descriptor |
|---|
| 431 | n/a | # is: we need to own pipe and close it at transport finishing |
|---|
| 432 | n/a | # Can got complicated errors if pass f.fileno(), |
|---|
| 433 | n/a | # close fd in pipe transport then close f and vise versa. |
|---|
| 434 | n/a | raise NotImplementedError |
|---|
| 435 | n/a | |
|---|
| 436 | n/a | def subprocess_shell(self, protocol_factory, cmd, *, stdin=subprocess.PIPE, |
|---|
| 437 | n/a | stdout=subprocess.PIPE, stderr=subprocess.PIPE, |
|---|
| 438 | n/a | **kwargs): |
|---|
| 439 | n/a | raise NotImplementedError |
|---|
| 440 | n/a | |
|---|
| 441 | n/a | def subprocess_exec(self, protocol_factory, *args, stdin=subprocess.PIPE, |
|---|
| 442 | n/a | stdout=subprocess.PIPE, stderr=subprocess.PIPE, |
|---|
| 443 | n/a | **kwargs): |
|---|
| 444 | n/a | raise NotImplementedError |
|---|
| 445 | n/a | |
|---|
| 446 | n/a | # Ready-based callback registration methods. |
|---|
| 447 | n/a | # The add_*() methods return None. |
|---|
| 448 | n/a | # The remove_*() methods return True if something was removed, |
|---|
| 449 | n/a | # False if there was nothing to delete. |
|---|
| 450 | n/a | |
|---|
| 451 | n/a | def add_reader(self, fd, callback, *args): |
|---|
| 452 | n/a | raise NotImplementedError |
|---|
| 453 | n/a | |
|---|
| 454 | n/a | def remove_reader(self, fd): |
|---|
| 455 | n/a | raise NotImplementedError |
|---|
| 456 | n/a | |
|---|
| 457 | n/a | def add_writer(self, fd, callback, *args): |
|---|
| 458 | n/a | raise NotImplementedError |
|---|
| 459 | n/a | |
|---|
| 460 | n/a | def remove_writer(self, fd): |
|---|
| 461 | n/a | raise NotImplementedError |
|---|
| 462 | n/a | |
|---|
| 463 | n/a | # Completion based I/O methods returning Futures. |
|---|
| 464 | n/a | |
|---|
| 465 | n/a | def sock_recv(self, sock, nbytes): |
|---|
| 466 | n/a | raise NotImplementedError |
|---|
| 467 | n/a | |
|---|
| 468 | n/a | def sock_sendall(self, sock, data): |
|---|
| 469 | n/a | raise NotImplementedError |
|---|
| 470 | n/a | |
|---|
| 471 | n/a | def sock_connect(self, sock, address): |
|---|
| 472 | n/a | raise NotImplementedError |
|---|
| 473 | n/a | |
|---|
| 474 | n/a | def sock_accept(self, sock): |
|---|
| 475 | n/a | raise NotImplementedError |
|---|
| 476 | n/a | |
|---|
| 477 | n/a | # Signal handling. |
|---|
| 478 | n/a | |
|---|
| 479 | n/a | def add_signal_handler(self, sig, callback, *args): |
|---|
| 480 | n/a | raise NotImplementedError |
|---|
| 481 | n/a | |
|---|
| 482 | n/a | def remove_signal_handler(self, sig): |
|---|
| 483 | n/a | raise NotImplementedError |
|---|
| 484 | n/a | |
|---|
| 485 | n/a | # Task factory. |
|---|
| 486 | n/a | |
|---|
| 487 | n/a | def set_task_factory(self, factory): |
|---|
| 488 | n/a | raise NotImplementedError |
|---|
| 489 | n/a | |
|---|
| 490 | n/a | def get_task_factory(self): |
|---|
| 491 | n/a | raise NotImplementedError |
|---|
| 492 | n/a | |
|---|
| 493 | n/a | # Error handlers. |
|---|
| 494 | n/a | |
|---|
| 495 | n/a | def get_exception_handler(self): |
|---|
| 496 | n/a | raise NotImplementedError |
|---|
| 497 | n/a | |
|---|
| 498 | n/a | def set_exception_handler(self, handler): |
|---|
| 499 | n/a | raise NotImplementedError |
|---|
| 500 | n/a | |
|---|
| 501 | n/a | def default_exception_handler(self, context): |
|---|
| 502 | n/a | raise NotImplementedError |
|---|
| 503 | n/a | |
|---|
| 504 | n/a | def call_exception_handler(self, context): |
|---|
| 505 | n/a | raise NotImplementedError |
|---|
| 506 | n/a | |
|---|
| 507 | n/a | # Debug flag management. |
|---|
| 508 | n/a | |
|---|
| 509 | n/a | def get_debug(self): |
|---|
| 510 | n/a | raise NotImplementedError |
|---|
| 511 | n/a | |
|---|
| 512 | n/a | def set_debug(self, enabled): |
|---|
| 513 | n/a | raise NotImplementedError |
|---|
| 514 | n/a | |
|---|
| 515 | n/a | |
|---|
| 516 | n/a | class AbstractEventLoopPolicy: |
|---|
| 517 | n/a | """Abstract policy for accessing the event loop.""" |
|---|
| 518 | n/a | |
|---|
| 519 | n/a | def get_event_loop(self): |
|---|
| 520 | n/a | """Get the event loop for the current context. |
|---|
| 521 | n/a | |
|---|
| 522 | n/a | Returns an event loop object implementing the BaseEventLoop interface, |
|---|
| 523 | n/a | or raises an exception in case no event loop has been set for the |
|---|
| 524 | n/a | current context and the current policy does not specify to create one. |
|---|
| 525 | n/a | |
|---|
| 526 | n/a | It should never return None.""" |
|---|
| 527 | n/a | raise NotImplementedError |
|---|
| 528 | n/a | |
|---|
| 529 | n/a | def set_event_loop(self, loop): |
|---|
| 530 | n/a | """Set the event loop for the current context to loop.""" |
|---|
| 531 | n/a | raise NotImplementedError |
|---|
| 532 | n/a | |
|---|
| 533 | n/a | def new_event_loop(self): |
|---|
| 534 | n/a | """Create and return a new event loop object according to this |
|---|
| 535 | n/a | policy's rules. If there's need to set this loop as the event loop for |
|---|
| 536 | n/a | the current context, set_event_loop must be called explicitly.""" |
|---|
| 537 | n/a | raise NotImplementedError |
|---|
| 538 | n/a | |
|---|
| 539 | n/a | # Child processes handling (Unix only). |
|---|
| 540 | n/a | |
|---|
| 541 | n/a | def get_child_watcher(self): |
|---|
| 542 | n/a | "Get the watcher for child processes." |
|---|
| 543 | n/a | raise NotImplementedError |
|---|
| 544 | n/a | |
|---|
| 545 | n/a | def set_child_watcher(self, watcher): |
|---|
| 546 | n/a | """Set the watcher for child processes.""" |
|---|
| 547 | n/a | raise NotImplementedError |
|---|
| 548 | n/a | |
|---|
| 549 | n/a | |
|---|
| 550 | n/a | class BaseDefaultEventLoopPolicy(AbstractEventLoopPolicy): |
|---|
| 551 | n/a | """Default policy implementation for accessing the event loop. |
|---|
| 552 | n/a | |
|---|
| 553 | n/a | In this policy, each thread has its own event loop. However, we |
|---|
| 554 | n/a | only automatically create an event loop by default for the main |
|---|
| 555 | n/a | thread; other threads by default have no event loop. |
|---|
| 556 | n/a | |
|---|
| 557 | n/a | Other policies may have different rules (e.g. a single global |
|---|
| 558 | n/a | event loop, or automatically creating an event loop per thread, or |
|---|
| 559 | n/a | using some other notion of context to which an event loop is |
|---|
| 560 | n/a | associated). |
|---|
| 561 | n/a | """ |
|---|
| 562 | n/a | |
|---|
| 563 | n/a | _loop_factory = None |
|---|
| 564 | n/a | |
|---|
| 565 | n/a | class _Local(threading.local): |
|---|
| 566 | n/a | _loop = None |
|---|
| 567 | n/a | _set_called = False |
|---|
| 568 | n/a | |
|---|
| 569 | n/a | def __init__(self): |
|---|
| 570 | n/a | self._local = self._Local() |
|---|
| 571 | n/a | |
|---|
| 572 | n/a | def get_event_loop(self): |
|---|
| 573 | n/a | """Get the event loop. |
|---|
| 574 | n/a | |
|---|
| 575 | n/a | This may be None or an instance of EventLoop. |
|---|
| 576 | n/a | """ |
|---|
| 577 | n/a | if (self._local._loop is None and |
|---|
| 578 | n/a | not self._local._set_called and |
|---|
| 579 | n/a | isinstance(threading.current_thread(), threading._MainThread)): |
|---|
| 580 | n/a | self.set_event_loop(self.new_event_loop()) |
|---|
| 581 | n/a | if self._local._loop is None: |
|---|
| 582 | n/a | raise RuntimeError('There is no current event loop in thread %r.' |
|---|
| 583 | n/a | % threading.current_thread().name) |
|---|
| 584 | n/a | return self._local._loop |
|---|
| 585 | n/a | |
|---|
| 586 | n/a | def set_event_loop(self, loop): |
|---|
| 587 | n/a | """Set the event loop.""" |
|---|
| 588 | n/a | self._local._set_called = True |
|---|
| 589 | n/a | assert loop is None or isinstance(loop, AbstractEventLoop) |
|---|
| 590 | n/a | self._local._loop = loop |
|---|
| 591 | n/a | |
|---|
| 592 | n/a | def new_event_loop(self): |
|---|
| 593 | n/a | """Create a new event loop. |
|---|
| 594 | n/a | |
|---|
| 595 | n/a | You must call set_event_loop() to make this the current event |
|---|
| 596 | n/a | loop. |
|---|
| 597 | n/a | """ |
|---|
| 598 | n/a | return self._loop_factory() |
|---|
| 599 | n/a | |
|---|
| 600 | n/a | |
|---|
| 601 | n/a | # Event loop policy. The policy itself is always global, even if the |
|---|
| 602 | n/a | # policy's rules say that there is an event loop per thread (or other |
|---|
| 603 | n/a | # notion of context). The default policy is installed by the first |
|---|
| 604 | n/a | # call to get_event_loop_policy(). |
|---|
| 605 | n/a | _event_loop_policy = None |
|---|
| 606 | n/a | |
|---|
| 607 | n/a | # Lock for protecting the on-the-fly creation of the event loop policy. |
|---|
| 608 | n/a | _lock = threading.Lock() |
|---|
| 609 | n/a | |
|---|
| 610 | n/a | |
|---|
| 611 | n/a | # A TLS for the running event loop, used by _get_running_loop. |
|---|
| 612 | n/a | class _RunningLoop(threading.local): |
|---|
| 613 | n/a | _loop = None |
|---|
| 614 | n/a | _running_loop = _RunningLoop() |
|---|
| 615 | n/a | |
|---|
| 616 | n/a | |
|---|
| 617 | n/a | def _get_running_loop(): |
|---|
| 618 | n/a | """Return the running event loop or None. |
|---|
| 619 | n/a | |
|---|
| 620 | n/a | This is a low-level function intended to be used by event loops. |
|---|
| 621 | n/a | This function is thread-specific. |
|---|
| 622 | n/a | """ |
|---|
| 623 | n/a | return _running_loop._loop |
|---|
| 624 | n/a | |
|---|
| 625 | n/a | |
|---|
| 626 | n/a | def _set_running_loop(loop): |
|---|
| 627 | n/a | """Set the running event loop. |
|---|
| 628 | n/a | |
|---|
| 629 | n/a | This is a low-level function intended to be used by event loops. |
|---|
| 630 | n/a | This function is thread-specific. |
|---|
| 631 | n/a | """ |
|---|
| 632 | n/a | _running_loop._loop = loop |
|---|
| 633 | n/a | |
|---|
| 634 | n/a | |
|---|
| 635 | n/a | def _init_event_loop_policy(): |
|---|
| 636 | n/a | global _event_loop_policy |
|---|
| 637 | n/a | with _lock: |
|---|
| 638 | n/a | if _event_loop_policy is None: # pragma: no branch |
|---|
| 639 | n/a | from . import DefaultEventLoopPolicy |
|---|
| 640 | n/a | _event_loop_policy = DefaultEventLoopPolicy() |
|---|
| 641 | n/a | |
|---|
| 642 | n/a | |
|---|
| 643 | n/a | def get_event_loop_policy(): |
|---|
| 644 | n/a | """Get the current event loop policy.""" |
|---|
| 645 | n/a | if _event_loop_policy is None: |
|---|
| 646 | n/a | _init_event_loop_policy() |
|---|
| 647 | n/a | return _event_loop_policy |
|---|
| 648 | n/a | |
|---|
| 649 | n/a | |
|---|
| 650 | n/a | def set_event_loop_policy(policy): |
|---|
| 651 | n/a | """Set the current event loop policy. |
|---|
| 652 | n/a | |
|---|
| 653 | n/a | If policy is None, the default policy is restored.""" |
|---|
| 654 | n/a | global _event_loop_policy |
|---|
| 655 | n/a | assert policy is None or isinstance(policy, AbstractEventLoopPolicy) |
|---|
| 656 | n/a | _event_loop_policy = policy |
|---|
| 657 | n/a | |
|---|
| 658 | n/a | |
|---|
| 659 | n/a | def get_event_loop(): |
|---|
| 660 | n/a | """Return an asyncio event loop. |
|---|
| 661 | n/a | |
|---|
| 662 | n/a | When called from a coroutine or a callback (e.g. scheduled with call_soon |
|---|
| 663 | n/a | or similar API), this function will always return the running event loop. |
|---|
| 664 | n/a | |
|---|
| 665 | n/a | If there is no running event loop set, the function will return |
|---|
| 666 | n/a | the result of `get_event_loop_policy().get_event_loop()` call. |
|---|
| 667 | n/a | """ |
|---|
| 668 | n/a | current_loop = _get_running_loop() |
|---|
| 669 | n/a | if current_loop is not None: |
|---|
| 670 | n/a | return current_loop |
|---|
| 671 | n/a | return get_event_loop_policy().get_event_loop() |
|---|
| 672 | n/a | |
|---|
| 673 | n/a | |
|---|
| 674 | n/a | def set_event_loop(loop): |
|---|
| 675 | n/a | """Equivalent to calling get_event_loop_policy().set_event_loop(loop).""" |
|---|
| 676 | n/a | get_event_loop_policy().set_event_loop(loop) |
|---|
| 677 | n/a | |
|---|
| 678 | n/a | |
|---|
| 679 | n/a | def new_event_loop(): |
|---|
| 680 | n/a | """Equivalent to calling get_event_loop_policy().new_event_loop().""" |
|---|
| 681 | n/a | return get_event_loop_policy().new_event_loop() |
|---|
| 682 | n/a | |
|---|
| 683 | n/a | |
|---|
| 684 | n/a | def get_child_watcher(): |
|---|
| 685 | n/a | """Equivalent to calling get_event_loop_policy().get_child_watcher().""" |
|---|
| 686 | n/a | return get_event_loop_policy().get_child_watcher() |
|---|
| 687 | n/a | |
|---|
| 688 | n/a | |
|---|
| 689 | n/a | def set_child_watcher(watcher): |
|---|
| 690 | n/a | """Equivalent to calling |
|---|
| 691 | n/a | get_event_loop_policy().set_child_watcher(watcher).""" |
|---|
| 692 | n/a | return get_event_loop_policy().set_child_watcher(watcher) |
|---|