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
5e4a7d8d
Commit
5e4a7d8d
authored
Sep 21, 2015
by
Victor Stinner
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Issue #23630, asyncio: host parameter of loop.create_server() can now be a
sequence of strings. Patch written by Yann Sionneau.
parent
f7dc7fb7
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
74 additions
and
11 deletions
+74
-11
Doc/library/asyncio-eventloop.rst
Doc/library/asyncio-eventloop.rst
+10
-3
Lib/asyncio/base_events.py
Lib/asyncio/base_events.py
+28
-7
Lib/asyncio/events.py
Lib/asyncio/events.py
+2
-1
Lib/test/test_asyncio/test_events.py
Lib/test/test_asyncio/test_events.py
+33
-0
Misc/ACKS
Misc/ACKS
+1
-0
No files found.
Doc/library/asyncio-eventloop.rst
View file @
5e4a7d8d
...
...
@@ -331,9 +331,12 @@ Creating listening connections
Parameters:
* If *host* is an empty string or ``None``, all interfaces are assumed
and a list of multiple sockets will be returned (most likely
one for IPv4 and another one for IPv6).
* The *host* parameter can be a string, in that case the TCP server is
bound to *host* and *port*. The *host* parameter can also be a sequence
of strings and in that case the TCP server is bound to all hosts of the
sequence. If *host* is an empty string or ``None``, all interfaces are
assumed and a list of multiple sockets will be returned (most likely one
for IPv4 and another one for IPv6).
* *family* can be set to either :data:`socket.AF_INET` or
:data:`~socket.AF_INET6` to force the socket to use IPv4 or IPv6. If not set
...
...
@@ -365,6 +368,10 @@ Creating listening connections
The function :func:`start_server` creates a (:class:`StreamReader`,
:class:`StreamWriter`) pair and calls back a function with this pair.
.. versionchanged:: 3.4.4
The *host* parameter can now be a sequence of strings.
.. coroutinemethod:: BaseEventLoop.create_unix_server(protocol_factory, path=None, \*, sock=None, backlog=100, ssl=None)
...
...
Lib/asyncio/base_events.py
View file @
5e4a7d8d
...
...
@@ -18,6 +18,7 @@ import collections
import
concurrent.futures
import
heapq
import
inspect
import
itertools
import
logging
import
os
import
socket
...
...
@@ -786,6 +787,15 @@ class BaseEventLoop(events.AbstractEventLoop):
return
transport
,
protocol
@
coroutine
def
_create_server_getaddrinfo
(
self
,
host
,
port
,
family
,
flags
):
infos
=
yield
from
self
.
getaddrinfo
(
host
,
port
,
family
=
family
,
type
=
socket
.
SOCK_STREAM
,
flags
=
flags
)
if
not
infos
:
raise
OSError
(
'getaddrinfo({!r}) returned empty list'
.
format
(
host
))
return
infos
@
coroutine
def
create_server
(
self
,
protocol_factory
,
host
=
None
,
port
=
None
,
*
,
...
...
@@ -795,7 +805,13 @@ class BaseEventLoop(events.AbstractEventLoop):
backlog
=
100
,
ssl
=
None
,
reuse_address
=
None
):
"""Create a TCP server bound to host and port.
"""Create a TCP server.
The host parameter can be a string, in that case the TCP server is bound
to host and port.
The host parameter can also be a sequence of strings and in that case
the TCP server is bound to all hosts of the sequence.
Return a Server object which can be used to stop the service.
...
...
@@ -813,13 +829,18 @@ class BaseEventLoop(events.AbstractEventLoop):
reuse_address
=
os
.
name
==
'posix'
and
sys
.
platform
!=
'cygwin'
sockets
=
[]
if
host
==
''
:
host
=
None
hosts
=
[
None
]
elif
(
isinstance
(
host
,
str
)
or
not
isinstance
(
host
,
collections
.
Iterable
)):
hosts
=
[
host
]
else
:
hosts
=
host
infos
=
yield
from
self
.
getaddrinfo
(
host
,
port
,
family
=
family
,
type
=
socket
.
SOCK_STREAM
,
proto
=
0
,
flags
=
flags
)
i
f
not
infos
:
raise
OSError
(
'getaddrinfo() returned empty list'
)
fs
=
[
self
.
_create_server_getaddrinfo
(
host
,
port
,
family
=
family
,
flags
=
flags
)
for
host
in
hosts
]
i
nfos
=
yield
from
tasks
.
gather
(
*
fs
,
loop
=
self
)
infos
=
itertools
.
chain
.
from_iterable
(
infos
)
completed
=
False
try
:
...
...
Lib/asyncio/events.py
View file @
5e4a7d8d
...
...
@@ -305,7 +305,8 @@ class AbstractEventLoop:
If host is an empty string or None all interfaces are assumed
and a list of multiple sockets will be returned (most likely
one for IPv4 and another one for IPv6).
one for IPv4 and another one for IPv6). The host parameter can also be a
sequence (e.g. list) of hosts to bind to.
family can be set to either AF_INET or AF_INET6 to force the
socket to use IPv4 or IPv6. If not set it will be determined
...
...
Lib/test/test_asyncio/test_events.py
View file @
5e4a7d8d
...
...
@@ -745,6 +745,39 @@ class EventLoopTestsMixin:
self
.
assertEqual
(
cm
.
exception
.
errno
,
errno
.
EADDRINUSE
)
self
.
assertIn
(
str
(
httpd
.
address
),
cm
.
exception
.
strerror
)
@
mock
.
patch
(
'asyncio.base_events.socket'
)
def
create_server_multiple_hosts
(
self
,
family
,
hosts
,
mock_sock
):
@
asyncio
.
coroutine
def
getaddrinfo
(
host
,
port
,
*
args
,
**
kw
):
if
family
==
socket
.
AF_INET
:
return
[[
family
,
socket
.
SOCK_STREAM
,
6
,
''
,
(
host
,
port
)]]
else
:
return
[[
family
,
socket
.
SOCK_STREAM
,
6
,
''
,
(
host
,
port
,
0
,
0
)]]
def
getaddrinfo_task
(
*
args
,
**
kwds
):
return
asyncio
.
Task
(
getaddrinfo
(
*
args
,
**
kwds
),
loop
=
self
.
loop
)
if
family
==
socket
.
AF_INET
:
mock_sock
.
socket
().
getsockbyname
.
side_effect
=
[(
host
,
80
)
for
host
in
hosts
]
else
:
mock_sock
.
socket
().
getsockbyname
.
side_effect
=
[(
host
,
80
,
0
,
0
)
for
host
in
hosts
]
self
.
loop
.
getaddrinfo
=
getaddrinfo_task
self
.
loop
.
_start_serving
=
mock
.
Mock
()
f
=
self
.
loop
.
create_server
(
lambda
:
MyProto
(
self
.
loop
),
hosts
,
80
)
server
=
self
.
loop
.
run_until_complete
(
f
)
self
.
addCleanup
(
server
.
close
)
server_hosts
=
[
sock
.
getsockbyname
()[
0
]
for
sock
in
server
.
sockets
]
self
.
assertEqual
(
server_hosts
,
hosts
)
def
test_create_server_multiple_hosts_ipv4
(
self
):
self
.
create_server_multiple_hosts
(
socket
.
AF_INET
,
[
'1.2.3.4'
,
'5.6.7.8'
])
def
test_create_server_multiple_hosts_ipv6
(
self
):
self
.
create_server_multiple_hosts
(
socket
.
AF_INET6
,
[
'::1'
,
'::2'
])
def
test_create_server
(
self
):
proto
=
MyProto
(
self
.
loop
)
f
=
self
.
loop
.
create_server
(
lambda
:
proto
,
'0.0.0.0'
,
0
)
...
...
Misc/ACKS
View file @
5e4a7d8d
...
...
@@ -1294,6 +1294,7 @@ Adam Simpkins
Ravi Sinha
Janne Sinkkonen
Ng Pheng Siong
Yann Sionneau
George Sipe
J. Sipprell
Kragen Sitaker
...
...
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