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
dc6a9c04
Commit
dc6a9c04
authored
May 11, 2015
by
Yury Selivanov
Browse files
Options
Browse Files
Download
Plain Diff
asyncio: Merge 3.4 -- Support PEP 492. Issue #24017.
parents
99bf9a25
1af2bf75
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
116 additions
and
27 deletions
+116
-27
Lib/asyncio/base_events.py
Lib/asyncio/base_events.py
+38
-9
Lib/asyncio/coroutines.py
Lib/asyncio/coroutines.py
+64
-13
Lib/asyncio/futures.py
Lib/asyncio/futures.py
+4
-0
Lib/asyncio/tasks.py
Lib/asyncio/tasks.py
+6
-2
Lib/test/test_asyncio/test_base_events.py
Lib/test/test_asyncio/test_base_events.py
+2
-1
Lib/test/test_asyncio/test_tasks.py
Lib/test/test_asyncio/test_tasks.py
+2
-2
No files found.
Lib/asyncio/base_events.py
View file @
dc6a9c04
...
...
@@ -191,8 +191,8 @@ class BaseEventLoop(events.AbstractEventLoop):
self
.
_thread_id
=
None
self
.
_clock_resolution
=
time
.
get_clock_info
(
'monotonic'
).
resolution
self
.
_exception_handler
=
None
self
.
_debug
=
(
not
sys
.
flags
.
ignore_environment
and
bool
(
os
.
environ
.
get
(
'PYTHONASYNCIODEBUG'
)))
self
.
set_debug
(
(
not
sys
.
flags
.
ignore_environment
and
bool
(
os
.
environ
.
get
(
'PYTHONASYNCIODEBUG'
)
)))
# In debug mode, if the execution of a callback or a step of a task
# exceed this duration in seconds, the slow callback/task is logged.
self
.
slow_callback_duration
=
0.1
...
...
@@ -360,13 +360,18 @@ class BaseEventLoop(events.AbstractEventLoop):
return
if
self
.
_debug
:
logger
.
debug
(
"Close %r"
,
self
)
self
.
_closed
=
True
self
.
_ready
.
clear
()
self
.
_scheduled
.
clear
()
executor
=
self
.
_default_executor
if
executor
is
not
None
:
self
.
_default_executor
=
None
executor
.
shutdown
(
wait
=
False
)
try
:
self
.
_closed
=
True
self
.
_ready
.
clear
()
self
.
_scheduled
.
clear
()
executor
=
self
.
_default_executor
if
executor
is
not
None
:
self
.
_default_executor
=
None
executor
.
shutdown
(
wait
=
False
)
finally
:
# It is important to unregister "sys.coroutine_wrapper"
# if it was registered.
self
.
set_debug
(
False
)
def
is_closed
(
self
):
"""Returns True if the event loop was closed."""
...
...
@@ -1199,3 +1204,27 @@ class BaseEventLoop(events.AbstractEventLoop):
def
set_debug
(
self
,
enabled
):
self
.
_debug
=
enabled
wrapper
=
coroutines
.
debug_wrapper
try
:
set_wrapper
=
sys
.
set_coroutine_wrapper
except
AttributeError
:
pass
else
:
current_wrapper
=
sys
.
get_coroutine_wrapper
()
if
enabled
:
if
current_wrapper
not
in
(
None
,
wrapper
):
warnings
.
warn
(
"loop.set_debug(True): cannot set debug coroutine "
"wrapper; another wrapper is already set %r"
%
current_wrapper
,
RuntimeWarning
)
else
:
set_wrapper
(
wrapper
)
else
:
if
current_wrapper
not
in
(
None
,
wrapper
):
warnings
.
warn
(
"loop.set_debug(False): cannot unset debug coroutine "
"wrapper; another wrapper was set %r"
%
current_wrapper
,
RuntimeWarning
)
else
:
set_wrapper
(
None
)
Lib/asyncio/coroutines.py
View file @
dc6a9c04
...
...
@@ -14,6 +14,9 @@ from . import futures
from
.log
import
logger
_PY35
=
sys
.
version_info
>=
(
3
,
5
)
# Opcode of "yield from" instruction
_YIELD_FROM
=
opcode
.
opmap
[
'YIELD_FROM'
]
...
...
@@ -30,6 +33,27 @@ _DEBUG = (not sys.flags.ignore_environment
and
bool
(
os
.
environ
.
get
(
'PYTHONASYNCIODEBUG'
)))
try
:
types
.
coroutine
except
AttributeError
:
native_coroutine_support
=
False
else
:
native_coroutine_support
=
True
try
:
_iscoroutinefunction
=
inspect
.
iscoroutinefunction
except
AttributeError
:
_iscoroutinefunction
=
lambda
func
:
False
try
:
inspect
.
CO_COROUTINE
except
AttributeError
:
_is_native_coro_code
=
lambda
code
:
False
else
:
_is_native_coro_code
=
lambda
code
:
(
code
.
co_flags
&
inspect
.
CO_COROUTINE
)
# Check for CPython issue #21209
def
has_yield_from_bug
():
class
MyGen
:
...
...
@@ -54,16 +78,27 @@ _YIELD_FROM_BUG = has_yield_from_bug()
del
has_yield_from_bug
def
debug_wrapper
(
gen
):
# This function is called from 'sys.set_coroutine_wrapper'.
# We only wrap here coroutines defined via 'async def' syntax.
# Generator-based coroutines are wrapped in @coroutine
# decorator.
if
_is_native_coro_code
(
gen
.
gi_code
):
return
CoroWrapper
(
gen
,
None
)
else
:
return
gen
class
CoroWrapper
:
# Wrapper for coroutine object in _DEBUG mode.
def
__init__
(
self
,
gen
,
func
):
assert
inspect
.
isgenerator
(
gen
),
gen
def
__init__
(
self
,
gen
,
func
=
None
):
assert
inspect
.
isgenerator
(
gen
)
or
inspect
.
iscoroutine
(
gen
)
,
gen
self
.
gen
=
gen
self
.
func
=
func
self
.
func
=
func
# Used to unwrap @coroutine decorator
self
.
_source_traceback
=
traceback
.
extract_stack
(
sys
.
_getframe
(
1
))
# __name__, __qualname__, __doc__ attributes are set by the coroutine(
)
# decorator
self
.
__name__
=
getattr
(
gen
,
'__name__'
,
None
)
self
.
__qualname__
=
getattr
(
gen
,
'__qualname__'
,
None
)
def
__repr__
(
self
):
coro_repr
=
_format_coroutine
(
self
)
...
...
@@ -75,6 +110,9 @@ class CoroWrapper:
def
__iter__
(
self
):
return
self
if
_PY35
:
__await__
=
__iter__
# make compatible with 'await' expression
def
__next__
(
self
):
return
next
(
self
.
gen
)
...
...
@@ -133,6 +171,14 @@ def coroutine(func):
If the coroutine is not yielded from before it is destroyed,
an error message is logged.
"""
is_coroutine
=
_iscoroutinefunction
(
func
)
if
is_coroutine
and
_is_native_coro_code
(
func
.
__code__
):
# In Python 3.5 that's all we need to do for coroutines
# defiend with "async def".
# Wrapping in CoroWrapper will happen via
# 'sys.set_coroutine_wrapper' function.
return
func
if
inspect
.
isgeneratorfunction
(
func
):
coro
=
func
else
:
...
...
@@ -144,18 +190,22 @@ def coroutine(func):
return
res
if
not
_DEBUG
:
wrapper
=
coro
if
native_coroutine_support
:
wrapper
=
types
.
coroutine
(
coro
)
else
:
wrapper
=
coro
else
:
@
functools
.
wraps
(
func
)
def
wrapper
(
*
args
,
**
kwds
):
w
=
CoroWrapper
(
coro
(
*
args
,
**
kwds
),
func
)
w
=
CoroWrapper
(
coro
(
*
args
,
**
kwds
),
func
=
func
)
if
w
.
_source_traceback
:
del
w
.
_source_traceback
[
-
1
]
if
hasattr
(
func
,
'__name__'
):
w
.
__name__
=
func
.
__name__
if
hasattr
(
func
,
'__qualname__'
):
w
.
__qualname__
=
func
.
__qualname__
w
.
__doc__
=
func
.
__doc__
# Python < 3.5 does not implement __qualname__
# on generator objects, so we set it manually.
# We use getattr as some callables (such as
# functools.partial may lack __qualname__).
w
.
__name__
=
getattr
(
func
,
'__name__'
,
None
)
w
.
__qualname__
=
getattr
(
func
,
'__qualname__'
,
None
)
return
w
wrapper
.
_is_coroutine
=
True
# For iscoroutinefunction().
...
...
@@ -164,7 +214,8 @@ def coroutine(func):
def
iscoroutinefunction
(
func
):
"""Return True if func is a decorated coroutine function."""
return
getattr
(
func
,
'_is_coroutine'
,
False
)
return
(
getattr
(
func
,
'_is_coroutine'
,
False
)
or
_iscoroutinefunction
(
func
))
_COROUTINE_TYPES
=
(
types
.
GeneratorType
,
CoroWrapper
)
...
...
Lib/asyncio/futures.py
View file @
dc6a9c04
...
...
@@ -19,6 +19,7 @@ _CANCELLED = 'CANCELLED'
_FINISHED
=
'FINISHED'
_PY34
=
sys
.
version_info
>=
(
3
,
4
)
_PY35
=
sys
.
version_info
>=
(
3
,
5
)
Error
=
concurrent
.
futures
.
_base
.
Error
CancelledError
=
concurrent
.
futures
.
CancelledError
...
...
@@ -387,6 +388,9 @@ class Future:
assert
self
.
done
(),
"yield from wasn't used with future"
return
self
.
result
()
# May raise too.
if
_PY35
:
__await__
=
__iter__
# make compatible with 'await' expression
def
wrap_future
(
fut
,
*
,
loop
=
None
):
"""Wrap concurrent.futures.Future object."""
...
...
Lib/asyncio/tasks.py
View file @
dc6a9c04
...
...
@@ -11,6 +11,7 @@ import functools
import
inspect
import
linecache
import
sys
import
types
import
traceback
import
warnings
import
weakref
...
...
@@ -73,7 +74,10 @@ class Task(futures.Future):
super
().
__init__
(
loop
=
loop
)
if
self
.
_source_traceback
:
del
self
.
_source_traceback
[
-
1
]
self
.
_coro
=
iter
(
coro
)
# Use the iterator just in case.
if
coro
.
__class__
is
types
.
GeneratorType
:
self
.
_coro
=
coro
else
:
self
.
_coro
=
iter
(
coro
)
# Use the iterator just in case.
self
.
_fut_waiter
=
None
self
.
_must_cancel
=
False
self
.
_loop
.
call_soon
(
self
.
_step
)
...
...
@@ -236,7 +240,7 @@ class Task(futures.Future):
elif
value
is
not
None
:
result
=
coro
.
send
(
value
)
else
:
result
=
next
(
coro
)
result
=
coro
.
send
(
None
)
except
StopIteration
as
exc
:
self
.
set_result
(
exc
.
value
)
except
futures
.
CancelledError
as
exc
:
...
...
Lib/test/test_asyncio/test_base_events.py
View file @
dc6a9c04
...
...
@@ -61,7 +61,8 @@ class BaseEventLoopTests(test_utils.TestCase):
NotImplementedError
,
self
.
loop
.
_make_write_pipe_transport
,
m
,
m
)
gen
=
self
.
loop
.
_make_subprocess_transport
(
m
,
m
,
m
,
m
,
m
,
m
,
m
)
self
.
assertRaises
(
NotImplementedError
,
next
,
iter
(
gen
))
with
self
.
assertRaises
(
NotImplementedError
):
gen
.
send
(
None
)
def
test_close
(
self
):
self
.
assertFalse
(
self
.
loop
.
is_closed
())
...
...
Lib/test/test_asyncio/test_tasks.py
View file @
dc6a9c04
...
...
@@ -1638,7 +1638,7 @@ class TaskTests(test_utils.TestCase):
return
a
def
call
(
arg
):
cw
=
asyncio
.
coroutines
.
CoroWrapper
(
foo
()
,
foo
)
cw
=
asyncio
.
coroutines
.
CoroWrapper
(
foo
())
cw
.
send
(
None
)
try
:
cw
.
send
(
arg
)
...
...
@@ -1653,7 +1653,7 @@ class TaskTests(test_utils.TestCase):
def
test_corowrapper_weakref
(
self
):
wd
=
weakref
.
WeakValueDictionary
()
def
foo
():
yield
from
[]
cw
=
asyncio
.
coroutines
.
CoroWrapper
(
foo
()
,
foo
)
cw
=
asyncio
.
coroutines
.
CoroWrapper
(
foo
())
wd
[
'cw'
]
=
cw
# Would fail without __weakref__ slot.
cw
.
gen
=
None
# Suppress warning from __del__.
...
...
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