Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
631546cf
Commit
631546cf
authored
Dec 16, 2015
by
Yury Selivanov
Browse files
Options
Browse Files
Download
Plain Diff
Merge 3.4
parents
a7f9933e
d5c2a621
Changes
7
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
284 additions
and
68 deletions
+284
-68
Lib/asyncio/base_events.py
Lib/asyncio/base_events.py
+80
-39
Lib/asyncio/proactor_events.py
Lib/asyncio/proactor_events.py
+1
-2
Lib/asyncio/selector_events.py
Lib/asyncio/selector_events.py
+1
-2
Lib/asyncio/test_utils.py
Lib/asyncio/test_utils.py
+7
-2
Lib/test/test_asyncio/test_base_events.py
Lib/test/test_asyncio/test_base_events.py
+192
-16
Lib/test/test_asyncio/test_events.py
Lib/test/test_asyncio/test_events.py
+0
-4
Lib/test/test_asyncio/test_proactor_events.py
Lib/test/test_asyncio/test_proactor_events.py
+3
-3
No files found.
Lib/asyncio/base_events.py
View file @
631546cf
...
...
@@ -16,8 +16,10 @@ to modify the meaning of the API call itself.
import
collections
import
concurrent.futures
import
functools
import
heapq
import
inspect
import
ipaddress
import
itertools
import
logging
import
os
...
...
@@ -70,49 +72,83 @@ def _format_pipe(fd):
return
repr
(
fd
)
# Linux's sock.type is a bitmask that can include extra info about socket.
_SOCKET_TYPE_MASK
=
0
if
hasattr
(
socket
,
'SOCK_NONBLOCK'
):
_SOCKET_TYPE_MASK
|=
socket
.
SOCK_NONBLOCK
if
hasattr
(
socket
,
'SOCK_CLOEXEC'
):
_SOCKET_TYPE_MASK
|=
socket
.
SOCK_CLOEXEC
@
functools
.
lru_cache
(
maxsize
=
1024
)
def
_ipaddr_info
(
host
,
port
,
family
,
type
,
proto
):
# Try to skip getaddrinfo if "host" is already an IP. Since getaddrinfo
# blocks on an exclusive lock on some platforms, users might handle name
# resolution in their own code and pass in resolved IPs.
if
proto
not
in
{
0
,
socket
.
IPPROTO_TCP
,
socket
.
IPPROTO_UDP
}
or
host
is
None
:
return
None
type
&=
~
_SOCKET_TYPE_MASK
if
type
==
socket
.
SOCK_STREAM
:
proto
=
socket
.
IPPROTO_TCP
elif
type
==
socket
.
SOCK_DGRAM
:
proto
=
socket
.
IPPROTO_UDP
else
:
return
None
if
hasattr
(
socket
,
'inet_pton'
):
if
family
==
socket
.
AF_UNSPEC
:
afs
=
[
socket
.
AF_INET
,
socket
.
AF_INET6
]
else
:
afs
=
[
family
]
for
af
in
afs
:
# Linux's inet_pton doesn't accept an IPv6 zone index after host,
# like '::1%lo0', so strip it. If we happen to make an invalid
# address look valid, we fail later in sock.connect or sock.bind.
try
:
if
af
==
socket
.
AF_INET6
:
socket
.
inet_pton
(
af
,
host
.
partition
(
'%'
)[
0
])
else
:
socket
.
inet_pton
(
af
,
host
)
return
af
,
type
,
proto
,
''
,
(
host
,
port
)
except
OSError
:
pass
# "host" is not an IP address.
return
None
# No inet_pton. (On Windows it's only available since Python 3.4.)
# Even though getaddrinfo with AI_NUMERICHOST would be non-blocking, it
# still requires a lock on some platforms, and waiting for that lock could
# block the event loop. Use ipaddress instead, it's just text parsing.
try
:
addr
=
ipaddress
.
IPv4Address
(
host
)
except
ValueError
:
try
:
addr
=
ipaddress
.
IPv6Address
(
host
.
partition
(
'%'
)[
0
])
except
ValueError
:
return
None
af
=
socket
.
AF_INET
if
addr
.
version
==
4
else
socket
.
AF_INET6
if
family
not
in
(
socket
.
AF_UNSPEC
,
af
):
# "host" is wrong IP version for "family".
return
None
return
af
,
type
,
proto
,
''
,
(
host
,
port
)
def
_check_resolved_address
(
sock
,
address
):
# Ensure that the address is already resolved to avoid the trap of hanging
# the entire event loop when the address requires doing a DNS lookup.
#
# getaddrinfo() is slow (around 10 us per call): this function should only
# be called in debug mode
family
=
sock
.
family
if
family
==
socket
.
AF_INET
:
host
,
port
=
address
elif
family
==
socket
.
AF_INET6
:
host
,
port
=
address
[:
2
]
else
:
if
hasattr
(
socket
,
'AF_UNIX'
)
and
sock
.
family
==
socket
.
AF_UNIX
:
return
# On Windows, socket.inet_pton() is only available since Python 3.4
if
hasattr
(
socket
,
'inet_pton'
):
# getaddrinfo() is slow and has known issue: prefer inet_pton()
# if available
try
:
socket
.
inet_pton
(
family
,
host
)
except
OSError
as
exc
:
raise
ValueError
(
"address must be resolved (IP address), "
"got host %r: %s"
%
(
host
,
exc
))
else
:
# Use getaddrinfo(flags=AI_NUMERICHOST) to ensure that the address is
# already resolved.
type_mask
=
0
if
hasattr
(
socket
,
'SOCK_NONBLOCK'
):
type_mask
|=
socket
.
SOCK_NONBLOCK
if
hasattr
(
socket
,
'SOCK_CLOEXEC'
):
type_mask
|=
socket
.
SOCK_CLOEXEC
try
:
socket
.
getaddrinfo
(
host
,
port
,
family
=
family
,
type
=
(
sock
.
type
&
~
type_mask
),
proto
=
sock
.
proto
,
flags
=
socket
.
AI_NUMERICHOST
)
except
socket
.
gaierror
as
err
:
raise
ValueError
(
"address must be resolved (IP address), "
"got host %r: %s"
%
(
host
,
err
))
host
,
port
=
address
[:
2
]
if
_ipaddr_info
(
host
,
port
,
sock
.
family
,
sock
.
type
,
sock
.
proto
)
is
None
:
raise
ValueError
(
"address must be resolved (IP address),"
" got host %r"
%
host
)
def
_run_until_complete_cb
(
fut
):
...
...
@@ -535,7 +571,12 @@ class BaseEventLoop(events.AbstractEventLoop):
def
getaddrinfo
(
self
,
host
,
port
,
*
,
family
=
0
,
type
=
0
,
proto
=
0
,
flags
=
0
):
if
self
.
_debug
:
info
=
_ipaddr_info
(
host
,
port
,
family
,
type
,
proto
)
if
info
is
not
None
:
fut
=
futures
.
Future
(
loop
=
self
)
fut
.
set_result
([
info
])
return
fut
elif
self
.
_debug
:
return
self
.
run_in_executor
(
None
,
self
.
_getaddrinfo_debug
,
host
,
port
,
family
,
type
,
proto
,
flags
)
else
:
...
...
Lib/asyncio/proactor_events.py
View file @
631546cf
...
...
@@ -441,8 +441,7 @@ class BaseProactorEventLoop(base_events.BaseEventLoop):
def
sock_connect
(
self
,
sock
,
address
):
try
:
if
self
.
_debug
:
base_events
.
_check_resolved_address
(
sock
,
address
)
base_events
.
_check_resolved_address
(
sock
,
address
)
except
ValueError
as
err
:
fut
=
futures
.
Future
(
loop
=
self
)
fut
.
set_exception
(
err
)
...
...
Lib/asyncio/selector_events.py
View file @
631546cf
...
...
@@ -397,8 +397,7 @@ class BaseSelectorEventLoop(base_events.BaseEventLoop):
raise
ValueError
(
"the socket must be non-blocking"
)
fut
=
futures
.
Future
(
loop
=
self
)
try
:
if
self
.
_debug
:
base_events
.
_check_resolved_address
(
sock
,
address
)
base_events
.
_check_resolved_address
(
sock
,
address
)
except
ValueError
as
err
:
fut
.
set_exception
(
err
)
else
:
...
...
Lib/asyncio/test_utils.py
View file @
631546cf
...
...
@@ -446,9 +446,14 @@ def disable_logger():
finally
:
logger
.
setLevel
(
old_level
)
def
mock_nonblocking_socket
():
def
mock_nonblocking_socket
(
proto
=
socket
.
IPPROTO_TCP
,
type
=
socket
.
SOCK_STREAM
,
family
=
socket
.
AF_INET
):
"""Create a mock of a non-blocking socket."""
sock
=
mock
.
Mock
(
socket
.
socket
)
sock
=
mock
.
MagicMock
(
socket
.
socket
)
sock
.
proto
=
proto
sock
.
type
=
type
sock
.
family
=
family
sock
.
gettimeout
.
return_value
=
0.0
return
sock
...
...
Lib/test/test_asyncio/test_base_events.py
View file @
631546cf
This diff is collapsed.
Click to expand it.
Lib/test/test_asyncio/test_events.py
View file @
631546cf
...
...
@@ -1573,10 +1573,6 @@ class EventLoopTestsMixin:
'selector'
:
self
.
loop
.
_selector
.
__class__
.
__name__
})
def
test_sock_connect_address
(
self
):
# In debug mode, sock_connect() must ensure that the address is already
# resolved (call _check_resolved_address())
self
.
loop
.
set_debug
(
True
)
addresses
=
[(
socket
.
AF_INET
,
(
'www.python.org'
,
80
))]
if
support
.
IPV6_ENABLED
:
addresses
.
extend
((
...
...
Lib/test/test_asyncio/test_proactor_events.py
View file @
631546cf
...
...
@@ -436,7 +436,7 @@ class ProactorSocketTransportTests(test_utils.TestCase):
class
BaseProactorEventLoopTests
(
test_utils
.
TestCase
):
def
setUp
(
self
):
self
.
sock
=
mock
.
Mock
(
socket
.
socket
)
self
.
sock
=
test_utils
.
mock_nonblocking_socket
(
)
self
.
proactor
=
mock
.
Mock
()
self
.
ssock
,
self
.
csock
=
mock
.
Mock
(),
mock
.
Mock
()
...
...
@@ -491,8 +491,8 @@ class BaseProactorEventLoopTests(test_utils.TestCase):
self
.
proactor
.
send
.
assert_called_with
(
self
.
sock
,
b'data'
)
def
test_sock_connect
(
self
):
self
.
loop
.
sock_connect
(
self
.
sock
,
123
)
self
.
proactor
.
connect
.
assert_called_with
(
self
.
sock
,
123
)
self
.
loop
.
sock_connect
(
self
.
sock
,
(
'1.2.3.4'
,
123
)
)
self
.
proactor
.
connect
.
assert_called_with
(
self
.
sock
,
(
'1.2.3.4'
,
123
)
)
def
test_sock_accept
(
self
):
self
.
loop
.
sock_accept
(
self
.
sock
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment