Commit 1f6bd091 authored by Jason Madden's avatar Jason Madden Committed by GitHub

Merge pull request #1311 from gevent/issue1310

Make gevent.socket.getaddrinfo return enums on Python 3
parents a2c56938 b74209a7
...@@ -46,6 +46,10 @@ ...@@ -46,6 +46,10 @@
reusable. In particular, the tests are now run with ``python -m reusable. In particular, the tests are now run with ``python -m
gevent.tests``. See :issue:`1293`. gevent.tests``. See :issue:`1293`.
- Make a monkey-patched ``socket.getaddrinfo`` return socket module
enums instead of plain integers for the socket type and address
family on Python 3. See :issue:`1310` reported by TheYOSH.
1.3.7 (2018-10-12) 1.3.7 (2018-10-12)
================== ==================
......
...@@ -204,11 +204,30 @@ if PY3: ...@@ -204,11 +204,30 @@ if PY3:
# the deprecation warning. # the deprecation warning.
d = getaddrinfo.__doc__ d = getaddrinfo.__doc__
def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): # pylint:disable=function-redefined def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0):
return get_hub().resolver.getaddrinfo(host, port, family, type, proto, flags) # pylint:disable=function-redefined, undefined-variable
# Also, on Python 3, we need to translate into the special enums.
# Our lower-level resolvers, including the thread and blocking, which use _socket,
# function simply with integers.
addrlist = get_hub().resolver.getaddrinfo(host, port, family, type, proto, flags)
result = [
(_intenum_converter(af, AddressFamily),
_intenum_converter(socktype, SocketKind),
proto, canonname, sa)
for af, socktype, proto, canonname, sa
in addrlist
]
return result
getaddrinfo.__doc__ = d getaddrinfo.__doc__ = d
del d del d
def _intenum_converter(value, enum_klass):
try:
return enum_klass(value)
except ValueError: # pragma: no cover
return value
def gethostbyaddr(ip_address): def gethostbyaddr(ip_address):
""" """
......
...@@ -4,18 +4,18 @@ from _socket import gaierror ...@@ -4,18 +4,18 @@ from _socket import gaierror
from _socket import error from _socket import error
from _socket import getservbyname from _socket import getservbyname
from _socket import getaddrinfo from _socket import getaddrinfo
from _socket import SOCK_STREAM
from _socket import SOCK_DGRAM
from _socket import SOL_TCP
from _socket import AI_CANONNAME
from _socket import EAI_SERVICE
from _socket import AF_INET
from _socket import AI_PASSIVE
from gevent._compat import string_types from gevent._compat import string_types
from gevent._compat import integer_types from gevent._compat import integer_types
from gevent.socket import SOCK_STREAM
from gevent.socket import SOCK_DGRAM
from gevent.socket import SOL_TCP
from gevent.socket import AI_CANONNAME
from gevent.socket import EAI_SERVICE
from gevent.socket import AF_INET
from gevent.socket import AI_PASSIVE
# Nothing public here. # Nothing public here.
__all__ = [] __all__ = []
......
from __future__ import print_function from __future__ import print_function
import pickle import pickle
import sys
import gevent.testing as greentest import gevent.testing as greentest
try: try:
from gevent.resolver.cares import ares_host_result from gevent.resolver.cares import ares_host_result
except ImportError as ex: except ImportError: # pragma: no cover
print(ex) ares_host_result = None
sys.exit(0)
@greentest.skipIf(ares_host_result is None,
"Must be able to import ares")
class TestPickle(greentest.TestCase): class TestPickle(greentest.TestCase):
# Issue 104: ares.ares_host_result unpickleable # Issue 104: ares.ares_host_result unpickleable
...@@ -17,8 +17,9 @@ class TestPickle(greentest.TestCase): ...@@ -17,8 +17,9 @@ class TestPickle(greentest.TestCase):
r = ares_host_result('family', ('arg1', 'arg2', )) r = ares_host_result('family', ('arg1', 'arg2', ))
dumped = pickle.dumps(r, protocol) dumped = pickle.dumps(r, protocol)
loaded = pickle.loads(dumped) loaded = pickle.loads(dumped)
assert r == loaded, (r, loaded) self.assertEqual(r, loaded)
assert r.family == loaded.family, (r, loaded) self.assertEqual(r.family, loaded.family)
for i in range(0, pickle.HIGHEST_PROTOCOL): for i in range(0, pickle.HIGHEST_PROTOCOL):
def make_test(j): def make_test(j):
......
...@@ -383,13 +383,18 @@ class TestLocalhost(TestCase): ...@@ -383,13 +383,18 @@ class TestLocalhost(TestCase):
return result return result
if not greentest.RUNNING_ON_TRAVIS: add(
# ares fails here, for some reason, presumably a badly TestLocalhost, 'ip6-localhost',
# configured /etc/hosts skip=greentest.RUNNING_ON_TRAVIS,
add(TestLocalhost, 'ip6-localhost') skip_reason="ares fails here, for some reason, presumably a badly "
# Beginning Dec 1 2017, ares started returning ip6-localhost "configured /etc/hosts"
# instead of localhost )
add(TestLocalhost, 'localhost') add(
TestLocalhost, 'localhost',
skip=greentest.RUNNING_ON_TRAVIS,
skip_reason="Beginning Dec 1 2017, ares started returning ip6-localhost "
"instead of localhost"
)
class TestNonexistent(TestCase): class TestNonexistent(TestCase):
...@@ -407,10 +412,12 @@ add(Test1234, '1.2.3.4') ...@@ -407,10 +412,12 @@ add(Test1234, '1.2.3.4')
class Test127001(TestCase): class Test127001(TestCase):
pass pass
if not greentest.RUNNING_ON_TRAVIS: add(Test127001, '127.0.0.1',
# Beginning Dec 1 2017, ares started returning ip6-localhost skip=greentest.RUNNING_ON_TRAVIS,
# instead of localhost skip_reason="Beginning Dec 1 2017, ares started returning ip6-localhost "
add(Test127001, '127.0.0.1') "instead of localhost"
)
class TestBroadcast(TestCase): class TestBroadcast(TestCase):
...@@ -440,7 +447,7 @@ class SanitizedHostsFile(HostsFile): ...@@ -440,7 +447,7 @@ class SanitizedHostsFile(HostsFile):
# We get extra results from some impls, like OS X # We get extra results from some impls, like OS X
# it returns DGRAM results # it returns DGRAM results
or name == 'localhost')): or name == 'localhost')):
continue continue # pragma: no cover
if name.endswith('local'): if name.endswith('local'):
# These can only be found if bonjour is running, # These can only be found if bonjour is running,
# and are very slow to do so with the system resolver on OS X # and are very slow to do so with the system resolver on OS X
...@@ -495,21 +502,6 @@ class TestFamily(TestCase): ...@@ -495,21 +502,6 @@ class TestFamily(TestCase):
cls._result = getattr(socket, 'getaddrinfo')(TestGeventOrg.HOSTNAME, None) cls._result = getattr(socket, 'getaddrinfo')(TestGeventOrg.HOSTNAME, None)
return cls._result return cls._result
def assert_error(self, error, function, *args): # pylint:disable=arguments-differ
try:
result = function(*args)
raise AssertionError('%s: Expected to raise %s, instead returned %r' % (function, error, result))
except Exception as ex:
if isinstance(error, six.string_types):
repr_error = error
else:
repr_error = repr(error)
if type(ex) is not type(error):
raise
if repr(ex) == repr_error:
return
raise
def test_inet(self): def test_inet(self):
self.assertEqualResults(self.getresult(), self.assertEqualResults(self.getresult(),
gevent_socket.getaddrinfo(TestGeventOrg.HOSTNAME, None, socket.AF_INET), gevent_socket.getaddrinfo(TestGeventOrg.HOSTNAME, None, socket.AF_INET),
...@@ -564,6 +556,20 @@ class Test_getaddrinfo(TestCase): ...@@ -564,6 +556,20 @@ class Test_getaddrinfo(TestCase):
return self._test_getaddrinfo('google.com', 'http', socket.AF_INET6) return self._test_getaddrinfo('google.com', 'http', socket.AF_INET6)
@greentest.skipIf(PY2, "Enums only on Python 3.4+")
def test_enums(self):
# https://github.com/gevent/gevent/issues/1310
# On Python 3, getaddrinfo does special things to make sure that
# the fancy enums are returned.
gai = gevent_socket.getaddrinfo('example.com', 80,
socket.AF_INET,
socket.SOCK_STREAM, socket.IPPROTO_TCP)
af, socktype, _proto, _canonname, _sa = gai[0]
self.assertIs(socktype, socket.SOCK_STREAM)
self.assertIs(af, socket.AF_INET)
class TestInternational(TestCase): class TestInternational(TestCase):
pass pass
...@@ -615,7 +621,7 @@ class TestInterrupted_gethostbyname(gevent.testing.timing.AbstractGenericWaitTes ...@@ -615,7 +621,7 @@ class TestInterrupted_gethostbyname(gevent.testing.timing.AbstractGenericWaitTes
# gaierror: [Errno -2] Name or service not known # gaierror: [Errno -2] Name or service not known
try: try:
gevent.get_hub().threadpool.join() gevent.get_hub().threadpool.join()
except Exception: # pylint:disable=broad-except except Exception: # pylint:disable=broad-except pragma: no cover
traceback.print_exc() traceback.print_exc()
......
#!/usr/bin/python #!/usr/bin/python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import print_function, absolute_import, division
import gevent.testing as greentest import gevent.testing as greentest
import socket import socket
from test__socket_dns import TestCase, add from gevent.tests.test__socket_dns import TestCase, add
from gevent.testing.sysinfo import RESOLVER_NOT_SYSTEM from gevent.testing.sysinfo import RESOLVER_NOT_SYSTEM
from gevent.testing.sysinfo import RESOLVER_DNSPYTHON from gevent.testing.sysinfo import RESOLVER_DNSPYTHON
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment