Commit 712b69b4 authored by Jason Madden's avatar Jason Madden

Some minor documentation cleanup for intro and basics. Prepping for some re-org.

parent 35348992
......@@ -243,3 +243,7 @@ import gevent.socket
for item in gevent.socket.__all__[:]:
if getattr(gevent.socket, item) is getattr(socket, item, None):
gevent.socket.__all__.remove(item)
if not hasattr(gevent.socket, '_fileobject'):
# Python 3 building Python 2 docs.
gevent.socket._fileobject = object()
......@@ -13,18 +13,20 @@ Greenlet objects
:class:`Greenlet` is a light-weight cooperatively-scheduled execution unit.
To start a new greenlet, pass the target function and its arguments to :class:`Greenlet` constructor and call :meth:`start`:
To start a new greenlet, pass the target function and its arguments to
:class:`Greenlet` constructor and call :meth:`Greenlet.start`:
>>> g = Greenlet(myfunction, 'arg1', 'arg2', kwarg1=1)
>>> g.start()
or use classmethod :meth:`spawn` which is a shortcut that does the same:
or use classmethod :meth:`Greenlet.spawn` which is a shortcut that
does the same:
>>> g = Greenlet.spawn(myfunction, 'arg1', 'arg2', kwarg1=1)
To subclass a :class:`Greenlet`, override its ``_run()`` method and
call ``Greenlet.__init__(self)`` in :meth:`__init__`: It also a good
idea to override :meth:`__str__`: if :meth:`_run` raises an exception,
call ``Greenlet.__init__(self)`` in the subclass ``__init__``. It also a good
idea to override :meth:`Greenlet.__str__`: if ``_run`` raises an exception,
its string representation will be printed after the traceback it
generated.
......@@ -37,9 +39,11 @@ generated.
.. autoattribute:: Greenlet.exception
.. autoattribute:: Greenlet.minimal_ident
.. autoattribute:: Greenlet.name
.. autoattribute:: Greenlet.dead
.. rubric:: Methods
.. automethod:: Greenlet.spawn
.. automethod:: Greenlet.ready
.. automethod:: Greenlet.successful
.. automethod:: Greenlet.start
......@@ -52,6 +56,7 @@ generated.
.. automethod:: Greenlet.link_exception(callback)
.. automethod:: Greenlet.rawlink
.. automethod:: Greenlet.unlink
.. automethod:: Greenlet.__str__
Boolean Contexts
----------------
......@@ -65,12 +70,12 @@ It's possible to use it like this::
>>> while g:
# do something while g is alive
The Greenlet's ``__nonzero__`` is an improvement on greenlet's
``__nonzero__``. The greenlet's :meth:`__nonzero__
<greenlet.greenlet.__nonzero__>` returns False if greenlet has not
been switched to yet or is already dead. While the latter is OK, the
former is not good, because a just spawned Greenlet has not been
switched to yet and thus would evaluate to False.
The Greenlet's boolean value is an improvement on the raw
:class:`greenlet's <greenlet.greenlet>` boolean value. The raw
greenlet's boolean value returns False if the greenlet has not been
switched to yet or is already dead. While the latter is OK, the former
is not good, because a just spawned Greenlet has not been switched to
yet and thus would evaluate to False.
Raw greenlet Methods
--------------------
......@@ -86,6 +91,10 @@ __ https://greenlet.readthedocs.io/en/latest/#instantiation
.. _switching: https://greenlet.readthedocs.io/en/latest/#switching
.. _throw: https://greenlet.readthedocs.io/en/latest/#methods-and-attributes-of-greenlets
.. class:: greenlet.greenlet
The base class from which `Greenlet` descends.
.. exception:: GreenletExit
A special exception that kills the greenlet silently.
......@@ -192,3 +201,6 @@ Configuration
=============
.. autoclass:: gevent._config.Config
.. LocalWords: Greenlet GreenletExit Greenlet's greenlet's
.. LocalWords: automethod
......@@ -38,6 +38,14 @@ Python 2 and Python 3, respectively.
Their organization is an implementation detail that may change at
any time.
.. autofunction:: gevent.socket.gethostbyname
.. class:: socket
The cooperative socket object. See the version documentation for
specifics.
.. toctree::
Python 3 interface <gevent._socket3>
......
......@@ -2,6 +2,8 @@
:mod:`gevent.ssl` -- Secure Sockets Layer (SSL/TLS) module
====================================================================
.. module:: gevent.ssl
This module provides SSL/TLS operations and some related functions. The
API of the functions and classes matches the API of the corresponding
items in the standard :mod:`ssl` module exactly, but the
......@@ -17,6 +19,11 @@ Python 3, Python 2.7.9 and above, and Python 2.7.8 and below, respectively.
Their organization is an implementation detail that may change at
any time.
.. class:: SSLObject
The gevent-cooperative SSL object. See the version-specific
documentation for details.
.. toctree::
Python 3 interface <gevent._ssl3>
......
......@@ -26,10 +26,11 @@ Installation and Requirements
is supported, and versions 3.4, 3.5 and 3.6 of Python 3 are supported.
(Users of older versions of Python 2 need to install gevent 1.0.x
(2.5), 1.1.x (2.6) or 1.2.x (<=2.7.8); gevent 1.2 can be installed on
Python 3.3.) gevent requires the greenlet__ library.
Python 3.3.) gevent requires the greenlet__ library and will install
the `cffi`_ library by default on Windows.
.. note:: Python 3.3 is no longer actively supported in gevent 1.3.
since it is not supported by the Python developers. However,
.. note:: Python 3.3 is no longer actively supported in gevent 1.2
because it is not supported by the Python developers. However,
it should continue to work with gevent 1.2 with the same
level of support as gevent 1.1. For Python 3.3, version
3.3.5 or newer is required to use the gevent's SSL support
......@@ -43,10 +44,10 @@ strongly recommended. On PyPy, there are no external dependencies.
gevent is tested on Windows, OS X, and Linux, and should run on most
other Unix-like operating systems (e.g., FreeBSD, Solaris, etc.)
.. note:: On Windows using the default libev backend, gevent is
.. note:: On Windows using the libev backend, gevent is
limited to a maximum of 1024 open sockets due to
`limitations in libev`_. This limitation should not exist
with the libuv backend.
with the default libuv backend.
gevent and greenlet can both be installed with `pip`_, e.g., ``pip
install gevent``. On Windows, OS X, and Linux, both gevent and greenlet are
......@@ -188,7 +189,7 @@ The event loop provided by libev uses the fastest polling mechanism
available on the system by default. Please read the `libev documentation`_ for more
information.
.. 1.3: libuv update needed
.. caution:: This section needs to be updated for gevent 1.3 and libuv.
.. As of 1.1 or before, we set the EVFLAG_NOENV so this isn't possible any more.
......@@ -201,13 +202,14 @@ information.
.. _`libev documentation`: http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#FUNCTIONS_CONTROLLING_EVENT_LOOPS
.. 1.3: libuv update needed
The libev API is available under the :mod:`gevent.core` module. Note that
the callbacks supplied to the libev API are run in the :class:`~gevent.hub.Hub`
greenlet and thus cannot use the synchronous gevent API. It is possible to
use the asynchronous API there, like :func:`gevent.spawn` and
:meth:`gevent.event.Event.set`.
The libev API is available under the :mod:`gevent.core` module. Note
that the callbacks supplied to the libev API are run in the
:class:`~gevent.hub.Hub` greenlet and thus cannot use the synchronous
gevent API. It is possible to use the asynchronous API there, like
:func:`gevent.spawn` and :meth:`gevent.event.Event.set`.
.. caution:: This section needs to be updated for gevent 1.3 and libuv.
Cooperative multitasking
......@@ -218,10 +220,10 @@ Cooperative multitasking
The greenlets all run in the same OS thread and are scheduled
cooperatively. This means that until a particular greenlet gives up
control, (by calling a blocking function that will switch to the
:class:`~gevent.hub.Hub`), other greenlets won't get a chance to run. This is
typically not an issue for an I/O bound app, but one should be aware
of this when doing something CPU intensive, or when calling blocking
I/O functions that bypass the libev event loop.
:class:`~gevent.hub.Hub`), other greenlets won't get a chance to run.
This is typically not an issue for an I/O bound app, but one should be
aware of this when doing something CPU intensive, or when calling
blocking I/O functions that bypass the libev event loop.
.. tip:: Even some apparently cooperative functions, like
:func:`gevent.sleep`, can temporarily take priority over
......@@ -235,8 +237,10 @@ explict), thus traditional synchronization devices like the
often. Other abstractions from threading and multiprocessing remain
useful in the cooperative world:
- :class:`~event.Event` allows one to wake up a number of greenlets that are calling :meth:`~event.Event.wait` method.
- :class:`~event.AsyncResult` is similar to :class:`~event.Event` but allows passing a value or an exception to the waiters.
- :class:`~event.Event` allows one to wake up a number of greenlets
that are calling :meth:`~event.Event.wait` method.
- :class:`~event.AsyncResult` is similar to :class:`~event.Event` but
allows passing a value or an exception to the waiters.
- :class:`~queue.Queue` and :class:`~queue.JoinableQueue`.
......@@ -245,14 +249,18 @@ Lightweight pseudothreads
.. currentmodule:: gevent
New greenlets are spawned by creating a :class:`~Greenlet` instance and calling its :meth:`start <gevent.Greenlet.start>`
method. (The :func:`gevent.spawn` function is a shortcut that does exactly that). The :meth:`start <gevent.Greenlet.start>`
method schedules a switch to the greenlet that will happen as soon as the current greenlet gives up control.
If there is more than one active greenlet, they will be executed one
by one, in an undefined order as they each give up control to the :class:`~gevent.hub.Hub`.
New greenlets are spawned by creating a :class:`~Greenlet` instance
and calling its :meth:`start <gevent.Greenlet.start>` method. (The
:func:`gevent.spawn` function is a shortcut that does exactly that).
The :meth:`start <gevent.Greenlet.start>` method schedules a switch to
the greenlet that will happen as soon as the current greenlet gives up
control. If there is more than one active greenlet, they will be
executed one by one, in an undefined order as they each give up
control to the :class:`~gevent.hub.Hub`.
If there is an error during execution it won't escape the greenlet's boundaries. An unhandled error results
in a stacktrace being printed, annotated by the failed function's signature and arguments:
If there is an error during execution it won't escape the greenlet's
boundaries. An unhandled error results in a stacktrace being printed,
annotated by the failed function's signature and arguments:
>>> gevent.spawn(lambda : 1/0)
>>> gevent.sleep(1)
......@@ -269,12 +277,12 @@ The traceback is asynchronously printed to ``sys.stderr`` when the greenlet dies
- :meth:`kill <gevent.Greenlet.kill>` -- interrupts greenlet's execution;
- :meth:`get <gevent.Greenlet.get>` -- returns the value returned by greenlet or re-raises the exception that killed it.
It is possible to customize the string printed after the traceback by subclassing the :class:`~gevent.Greenlet` class
and redefining its ``__str__`` method.
It is possible to customize the string printed after the traceback by
subclassing the :class:`~gevent.Greenlet` class and redefining its
``__str__`` method.
To subclass a :class:`gevent.Greenlet`, override its
:meth:`gevent.Greenlet._run` method and call
``Greenlet.__init__(self)`` in ``__init__``::
To subclass a :class:`gevent.Greenlet`, override its ``_run`` method
and call ``Greenlet.__init__(self)`` in ``__init__``::
class MyNoopGreenlet(Greenlet):
......@@ -288,8 +296,9 @@ To subclass a :class:`gevent.Greenlet`, override its
def __str__(self):
return 'MyNoopGreenlet(%s)' % self.seconds
Greenlets can be killed synchronously from another greenlet. Killing will resume the sleeping greenlet, but instead
of continuing execution, a :exc:`GreenletExit` will be raised.
Greenlets can be killed synchronously from another greenlet. Killing
will resume the sleeping greenlet, but instead of continuing
execution, a :exc:`GreenletExit` will be raised.
>>> g = MyNoopGreenlet(4)
>>> g.start()
......@@ -297,9 +306,12 @@ of continuing execution, a :exc:`GreenletExit` will be raised.
>>> g.dead
True
The :exc:`GreenletExit` exception and its subclasses are handled differently than other exceptions.
Raising :exc:`~GreenletExit` is not considered an exceptional situation, so the traceback is not printed.
The :exc:`~GreenletExit` is returned by :meth:`get <gevent.Greenlet.get>` as if it were returned by the greenlet, not raised.
The :exc:`GreenletExit` exception and its subclasses are handled
differently than other exceptions. Raising :exc:`~GreenletExit` is not
considered an exceptional situation, so the traceback is not printed.
The :exc:`~GreenletExit` is returned by :meth:`get
<gevent.Greenlet.get>` as if it were returned by the greenlet, not
raised.
The :meth:`kill <gevent.Greenlet.kill>` method can accept a custom exception to be raised:
......@@ -323,24 +335,24 @@ killing will remain blocked forever).
<gevent.Greenlet.kill>` is not defined. See that function's
documentation for more details.
.. caution:: Use care when killing greenlets, especially arbitrary
greenlets spawned by a library or otherwise executing
code you are not familiar with. If the code being
executed is not prepared to deal with exceptions, object
state may be corrupted. For example, if it has acquired a
``Lock`` but *does not* use a ``finally`` block to
release it, killing the greenlet at the wrong time could
result in the lock being permanently locked::
def func():
# DON'T DO THIS
lock.acquire()
socket.sendall(data) # This could raise many exceptions, including GreenletExit
lock.release()
`This document
<http://docs.oracle.com/javase/8/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html>`_
describes a similar situation for threads.
.. caution::
Use care when killing greenlets, especially arbitrary
greenlets spawned by a library or otherwise executing code you are
not familiar with. If the code being executed is not prepared to
deal with exceptions, object state may be corrupted. For example,
if it has acquired a ``Lock`` but *does not* use a ``finally``
block to release it, killing the greenlet at the wrong time could
result in the lock being permanently locked::
def func():
# DON'T DO THIS
lock.acquire()
socket.sendall(data) # This could raise many exceptions, including GreenletExit
lock.release()
`This document
<http://docs.oracle.com/javase/8/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html>`_
describes a similar situation for threads.
Timeouts
========
......@@ -348,7 +360,7 @@ Timeouts
Many functions in the gevent API are synchronous, blocking the current
greenlet until the operation is done. For example, :meth:`kill
<gevent.Greenlet.kill>` waits until the target greenlet is
:attr:`~gevent.greenlet.Greenlet.dead` before returning [#f1]_. Many of
:attr:`~gevent.Greenlet.dead` before returning [#f1]_. Many of
those functions can be made asynchronous by passing the keyword argument
``block=False``.
......@@ -360,9 +372,9 @@ argument, which specifies a limit on how long the function can block
The :class:`socket <gevent.socket.socket>` and :class:`SSLObject
<gevent.ssl.SSLObject>` instances can also have a timeout, set by the
:meth:`settimeout <gevent.socket.socket.settimeout>` method.
:meth:`settimeout <socket.socket.settimeout>` method.
When these are not enough, the :class:`~gevent.timeout.Timeout` class can be used to
When these are not enough, the :class:`~gevent.Timeout` class can be used to
add timeouts to arbitrary sections of (cooperative, yielding) code.
......@@ -383,4 +395,6 @@ __ http://sdiehl.github.io/gevent-tutorial/
.. rubric:: Footnotes
.. [#f1] This was not the case before 0.13.0, :meth:`kill <gevent.greenlet.Greenlet.kill>` method in 0.12.2 and older was asynchronous by default.
.. [#f1] This was not the case before 0.13.0, :meth:`kill <gevent.Greenlet.kill>` method in 0.12.2 and older was asynchronous by default.
.. LocalWords: Greenlets
# Wrapper module for _ssl. Written by Bill Janssen.
# Ported to gevent by Denis Bilenko.
"""SSL wrapper for socket objects on Python 2.7.8 and below.
"""
SSL wrapper for socket objects on Python 2.7.8 and below.
For the documentation, refer to :mod:`ssl` module manual.
This module implements cooperative SSL socket wrappers.
.. deprecated:: 1.3
This module is not secure. Support for Python versions
with only this level of SSL will be dropped in gevent 1.4.
"""
from __future__ import absolute_import
......
......@@ -367,6 +367,7 @@ class Greenlet(greenlet):
# oops - pypy's .dead relies on __nonzero__ which we overriden above
@property
def dead(self):
"Boolean indicating that the greenlet is dead and will not run again."
if self._greenlet__main:
return False
if self.__start_cancelled_by_kill() or self.__started_but_aborted():
......@@ -376,6 +377,7 @@ class Greenlet(greenlet):
else:
@property
def dead(self):
"Boolean indicating that the greenlet is dead and will not run again."
return self.__start_cancelled_by_kill() or self.__started_but_aborted() or greenlet.dead.__get__(self)
def __never_started_or_killed(self):
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment