Skip to content

Commit 938e0cb

Browse files
committed
Adding a readthedocs site
The readme was blocking the upload to pypi and this was the easiest solution
1 parent 6602a70 commit 938e0cb

File tree

11 files changed

+965
-319
lines changed

11 files changed

+965
-319
lines changed

.readthedocs.yaml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
version: 2
2+
3+
build:
4+
os: ubuntu-22.04
5+
tools:
6+
python: "3.11"
7+
8+
sphinx:
9+
configuration: docs/conf.py
10+
11+
python:
12+
install:
13+
- requirements: ./tools/.requirements.readthedocs.txt
14+
- method: pip
15+
path: .

README.rst

Lines changed: 1 addition & 314 deletions
Original file line numberDiff line numberDiff line change
@@ -18,317 +18,4 @@ The code here is influenced by pytest-asyncio but with some differences:
1818
Like pytest-asyncio it supports async tests, coroutine fixtures and async
1919
generator fixtures.
2020

21-
Changelog
22-
---------
23-
24-
0.9.0 - 20 October 2024
25-
* Enabling the plugin must now be done by adding ``alt_pytest_asyncio.enable``
26-
to the pytest list of enabled plugins if it's not being manually enabled.
27-
* Removed ``pytest.mark.async_timeout`` and replaced the functionality with
28-
a fixture.
29-
* Changed the exported api of the plugin
30-
31-
* ``alt_pytest_asyncio.plugin.OverrideLoop`` is now ``alt_pytest_asyncio.Loop``
32-
* ``alt_pytest_asyncio.plugin.AltPytestAsyncioPlugin`` now takes ``managed_loop``
33-
as a keyword argument instead of the first positional argument with the
34-
name ``loop``.
35-
* The new ``Loop`` that replaces ``OverrideLoop`` now has an attributed
36-
``controlled_loop`` instead of ``loop``.
37-
38-
0.8.2 - 12 October 2024
39-
* Added type annotations
40-
* CI now tests against python 3.13
41-
42-
0.8.1 - 3 June 2024
43-
* Remove a namespace conflict that restricted what names could be used as
44-
parametrize arguments.
45-
46-
0.8.0 - 1 June 2024
47-
* Provide simple support for tests being aware of asyncio.Context
48-
* Remove support for python less than 3.11
49-
* Added support for asyncio ContextVars
50-
51-
0.7.2 - 1 October 2023
52-
* Timeouts don't take affect if the debugger is active
53-
54-
0.7.1 - 23 June 2023
55-
* No functional changes, only fixing how hatchling understands the
56-
license field in the pyproject.toml with thanks to @piotrm-nvidia
57-
58-
0.7.0 - 12 April 2023
59-
* Changed the pytest dependency to be greater than pytest version 7
60-
* Using isort now
61-
* Went from setuptools to hatch
62-
* CI now runs against python 3.11
63-
64-
0.6.0 - 23 October 2021
65-
* Fix bug where it was possible for an async generator fixture to
66-
be cleaned up even if it was never started.
67-
* This library is now 3.7+ only
68-
* Added an equivalent ``shutdown_asyncgen`` to the OverrideLoop helper
69-
70-
0.5.4 - 26 January 2021
71-
* Added a ``--default-async-timeout`` option from the CLI. With many thanks
72-
to @andredias.
73-
* Renamed existing pytest.ini option from ``default_alt_async_timeout`` to
74-
be ``default_async_timeout``.
75-
76-
0.5.3 - 25 July 2020
77-
* Make sure a KeyboardInterrupt on running tests still shows errors from
78-
failed tests
79-
80-
0.5.2 - 6 February 2020
81-
* Added ability to make a different event loop for some tests
82-
83-
0.5.1 - 15 December 2019
84-
* Added an ini option ``default_alt_async_timeout`` for the default async
85-
timeout for fixtures and tests. The default is now 5 seconds. So say
86-
you wanted the default to be 3.5 seconds, you would set
87-
``default_alt_async_timeout`` to be 3.5
88-
89-
0.5 - 16 August 2019
90-
* I made this functionality in a work project where I needed to run
91-
pytest.main from an existing event loop. I decided to make this it's
92-
own module so I can have tests for this code.
93-
94-
Installation
95-
------------
96-
97-
Most users of this plugin won't need to manually construct the plugin as that's
98-
only required if you're doing funky things where you want to manually call
99-
``pytest.main`` (see next section).
100-
101-
For this majority case, enabling the plugin requires:
102-
* The plugin be installed in the python environment
103-
* Adding ``alt_pytest_asyncio.enable`` to the list of pytest plugins that are
104-
enabled.
105-
106-
Running from your own event loop
107-
--------------------------------
108-
109-
If you want to run pytest.main from with an existing event loop then you can
110-
do something like:
111-
112-
.. code-block:: python
113-
114-
import alt_pytest_asyncio
115-
import nest_asyncio
116-
import asyncio
117-
import pytest
118-
119-
async def my_tests():
120-
await do_some_setup_before_pytest()
121-
122-
loop: asyncio.AbstractEventLoop = ...
123-
124-
plugins = [
125-
alt_pytest_asyncio.plugin.AltPytestAsyncioPlugin(
126-
managed_loop=loop
127-
),
128-
]
129-
130-
try:
131-
code = pytest.main([], plugins=plugins)
132-
finally:
133-
# Note that alt_pytest_asyncio will make sure all your async tests
134-
# have been finalized by this point, even if you KeyboardInterrupt
135-
# the pytest.main
136-
await do_any_teardown_after_pytest()
137-
138-
if code != 0:
139-
raise Exception(repr(code))
140-
141-
if __name__ == '__main__':
142-
# Nest asyncio is required so that we can do run_until_complete in an
143-
# existing event loop - https://github.com/erdewit/nest_asyncio
144-
loop = asyncio.get_event_loop()
145-
nest_asyncio.apply(loop)
146-
147-
alt_pytest_asyncio.run_coro_as_main(loop, my_tests())
148-
149-
Note that if you don't need to run pytest from an existing event loop, you don't
150-
need to do anything other than have ``alt_pytest_asyncio`` installed in your
151-
environment and ``alt_pytest_asyncio.enable`` in your pytest plugins list
152-
and you'll be able to just use async keywords on your fixtures and
153-
tests.
154-
155-
Timeouts
156-
--------
157-
158-
.. note:: The ``pytest.mark.async_timeout(seconds)`` that existed before
159-
version 0.9.0 no longer has an effect and has been replaced with the fixtures
160-
as mentioned below
161-
162-
This plugin can configure the timeout for any async fixture or test using the
163-
``async_timeout`` fixture or by creating a ``default_async_timeout`` fixture.
164-
165-
For example:
166-
167-
.. code-block:: python
168-
169-
import pytest
170-
import alt_pytest_asyncio
171-
172-
AsyncTimeout = alt_pytest_asyncio.protocols.AsyncTimeout
173-
174-
async def test_something(async_timeout: AsyncTimeout) -> None:
175-
async_timeout.set_timeout_seconds(10)
176-
await something_that_may_take_a_while()
177-
178-
This test will be cancelled after 10 seconds and raise an assertion error saying
179-
the test took too long and the file and line number where the test is.
180-
181-
.. note:: The async_timeout passed into a fixture or a test is a new instance
182-
specific to that fixture or test. Setting it in a fixture only affects that
183-
fixture and setting it in a test only affects that test.
184-
185-
You can also set a ``default_async_timeout`` fixture to change the default:
186-
187-
.. code-block:: python
188-
189-
import pytest
190-
import alt_pytest_asyncio
191-
192-
AsyncTimeout = alt_pytest_asyncio.protocols.AsyncTimeout
193-
194-
195-
@pytest.fixture()
196-
def default_async_timeout() -> float:
197-
return 0.5
198-
199-
@pytest.fixture
200-
async def my_amazing_fixture() -> int:
201-
# Will timeout because of our default 0.5
202-
await asyncio.sleep(1)
203-
return 1
204-
205-
@pytest.fixture
206-
async def my_amazing_fixture(async_timeout: AsyncTimeout) -> int:
207-
# Change timeout for just this fixture
208-
async_timeout.set_timeout_seconds(2)
209-
await asyncio.sleep(1)
210-
return 1
211-
212-
For fixtures that have a non function scope, they require a
213-
``{scope}_default_async_timeout`` fixture:
214-
215-
.. code-block:: python
216-
217-
import pytest
218-
219-
220-
@pytest.fixture(scope="session")
221-
def session_default_async_timeout() -> float:
222-
return 5
223-
224-
@pytest.fixture(scope="session")
225-
async def some_fixture() -> None:
226-
# timeout here is 5
227-
pass
228-
229-
class TestStuff:
230-
@pytest.fixture(scope="class")
231-
async def some_fixture() -> None:
232-
# timeout here is 5
233-
pass
234-
235-
class TestMore:
236-
@pytest.fixture(scope="class")
237-
async def class_default_async_timeout() -> int:
238-
return 8
239-
240-
@pytest.fixture(scope="class")
241-
async def some_fixture() -> None:
242-
# timeout here is 8
243-
pass
244-
245-
The plugin knows about the scopes ``function``, ``class``, ``module``, ``package``
246-
and ``session``. So say a ``scope="class"`` async fixture is executed, the closest
247-
``class_default_async_timeout`` fixture is used unless that doesn't exist, in which
248-
case ``module_default_async_timeout`` is used, otherwise ``package_default_async_timeout``,
249-
otherwise ``session_default_async_timeout``.
250-
251-
There is a default ``session_default_async_timeout`` available which returns the
252-
value set by the ``default_async_timeout`` pytest option the plugin provides.
253-
254-
And you can have a timeout on generator fixtures:
255-
256-
.. code-block:: python
257-
258-
import pytest
259-
from collections.abc import Iterator
260-
import alt_pytest_asyncio
261-
262-
AsyncTimeout = alt_pytest_asyncio.protocols.AsyncTimeout
263-
264-
@pytest.fixture()
265-
async def my_amazing_fixture(async_timeout: AsyncTimeout) -> Iterator[int]:
266-
async_timeout.set_timeout_seconds(0.5)
267-
268-
try:
269-
await asyncio.sleep(1)
270-
yield 1
271-
finally:
272-
await asyncio.sleep(1)
273-
274-
Note that for generator fixtures, the timeout is applied in whole to both the
275-
setup and finalization of the fixture. As in the real timeout for the entire
276-
fixture is essentially double the single timeout specified.
277-
278-
The default timeout is 5 seconds. You can change this default by setting the
279-
``default_async_timeout`` option to the number of seconds you want.
280-
281-
This setting is also available from the CLI using the ``--default-async-timeout``
282-
option.
283-
284-
Note that if the timeout fires whilst you have the debugger active then the timeout
285-
will not cancel the current test. This is determined by checking if ``sys.gettrace()``
286-
returns a non-None value.
287-
288-
The object that is provided when the fixture/test asks for ``async_timeout`` can
289-
be modified by overriding the ``async_timeout`` session scope'd fixture and
290-
returning an object that inherits from and implements
291-
``alt_pytest_asyncio.base.AsyncTimeoutProvider``. This is a python "abc" class
292-
with a single method ``load`` which is called to return the object given to the
293-
fixture or test. This object must implement
294-
``alt_pytest_asyncio.base.AsyncTimeout``. The default implementation can be found
295-
at ``alt_pytest_asyncio.plugin.LoadedAsyncTimeout``.
296-
297-
Overriding the loop
298-
-------------------
299-
300-
Sometimes it may be necessary to close the current loop in a test. For this to
301-
not then break the rest of your tests, you will need to set a new event loop for
302-
your test and then restore the old loop afterwards.
303-
304-
For this, we have a context manager that will install a new asyncio loop and
305-
then restore the original loop on exit.
306-
307-
Usage looks like::
308-
309-
import alt_pytest_asyncio
310-
311-
class TestThing:
312-
@pytest.fixture(autouse=True)
313-
def custom_loop(self) -> alt_pytest_asyncio.protocols.Loop:
314-
with alt_pytest_asyncio.Loop() as custom_loop:
315-
yield custom_loop
316-
317-
def test_thing(self, custom_loop: alt_pytest_asyncio.protocols.Loop):
318-
custom_loop.run_until_complete(my_thing())
319-
320-
By putting the loop into an autouse fixture, all fixtures used by the test
321-
will have the custom loop. If you want to include module level fixtures too
322-
then use the OverrideLoop in a module level fixture too.
323-
324-
If the Loop is instantiated with ``new_loop=True`` then it will create and manage
325-
a new event loop whilst it's being used as a context manager. This new loop
326-
will be available on the object as ``.controlled_loop``.
327-
328-
The ``run_until_complete`` on the ``custom_loop`` in the above example will
329-
do a ``run_until_complete`` on the new loop, but in a way that means you
330-
won't get ``unhandled exception during shutdown`` errors when the context
331-
manager closes the new loop.
332-
333-
When the context manager exits and closes the new loop, it will first cancel
334-
all tasks to ensure finally blocks are run.
21+
Full documentation can be found at https://alt-pytest-asyncio.readthedocs.io

