From f2391b5c885ad66f878a139c68a1fa3ed2384638 Mon Sep 17 00:00:00 2001 From: CoolCat467 <52022020+CoolCat467@users.noreply.github.com> Date: Tue, 8 Jul 2025 23:34:49 -0500 Subject: [PATCH 01/12] Switch to --- pyproject.toml | 70 ++++++++++++++++++++++++++++++++++ setup.py | 100 ------------------------------------------------- 2 files changed, 70 insertions(+), 100 deletions(-) delete mode 100644 setup.py diff --git a/pyproject.toml b/pyproject.toml index cac350a..9e0e9de 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,3 +1,73 @@ +[build-system] +# setuptools v77 adds PEP 639 support +requires = ["setuptools >= 77"] +build-backend = "setuptools.build_meta" + +[project] +name = "trio_asyncio" +description = "A re-implementation of the asyncio mainloop on top of Trio" +authors = [{name = "Matthias Urlichs", email = "matthias@urlichs.de"}] +license = "MIT OR Apache-2.0" +license-files = ["LICENSE*"] +keywords = [ + "async", + "io", + "trio", + "asyncio", + "trio-asyncio" +] +classifiers = [ + "Development Status :: 4 - Beta", + "Intended Audience :: Developers", + "Operating System :: POSIX :: Linux", + "Operating System :: MacOS :: MacOS X", + "Operating System :: POSIX :: BSD", + "Operating System :: Microsoft :: Windows", + "Programming Language :: Python :: Implementation :: CPython", + "Programming Language :: Python :: Implementation :: PyPy", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Topic :: System :: Networking", + "Framework :: Trio", + "Framework :: AsyncIO", +] +requires-python = ">=3.9" +dependencies = [ + "trio >= 0.22.0", + "outcome", + "sniffio >= 1.3.0", + "exceptiongroup >= 1.0.0; python_version < '3.11'", + "greenlet", +] +dynamic = ["version"] + +[project.readme] +file = "README.rst" +content-type = "text/x-rst" + +[project.urls] +Homepage = "https://github.com/python-trio/trio-asyncio" +Documentation = "http://trio-asyncio.readthedocs.io" +Changelog = "https://trio-asyncio.readthedocs.io/en/latest/history.html" + +[tool.setuptools] +# This means, just install *everything* you see under trio/, even if it +# doesn't look like a source file, so long as it appears in MANIFEST.in: +include-package-data = true + +[tool.setuptools.dynamic] +version = {attr = "trio_asyncio._version.__version__"} + +[project.optional-dependencies] +tests = [ + "pytest>=5.4", + "pytest-trio >= 0.6", +] + [tool.pytest.ini_options] addopts = ["-p", "no:asyncio"] filterwarnings = [ diff --git a/setup.py b/setup.py deleted file mode 100644 index 1d2a44e..0000000 --- a/setup.py +++ /dev/null @@ -1,100 +0,0 @@ -from setuptools import setup -import sys - -exec(open("trio_asyncio/_version.py", encoding="utf-8").read()) - -LONG_DESC = """\ -``trio-asyncio`` is a re-implementation of the ``asyncio`` mainloop on top of -Trio. - -Rationale -========= - -There are quite a few asyncio-compatible libraries. - -On the other hand, Trio has native concepts of tasks and task cancellation. -Asyncio, on the other hand, is based on chaining Future objects, albeit -with nicer syntax. - -Thus, being able to use asyncio libraries from Trio is useful. - -Principle of operation -====================== - -The core of the "normal" asyncio main loop is the repeated execution of -synchronous code that's submitted to ``call_soon`` or -``add_reader``/``add_writer``. - -Everything else within ``asyncio``, i.e. Futures and ``async``/``await``, -is just syntactic sugar. There is no concept of a task; while a Future can -be cancelled, that in itself doesn't affect the code responsible for -fulfilling it. - -On the other hand, trio has genuine tasks with no separation between -returning a value asynchronously, and the code responsible for providing -that value. - -``trio_asyncio`` implements a task which runs (its own version of) the -asyncio main loop. It also contains shim code which translates between these -concepts as transparently and correctly as possible, and it supplants a few -of the standard loop's key functions. - -This works rather well: ``trio_asyncio`` consists of just ~700 lines of -code (asyncio: ~8000) but passes the complete Python 3.6 test suite with no -errors. - -``trio_asyncio`` requires Python 3.9 or later. - -Author -====== - -Matthias Urlichs - -""" - -setup( - name="trio_asyncio", - version=__version__, # noqa: F821 - description="A re-implementation of the asyncio mainloop on top of Trio", - long_description=LONG_DESC, - author="Matthias Urlichs", - author_email="matthias@urlichs.de", - url="https://github.com/python-trio/trio-asyncio", - license="MIT -or- Apache License 2.0", - packages=["trio_asyncio"], - install_requires=[ - "trio >= 0.22.0", - "outcome", - "sniffio >= 1.3.0", - "exceptiongroup >= 1.0.0; python_version < '3.11'", - "greenlet", - ], - # This means, just install *everything* you see under trio/, even if it - # doesn't look like a source file, so long as it appears in MANIFEST.in: - include_package_data=True, - python_requires=">=3.9", - keywords=["async", "io", "trio", "asyncio", "trio-asyncio"], - setup_requires=["pytest-runner"], - tests_require=["pytest >= 5.4", "pytest-trio >= 0.6", "outcome"], - classifiers=[ - "Development Status :: 4 - Beta", - "Intended Audience :: Developers", - "License :: OSI Approved :: MIT License", - "License :: OSI Approved :: Apache Software License", - "Operating System :: POSIX :: Linux", - "Operating System :: MacOS :: MacOS X", - "Operating System :: POSIX :: BSD", - "Operating System :: Microsoft :: Windows", - "Programming Language :: Python :: Implementation :: CPython", - "Programming Language :: Python :: Implementation :: PyPy", - "Programming Language :: Python :: 3 :: Only", - "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", - "Programming Language :: Python :: 3.12", - "Programming Language :: Python :: 3.13", - "Topic :: System :: Networking", - "Framework :: Trio", - "Framework :: AsyncIO", - ], -) From dcaa64f6d632aab3b953ee2e3634906e187893b5 Mon Sep 17 00:00:00 2001 From: CoolCat467 <52022020+CoolCat467@users.noreply.github.com> Date: Tue, 8 Jul 2025 23:43:03 -0500 Subject: [PATCH 02/12] Remove most of the references to `setup.py` --- CHEATSHEET.rst | 6 +++--- Makefile | 2 +- ci.sh | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/CHEATSHEET.rst b/CHEATSHEET.rst index 2deead4..7328447 100644 --- a/CHEATSHEET.rst +++ b/CHEATSHEET.rst @@ -14,12 +14,12 @@ To run yapf ----------- * Show what changes yapf wants to make: - ``yapf3 -rpd setup.py trio_asyncio tests`` + ``yapf3 -rpd trio_asyncio tests`` * Apply all changes directly to the source tree: - ``yapf -rpi setup.py trio_asyncio tests`` + ``yapf -rpi trio_asyncio tests`` -* Find semantic problems: ``flake8 setup.py trio_asyncio tests`` +* Find semantic problems: ``flake8 trio_asyncio tests`` To make a release diff --git a/Makefile b/Makefile index 9079954..66640d2 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ .PHONY: doc test update all tag pypi upload all: - @echo "Please use 'python setup.py'." + @echo "Please use 'pip install -e .'." @exit 1 # need to use python3 sphinx-build diff --git a/ci.sh b/ci.sh index ba194d6..2ae95ee 100755 --- a/ci.sh +++ b/ci.sh @@ -41,8 +41,8 @@ BLACK_VERSION=24.1.0 if [ "$CHECK_FORMATTING" = "1" ]; then pip install black==${BLACK_VERSION} - if ! black --check setup.py tests trio_asyncio; then - black --diff setup.py tests trio_asyncio + if ! black --check tests trio_asyncio; then + black --diff tests trio_asyncio cat < Date: Tue, 8 Jul 2025 23:47:57 -0500 Subject: [PATCH 03/12] Run black --- tests/test_trio_asyncio.py | 5 ++++- trio_asyncio/_base.py | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/test_trio_asyncio.py b/tests/test_trio_asyncio.py index dfbb7e5..4c8acdf 100644 --- a/tests/test_trio_asyncio.py +++ b/tests/test_trio_asyncio.py @@ -249,7 +249,10 @@ async def iterate_one(label, extra=""): with trio.move_on_after(loop_timeout) as scope: if loop_timeout == 0: scope.cancel() - async with trio_asyncio.open_loop() as loop, trio_asyncio.open_loop() as loop2: + async with ( + trio_asyncio.open_loop() as loop, + trio_asyncio.open_loop() as loop2, + ): assert sys.get_asyncgen_hooks() != before_hooks async with trio.open_nursery() as nursery: # Make sure the iterate_one aio tasks don't get diff --git a/trio_asyncio/_base.py b/trio_asyncio/_base.py index 1bd4ddb..f151081 100644 --- a/trio_asyncio/_base.py +++ b/trio_asyncio/_base.py @@ -432,7 +432,7 @@ async def _make_subprocess_transport( stderr, bufsize, extra=None, - **kwargs + **kwargs, ): """Make a subprocess transport. Asyncio context.""" @@ -448,7 +448,7 @@ async def _make_subprocess_transport( bufsize, waiter=waiter, extra=extra, - **kwargs + **kwargs, ) async def child_wait(transp): From 894d9a91478bba5b7ff44b09a7cdbb918f49e019 Mon Sep 17 00:00:00 2001 From: CoolCat467 <52022020+CoolCat467@users.noreply.github.com> Date: Tue, 8 Jul 2025 23:54:11 -0500 Subject: [PATCH 04/12] Update getting version --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 66640d2..e0aff90 100644 --- a/Makefile +++ b/Makefile @@ -43,7 +43,7 @@ test: tag: - @-git tag v$(shell python3 setup.py -V) + @-git tag v$(shell python3 -c "from trio_asyncio._version import __version__; print(__version__)") pypi: tag @if python3 setup.py -V 2>/dev/null | grep -qs + >/dev/null 2>&1 ; \ From 93260c513c6c48962d19015bc6360abbae87f485 Mon Sep 17 00:00:00 2001 From: CoolCat467 <52022020+CoolCat467@users.noreply.github.com> Date: Tue, 8 Jul 2025 23:56:51 -0500 Subject: [PATCH 05/12] More `setup.py` things --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index e0aff90..d417ffa 100644 --- a/Makefile +++ b/Makefile @@ -46,7 +46,7 @@ tag: @-git tag v$(shell python3 -c "from trio_asyncio._version import __version__; print(__version__)") pypi: tag - @if python3 setup.py -V 2>/dev/null | grep -qs + >/dev/null 2>&1 ; \ + @if python3 python3 -c "from trio_asyncio._version import __version__; print(__version__)" 2>/dev/null | grep -qs + >/dev/null 2>&1 ; \ then echo "You need a clean, tagged tree" >&2; exit 1 ; fi python3 setup.py sdist upload ## version depends on tag, so re-tagging doesn't make sense From 6d68050ede72d147a2ce51770a4792c1098ccaba Mon Sep 17 00:00:00 2001 From: CoolCat467 <52022020+CoolCat467@users.noreply.github.com> Date: Wed, 9 Jul 2025 00:01:57 -0500 Subject: [PATCH 06/12] Use uv for building and uploading instead of setup.py --- Makefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index d417ffa..cf8af7b 100644 --- a/Makefile +++ b/Makefile @@ -48,7 +48,9 @@ tag: pypi: tag @if python3 python3 -c "from trio_asyncio._version import __version__; print(__version__)" 2>/dev/null | grep -qs + >/dev/null 2>&1 ; \ then echo "You need a clean, tagged tree" >&2; exit 1 ; fi - python3 setup.py sdist upload + python3 -m pip install uv + uv build + uv publish ## version depends on tag, so re-tagging doesn't make sense upload: pypi From 6a1b30962deaccf42af79447ecdc6178c7a77ad6 Mon Sep 17 00:00:00 2001 From: CoolCat467 <52022020+CoolCat467@users.noreply.github.com> Date: Wed, 9 Jul 2025 00:02:23 -0500 Subject: [PATCH 07/12] Switch to `src`-based project layout --- src/trio_asyncio.egg-info/PKG-INFO | 133 ++++++++++++++++++ src/trio_asyncio.egg-info/SOURCES.txt | 58 ++++++++ .../dependency_links.txt | 1 + src/trio_asyncio.egg-info/requires.txt | 11 ++ src/trio_asyncio.egg-info/top_level.txt | 1 + .../trio_asyncio}/__init__.py | 0 .../trio_asyncio}/_adapter.py | 0 {trio_asyncio => src/trio_asyncio}/_async.py | 0 {trio_asyncio => src/trio_asyncio}/_base.py | 0 {trio_asyncio => src/trio_asyncio}/_child.py | 0 .../trio_asyncio}/_deprecate.py | 0 .../trio_asyncio}/_handles.py | 0 {trio_asyncio => src/trio_asyncio}/_loop.py | 0 {trio_asyncio => src/trio_asyncio}/_sync.py | 0 {trio_asyncio => src/trio_asyncio}/_util.py | 0 .../trio_asyncio}/_version.py | 0 16 files changed, 204 insertions(+) create mode 100644 src/trio_asyncio.egg-info/PKG-INFO create mode 100644 src/trio_asyncio.egg-info/SOURCES.txt create mode 100644 src/trio_asyncio.egg-info/dependency_links.txt create mode 100644 src/trio_asyncio.egg-info/requires.txt create mode 100644 src/trio_asyncio.egg-info/top_level.txt rename {trio_asyncio => src/trio_asyncio}/__init__.py (100%) rename {trio_asyncio => src/trio_asyncio}/_adapter.py (100%) rename {trio_asyncio => src/trio_asyncio}/_async.py (100%) rename {trio_asyncio => src/trio_asyncio}/_base.py (100%) rename {trio_asyncio => src/trio_asyncio}/_child.py (100%) rename {trio_asyncio => src/trio_asyncio}/_deprecate.py (100%) rename {trio_asyncio => src/trio_asyncio}/_handles.py (100%) rename {trio_asyncio => src/trio_asyncio}/_loop.py (100%) rename {trio_asyncio => src/trio_asyncio}/_sync.py (100%) rename {trio_asyncio => src/trio_asyncio}/_util.py (100%) rename {trio_asyncio => src/trio_asyncio}/_version.py (100%) diff --git a/src/trio_asyncio.egg-info/PKG-INFO b/src/trio_asyncio.egg-info/PKG-INFO new file mode 100644 index 0000000..14f1dbf --- /dev/null +++ b/src/trio_asyncio.egg-info/PKG-INFO @@ -0,0 +1,133 @@ +Metadata-Version: 2.4 +Name: trio_asyncio +Version: 0.15.0+dev +Summary: A re-implementation of the asyncio mainloop on top of Trio +Author-email: Matthias Urlichs +License-Expression: MIT OR Apache-2.0 +Project-URL: Homepage, https://github.com/python-trio/trio-asyncio +Project-URL: Documentation, http://trio-asyncio.readthedocs.io +Project-URL: Changelog, https://trio-asyncio.readthedocs.io/en/latest/history.html +Keywords: async,io,trio,asyncio,trio-asyncio +Classifier: Development Status :: 4 - Beta +Classifier: Intended Audience :: Developers +Classifier: Operating System :: POSIX :: Linux +Classifier: Operating System :: MacOS :: MacOS X +Classifier: Operating System :: POSIX :: BSD +Classifier: Operating System :: Microsoft :: Windows +Classifier: Programming Language :: Python :: Implementation :: CPython +Classifier: Programming Language :: Python :: Implementation :: PyPy +Classifier: Programming Language :: Python :: 3 :: Only +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: 3.11 +Classifier: Programming Language :: Python :: 3.12 +Classifier: Programming Language :: Python :: 3.13 +Classifier: Topic :: System :: Networking +Classifier: Framework :: Trio +Classifier: Framework :: AsyncIO +Requires-Python: >=3.9 +Description-Content-Type: text/x-rst +License-File: LICENSE +License-File: LICENSE.APACHE2 +License-File: LICENSE.MIT +Requires-Dist: trio>=0.22.0 +Requires-Dist: outcome +Requires-Dist: sniffio>=1.3.0 +Requires-Dist: exceptiongroup>=1.0.0; python_version < "3.11" +Requires-Dist: greenlet +Provides-Extra: tests +Requires-Dist: pytest>=5.4; extra == "tests" +Requires-Dist: pytest-trio>=0.6; extra == "tests" +Dynamic: license-file + +.. image:: https://img.shields.io/pypi/v/trio-asyncio.svg + :target: https://pypi.org/project/trio-asyncio + :alt: Latest PyPI version + +.. image:: https://img.shields.io/badge/chat-join%20now-blue.svg + :target: https://gitter.im/python-trio/general + :alt: Join chatroom + +.. image:: https://img.shields.io/badge/docs-read%20now-blue.svg + :target: https://trio-asyncio.readthedocs.io/en/latest/?badge=latest + :alt: Documentation status + +.. image:: https://github.com/python-trio/trio-asyncio/actions/workflows/ci.yml/badge.svg + :target: https://github.com/python-trio/trio-asyncio/actions/workflows/ci.yml + :alt: Automated test status + +.. image:: https://codecov.io/gh/python-trio/trio-asyncio/branch/master/graph/badge.svg + :target: https://codecov.io/gh/python-trio/trio-asyncio + :alt: Test coverage + + +============== + trio-asyncio +============== + +**trio-asyncio** is a re-implementation of the ``asyncio`` mainloop on top of +Trio. + +trio-asyncio requires at least Python 3.9. It is tested on recent versions of +3.9 through 3.13. + ++++++++++++ + Rationale ++++++++++++ + +Trio has native concepts of tasks and task cancellation. Asyncio is based +on callbacks and chaining Futures, albeit with nicer syntax, making +handling failures and timeouts fundamentally less reliable, especially in +larger programs. Thus, you *really* want to base your async project on Trio. + +On the other hand, there are quite a few asyncio-enhanced libraries. You +*really* don't want to re-invent any wheels in your project. + +Thus, being able to use asyncio libraries from Trio is useful. +trio-asyncio enables you to do that and more. + +-------------------------------------- + Transparent vs. explicit translation +-------------------------------------- + +``trio_asyncio`` does not try to magically allow calling ``await +trio_code()`` from asyncio or vice versa. There are multiple reasons for +this; the executive summary is that cross-domain calls can't be made to +work correctly, and any such call is likely to result in an irrecoverable +error. You need to keep your code's ``asyncio`` and ``trio`` domains +rigidly separate. + +Fortunately, this is not difficult. + ++++++++ + Usage ++++++++ + +Trio-Asyncio's documentation is too large for a README. + +For further information, `see the manual on readthedocs `_. + +++++++++++++++ + Contributing +++++++++++++++ + +Like Trio, trio-asyncio is licensed under both the MIT and Apache licenses. +Submitting a patch or pull request implies your acceptance of these licenses. + +Testing is done with ``pytest``. Test coverage is pretty thorough; please +keep it that way when adding new code. + +See the `Trio contributor guide +`__ for much +more detail on how to get involved. + +Contributors are requested to follow our `code of conduct +`__ in all +project spaces. + +++++++++ + Author +++++++++ + +Matthias Urlichs originally wrote trio-asyncio. +It is now maintained by the `Trio project `_. diff --git a/src/trio_asyncio.egg-info/SOURCES.txt b/src/trio_asyncio.egg-info/SOURCES.txt new file mode 100644 index 0000000..2ed6c19 --- /dev/null +++ b/src/trio_asyncio.egg-info/SOURCES.txt @@ -0,0 +1,58 @@ +.coveragerc +CODE_OF_CONDUCT.md +CONTRIBUTING.md +LICENSE +LICENSE.APACHE2 +LICENSE.MIT +MANIFEST.in +README.rst +pyproject.toml +docs/Makefile +docs/make.bat +docs/source/conf.py +docs/source/history.rst +docs/source/index.rst +docs/source/principles.rst +docs/source/usage.rst +docs/source/_static/.gitkeep +src/trio_asyncio/__init__.py +src/trio_asyncio/_adapter.py +src/trio_asyncio/_async.py +src/trio_asyncio/_base.py +src/trio_asyncio/_child.py +src/trio_asyncio/_deprecate.py +src/trio_asyncio/_handles.py +src/trio_asyncio/_loop.py +src/trio_asyncio/_sync.py +src/trio_asyncio/_util.py +src/trio_asyncio/_version.py +src/trio_asyncio.egg-info/PKG-INFO +src/trio_asyncio.egg-info/SOURCES.txt +src/trio_asyncio.egg-info/dependency_links.txt +src/trio_asyncio.egg-info/requires.txt +src/trio_asyncio.egg-info/top_level.txt +tests/__init__.py +tests/conftest.py +tests/module_with_deprecations.py +tests/test_aio_subprocess.py +tests/test_concurrent.py +tests/test_deprecate.py +tests/test_misc.py +tests/test_sync.py +tests/test_trio_asyncio.py +tests/utils.py +tests/aiotest/__init__.py +tests/aiotest/conftest.py +tests/aiotest/test_add_reader.py +tests/aiotest/test_callback.py +tests/aiotest/test_coroutine.py +tests/aiotest/test_network.py +tests/aiotest/test_thread.py +tests/aiotest/test_timer.py +tests/interop/__init__.py +tests/interop/test_adapter.py +tests/interop/test_calls.py +tests/python/__init__.py +tests/scripts/echo.py +tests/scripts/echo2.py +tests/scripts/echo3.py \ No newline at end of file diff --git a/src/trio_asyncio.egg-info/dependency_links.txt b/src/trio_asyncio.egg-info/dependency_links.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/trio_asyncio.egg-info/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/src/trio_asyncio.egg-info/requires.txt b/src/trio_asyncio.egg-info/requires.txt new file mode 100644 index 0000000..59f404f --- /dev/null +++ b/src/trio_asyncio.egg-info/requires.txt @@ -0,0 +1,11 @@ +trio>=0.22.0 +outcome +sniffio>=1.3.0 +greenlet + +[:python_version < "3.11"] +exceptiongroup>=1.0.0 + +[tests] +pytest>=5.4 +pytest-trio>=0.6 diff --git a/src/trio_asyncio.egg-info/top_level.txt b/src/trio_asyncio.egg-info/top_level.txt new file mode 100644 index 0000000..771ea6c --- /dev/null +++ b/src/trio_asyncio.egg-info/top_level.txt @@ -0,0 +1 @@ +trio_asyncio diff --git a/trio_asyncio/__init__.py b/src/trio_asyncio/__init__.py similarity index 100% rename from trio_asyncio/__init__.py rename to src/trio_asyncio/__init__.py diff --git a/trio_asyncio/_adapter.py b/src/trio_asyncio/_adapter.py similarity index 100% rename from trio_asyncio/_adapter.py rename to src/trio_asyncio/_adapter.py diff --git a/trio_asyncio/_async.py b/src/trio_asyncio/_async.py similarity index 100% rename from trio_asyncio/_async.py rename to src/trio_asyncio/_async.py diff --git a/trio_asyncio/_base.py b/src/trio_asyncio/_base.py similarity index 100% rename from trio_asyncio/_base.py rename to src/trio_asyncio/_base.py diff --git a/trio_asyncio/_child.py b/src/trio_asyncio/_child.py similarity index 100% rename from trio_asyncio/_child.py rename to src/trio_asyncio/_child.py diff --git a/trio_asyncio/_deprecate.py b/src/trio_asyncio/_deprecate.py similarity index 100% rename from trio_asyncio/_deprecate.py rename to src/trio_asyncio/_deprecate.py diff --git a/trio_asyncio/_handles.py b/src/trio_asyncio/_handles.py similarity index 100% rename from trio_asyncio/_handles.py rename to src/trio_asyncio/_handles.py diff --git a/trio_asyncio/_loop.py b/src/trio_asyncio/_loop.py similarity index 100% rename from trio_asyncio/_loop.py rename to src/trio_asyncio/_loop.py diff --git a/trio_asyncio/_sync.py b/src/trio_asyncio/_sync.py similarity index 100% rename from trio_asyncio/_sync.py rename to src/trio_asyncio/_sync.py diff --git a/trio_asyncio/_util.py b/src/trio_asyncio/_util.py similarity index 100% rename from trio_asyncio/_util.py rename to src/trio_asyncio/_util.py diff --git a/trio_asyncio/_version.py b/src/trio_asyncio/_version.py similarity index 100% rename from trio_asyncio/_version.py rename to src/trio_asyncio/_version.py From 4ff7ca6a30ca396fef3d4ccde1e0ef3373ce89f8 Mon Sep 17 00:00:00 2001 From: CoolCat467 <52022020+CoolCat467@users.noreply.github.com> Date: Wed, 9 Jul 2025 00:06:45 -0500 Subject: [PATCH 08/12] Update paths --- ci.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ci.sh b/ci.sh index 2ae95ee..5587fd0 100755 --- a/ci.sh +++ b/ci.sh @@ -41,8 +41,8 @@ BLACK_VERSION=24.1.0 if [ "$CHECK_FORMATTING" = "1" ]; then pip install black==${BLACK_VERSION} - if ! black --check tests trio_asyncio; then - black --diff tests trio_asyncio + if ! black --check tests src; then + black --diff tests src cat < Date: Wed, 9 Jul 2025 00:13:05 -0500 Subject: [PATCH 09/12] Hopefully fix readthedocs --- docs/source/conf.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index f400d4b..b43636f 100755 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -94,8 +94,9 @@ # built documents. # # The short X.Y version. -import trio_asyncio -version = trio_asyncio.__version__ +import importlib.metadata + +version = importlib.metadata.version("trio_asyncio") # The full version, including alpha/beta/rc tags. release = version From ce1a757b7bca0d0a5308e1e7c3c9ec48b9208495 Mon Sep 17 00:00:00 2001 From: CoolCat467 <52022020+CoolCat467@users.noreply.github.com> Date: Wed, 9 Jul 2025 00:17:21 -0500 Subject: [PATCH 10/12] Update `.gitignore` --- .eggs/README.txt | 6 + .gitignore | 80 +++++++++-- src/trio_asyncio.egg-info/PKG-INFO | 133 ------------------ src/trio_asyncio.egg-info/SOURCES.txt | 58 -------- .../dependency_links.txt | 1 - src/trio_asyncio.egg-info/requires.txt | 11 -- src/trio_asyncio.egg-info/top_level.txt | 1 - 7 files changed, 75 insertions(+), 215 deletions(-) create mode 100644 .eggs/README.txt delete mode 100644 src/trio_asyncio.egg-info/PKG-INFO delete mode 100644 src/trio_asyncio.egg-info/SOURCES.txt delete mode 100644 src/trio_asyncio.egg-info/dependency_links.txt delete mode 100644 src/trio_asyncio.egg-info/requires.txt delete mode 100644 src/trio_asyncio.egg-info/top_level.txt diff --git a/.eggs/README.txt b/.eggs/README.txt new file mode 100644 index 0000000..5d01668 --- /dev/null +++ b/.eggs/README.txt @@ -0,0 +1,6 @@ +This directory contains eggs that were downloaded by setuptools to build, test, and run plug-ins. + +This directory caches those eggs to prevent repeated downloads. + +However, it is safe to delete this directory. + diff --git a/.gitignore b/.gitignore index 1d465a2..d9db2f1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,14 +1,72 @@ +# Project-specific generated files +docs/build/ + +/empty + +# Byte-compiled / optimized / DLL files / editor temp files +__pycache__/ +*.py[cod] +*~ +\#* +.#* *.swp -/.pytest_cache/ -/.coverage -/.cache/ -/.eggs/ -/.pybuild/ +# C extensions +*.so + +# Distribution / packaging +.Python /build/ -/docs/build/ -__pycache__/ -/trio_asyncio.egg-info/ -/.pybuild/ -/dist -/empty +/develop-eggs/ +/dist/ +/eggs/ +/lib/ +/lib64/ +/parts/ +/sdist/ +/var/ +*.egg-info/ +.installed.cfg +*.egg +/.pybuild +pip-wheel-metadata/ + +# Installer logs +pip-log.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.venv/ +pyvenv.cfg +.coverage +.coverage.* +.cache +.pytest_cache/ +.mypy_cache/ +nosetests.xml +coverage.xml + +# Temp file during Mypy processing +mypy_annotate.dat + +# Translations +*.mo + +# Mr Developer +.mr.developer.cfg +.project +.pydevproject + +# Rope +.ropeproject + +# Django stuff: +*.log +*.pot + +# Sphinx documentation +doc/_build/ + +# PyCharm +.idea/ diff --git a/src/trio_asyncio.egg-info/PKG-INFO b/src/trio_asyncio.egg-info/PKG-INFO deleted file mode 100644 index 14f1dbf..0000000 --- a/src/trio_asyncio.egg-info/PKG-INFO +++ /dev/null @@ -1,133 +0,0 @@ -Metadata-Version: 2.4 -Name: trio_asyncio -Version: 0.15.0+dev -Summary: A re-implementation of the asyncio mainloop on top of Trio -Author-email: Matthias Urlichs -License-Expression: MIT OR Apache-2.0 -Project-URL: Homepage, https://github.com/python-trio/trio-asyncio -Project-URL: Documentation, http://trio-asyncio.readthedocs.io -Project-URL: Changelog, https://trio-asyncio.readthedocs.io/en/latest/history.html -Keywords: async,io,trio,asyncio,trio-asyncio -Classifier: Development Status :: 4 - Beta -Classifier: Intended Audience :: Developers -Classifier: Operating System :: POSIX :: Linux -Classifier: Operating System :: MacOS :: MacOS X -Classifier: Operating System :: POSIX :: BSD -Classifier: Operating System :: Microsoft :: Windows -Classifier: Programming Language :: Python :: Implementation :: CPython -Classifier: Programming Language :: Python :: Implementation :: PyPy -Classifier: Programming Language :: Python :: 3 :: Only -Classifier: Programming Language :: Python :: 3.9 -Classifier: Programming Language :: Python :: 3.10 -Classifier: Programming Language :: Python :: 3.11 -Classifier: Programming Language :: Python :: 3.12 -Classifier: Programming Language :: Python :: 3.13 -Classifier: Topic :: System :: Networking -Classifier: Framework :: Trio -Classifier: Framework :: AsyncIO -Requires-Python: >=3.9 -Description-Content-Type: text/x-rst -License-File: LICENSE -License-File: LICENSE.APACHE2 -License-File: LICENSE.MIT -Requires-Dist: trio>=0.22.0 -Requires-Dist: outcome -Requires-Dist: sniffio>=1.3.0 -Requires-Dist: exceptiongroup>=1.0.0; python_version < "3.11" -Requires-Dist: greenlet -Provides-Extra: tests -Requires-Dist: pytest>=5.4; extra == "tests" -Requires-Dist: pytest-trio>=0.6; extra == "tests" -Dynamic: license-file - -.. image:: https://img.shields.io/pypi/v/trio-asyncio.svg - :target: https://pypi.org/project/trio-asyncio - :alt: Latest PyPI version - -.. image:: https://img.shields.io/badge/chat-join%20now-blue.svg - :target: https://gitter.im/python-trio/general - :alt: Join chatroom - -.. image:: https://img.shields.io/badge/docs-read%20now-blue.svg - :target: https://trio-asyncio.readthedocs.io/en/latest/?badge=latest - :alt: Documentation status - -.. image:: https://github.com/python-trio/trio-asyncio/actions/workflows/ci.yml/badge.svg - :target: https://github.com/python-trio/trio-asyncio/actions/workflows/ci.yml - :alt: Automated test status - -.. image:: https://codecov.io/gh/python-trio/trio-asyncio/branch/master/graph/badge.svg - :target: https://codecov.io/gh/python-trio/trio-asyncio - :alt: Test coverage - - -============== - trio-asyncio -============== - -**trio-asyncio** is a re-implementation of the ``asyncio`` mainloop on top of -Trio. - -trio-asyncio requires at least Python 3.9. It is tested on recent versions of -3.9 through 3.13. - -+++++++++++ - Rationale -+++++++++++ - -Trio has native concepts of tasks and task cancellation. Asyncio is based -on callbacks and chaining Futures, albeit with nicer syntax, making -handling failures and timeouts fundamentally less reliable, especially in -larger programs. Thus, you *really* want to base your async project on Trio. - -On the other hand, there are quite a few asyncio-enhanced libraries. You -*really* don't want to re-invent any wheels in your project. - -Thus, being able to use asyncio libraries from Trio is useful. -trio-asyncio enables you to do that and more. - --------------------------------------- - Transparent vs. explicit translation --------------------------------------- - -``trio_asyncio`` does not try to magically allow calling ``await -trio_code()`` from asyncio or vice versa. There are multiple reasons for -this; the executive summary is that cross-domain calls can't be made to -work correctly, and any such call is likely to result in an irrecoverable -error. You need to keep your code's ``asyncio`` and ``trio`` domains -rigidly separate. - -Fortunately, this is not difficult. - -+++++++ - Usage -+++++++ - -Trio-Asyncio's documentation is too large for a README. - -For further information, `see the manual on readthedocs `_. - -++++++++++++++ - Contributing -++++++++++++++ - -Like Trio, trio-asyncio is licensed under both the MIT and Apache licenses. -Submitting a patch or pull request implies your acceptance of these licenses. - -Testing is done with ``pytest``. Test coverage is pretty thorough; please -keep it that way when adding new code. - -See the `Trio contributor guide -`__ for much -more detail on how to get involved. - -Contributors are requested to follow our `code of conduct -`__ in all -project spaces. - -++++++++ - Author -++++++++ - -Matthias Urlichs originally wrote trio-asyncio. -It is now maintained by the `Trio project `_. diff --git a/src/trio_asyncio.egg-info/SOURCES.txt b/src/trio_asyncio.egg-info/SOURCES.txt deleted file mode 100644 index 2ed6c19..0000000 --- a/src/trio_asyncio.egg-info/SOURCES.txt +++ /dev/null @@ -1,58 +0,0 @@ -.coveragerc -CODE_OF_CONDUCT.md -CONTRIBUTING.md -LICENSE -LICENSE.APACHE2 -LICENSE.MIT -MANIFEST.in -README.rst -pyproject.toml -docs/Makefile -docs/make.bat -docs/source/conf.py -docs/source/history.rst -docs/source/index.rst -docs/source/principles.rst -docs/source/usage.rst -docs/source/_static/.gitkeep -src/trio_asyncio/__init__.py -src/trio_asyncio/_adapter.py -src/trio_asyncio/_async.py -src/trio_asyncio/_base.py -src/trio_asyncio/_child.py -src/trio_asyncio/_deprecate.py -src/trio_asyncio/_handles.py -src/trio_asyncio/_loop.py -src/trio_asyncio/_sync.py -src/trio_asyncio/_util.py -src/trio_asyncio/_version.py -src/trio_asyncio.egg-info/PKG-INFO -src/trio_asyncio.egg-info/SOURCES.txt -src/trio_asyncio.egg-info/dependency_links.txt -src/trio_asyncio.egg-info/requires.txt -src/trio_asyncio.egg-info/top_level.txt -tests/__init__.py -tests/conftest.py -tests/module_with_deprecations.py -tests/test_aio_subprocess.py -tests/test_concurrent.py -tests/test_deprecate.py -tests/test_misc.py -tests/test_sync.py -tests/test_trio_asyncio.py -tests/utils.py -tests/aiotest/__init__.py -tests/aiotest/conftest.py -tests/aiotest/test_add_reader.py -tests/aiotest/test_callback.py -tests/aiotest/test_coroutine.py -tests/aiotest/test_network.py -tests/aiotest/test_thread.py -tests/aiotest/test_timer.py -tests/interop/__init__.py -tests/interop/test_adapter.py -tests/interop/test_calls.py -tests/python/__init__.py -tests/scripts/echo.py -tests/scripts/echo2.py -tests/scripts/echo3.py \ No newline at end of file diff --git a/src/trio_asyncio.egg-info/dependency_links.txt b/src/trio_asyncio.egg-info/dependency_links.txt deleted file mode 100644 index 8b13789..0000000 --- a/src/trio_asyncio.egg-info/dependency_links.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/trio_asyncio.egg-info/requires.txt b/src/trio_asyncio.egg-info/requires.txt deleted file mode 100644 index 59f404f..0000000 --- a/src/trio_asyncio.egg-info/requires.txt +++ /dev/null @@ -1,11 +0,0 @@ -trio>=0.22.0 -outcome -sniffio>=1.3.0 -greenlet - -[:python_version < "3.11"] -exceptiongroup>=1.0.0 - -[tests] -pytest>=5.4 -pytest-trio>=0.6 diff --git a/src/trio_asyncio.egg-info/top_level.txt b/src/trio_asyncio.egg-info/top_level.txt deleted file mode 100644 index 771ea6c..0000000 --- a/src/trio_asyncio.egg-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -trio_asyncio From b3b49050031ddd98d890ab0a229cab74e6a9061d Mon Sep 17 00:00:00 2001 From: CoolCat467 <52022020+CoolCat467@users.noreply.github.com> Date: Wed, 9 Jul 2025 00:22:42 -0500 Subject: [PATCH 11/12] Fix `.gitignore` --- .eggs/README.txt | 6 --- .gitignore | 126 ++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 102 insertions(+), 30 deletions(-) delete mode 100644 .eggs/README.txt diff --git a/.eggs/README.txt b/.eggs/README.txt deleted file mode 100644 index 5d01668..0000000 --- a/.eggs/README.txt +++ /dev/null @@ -1,6 +0,0 @@ -This directory contains eggs that were downloaded by setuptools to build, test, and run plug-ins. - -This directory caches those eggs to prevent repeated downloads. - -However, it is safe to delete this directory. - diff --git a/.gitignore b/.gitignore index d9db2f1..0a2761c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,11 +1,18 @@ # Project-specific generated files docs/build/ +# Temp file during Mypy processing +mypy_annotate.dat + /empty +# MacOS files +**/.DS_Store + # Byte-compiled / optimized / DLL files / editor temp files __pycache__/ *.py[cod] +*$py.class *~ \#* .#* @@ -16,54 +23,125 @@ __pycache__/ # Distribution / packaging .Python -/build/ -/develop-eggs/ -/dist/ -/eggs/ -/lib/ -/lib64/ -/parts/ -/sdist/ -/var/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +pip-wheel-metadata/ +share/python-wheels/ *.egg-info/ .installed.cfg *.egg -/.pybuild pip-wheel-metadata/ # Installer logs pip-log.txt +pip-delete-this-directory.txt # Unit test / coverage reports htmlcov/ .tox/ -.venv/ pyvenv.cfg +.venv/ +.nox/ .coverage .coverage.* .cache -.pytest_cache/ -.mypy_cache/ nosetests.xml coverage.xml - -# Temp file during Mypy processing -mypy_annotate.dat +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +.mypy_cache/ # Translations *.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache -# Mr Developer -.mr.developer.cfg -.project -.pydevproject +# Scrapy stuff: +.scrapy -# Rope +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +.python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings .ropeproject -# Django stuff: -*.log -*.pot +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# Ruff +.ruff_cache # Sphinx documentation doc/_build/ From c2c3afb810d684b4d681c1917f58f5852efcfcce Mon Sep 17 00:00:00 2001 From: CoolCat467 <52022020+CoolCat467@users.noreply.github.com> Date: Wed, 9 Jul 2025 00:34:39 -0500 Subject: [PATCH 12/12] More things to match Trio's readthedocs --- docs/source/conf.py | 72 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 65 insertions(+), 7 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index b43636f..b2afd10 100755 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -17,22 +17,80 @@ # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. # +from __future__ import annotations + +import glob import os import sys +from pathlib import Path +from typing import TYPE_CHECKING, cast + +if TYPE_CHECKING: + from sphinx.application import Sphinx + from sphinx.util.typing import Inventory + # So autodoc can import our package sys.path.insert(0, os.path.abspath('../..')) -# https://docs.readthedocs.io/en/stable/builds.html#build-environment -if "READTHEDOCS" in os.environ: - import glob - if glob.glob("../../newsfragments/*.*.rst"): - print("-- Found newsfragments; running towncrier --", flush=True) - import subprocess +# Enable reloading with `typing.TYPE_CHECKING` being True +os.environ["SPHINX_AUTODOC_RELOAD_MODULES"] = "1" + +# Handle writing newsfragments into the history file. +# We want to keep files unchanged when testing locally. +# So immediately revert the contents after running towncrier, +# then substitute when Sphinx wants to read it in. +history_file = Path("history.rst") + +history_new: str | None +if glob.glob("../../newsfragments/*.*.rst"): + print("-- Found newsfragments; running towncrier --", flush=True) + history_orig = history_file.read_bytes() + import subprocess + + # In case changes were staged, preserve indexed version. + # This grabs the hash of the current staged version. + history_staged = subprocess.run( + ["git", "rev-parse", "--verify", ":docs/source/history.rst"], + check=True, + cwd="../..", + stdout=subprocess.PIPE, + encoding="ascii", + ).stdout.strip() + try: subprocess.run( - ["towncrier", "--yes", "--date", "not released yet"], + ["towncrier", "--keep", "--date", "not released yet"], cwd="../..", check=True, ) + history_new = history_file.read_text("utf8") + finally: + # Make sure this reverts even if a failure occurred. + # Restore whatever was staged. + print(f"Restoring history.rst = {history_staged}") + subprocess.run( + [ + "git", + "update-index", + "--cacheinfo", + f"100644,{history_staged},docs/source/history.rst", + ], + cwd="../..", + check=False, + ) + # And restore the working copy. + history_file.write_bytes(history_orig) + del history_orig # We don't need this any more. +else: + # Leave it as is. + history_new = None + + +def on_read_source(app: Sphinx, docname: str, content: list[str]) -> None: + """Substitute the modified history file.""" + if docname == "history" and history_new is not None: + # This is a 1-item list with the file contents. + content[0] = history_new + # Warn about all references to unknown targets nitpicky = True