-
Notifications
You must be signed in to change notification settings - Fork 244
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add proper cross-linkable API docs, and begin breaking the documentat…
…ion into topics.
- Loading branch information
Showing
9 changed files
with
673 additions
and
481 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
====================== | ||
Python API Reference | ||
====================== | ||
|
||
.. currentmodule:: greenlet | ||
|
||
Exceptions | ||
========== | ||
|
||
.. autoexception:: GreenletExit | ||
.. autoexception:: error | ||
|
||
Greenlets | ||
========= | ||
|
||
.. autofunction:: getcurrent | ||
|
||
.. autoclass:: greenlet | ||
|
||
Greenlets support boolean tests: ``bool(g)`` is true if ``g`` is | ||
active and false if it is dead or not yet started. | ||
|
||
.. method:: switch(*args, **kwargs) | ||
|
||
Switches execution to this greenlet. See :ref:`switching`. | ||
|
||
.. automethod:: throw([typ, [val, [tb]]]) | ||
|
||
.. autoattribute:: dead | ||
|
||
True if this greenlet is dead (i.e., it finished its execution). | ||
|
||
.. autoattribute:: gr_context | ||
|
||
|
||
The :class:`contextvars.Context` in which ``g`` will run. | ||
Writable; defaults to ``None``, reflecting that a greenlet | ||
starts execution in an empty context unless told otherwise. | ||
Generally, this should only be set once, before a greenlet | ||
begins running. Accessing or modifying this attribute raises | ||
:exc:`AttributeError` on Python versions 3.6 and earlier (which | ||
don't natively support the `contextvars` module) or if | ||
``greenlet`` was built without contextvars support. | ||
|
||
For more information, see :doc:`contextvars`. | ||
|
||
.. versionadded:: 1.0.0 | ||
|
||
.. autoattribute:: gr_frame | ||
|
||
The frame that was active in this greenlet when it most recently | ||
called ``some_other_greenlet.switch()``, and that will resume | ||
execution when ``this_greenlet.switch()`` is next called. The remainder of | ||
the greenlet's stack can be accessed by following the frame | ||
object's ``f_back`` attributes. ``gr_frame`` is non-None only | ||
for suspended greenlets; it is None if the greenlet is dead, not | ||
yet started, or currently executing. | ||
|
||
.. autoattribute:: parent | ||
|
||
The parent greenlet. This is writable, but it is not allowed to create | ||
cycles of parents. | ||
|
||
A greenlet without a parent is the main greenlet of its thread. | ||
|
||
Cannot be set to anything except a greenlet. | ||
|
||
.. autoattribute:: run | ||
|
||
The callable that this greenlet will run when it starts. After | ||
it is started, this attribute no longer exists. | ||
|
||
Subclasses can define this as a method on the type. | ||
|
||
|
||
|
||
Tracing | ||
======= | ||
|
||
For details on tracing, see :doc:`tracing`. | ||
|
||
.. autofunction:: gettrace | ||
|
||
.. autofunction:: settrace | ||
|
||
:param callback: A callable object with the signature | ||
``callback(event, args)``. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
================= | ||
C API Reference | ||
================= | ||
|
||
Greenlets can be created and manipulated from extension modules written in C or | ||
C++, or from applications that embed Python. The ``greenlet.h`` header is | ||
provided, and exposes the entire API available to pure Python modules. | ||
|
||
Note that much of the API is implemented in terms of macros, meaning | ||
that it is not necessarily ABI stable. | ||
|
||
Types | ||
===== | ||
|
||
.. c:type:: PyGreenlet | ||
The C name corresponding to the Python :class:`greenlet.greenlet`. | ||
|
||
Exceptions | ||
========== | ||
|
||
.. c:type:: PyExc_GreenletError | ||
The C name corresponding to the Python :exc:`greenlet.error` | ||
|
||
.. c:type:: PyExc_GreenletExit | ||
The C name corresponding to the Python :exc:`greenlet.GreenletExit` | ||
|
||
Functions | ||
========= | ||
|
||
.. c:function:: void PyGreenlet_Import(void) | ||
A macro that imports the greenlet module and initializes the C API. This | ||
must be called once for each extension module that uses the greenlet C API, | ||
usually in the module's init function. | ||
.. c:function:: int PyGreenlet_Check(PyObject* p) | ||
Macro that returns true if the argument is a :c:type:`PyGreenlet`. | ||
.. c:function:: int PyGreenlet_STARTED(PyGreenlet* g) | ||
Macro that returns true if the greenlet *g* has started. | ||
.. c:function:: int PyGreenlet_ACTIVE(PyGreenlet* g) | ||
Macro that returns true if the greenlet *g* has started and has not died. | ||
.. c:function:: PyGreenlet* PyGreenlet_GET_PARENT(PyGreenlet* g) | ||
Macro that returns the parent greenlet of *g*. | ||
.. c:function:: int PyGreenlet_SetParent(PyGreenlet* g, PyGreenlet* nparent) | ||
Set the parent greenlet of *g*. | ||
:return: 0 for succes, or -1 on error. When an error is returned, | ||
*g* is not a pointer to a greenlet, and an | ||
:exc:`AttributeError` has been raised. | ||
.. c:function:: PyGreenlet* PyGreenlet_GetCurrent(void) | ||
Returns the currently active greenlet object. | ||
.. c:function:: PyGreenlet* PyGreenlet_New(PyObject* run, PyObject* parent) | ||
Creates a new greenlet object with the callable *run* and parent | ||
*parent*. Both parameters are optional and may be ``NULL``. | ||
:param run: If ``NULL``, the greenlet will be created, but will | ||
fail when switched to. | ||
:param parent: If ``NULL``, the parent is automatically set to the | ||
current greenlet. | ||
.. c:function:: PyObject* PyGreenlet_Switch(PyGreenlet* g, PyObject* args, PyObject* kwargs) | ||
Switches to the greenlet *g*. Besides *g*, the remaining | ||
parameters are optional and may be ``NULL``. | ||
:param args: If ``args`` is NULL, an empty tuple is passed to the | ||
target greenlet. If given, must be a :class:`tuple`. | ||
:param kwargs: If kwargs is ``NULL``, no keyword arguments are | ||
passed to the target greenlet. If given, must be a | ||
:class:`dict`. | ||
.. c:function:: PyObject* PyGreenlet_Throw(PyGreenlet* g, PyObject* typ, PyObject* val, PyObject* tb) | ||
Switches to greenlet *g*, but immediately raise an exception of type | ||
*typ* with the value *val*, and optionally, the traceback object | ||
*tb*. *tb* can be ``NULL``. | ||
The arguments *typ*, *val* and *tb* are interpreted as for :c:func:`PyErr_Restore`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
============================= | ||
Context Variables (asyncio) | ||
============================= | ||
|
||
.. versionadded:: 1.0.0 | ||
|
||
On Python versions (3.7 and above) that natively support context | ||
variables as defined in :pep:`525`, each greenlet runs by default in | ||
its own :class:`contextvars.Context`, enabling | ||
:class:`~contextvars.ContextVar`\s to be used for "greenlet-local | ||
storage". (If you need to support earlier Python versions, you can use | ||
attributes on the greenlet object instead.) | ||
|
||
A new greenlet's context is initially empty, i.e., all | ||
:class:`~contextvars.ContextVar`\s have their default values. This | ||
matches the behavior of a new thread, but differs from that of a new | ||
:class:`asyncio.Task`, which inherits a copy of the context that was | ||
active when it was spawned. You can assign to a greenlet's | ||
``gr_context`` attribute to change the context that it will use. For | ||
example: | ||
|
||
.. doctest:: | ||
:pyversion: > 3.7 | ||
|
||
>>> import greenlet | ||
>>> import contextvars | ||
|
||
>>> example = contextvars.ContextVar("example", default=0) | ||
|
||
>>> def set_it(next_value): | ||
... previous_value = example.get() | ||
... print("Value of example in greenlet :", previous_value) | ||
... print("Setting example in greenlet to:", next_value) | ||
... example.set(next_value) | ||
|
||
>>> _ = example.set(1) | ||
|
||
By default, a new greenlet gets an empty context, unrelated to the | ||
current context: | ||
|
||
.. doctest:: | ||
:pyversion: > 3.7 | ||
|
||
>>> gr1 = greenlet.greenlet(set_it) | ||
>>> gr1.switch(2) | ||
Value of example in greenlet : 0 | ||
Setting example in greenlet to: 2 | ||
>>> example.get() | ||
1 | ||
|
||
You can make a greenlet get a copy of the current context when it is | ||
created, like asyncio: | ||
|
||
.. doctest:: | ||
:pyversion: > 3.7 | ||
|
||
>>> gr2 = greenlet.greenlet(set_it) | ||
>>> gr2.gr_context = contextvars.copy_context() | ||
>>> gr2.switch(2) | ||
Value of example in greenlet : 1 | ||
Setting example in greenlet to: 2 | ||
|
||
You can also make a greenlet *share* the current context, like older, | ||
non-contextvars-aware versions of greenlet: | ||
|
||
.. doctest:: | ||
:pyversion: > 3.7 | ||
|
||
>>> gr3 = greenlet.greenlet(set_it) | ||
>>> gr3.gr_context = greenlet.getcurrent().gr_context | ||
>>> gr3.switch(2) | ||
Value of example in greenlet : 1 | ||
Setting example in greenlet to: 2 | ||
|
||
You can alternatively set a new greenlet's context by surrounding its | ||
top-level function in a call to :meth:`Context.run() | ||
<contextvars.Context.run>`: | ||
|
||
.. doctest:: | ||
:pyversion: > 3.7 | ||
|
||
>>> _ = example.set(1) | ||
>>> gr4 = greenlet.greenlet(contextvars.copy_context().run) | ||
>>> gr4.switch(set_it, 2) | ||
Value of example in greenlet : 1 | ||
Setting example in greenlet to: 2 | ||
>>> example.get() | ||
1 | ||
|
||
However, contextvars were not designed with greenlets in mind, so | ||
using :meth:`Context.run() <contextvars.Context.run>` becomes | ||
challenging in an environment with arbitrary greenlet-to-greenlet | ||
control transfers. The :meth:`~contextvars.Context.run` calls across | ||
all greenlets in a thread must effectively form a stack, where the | ||
last context entered is the first one to be exited. Also, it's | ||
not possible to have two calls to :meth:`~contextvars.Context.run` for | ||
the same context active in two different greenlets at the same | ||
time. Assigning to ``gr_context`` does not share these | ||
restrictions. | ||
|
||
You can access and change a greenlet's context almost no matter what | ||
state the greenlet is in. It can be dead, not yet started, or | ||
suspended (on any thread), or running (on the current thread only). | ||
Accessing or modifying ``gr_context`` of a greenlet running on a | ||
different thread raises :exc:`ValueError`. | ||
|
||
.. warning:: | ||
|
||
Changing the ``gr_context`` after a greenlet has begun | ||
running is not recommended for reasons outlined below. | ||
|
||
Once a greenlet has started running, ``gr_context`` tracks its | ||
*current* context: the one that would be active if you switched to the | ||
greenlet right now. This may not be the same as the value of | ||
``gr_context`` before the greenlet started running. One potential | ||
difference occurs if a greenlet running in the default empty context | ||
(represented as ``None``) sets any context variables: a new | ||
:class:`~contextvars.Context` will be implicitly created to hold them, | ||
which will be reflected in ``gr_context``. Another one occurs if a | ||
greenlet makes a call to ``Context.run(some_inner, func)``: its | ||
``gr_context`` will be ``some_inner`` until ``func()`` returns. | ||
|
||
.. warning:: | ||
|
||
Assigning to ``gr_context`` of an active greenlet that might be | ||
inside a call to :meth:`Context.run() <contextvars.Context.run>` is | ||
not recommended, because :meth:`~contextvars.Context.run` will | ||
raise an exception if the current context when it exits doesn't | ||
match the context that it set upon entry. The safest thing to do is | ||
set ``gr_context`` once, before starting the greenlet; then there's | ||
no potential conflict with :meth:`Context.run() | ||
<contextvars.Context.run>` calls. |
Oops, something went wrong.