diff options
author | James Taylor <user234683@users.noreply.github.com> | 2018-07-12 23:40:30 -0700 |
---|---|---|
committer | James Taylor <user234683@users.noreply.github.com> | 2018-07-12 23:41:07 -0700 |
commit | c3b9f8c4582882cd1f768b0727eca75475bb4f94 (patch) | |
tree | 5b4a1c693fd5b7416f1d5a75862e633502e77ca7 /python/gevent/_socketcommon.py | |
parent | fe9fe8257740529f5880693992e4eeca35c7ea3e (diff) | |
download | yt-local-c3b9f8c4582882cd1f768b0727eca75475bb4f94.tar.lz yt-local-c3b9f8c4582882cd1f768b0727eca75475bb4f94.tar.xz yt-local-c3b9f8c4582882cd1f768b0727eca75475bb4f94.zip |
track embedded python distribution
Diffstat (limited to 'python/gevent/_socketcommon.py')
-rw-r--r-- | python/gevent/_socketcommon.py | 343 |
1 files changed, 343 insertions, 0 deletions
diff --git a/python/gevent/_socketcommon.py b/python/gevent/_socketcommon.py new file mode 100644 index 0000000..4da29c8 --- /dev/null +++ b/python/gevent/_socketcommon.py @@ -0,0 +1,343 @@ +# Copyright (c) 2009-2014 Denis Bilenko and gevent contributors. See LICENSE for details. +from __future__ import absolute_import + +# standard functions and classes that this module re-implements in a gevent-aware way: +_implements = [ + 'create_connection', + 'socket', + 'SocketType', + 'fromfd', + 'socketpair', +] + +__dns__ = [ + 'getaddrinfo', + 'gethostbyname', + 'gethostbyname_ex', + 'gethostbyaddr', + 'getnameinfo', + 'getfqdn', +] + +_implements += __dns__ + +# non-standard functions that this module provides: +__extensions__ = [ + 'cancel_wait', + 'wait_read', + 'wait_write', + 'wait_readwrite', +] + +# standard functions and classes that this module re-imports +__imports__ = [ + 'error', + 'gaierror', + 'herror', + 'htonl', + 'htons', + 'ntohl', + 'ntohs', + 'inet_aton', + 'inet_ntoa', + 'inet_pton', + 'inet_ntop', + 'timeout', + 'gethostname', + 'getprotobyname', + 'getservbyname', + 'getservbyport', + 'getdefaulttimeout', + 'setdefaulttimeout', + # Windows: + 'errorTab', +] + +__py3_imports__ = [ + # Python 3 + 'AddressFamily', + 'SocketKind', + 'CMSG_LEN', + 'CMSG_SPACE', + 'dup', + 'if_indextoname', + 'if_nameindex', + 'if_nametoindex', + 'sethostname', +] + +__imports__.extend(__py3_imports__) + + +import sys +from gevent.hub import get_hub +from gevent.hub import ConcurrentObjectUseError +from gevent.timeout import Timeout +from gevent._compat import string_types, integer_types, PY3 +from gevent._util import copy_globals +from gevent._util import _NONE + +is_windows = sys.platform == 'win32' +# pylint:disable=no-name-in-module,unused-import +if is_windows: + # no such thing as WSAEPERM or error code 10001 according to winsock.h or MSDN + from errno import WSAEINVAL as EINVAL + from errno import WSAEWOULDBLOCK as EWOULDBLOCK + from errno import WSAEINPROGRESS as EINPROGRESS + from errno import WSAEALREADY as EALREADY + from errno import WSAEISCONN as EISCONN + from gevent.win32util import formatError as strerror + EAGAIN = EWOULDBLOCK +else: + from errno import EINVAL + from errno import EWOULDBLOCK + from errno import EINPROGRESS + from errno import EALREADY + from errno import EAGAIN + from errno import EISCONN + from os import strerror + +try: + from errno import EBADF +except ImportError: + EBADF = 9 + +import _socket +_realsocket = _socket.socket +import socket as __socket__ + +_name = _value = None +__imports__ = copy_globals(__socket__, globals(), + only_names=__imports__, + ignore_missing_names=True) + +for _name in __socket__.__all__: + _value = getattr(__socket__, _name) + if isinstance(_value, (integer_types, string_types)): + globals()[_name] = _value + __imports__.append(_name) + +del _name, _value + +_timeout_error = timeout # pylint: disable=undefined-variable + + +def wait(io, timeout=None, timeout_exc=_NONE): + """ + Block the current greenlet until *io* is ready. + + If *timeout* is non-negative, then *timeout_exc* is raised after + *timeout* second has passed. By default *timeout_exc* is + ``socket.timeout('timed out')``. + + If :func:`cancel_wait` is called on *io* by another greenlet, + raise an exception in this blocking greenlet + (``socket.error(EBADF, 'File descriptor was closed in another + greenlet')`` by default). + + :param io: A libev watcher, most commonly an IO watcher obtained from + :meth:`gevent.core.loop.io` + :keyword timeout_exc: The exception to raise if the timeout expires. + By default, a :class:`socket.timeout` exception is raised. + If you pass a value for this keyword, it is interpreted as for + :class:`gevent.timeout.Timeout`. + """ + if io.callback is not None: + raise ConcurrentObjectUseError('This socket is already used by another greenlet: %r' % (io.callback, )) + if timeout is not None: + timeout_exc = timeout_exc if timeout_exc is not _NONE else _timeout_error('timed out') + timeout = Timeout.start_new(timeout, timeout_exc) + + try: + return get_hub().wait(io) + finally: + if timeout is not None: + timeout.cancel() + # rename "io" to "watcher" because wait() works with any watcher + + +def wait_read(fileno, timeout=None, timeout_exc=_NONE): + """ + Block the current greenlet until *fileno* is ready to read. + + For the meaning of the other parameters and possible exceptions, + see :func:`wait`. + + .. seealso:: :func:`cancel_wait` + """ + io = get_hub().loop.io(fileno, 1) + return wait(io, timeout, timeout_exc) + + +def wait_write(fileno, timeout=None, timeout_exc=_NONE, event=_NONE): + """ + Block the current greenlet until *fileno* is ready to write. + + For the meaning of the other parameters and possible exceptions, + see :func:`wait`. + + :keyword event: Ignored. Applications should not pass this parameter. + In the future, it may become an error. + + .. seealso:: :func:`cancel_wait` + """ + # pylint:disable=unused-argument + io = get_hub().loop.io(fileno, 2) + return wait(io, timeout, timeout_exc) + + +def wait_readwrite(fileno, timeout=None, timeout_exc=_NONE, event=_NONE): + """ + Block the current greenlet until *fileno* is ready to read or + write. + + For the meaning of the other parameters and possible exceptions, + see :func:`wait`. + + :keyword event: Ignored. Applications should not pass this parameter. + In the future, it may become an error. + + .. seealso:: :func:`cancel_wait` + """ + # pylint:disable=unused-argument + io = get_hub().loop.io(fileno, 3) + return wait(io, timeout, timeout_exc) + +#: The exception raised by default on a call to :func:`cancel_wait` +class cancel_wait_ex(error): # pylint: disable=undefined-variable + def __init__(self): + super(cancel_wait_ex, self).__init__( + EBADF, + 'File descriptor was closed in another greenlet') + + +def cancel_wait(watcher, error=cancel_wait_ex): + """See :meth:`gevent.hub.Hub.cancel_wait`""" + get_hub().cancel_wait(watcher, error) + + +class BlockingResolver(object): + + def __init__(self, hub=None): + pass + + def close(self): + pass + + for method in ['gethostbyname', + 'gethostbyname_ex', + 'getaddrinfo', + 'gethostbyaddr', + 'getnameinfo']: + locals()[method] = staticmethod(getattr(_socket, method)) + + +def gethostbyname(hostname): + """ + gethostbyname(host) -> address + + Return the IP address (a string of the form '255.255.255.255') for a host. + + .. seealso:: :doc:`dns` + """ + return get_hub().resolver.gethostbyname(hostname) + + +def gethostbyname_ex(hostname): + """ + gethostbyname_ex(host) -> (name, aliaslist, addresslist) + + Return the true host name, a list of aliases, and a list of IP addresses, + for a host. The host argument is a string giving a host name or IP number. + Resolve host and port into list of address info entries. + + .. seealso:: :doc:`dns` + """ + return get_hub().resolver.gethostbyname_ex(hostname) + + +def getaddrinfo(host, port, family=0, socktype=0, proto=0, flags=0): + """ + Resolve host and port into list of address info entries. + + Translate the host/port argument into a sequence of 5-tuples that contain + all the necessary arguments for creating a socket connected to that service. + host is a domain name, a string representation of an IPv4/v6 address or + None. port is a string service name such as 'http', a numeric port number or + None. By passing None as the value of host and port, you can pass NULL to + the underlying C API. + + The family, type and proto arguments can be optionally specified in order to + narrow the list of addresses returned. Passing zero as a value for each of + these arguments selects the full range of results. + + .. seealso:: :doc:`dns` + """ + return get_hub().resolver.getaddrinfo(host, port, family, socktype, proto, flags) + +if PY3: + # The name of the socktype param changed to type in Python 3. + # See https://github.com/gevent/gevent/issues/960 + # Using inspect here to directly detect the condition is painful because we have to + # wrap it with a try/except TypeError because not all Python 2 + # versions can get the args of a builtin; we also have to use a with to suppress + # the deprecation warning. + d = getaddrinfo.__doc__ + + def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): # pylint:disable=function-redefined + return get_hub().resolver.getaddrinfo(host, port, family, type, proto, flags) + getaddrinfo.__doc__ = d + del d + + +def gethostbyaddr(ip_address): + """ + gethostbyaddr(ip_address) -> (name, aliaslist, addresslist) + + Return the true host name, a list of aliases, and a list of IP addresses, + for a host. The host argument is a string giving a host name or IP number. + + .. seealso:: :doc:`dns` + """ + return get_hub().resolver.gethostbyaddr(ip_address) + + +def getnameinfo(sockaddr, flags): + """ + getnameinfo(sockaddr, flags) -> (host, port) + + Get host and port for a sockaddr. + + .. seealso:: :doc:`dns` + """ + return get_hub().resolver.getnameinfo(sockaddr, flags) + + +def getfqdn(name=''): + """Get fully qualified domain name from name. + + An empty argument is interpreted as meaning the local host. + + First the hostname returned by gethostbyaddr() is checked, then + possibly existing aliases. In case no FQDN is available, hostname + from gethostname() is returned. + """ + # pylint: disable=undefined-variable + name = name.strip() + if not name or name == '0.0.0.0': + name = gethostname() + try: + hostname, aliases, _ = gethostbyaddr(name) + except error: + pass + else: + aliases.insert(0, hostname) + for name in aliases: # EWW! pylint:disable=redefined-argument-from-local + if isinstance(name, bytes): + if b'.' in name: + break + elif '.' in name: + break + else: + name = hostname + return name |