docs/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
_build/
2+
.sphinx-build/

docs/README.rst

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
Documentation
2+
=============
3+
4+
From the root of the repo, to build the documentation run::
5+
6+
> ./dev docs
7+
8+
If you want to build from fresh then say::
9+
10+
> ./dev docs fresh
11+
12+
Once your documentation is built do something like::
13+
14+
> ./dev docs view

docs/_static/css/extra.css

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
h2,
2+
p.rubric {
3+
background: rgba(26, 255, 0, 0.12);
4+
padding: 3px;
5+
}

docs/conf.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import pathlib
2+
import sys
3+
4+
sys.path.append(str(pathlib.Path(__file__).parent))
5+
6+
extensions = [
7+
"sphinx.ext.autodoc",
8+
"sphinx_rtd_theme",
9+
]
10+
11+
html_theme = "sphinx_rtd_theme"
12+
html_static_path = ["_static"]
13+
html_css_files = ["css/extra.css"]
14+
15+
exclude_patterns = ["_build/**", ".sphinx-build/**", "README.rst"]
16+
17+
master_doc = "index"
18+
source_suffix = ".rst"
19+
20+
pygments_style = "pastie"
21+
22+
copyright = "Stephen Moore"
23+
project = "alt-pytest-asyncio"
24+
25+
version = "0.1"
26+
release = "0.1"

0 commit comments

Comments
 (0)