From c22b896473fc38864a3ace488ddc4b0514177cae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Beraud?= Date: Tue, 2 Apr 2024 15:18:14 +0200 Subject: [PATCH] Make the docs more user friendly (#950) Improve the general index by adding a contribution guide, changelog, etc. Refactor sections to host various topics and to generate a more sexy table of context which will be more user friendly. Refactor formatting heading levels. Make Asyncio warning message reusable and centralized. Give more visibility to the Asyncio topic. --- AUTHORS | 16 ++- doc/source/asyncio/asyncio.rst | 29 ++++++ .../source/asyncio/compatibility.rst | 97 +++++++++++-------- doc/source/{ => asyncio}/migration.rst | 0 doc/source/asyncio/warning.rst | 10 ++ doc/source/authors.rst | 2 + doc/source/contribute.rst | 46 +++++++++ doc/source/history.rst | 2 + doc/source/hubs.rst | 3 +- doc/source/index.rst | 58 ++++++++--- .../process.rst => maintenance.rst} | 19 ++-- doc/source/reference/api/eventlet.greenio.rst | 8 -- doc/source/reference/api/eventlet.rst | 8 -- doc/source/testing.rst | 2 + 14 files changed, 222 insertions(+), 78 deletions(-) create mode 100644 doc/source/asyncio/asyncio.rst rename asyncio_compat.md => doc/source/asyncio/compatibility.rst (56%) rename doc/source/{ => asyncio}/migration.rst (100%) create mode 100644 doc/source/asyncio/warning.rst create mode 100644 doc/source/contribute.rst rename doc/source/{maintenance/process.rst => maintenance.rst} (91%) diff --git a/AUTHORS b/AUTHORS index 015171af8e..c4c493a6f6 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,12 +1,24 @@ Maintainer (i.e., Who To Hassle If You Find Bugs) ------------------------------------------------- -Jakub Stasiak -Nat Goodspeed The current maintainer(s) are volunteers with unrelated jobs. We can only pay sporadic attention to responding to your issue and pull request submissions. Your patience is greatly appreciated! +Active maintainers +~~~~~~~~~~~~~~~~~~ + +* Itamar Turner-Trauring https://github.com/itamarst +* Tim Burke https://github.com/tipabu +* Hervé Beraud https://github.com/4383 + +Less active maintainers +~~~~~~~~~~~~~~~~~~~~~~~ + +* Sergey Shepelev https://github.com/temoto +* Jakub Stasiak https://github.com/jstasiak +* Nat Goodspeed https://github.com/nat-goodspeed + Original Authors ---------------- * Bob Ippolito diff --git a/doc/source/asyncio/asyncio.rst b/doc/source/asyncio/asyncio.rst new file mode 100644 index 0000000000..495abb8b38 --- /dev/null +++ b/doc/source/asyncio/asyncio.rst @@ -0,0 +1,29 @@ +.. _asyncio-index: + +Asyncio in Eventlet +################### + +Asyncio Compatibility +===================== + +Compatibility between Asyncio and Eventlet has been recently introduced. + +You may be interested by the state of the art of this compatibility and by +the potential limitations, so please take a look at +:ref:`asyncio-compatibility`. + +Asyncio Hub & Functions +======================= + +Discover the :mod:`Asyncio Hub ` + +You may also want to take a look to the +:mod:`Asyncio compatibility functions `. + +Migrating from Eventlet to Asyncio +================================== + +Want to use Asyncio and Eventlet together or you simply want to migrate +off of Eventlet? + +Follow the :ref:`official migration guide `. diff --git a/asyncio_compat.md b/doc/source/asyncio/compatibility.rst similarity index 56% rename from asyncio_compat.md rename to doc/source/asyncio/compatibility.rst index 0202de5cc3..2a7671f235 100644 --- a/asyncio_compat.md +++ b/doc/source/asyncio/compatibility.rst @@ -1,4 +1,7 @@ -# Asyncio compatibility in eventlet +.. _asyncio-compatibility: + +Asyncio compatibility in eventlet +################################# It should be possible to: @@ -11,7 +14,8 @@ If this works, it would allow migrating from eventlet to asyncio in a gradual ma This means migration doesn't have to be done in one stop, neither in libraries nor in the applications that depend on them. 2. Even when an OpenStack library fully migrates to asyncio, it will still be usable by anything that is still running on eventlet. -## Prior art +Prior art +========= * Gevent has a similar model to eventlet. There exists an integration between gevent and asyncio that follows model proposed below: https://pypi.org/project/asyncio-gevent/ @@ -19,11 +23,13 @@ If this works, it would allow migrating from eventlet to asyncio in a gradual ma Separately, it includes utilities for mapping its `Deferred` objects (similar to a JavaScript Promise) to the async/await model introduced in newer versions in Python 3, and in the opposite direction it added support for turning async/await functions into `Deferred`s. In an eventlet context, `GreenThread` would need a similar former of integration to Twisted's `Deferred`. -## Part 1: Implementing asyncio/eventlet interoperability +Part 1: Implementing asyncio/eventlet interoperability +====================================================== There are three different parts involved in integrating eventlet and asyncio for purposes -### 1. Create a hub that runs on asyncio +1. Create a hub that runs on asyncio +------------------------------------ Like many networking frameworks, eventlet has pluggable event loops, in this case called a "hub". Typically hubs wrap system APIs like `select()` and `epoll()`, but there also used to be a hub that ran on Twisted. Creating a hub that runs on top of the asyncio event loop should be fairly straightforward. @@ -31,64 +37,77 @@ Creating a hub that runs on top of the asyncio event loop should be fairly strai Once this is done, eventlet and asyncio code can run in the same process and the same thread, but they would still have difficulties talking to each other. This latter requirement requires additional work, as covered by the next two items. -### 2. Calling `async def` functions from eventlet +2. Calling `async def` functions from eventlet +---------------------------------------------- The goal is to allow something like this: -```python -import aiohttp -from eventlet_asyncio import future_to_greenlet # hypothetical API - -async def get_url_body(url): - async with aiohttp.ClientSession() as session: - async with session.get(url) as response: - return await response.text() +.. code:: -def eventlet_code(): - green_thread = future_to_greenlet(get_url_body("https://example.com")) - return green_thread.wait() -``` + import aiohttp + from eventlet_asyncio import future_to_greenlet # hypothetical API + + async def get_url_body(url): + async with aiohttp.ClientSession() as session: + async with session.get(url) as response: + return await response.text() + + def eventlet_code(): + green_thread = future_to_greenlet(get_url_body("https://example.com")) + return green_thread.wait() The code would presumably be similar to https://github.com/gfmio/asyncio-gevent/blob/main/asyncio_gevent/future_to_greenlet.py -### 3. Calling eventlet code from asyncio +3. Calling eventlet code from asyncio +------------------------------------- The goal is to allow something like this: -```python -from urllib.request import urlopen -from eventlet import spawn -from eventlet_asyncio import greenlet_to_future # hypothetical API - -def get_url_body(url): - # Looks blocking, but actually isn't - return urlopen(url).read() - -# This would likely be common pattern, so could be implemented as decorator... -async def asyncio_code(): - greenlet = eventlet.spawn(get_url_body, "https://example.com") - future = greenlet_to_future(greenlet) - return await future -``` +.. code:: + + from urllib.request import urlopen + from eventlet import spawn + from eventlet_asyncio import greenlet_to_future # hypothetical API + + def get_url_body(url): + # Looks blocking, but actually isn't + return urlopen(url).read() + + # This would likely be common pattern, so could be implemented as decorator... + async def asyncio_code(): + greenlet = eventlet.spawn(get_url_body, "https://example.com") + future = greenlet_to_future(greenlet) + return await future The code would presumably be similar to https://github.com/gfmio/asyncio-gevent/blob/main/asyncio_gevent/future_to_greenlet.py -### 4. Limitations and potential unexpected behavior +4. Limitations and potential unexpected behavior +------------------------------------------------ ``concurrent.futures.thread`` just uses normal threads, not Eventlet's special threads. -Similarly, [``asyncio.to_thread()``](https://docs.python.org/3/library/asyncio-task.html#asyncio.to_thread) specifically requires regular blocking code, it won't work correctly with Eventlet code. +Similarly, `asyncio.to_thread() `_ +specifically requires regular blocking code, it won't work correctly with Eventlet code. + +Multiple readers are not supported by the Asyncio hub. -## Part 2: How a port would work on a technical level +Part 2: How a port would work on a technical level +================================================== -### Porting a library +Porting a library +================= 1. Usage of eventlet-based APIs would be replaced with usage of asyncio APIs. - For example, `urllib` or `requests` might be replaced with [`aiohttp`](https://docs.aiohttp.org/en/stable/). + For example, `urllib` or `requests` might be replaced with `aiohttp `_. The interoperability above can be used to make sure this continues to work with eventlet-based APIs. + + The `awesome-asyncio `_ github repository propose a curated list of awesome + Python asyncio frameworks, libraries, software and resources. Do not hesitate to take a look at it. You may find + candidates compatible with asyncio that can allow you to replace some of your actual underlying libraries. 2. Over time, APIs would need be migrated to be `async` function, but in the intermediate time frame a standard `def` can still be used, again using the interoperability layer above. 3. Eventually all "blocking" APIs have been removed, at which point everything can be switched to `async def` and `await`, including external API, and the library will no longer depend on eventlet. -### Porting an application +Porting an application +====================== An application would need to install the asyncio hub before kicking off eventlet. Beyond that porting would be the same as a library. diff --git a/doc/source/migration.rst b/doc/source/asyncio/migration.rst similarity index 100% rename from doc/source/migration.rst rename to doc/source/asyncio/migration.rst diff --git a/doc/source/asyncio/warning.rst b/doc/source/asyncio/warning.rst new file mode 100644 index 0000000000..f96760e0cd --- /dev/null +++ b/doc/source/asyncio/warning.rst @@ -0,0 +1,10 @@ +.. warning:: + + Eventlet is now in maintenance mode, so only the changes who are related + to fixing a bug or who are related to the new Asyncio hub will be accepted. + New features outside of the scope of the Asyncio hub won't be accepted. + + :ref:`migration-guide` is strongly encouraged. We encourage existing + users to migrate to Asyncio. For further details see the official + :ref:`migration guide `. + diff --git a/doc/source/authors.rst b/doc/source/authors.rst index 027630ae99..6877a5ad38 100644 --- a/doc/source/authors.rst +++ b/doc/source/authors.rst @@ -1,3 +1,5 @@ +.. _authors: + Authors ======= diff --git a/doc/source/contribute.rst b/doc/source/contribute.rst new file mode 100644 index 0000000000..7020792381 --- /dev/null +++ b/doc/source/contribute.rst @@ -0,0 +1,46 @@ +.. _how-to-contribute: + +How to Contribute to Eventlet +############################# + +.. include:: asyncio/warning.rst + +Contribution are welcome. + +You want to report something? Read :ref:`report-a-bug`. + +You want to propose changes? Read :ref:`propose-changes`. + +.. _report-a-bug: + +Report a Bug +============= + +You find a bug and you want to report it? + +You simply have to `create a new github issue `_ +where you describe your problem. + +Do not forget to provide technical details like: + +* the hub you use +* the context of your bug +* the error message you get +* everything else that may help us to understand your problem. + +The more you give details, the more we will be able to help you. + +.. _propose-changes: + +Propose Changes +=============== + +You may want to propose changes to fix a bug, improve the documentation, etc. + +Feel free to open a pull request: https://github.com/eventlet/eventlet/pulls + +.. include:: asyncio/warning.rst + +We will be happy to review it. + +At this point you may be also interested by :ref:`how to test Eventlet `. diff --git a/doc/source/history.rst b/doc/source/history.rst index 8f89b45d81..9e051e0565 100644 --- a/doc/source/history.rst +++ b/doc/source/history.rst @@ -1,3 +1,5 @@ +.. _history: + History ------- diff --git a/doc/source/hubs.rst b/doc/source/hubs.rst index 33111e3520..d1dce22035 100644 --- a/doc/source/hubs.rst +++ b/doc/source/hubs.rst @@ -13,7 +13,8 @@ Eventlet has multiple hub implementations, and when you start using it, it tries | We discourage new Eventlet projects. | We encourage existing Eventlet projects to migrate from Eventlet to Asyncio. | This hub allow you incremental and smooth migration. - | See the `migration guide `_ for further details. + | See the :ref:`migration-guide` for further details. + | See the :ref:`asyncio-compatibility` for the current state of the art. **epolls** Linux. This is the fastest hub for Linux. **kqueue** diff --git a/doc/source/index.rst b/doc/source/index.rst index d9a2471306..c6029e6858 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -1,3 +1,6 @@ +Eventlet Documentation +###################### + Warning ======= @@ -34,8 +37,19 @@ answer them. .. _asyncio: https://docs.python.org/3/library/asyncio.html .. _open a new issue: https://github.com/eventlet/eventlet/issues/new -Eventlet Documentation -====================== +Installation +============ + +The easiest way to get Eventlet is to use pip:: + + pip install -U eventlet + +To install latest development version once:: + + pip install -U https://github.com/eventlet/eventlet/archive/master.zip + +Usage +===== Code talks! This is a simple web crawler that fetches a bunch of urls concurrently: @@ -57,19 +71,19 @@ Code talks! This is a simple web crawler that fetches a bunch of urls concurren for body in pool.imap(fetch, urls): print("got body", len(body)) -Supported Python versions +Supported Python Versions ========================= Currently supporting CPython 3.7+. -Contents -========= +Concepts & References +===================== .. toctree:: :maxdepth: 2 - migration + asyncio/asyncio basic_usage design_patterns patching @@ -78,22 +92,42 @@ Contents threading zeromq hubs - testing environment - modules - process - authors - history +Want to contribute? +=================== + +.. toctree:: + :maxdepth: 2 + + contribute + testing + maintenance License ---------- +======= Eventlet is made available under the terms of the open source `MIT license `_ +Changelog +========= + +For further details about released versions of Eventlet please take a +look at the :ref:`changelog`. + +Authors & History +================= + +You have questions or you may have find a bug and you want to contact authors +or maintainers, then please take a look at :ref:`authors`. + +You want to learn more about the history of Eventlet, then, please take a +look at :ref:`history`. + Indices and tables ================== * :ref:`genindex` * :ref:`modindex` * :ref:`search` +* :ref:`changelog` diff --git a/doc/source/maintenance/process.rst b/doc/source/maintenance.rst similarity index 91% rename from doc/source/maintenance/process.rst rename to doc/source/maintenance.rst index aa4d836993..edce1f30a0 100644 --- a/doc/source/maintenance/process.rst +++ b/doc/source/maintenance.rst @@ -1,17 +1,20 @@ +.. _maintenance_process: + Maintenance Process -=================== +################### This section provide guidances and process to eventlet -maintainers. They are useful to lead the life cycle of eventlet. +maintainers. They are mostly dedicated to Eventlet' core maintainers lead the +life cycle of eventlet. Releases --------- +======== Here we describe the process we usually follow to process a new release. 1. Create a github issue to track the release -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +--------------------------------------------- The first step will be to `open a new github issue`_ to warn other maintainers about our intention @@ -28,7 +31,7 @@ Please add the `release` label to this issue. It would ease the tracking of works related to releases. 2. Prepare the changelog -~~~~~~~~~~~~~~~~~~~~~~~~ +------------------------ You now have to update the changelog by updating the `NEWS` file available at the root of eventlet the project. @@ -47,7 +50,7 @@ If you want, you can use the issue previously created to list each commits landed in this new version. Here is an example https://github.com/eventlet/eventlet/issues/897. 3. Create the tag -~~~~~~~~~~~~~~~~~ +----------------- Once the changelog patch is merged, then we are now able to produce the new corresponding tag, here are the @@ -66,7 +69,7 @@ You can simply reuse the changelog you made previously. Alternatively, the Github UI also allow you creating tags. 4. Final checks -~~~~~~~~~~~~~~~ +--------------- Pushing the previous will produce a new build. This build will generate our release and will push this @@ -78,7 +81,7 @@ well available on Pypi https://pypi.org/project/eventlet/#history. Your tag should be listed there https://github.com/eventlet/eventlet/tags. 5. Close the issue -~~~~~~~~~~~~~~~~~~ +------------------ If the previous steps were successful, then you can now update the Github issue that you previously created. diff --git a/doc/source/reference/api/eventlet.greenio.rst b/doc/source/reference/api/eventlet.greenio.rst index f14e42802b..92e625ba11 100644 --- a/doc/source/reference/api/eventlet.greenio.rst +++ b/doc/source/reference/api/eventlet.greenio.rst @@ -12,14 +12,6 @@ eventlet.greenio.base module :undoc-members: :show-inheritance: -eventlet.greenio.py2 module ---------------------------- - -.. automodule:: eventlet.greenio.py2 - :members: - :undoc-members: - :show-inheritance: - eventlet.greenio.py3 module --------------------------- diff --git a/doc/source/reference/api/eventlet.rst b/doc/source/reference/api/eventlet.rst index 6454bd2b10..0e08e922dc 100644 --- a/doc/source/reference/api/eventlet.rst +++ b/doc/source/reference/api/eventlet.rst @@ -144,14 +144,6 @@ eventlet.semaphore module :undoc-members: :show-inheritance: -eventlet.temp module --------------------- - -.. automodule:: eventlet.temp - :members: - :undoc-members: - :show-inheritance: - eventlet.timeout module ----------------------- diff --git a/doc/source/testing.rst b/doc/source/testing.rst index 88608587aa..d3de272131 100644 --- a/doc/source/testing.rst +++ b/doc/source/testing.rst @@ -1,3 +1,5 @@ +.. _testing-eventlet: + Testing Eventlet ================