Skip to content
Projeler
Gruplar
Parçacıklar
Yardım
Yükleniyor...
Oturum aç / Kaydol
Gezinmeyi değiştir
C
cpython
Proje
Proje
Ayrıntılar
Etkinlik
Cycle Analytics
Depo (repository)
Depo (repository)
Dosyalar
Kayıtlar (commit)
Dallar (branch)
Etiketler
Katkıda bulunanlar
Grafik
Karşılaştır
Grafikler
Konular (issue)
0
Konular (issue)
0
Liste
Pano
Etiketler
Kilometre Taşları
Birleştirme (merge) Talepleri
0
Birleştirme (merge) Talepleri
0
CI / CD
CI / CD
İş akışları (pipeline)
İşler
Zamanlamalar
Grafikler
Paketler
Paketler
Wiki
Wiki
Parçacıklar
Parçacıklar
Üyeler
Üyeler
Collapse sidebar
Close sidebar
Etkinlik
Grafik
Grafikler
Yeni bir konu (issue) oluştur
İşler
Kayıtlar (commit)
Konu (issue) Panoları
Kenar çubuğunu aç
Batuhan Osman TASKAYA
cpython
Commits
f74ef458
Unverified
Kaydet (Commit)
f74ef458
authored
Ara 15, 2017
tarafından
Andrew Svetlov
Kaydeden (comit)
GitHub
Ara 15, 2017
Dosyalara gözat
Seçenekler
Dosyalara Gözat
İndir
Eposta Yamaları
Sade Fark
bpo-32311: Implement asyncio.create_task() shortcut (#4848)
* Implement functionality * Add documentation
üst
19a44f63
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
201 additions
and
95 deletions
+201
-95
asyncio-task.rst
Doc/library/asyncio-task.rst
+21
-4
base_futures.py
Lib/asyncio/base_futures.py
+2
-2
constants.py
Lib/asyncio/constants.py
+1
-1
coroutines.py
Lib/asyncio/coroutines.py
+5
-5
events.py
Lib/asyncio/events.py
+7
-76
format_helpers.py
Lib/asyncio/format_helpers.py
+75
-0
futures.py
Lib/asyncio/futures.py
+3
-1
tasks.py
Lib/asyncio/tasks.py
+19
-4
test_tasks.py
Lib/test/test_asyncio/test_tasks.py
+37
-0
utils.py
Lib/test/test_asyncio/utils.py
+2
-1
2017-12-14-17-28-54.bpo-32311.DL5Ytn.rst
...S.d/next/Library/2017-12-14-17-28-54.bpo-32311.DL5Ytn.rst
+1
-0
_asynciomodule.c
Modules/_asynciomodule.c
+28
-1
No files found.
Doc/library/asyncio-task.rst
Dosyayı görüntüle @
f74ef458
...
...
@@ -371,10 +371,21 @@ with the result.
Task
----
.. function:: create_task(coro)
Wrap a :ref:`coroutine <coroutine>` *coro* into a task and schedule
its execution. Return the task object.
The task is executed in :func:`get_running_loop` context,
:exc:`RuntimeError` is raised if there is no running loop in
current thread.
.. versionadded:: 3.7
.. class:: Task(coro, \*, loop=None)
Schedule the execution of a :ref:`coroutine <coroutine>`: wrap it in a
future. A task is a
subclass of :class:`Future`.
A unit for concurrent running of :ref:`coroutines <coroutine>`,
subclass of :class:`Future`.
A task is responsible for executing a coroutine object in an event loop. If
the wrapped coroutine yields from a future, the task suspends the execution
...
...
@@ -399,7 +410,7 @@ Task
<coroutine>` did not complete. It is probably a bug and a warning is
logged: see :ref:`Pending task destroyed <asyncio-pending-task-destroyed>`.
Don't directly create :class:`Task` instances: use the :func:`
ensure_future
`
Don't directly create :class:`Task` instances: use the :func:`
create_task
`
function or the :meth:`AbstractEventLoop.create_task` method.
This class is :ref:`not thread safe <asyncio-multithreading>`.
...
...
@@ -547,9 +558,15 @@ Task functions
.. versionchanged:: 3.5.1
The function accepts any :term:`awaitable` object.
.. note::
:func:`create_task` (added in Python 3.7) is the preferable way
for spawning new tasks.
.. seealso::
The :meth:`AbstractEventLoop.create_task` method.
The :func:`create_task` function and
:meth:`AbstractEventLoop.create_task` method.
.. function:: wrap_future(future, \*, loop=None)
...
...
Lib/asyncio/base_futures.py
Dosyayı görüntüle @
f74ef458
...
...
@@ -3,7 +3,7 @@ __all__ = ()
import
concurrent.futures._base
import
reprlib
from
.
import
event
s
from
.
import
format_helper
s
Error
=
concurrent
.
futures
.
_base
.
Error
CancelledError
=
concurrent
.
futures
.
CancelledError
...
...
@@ -38,7 +38,7 @@ def _format_callbacks(cb):
cb
=
''
def
format_cb
(
callback
):
return
event
s
.
_format_callback_source
(
callback
,
())
return
format_helper
s
.
_format_callback_source
(
callback
,
())
if
size
==
1
:
cb
=
format_cb
(
cb
[
0
])
...
...
Lib/asyncio/constants.py
Dosyayı görüntüle @
f74ef458
...
...
@@ -6,5 +6,5 @@ ACCEPT_RETRY_DELAY = 1
# Number of stack entries to capture in debug mode.
# The larger the number, the slower the operation in debug mode
# (see extract_stack() in
event
s.py).
# (see extract_stack() in
format_helper
s.py).
DEBUG_STACK_DEPTH
=
10
Lib/asyncio/coroutines.py
Dosyayı görüntüle @
f74ef458
...
...
@@ -9,9 +9,9 @@ import types
from
collections.abc
import
Awaitable
,
Coroutine
from
.
import
constants
from
.
import
events
from
.
import
base_futures
from
.
import
constants
from
.
import
format_helpers
from
.log
import
logger
...
...
@@ -48,7 +48,7 @@ class CoroWrapper:
assert
inspect
.
isgenerator
(
gen
)
or
inspect
.
iscoroutine
(
gen
),
gen
self
.
gen
=
gen
self
.
func
=
func
# Used to unwrap @coroutine decorator
self
.
_source_traceback
=
event
s
.
extract_stack
(
sys
.
_getframe
(
1
))
self
.
_source_traceback
=
format_helper
s
.
extract_stack
(
sys
.
_getframe
(
1
))
self
.
__name__
=
getattr
(
gen
,
'__name__'
,
None
)
self
.
__qualname__
=
getattr
(
gen
,
'__qualname__'
,
None
)
...
...
@@ -243,7 +243,7 @@ def _format_coroutine(coro):
func
=
coro
if
coro_name
is
None
:
coro_name
=
event
s
.
_format_callback
(
func
,
(),
{})
coro_name
=
format_helper
s
.
_format_callback
(
func
,
(),
{})
try
:
coro_code
=
coro
.
gi_code
...
...
@@ -260,7 +260,7 @@ def _format_coroutine(coro):
if
(
isinstance
(
coro
,
CoroWrapper
)
and
not
inspect
.
isgeneratorfunction
(
coro
.
func
)
and
coro
.
func
is
not
None
):
source
=
event
s
.
_get_function_source
(
coro
.
func
)
source
=
format_helper
s
.
_get_function_source
(
coro
.
func
)
if
source
is
not
None
:
filename
,
lineno
=
source
if
coro_frame
is
None
:
...
...
Lib/asyncio/events.py
Dosyayı görüntüle @
f74ef458
...
...
@@ -11,86 +11,14 @@ __all__ = (
'_get_running_loop'
,
)
import
functools
import
inspect
import
os
import
reprlib
import
socket
import
subprocess
import
sys
import
threading
import
traceback
from
.
import
constants
def
_get_function_source
(
func
):
func
=
inspect
.
unwrap
(
func
)
if
inspect
.
isfunction
(
func
):
code
=
func
.
__code__
return
(
code
.
co_filename
,
code
.
co_firstlineno
)
if
isinstance
(
func
,
functools
.
partial
):
return
_get_function_source
(
func
.
func
)
if
isinstance
(
func
,
functools
.
partialmethod
):
return
_get_function_source
(
func
.
func
)
return
None
def
_format_args_and_kwargs
(
args
,
kwargs
):
"""Format function arguments and keyword arguments.
Special case for a single parameter: ('hello',) is formatted as ('hello').
"""
# use reprlib to limit the length of the output
items
=
[]
if
args
:
items
.
extend
(
reprlib
.
repr
(
arg
)
for
arg
in
args
)
if
kwargs
:
items
.
extend
(
f
'{k}={reprlib.repr(v)}'
for
k
,
v
in
kwargs
.
items
())
return
'({})'
.
format
(
', '
.
join
(
items
))
def
_format_callback
(
func
,
args
,
kwargs
,
suffix
=
''
):
if
isinstance
(
func
,
functools
.
partial
):
suffix
=
_format_args_and_kwargs
(
args
,
kwargs
)
+
suffix
return
_format_callback
(
func
.
func
,
func
.
args
,
func
.
keywords
,
suffix
)
if
hasattr
(
func
,
'__qualname__'
):
func_repr
=
getattr
(
func
,
'__qualname__'
)
elif
hasattr
(
func
,
'__name__'
):
func_repr
=
getattr
(
func
,
'__name__'
)
else
:
func_repr
=
repr
(
func
)
func_repr
+=
_format_args_and_kwargs
(
args
,
kwargs
)
if
suffix
:
func_repr
+=
suffix
return
func_repr
def
_format_callback_source
(
func
,
args
):
func_repr
=
_format_callback
(
func
,
args
,
None
)
source
=
_get_function_source
(
func
)
if
source
:
func_repr
+=
f
' at {source[0]}:{source[1]}'
return
func_repr
def
extract_stack
(
f
=
None
,
limit
=
None
):
"""Replacement for traceback.extract_stack() that only does the
necessary work for asyncio debug mode.
"""
if
f
is
None
:
f
=
sys
.
_getframe
()
.
f_back
if
limit
is
None
:
# Limit the amount of work to a reasonable amount, as extract_stack()
# can be called for each coroutine and future in debug mode.
limit
=
constants
.
DEBUG_STACK_DEPTH
stack
=
traceback
.
StackSummary
.
extract
(
traceback
.
walk_stack
(
f
),
limit
=
limit
,
lookup_lines
=
False
)
stack
.
reverse
()
return
stack
from
.
import
format_helpers
class
Handle
:
...
...
@@ -106,7 +34,8 @@ class Handle:
self
.
_cancelled
=
False
self
.
_repr
=
None
if
self
.
_loop
.
get_debug
():
self
.
_source_traceback
=
extract_stack
(
sys
.
_getframe
(
1
))
self
.
_source_traceback
=
format_helpers
.
extract_stack
(
sys
.
_getframe
(
1
))
else
:
self
.
_source_traceback
=
None
...
...
@@ -115,7 +44,8 @@ class Handle:
if
self
.
_cancelled
:
info
.
append
(
'cancelled'
)
if
self
.
_callback
is
not
None
:
info
.
append
(
_format_callback_source
(
self
.
_callback
,
self
.
_args
))
info
.
append
(
format_helpers
.
_format_callback_source
(
self
.
_callback
,
self
.
_args
))
if
self
.
_source_traceback
:
frame
=
self
.
_source_traceback
[
-
1
]
info
.
append
(
f
'created at {frame[0]}:{frame[1]}'
)
...
...
@@ -145,7 +75,8 @@ class Handle:
try
:
self
.
_callback
(
*
self
.
_args
)
except
Exception
as
exc
:
cb
=
_format_callback_source
(
self
.
_callback
,
self
.
_args
)
cb
=
format_helpers
.
_format_callback_source
(
self
.
_callback
,
self
.
_args
)
msg
=
f
'Exception in callback {cb}'
context
=
{
'message'
:
msg
,
...
...
Lib/asyncio/format_helpers.py
0 → 100644
Dosyayı görüntüle @
f74ef458
import
functools
import
inspect
import
reprlib
import
traceback
from
.
import
constants
def
_get_function_source
(
func
):
func
=
inspect
.
unwrap
(
func
)
if
inspect
.
isfunction
(
func
):
code
=
func
.
__code__
return
(
code
.
co_filename
,
code
.
co_firstlineno
)
if
isinstance
(
func
,
functools
.
partial
):
return
_get_function_source
(
func
.
func
)
if
isinstance
(
func
,
functools
.
partialmethod
):
return
_get_function_source
(
func
.
func
)
return
None
def
_format_callback_source
(
func
,
args
):
func_repr
=
_format_callback
(
func
,
args
,
None
)
source
=
_get_function_source
(
func
)
if
source
:
func_repr
+=
f
' at {source[0]}:{source[1]}'
return
func_repr
def
_format_args_and_kwargs
(
args
,
kwargs
):
"""Format function arguments and keyword arguments.
Special case for a single parameter: ('hello',) is formatted as ('hello').
"""
# use reprlib to limit the length of the output
items
=
[]
if
args
:
items
.
extend
(
reprlib
.
repr
(
arg
)
for
arg
in
args
)
if
kwargs
:
items
.
extend
(
f
'{k}={reprlib.repr(v)}'
for
k
,
v
in
kwargs
.
items
())
return
'({})'
.
format
(
', '
.
join
(
items
))
def
_format_callback
(
func
,
args
,
kwargs
,
suffix
=
''
):
if
isinstance
(
func
,
functools
.
partial
):
suffix
=
_format_args_and_kwargs
(
args
,
kwargs
)
+
suffix
return
_format_callback
(
func
.
func
,
func
.
args
,
func
.
keywords
,
suffix
)
if
hasattr
(
func
,
'__qualname__'
):
func_repr
=
getattr
(
func
,
'__qualname__'
)
elif
hasattr
(
func
,
'__name__'
):
func_repr
=
getattr
(
func
,
'__name__'
)
else
:
func_repr
=
repr
(
func
)
func_repr
+=
_format_args_and_kwargs
(
args
,
kwargs
)
if
suffix
:
func_repr
+=
suffix
return
func_repr
def
extract_stack
(
f
=
None
,
limit
=
None
):
"""Replacement for traceback.extract_stack() that only does the
necessary work for asyncio debug mode.
"""
if
f
is
None
:
f
=
sys
.
_getframe
()
.
f_back
if
limit
is
None
:
# Limit the amount of work to a reasonable amount, as extract_stack()
# can be called for each coroutine and future in debug mode.
limit
=
constants
.
DEBUG_STACK_DEPTH
stack
=
traceback
.
StackSummary
.
extract
(
traceback
.
walk_stack
(
f
),
limit
=
limit
,
lookup_lines
=
False
)
stack
.
reverse
()
return
stack
Lib/asyncio/futures.py
Dosyayı görüntüle @
f74ef458
...
...
@@ -11,6 +11,7 @@ import sys
from
.
import
base_futures
from
.
import
events
from
.
import
format_helpers
CancelledError
=
base_futures
.
CancelledError
...
...
@@ -79,7 +80,8 @@ class Future:
self
.
_loop
=
loop
self
.
_callbacks
=
[]
if
self
.
_loop
.
get_debug
():
self
.
_source_traceback
=
events
.
extract_stack
(
sys
.
_getframe
(
1
))
self
.
_source_traceback
=
format_helpers
.
extract_stack
(
sys
.
_getframe
(
1
))
_repr_info
=
base_futures
.
_future_repr_info
...
...
Lib/asyncio/tasks.py
Dosyayı görüntüle @
f74ef458
"""Support for tasks, coroutines and the scheduler."""
__all__
=
(
'Task'
,
'Task'
,
'create_task'
,
'FIRST_COMPLETED'
,
'FIRST_EXCEPTION'
,
'ALL_COMPLETED'
,
'wait'
,
'wait_for'
,
'as_completed'
,
'sleep'
,
'gather'
,
'shield'
,
'ensure_future'
,
'run_coroutine_threadsafe'
,
...
...
@@ -67,13 +67,19 @@ class Task(futures.Future):
return
{
t
for
t
in
cls
.
_all_tasks
if
t
.
_loop
is
loop
}
def
__init__
(
self
,
coro
,
*
,
loop
=
None
):
assert
coroutines
.
iscoroutine
(
coro
),
repr
(
coro
)
super
()
.
__init__
(
loop
=
loop
)
if
self
.
_source_traceback
:
del
self
.
_source_traceback
[
-
1
]
self
.
_coro
=
coro
self
.
_fut_waiter
=
None
if
not
coroutines
.
iscoroutine
(
coro
):
# raise after Future.__init__(), attrs are required for __del__
# prevent logging for pending task in __del__
self
.
_log_destroy_pending
=
False
raise
TypeError
(
f
"a coroutine was expected, got {coro!r}"
)
self
.
_must_cancel
=
False
self
.
_fut_waiter
=
None
self
.
_coro
=
coro
self
.
_loop
.
call_soon
(
self
.
_step
)
self
.
__class__
.
_all_tasks
.
add
(
self
)
...
...
@@ -263,6 +269,15 @@ else:
Task
=
_CTask
=
_asyncio
.
Task
def
create_task
(
coro
):
"""Schedule the execution of a coroutine object in a spawn task.
Return a Task object.
"""
loop
=
events
.
get_running_loop
()
return
loop
.
create_task
(
coro
)
# wait() and as_completed() similar to those in PEP 3148.
FIRST_COMPLETED
=
concurrent
.
futures
.
FIRST_COMPLETED
...
...
Lib/test/test_asyncio/test_tasks.py
Dosyayı görüntüle @
f74ef458
...
...
@@ -2054,6 +2054,43 @@ class BaseTaskTests:
self
.
assertEqual
(
self
.
Task
.
all_tasks
(
self
.
loop
),
set
())
def
test_create_task_with_noncoroutine
(
self
):
with
self
.
assertRaisesRegex
(
TypeError
,
"a coroutine was expected, got 123"
):
self
.
new_task
(
self
.
loop
,
123
)
def
test_create_task_with_oldstyle_coroutine
(
self
):
@asyncio.coroutine
def
coro
():
pass
task
=
self
.
new_task
(
self
.
loop
,
coro
())
self
.
assertIsInstance
(
task
,
self
.
Task
)
self
.
loop
.
run_until_complete
(
task
)
def
test_create_task_with_async_function
(
self
):
async
def
coro
():
pass
task
=
self
.
new_task
(
self
.
loop
,
coro
())
self
.
assertIsInstance
(
task
,
self
.
Task
)
self
.
loop
.
run_until_complete
(
task
)
def
test_bare_create_task
(
self
):
async
def
inner
():
return
1
async
def
coro
():
task
=
asyncio
.
create_task
(
inner
())
self
.
assertIsInstance
(
task
,
self
.
Task
)
ret
=
await
task
self
.
assertEqual
(
1
,
ret
)
self
.
loop
.
run_until_complete
(
coro
())
def
add_subclass_tests
(
cls
):
BaseTask
=
cls
.
Task
...
...
Lib/test/test_asyncio/utils.py
Dosyayı görüntüle @
f74ef458
...
...
@@ -28,6 +28,7 @@ except ImportError: # pragma: no cover
from
asyncio
import
base_events
from
asyncio
import
events
from
asyncio
import
format_helpers
from
asyncio
import
futures
from
asyncio
import
tasks
from
asyncio.log
import
logger
...
...
@@ -429,7 +430,7 @@ class MockPattern(str):
def
get_function_source
(
func
):
source
=
event
s
.
_get_function_source
(
func
)
source
=
format_helper
s
.
_get_function_source
(
func
)
if
source
is
None
:
raise
ValueError
(
"unable to get the source of
%
r"
%
(
func
,))
return
source
...
...
Misc/NEWS.d/next/Library/2017-12-14-17-28-54.bpo-32311.DL5Ytn.rst
0 → 100644
Dosyayı görüntüle @
f74ef458
Implement asyncio.create_task(coro) shortcut
Modules/_asynciomodule.c
Dosyayı görüntüle @
f74ef458
...
...
@@ -26,6 +26,7 @@ static PyObject *all_tasks;
static
PyObject
*
current_tasks
;
static
PyObject
*
traceback_extract_stack
;
static
PyObject
*
asyncio_get_event_loop_policy
;
static
PyObject
*
asyncio_iscoroutine_func
;
static
PyObject
*
asyncio_future_repr_info_func
;
static
PyObject
*
asyncio_task_repr_info_func
;
static
PyObject
*
asyncio_task_get_stack_func
;
...
...
@@ -1461,16 +1462,38 @@ _asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop)
/*[clinic end generated code: output=9f24774c2287fc2f input=8d132974b049593e]*/
{
PyObject
*
res
;
int
tmp
;
_Py_IDENTIFIER
(
add
);
if
(
future_init
((
FutureObj
*
)
self
,
loop
))
{
return
-
1
;
}
if
(
!
PyCoro_CheckExact
(
coro
))
{
// fastpath failed, perfom slow check
// raise after Future.__init__(), attrs are required for __del__
res
=
PyObject_CallFunctionObjArgs
(
asyncio_iscoroutine_func
,
coro
,
NULL
);
if
(
res
==
NULL
)
{
return
-
1
;
}
tmp
=
PyObject_Not
(
res
);
Py_DECREF
(
res
);
if
(
tmp
<
0
)
{
return
-
1
;
}
if
(
tmp
)
{
self
->
task_log_destroy_pending
=
0
;
PyErr_Format
(
PyExc_TypeError
,
"a coroutine was expected, got %R"
,
coro
,
NULL
);
return
-
1
;
}
}
self
->
task_fut_waiter
=
NULL
;
self
->
task_must_cancel
=
0
;
self
->
task_log_destroy_pending
=
1
;
Py_INCREF
(
coro
);
self
->
task_coro
=
coro
;
...
...
@@ -2604,6 +2627,7 @@ module_free(void *m)
Py_CLEAR
(
traceback_extract_stack
);
Py_CLEAR
(
asyncio_get_event_loop_policy
);
Py_CLEAR
(
asyncio_future_repr_info_func
);
Py_CLEAR
(
asyncio_iscoroutine_func
);
Py_CLEAR
(
asyncio_task_repr_info_func
);
Py_CLEAR
(
asyncio_task_get_stack_func
);
Py_CLEAR
(
asyncio_task_print_stack_func
);
...
...
@@ -2645,6 +2669,9 @@ module_init(void)
GET_MOD_ATTR
(
asyncio_task_get_stack_func
,
"_task_get_stack"
)
GET_MOD_ATTR
(
asyncio_task_print_stack_func
,
"_task_print_stack"
)
WITH_MOD
(
"asyncio.coroutines"
)
GET_MOD_ATTR
(
asyncio_iscoroutine_func
,
"iscoroutine"
)
WITH_MOD
(
"inspect"
)
GET_MOD_ATTR
(
inspect_isgenerator
,
"isgenerator"
)
...
...
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