Author: Armin Rigo <[email protected]>
Branch: py3.5
Changeset: r89307:9705352d5190
Date: 2017-01-02 17:53 +0100
http://bitbucket.org/pypy/pypy/changeset/9705352d5190/
Log: Starting to support idna hostnames in the socket methods
diff --git a/pypy/module/_socket/interp_func.py
b/pypy/module/_socket/interp_func.py
--- a/pypy/module/_socket/interp_func.py
+++ b/pypy/module/_socket/interp_func.py
@@ -22,8 +22,8 @@
return space.fsdecode(space.newbytes(res))
def encode_idna(space, w_host):
- # call unicode.encode(host, 'idna'), and not host.encode('idna') in
- # case type(host) is not unicode
+ # call unicode.encode(host, 'idna'), and not host.encode('idna') in case
+ # type(host) is not unicode. See also interp_socket.idna_converter()
return space.bytes_w(space.call_method(space.w_unicode, 'encode',
w_host, space.wrap('idna')))
diff --git a/pypy/module/_socket/interp_socket.py
b/pypy/module/_socket/interp_socket.py
--- a/pypy/module/_socket/interp_socket.py
+++ b/pypy/module/_socket/interp_socket.py
@@ -85,11 +85,35 @@
else:
raise NotImplementedError
+def idna_converter(space, w_host):
+ # Converts w_host to a byte string. Similar to encode_idna()
+ # but accepts more types and refuses NULL bytes.
+ if space.isinstance_w(w_host, space.w_unicode):
+ try:
+ w_s = space.encode_unicode_object(w_host, 'ascii', None)
+ except OperationError as e:
+ if not e.match(space, space.w_UnicodeEncodeError):
+ raise
+ w_s = space.encode_unicode_object(w_host, 'idna', None)
+ s = space.bytes_w(w_s)
+ elif space.isinstance_w(w_host, space.w_bytes):
+ s = space.bytes_w(w_host)
+ elif space.isinstance_w(w_host, space.w_bytearray):
+ s = space.charbuf_w(w_host)
+ else:
+ raise oefmt(space.w_TypeError,
+ "string or unicode text buffer expected, not %T", w_host)
+ if '\x00' in s:
+ raise oefmt(space.w_TypeError,
+ "host name must not contain null character")
+ return s
+
+
# XXX Hack to seperate rpython and pypy
def addr_from_object(family, fd, space, w_address):
if family == rsocket.AF_INET:
w_host, w_port = space.unpackiterable(w_address, 2)
- host = space.str_w(w_host)
+ host = idna_converter(space, w_host)
port = space.int_w(w_port)
port = make_ushort_port(space, port)
return rsocket.INETAddress(host, port)
@@ -99,7 +123,7 @@
raise oefmt(space.w_TypeError,
"AF_INET6 address must be a tuple of length 2 "
"to 4, not %d", len(pieces_w))
- host = space.str_w(pieces_w[0])
+ host = idna_converter(space, pieces_w[0])
port = space.int_w(pieces_w[1])
port = make_ushort_port(space, port)
if len(pieces_w) > 2: flowinfo = space.int_w(pieces_w[2])
diff --git a/pypy/module/_socket/test/test_sock_app.py
b/pypy/module/_socket/test/test_sock_app.py
--- a/pypy/module/_socket/test/test_sock_app.py
+++ b/pypy/module/_socket/test/test_sock_app.py
@@ -428,7 +428,8 @@
def test_socket_connect_typeerrors(self):
tests = [
"",
- ("80"),
+ "80",
+ ("80",),
("80", "80"),
(80, 80),
]
@@ -682,12 +683,16 @@
s1.close()
s2.close()
- def test_gethostbyname_unicode(self):
+ def test_hostname_unicode(self):
import _socket
domain =
u"испытание.pythontest.net"
_socket.gethostbyname(domain)
_socket.gethostbyname_ex(domain)
_socket.getaddrinfo(domain, 0, _socket.AF_UNSPEC, _socket.SOCK_STREAM)
+ s = _socket.socket(_socket.AF_INET, _socket.SOCK_STREAM)
+ s.connect((domain, 80))
+ s.close()
+ raises(TypeError, s.connect, (domain + '\x00', 80))
class AppTestNetlink:
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit