Showing preview only (810K chars total). Download the full file or copy to clipboard to get everything.
Repository: MagicStack/uvloop
Branch: master
Commit: a308f75ff8f1
Files: 110
Total size: 774.9 KB
Directory structure:
gitextract_3ml8fczj/
├── .editorconfig
├── .flake8
├── .github/
│ ├── ISSUE_TEMPLATE.md
│ ├── release_log.py
│ └── workflows/
│ ├── release.yml
│ └── tests.yml
├── .gitignore
├── .gitmodules
├── LICENSE-APACHE
├── LICENSE-MIT
├── MANIFEST.in
├── Makefile
├── README.rst
├── docs/
│ ├── .gitignore
│ ├── api/
│ │ └── index.rst
│ ├── conf.py
│ ├── dev/
│ │ └── index.rst
│ ├── index.rst
│ └── user/
│ └── index.rst
├── examples/
│ └── bench/
│ ├── echoclient.py
│ ├── echoserver.py
│ └── rlserver.py
├── mypy.ini
├── pyproject.toml
├── setup.py
├── tests/
│ ├── __init__.py
│ ├── __main__.py
│ ├── certs/
│ │ ├── ssl_cert.pem
│ │ └── ssl_key.pem
│ ├── test_aiohttp.py
│ ├── test_base.py
│ ├── test_context.py
│ ├── test_cython.py
│ ├── test_dealloc.py
│ ├── test_dns.py
│ ├── test_executors.py
│ ├── test_fs_event.py
│ ├── test_libuv_api.py
│ ├── test_pipes.py
│ ├── test_process.py
│ ├── test_process_spawning.py
│ ├── test_regr1.py
│ ├── test_runner.py
│ ├── test_signals.py
│ ├── test_sockets.py
│ ├── test_sourcecode.py
│ ├── test_tcp.py
│ ├── test_testbase.py
│ ├── test_udp.py
│ └── test_unix.py
└── uvloop/
├── .gitignore
├── __init__.py
├── _noop.py
├── _testbase.py
├── _version.py
├── cbhandles.pxd
├── cbhandles.pyx
├── dns.pyx
├── errors.pyx
├── handles/
│ ├── async_.pxd
│ ├── async_.pyx
│ ├── basetransport.pxd
│ ├── basetransport.pyx
│ ├── check.pxd
│ ├── check.pyx
│ ├── fsevent.pxd
│ ├── fsevent.pyx
│ ├── handle.pxd
│ ├── handle.pyx
│ ├── idle.pxd
│ ├── idle.pyx
│ ├── pipe.pxd
│ ├── pipe.pyx
│ ├── poll.pxd
│ ├── poll.pyx
│ ├── process.pxd
│ ├── process.pyx
│ ├── stream.pxd
│ ├── stream.pyx
│ ├── streamserver.pxd
│ ├── streamserver.pyx
│ ├── tcp.pxd
│ ├── tcp.pyx
│ ├── timer.pxd
│ ├── timer.pyx
│ ├── udp.pxd
│ └── udp.pyx
├── includes/
│ ├── __init__.py
│ ├── compat.h
│ ├── consts.pxi
│ ├── debug.h
│ ├── debug.pxd
│ ├── flowcontrol.pxd
│ ├── fork_handler.h
│ ├── python.pxd
│ ├── stdlib.pxi
│ ├── system.pxd
│ └── uv.pxd
├── loop.pxd
├── loop.pyi
├── loop.pyx
├── lru.pyx
├── pseudosock.pyx
├── py.typed
├── request.pxd
├── request.pyx
├── server.pxd
├── server.pyx
├── sslproto.pxd
└── sslproto.pyx
================================================
FILE CONTENTS
================================================
================================================
FILE: .editorconfig
================================================
root = true
[*]
trim_trailing_whitespace = true
insert_final_newline = true
[Makefile]
indent_style = tab
[*.{py,pyx,pxd,pxi,yml,h}]
indent_size = 4
indent_style = space
================================================
FILE: .flake8
================================================
[flake8]
filename = *.py,*.pyi
ignore = E402,E731,D100,D101,D102,D103,D104,D105,W503,W504,E252
exclude = .git,__pycache__,build,dist,.eggs,postgres,vendor
per-file-ignores =
*.pyx,*.pxd,*.pxi: E211, E222, E225, E226, E227, E999
*.pyi: F401, F403, F405, F811, E127, E128, E203, E266, E301, E302, E305, E501, E701, E704, E741, B303, W503, W504
================================================
FILE: .github/ISSUE_TEMPLATE.md
================================================
<!--
Thanks for wanting to report an issue you've found in uvloop. Please fill in
the template below.
It will be much easier for us to fix the issue if a test case that reproduces
the problem is provided, with clear instructions on how to run it.
Thank you!
-->
* **uvloop version**:
* **Python version**:
* **Platform**:
* **Can you reproduce the bug with `PYTHONASYNCIODEBUG` in env?**:
* **Does uvloop behave differently from vanilla asyncio? How?**:
<!-- Enter your issue details below this comment. -->
================================================
FILE: .github/release_log.py
================================================
#!/usr/bin/env python3
import argparse
import json
import requests
import re
BASE_URL = 'https://api.github.com/repos/magicstack/uvloop/compare'
def main():
parser = argparse.ArgumentParser(
description='Generate release log.')
parser.add_argument('--to', dest='to_hash', default='master', type=str)
parser.add_argument('--from', dest='from_hash', type=str)
args = parser.parse_args()
r = requests.get(f'{BASE_URL}/{args.from_hash}...{args.to_hash}')
data = json.loads(r.text)
for commit in data['commits']:
message = commit['commit']['message']
first_line = message.partition('\n\n')[0]
if commit.get('author'):
username = '@{}'.format(commit['author']['login'])
else:
username = commit['commit']['author']['name']
sha = commit["sha"][:8]
m = re.search(r'\#(?P<num>\d+)\b', message)
if m:
issue_num = m.group('num')
else:
issue_num = None
print(f'* {first_line}')
print(f' (by {username} in {sha}', end='')
if issue_num:
print(f' for #{issue_num})')
else:
print(')')
print()
if __name__ == '__main__':
main()
================================================
FILE: .github/workflows/release.yml
================================================
name: Release
on:
pull_request:
branches:
- "master"
- "ci"
- "[0-9]+.[0-9x]+*"
paths:
- "uvloop/_version.py"
jobs:
validate-release-request:
runs-on: ubuntu-latest
steps:
- name: Validate release PR
uses: edgedb/action-release/validate-pr@bae6b9134e872166b43d218dd79397c851c41c9a
id: checkver
with:
require_team: Release Managers
require_approval: no
github_token: ${{ secrets.RELEASE_BOT_GITHUB_TOKEN }}
version_file: uvloop/_version.py
version_line_pattern: |
__version__\s*=\s*(?:['"])([[:PEP440:]])(?:['"])
- name: Stop if not approved
if: steps.checkver.outputs.approved != 'true'
run: |
echo ::error::PR is not approved yet.
exit 1
- name: Store release version for later use
env:
VERSION: ${{ steps.checkver.outputs.version }}
run: |
mkdir -p dist/
echo "${VERSION}" > dist/VERSION
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: dist-version
path: dist/
build-sdist:
needs: validate-release-request
runs-on: ubuntu-22.04
env:
PIP_DISABLE_PIP_VERSION_CHECK: 1
steps:
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
with:
fetch-depth: 50
submodules: true
- uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0
with:
python-version: 3.x
- name: Build source distribution
run: |
python -m pip install --upgrade setuptools wheel pip
python setup.py sdist
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: dist-sdist
path: dist/*.tar.*
build-wheels:
needs: validate-release-request
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, ubuntu-22.04-arm]
python:
- "cp38"
- "cp39"
- "cp310"
- "cp311"
- "cp312"
- "cp313"
- "cp314"
- "cp314t"
cibw_arch: ["x86_64", "aarch64", "universal2"]
exclude:
- os: ubuntu-latest
cibw_arch: universal2
- os: ubuntu-latest
cibw_arch: aarch64
- os: macos-latest
cibw_arch: aarch64
- os: ubuntu-22.04-arm
cibw_arch: x86_64
- os: ubuntu-22.04-arm
cibw_arch: universal2
defaults:
run:
shell: bash
env:
PIP_DISABLE_PIP_VERSION_CHECK: 1
steps:
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
with:
fetch-depth: 50
submodules: true
- name: Install macOS deps
if: startsWith(matrix.os, 'macos')
run: |
brew install gnu-sed libtool autoconf automake
- uses: pypa/cibuildwheel@7c619efba910c04005a835b110b057fc28fd6e93 # v3.2.0
env:
CIBW_BUILD_VERBOSITY: 1
CIBW_BUILD: ${{ matrix.python }}-*
CIBW_ARCHS: ${{ matrix.cibw_arch }}
CIBW_TEST_SKIP: "*universal2:arm64"
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: dist-wheels-${{ matrix.os }}-${{ matrix.python }}-${{ matrix.cibw_arch }}
path: wheelhouse/*.whl
publish:
needs: [build-sdist, build-wheels]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
with:
fetch-depth: 5
submodules: false
- uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
with:
pattern: dist-*
merge-multiple: true
path: dist/
- name: Extract Release Version
id: relver
run: |
set -e
echo version=$(cat dist/VERSION) >> $GITHUB_OUTPUT
rm dist/VERSION
- name: Merge and tag the PR
uses: edgedb/action-release/merge@bae6b9134e872166b43d218dd79397c851c41c9a
with:
github_token: ${{ secrets.RELEASE_BOT_GITHUB_TOKEN }}
ssh_key: ${{ secrets.RELEASE_BOT_SSH_KEY }}
gpg_key: ${{ secrets.RELEASE_BOT_GPG_KEY }}
gpg_key_id: "5C468778062D87BF!"
tag_name: v${{ steps.relver.outputs.version }}
- name: Publish Github Release
uses: elprans/gh-action-create-release@master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: v${{ steps.relver.outputs.version }}
release_name: v${{ steps.relver.outputs.version }}
target: ${{ github.event.pull_request.base.ref }}
body: ${{ github.event.pull_request.body }}
draft: false
- run: |
ls -al dist/
- name: Upload to PyPI
uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0
with:
user: __token__
password: ${{ secrets.PYPI_TOKEN }}
# password: ${{ secrets.TEST_PYPI_TOKEN }}
# repository_url: https://test.pypi.org/legacy/
================================================
FILE: .github/workflows/tests.yml
================================================
name: Tests
on:
push:
branches:
- master
- ci
pull_request:
branches:
- master
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
python-version:
- "3.8"
- "3.9"
- "3.10"
- "3.11"
- "3.12"
- "3.13"
- "3.14"
- "3.14t"
os: [ubuntu-latest, macos-latest]
env:
PIP_DISABLE_PIP_VERSION_CHECK: 1
steps:
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
with:
fetch-depth: 50
submodules: true
- name: Check if release PR.
uses: edgedb/action-release/validate-pr@bae6b9134e872166b43d218dd79397c851c41c9a
id: release
with:
github_token: ${{ secrets.RELEASE_BOT_GITHUB_TOKEN }}
missing_version_ok: yes
version_file: uvloop/_version.py
version_line_pattern: |
__version__\s*=\s*(?:['"])([[:PEP440:]])(?:['"])
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0
if: steps.release.outputs.version == 0
with:
python-version: ${{ matrix.python-version }}
allow-prereleases: true
- name: Install macOS deps
if: matrix.os == 'macos-latest' && steps.release.outputs.version == 0
run: |
brew install gnu-sed libtool autoconf automake
- name: Install Python Deps
if: steps.release.outputs.version == 0
run: |
pip install -e .[test,dev]
- name: Test
if: steps.release.outputs.version == 0
run: |
make test
- name: Test (debug build)
if: steps.release.outputs.version == 0
run: |
make distclean && make debug && make test
# This job exists solely to act as the test job aggregate to be
# targeted by branch policies.
regression-tests:
name: "Regression Tests"
needs: [test]
runs-on: ubuntu-latest
steps:
- run: echo OK
================================================
FILE: .gitignore
================================================
*._*
*.pyc
*.pyo
*.ymlc
*.ymlc~
*.scssc
*.so
*~
.#*
.DS_Store
.project
.pydevproject
.settings
.idea
/.ropeproject
\#*#
/pub
/test*.py
/.local
/perf.data*
/config_local.yml
/build
__pycache__/
.d8_history
/*.egg
/*.egg-info
/dist
/.cache
docs/_build
uvloop/loop.*.pyd
/.pytest_cache/
/.mypy_cache/
/.vscode
/.eggs
/.venv*
/wheelhouse
/uvloop-dev
================================================
FILE: .gitmodules
================================================
[submodule "vendor/libuv"]
path = vendor/libuv
url = https://github.com/libuv/libuv.git
================================================
FILE: LICENSE-APACHE
================================================
Copyright (C) 2016-present the uvloop authors and contributors.
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright (c) 2015-present MagicStack Inc. http://magic.io
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
================================================
FILE: LICENSE-MIT
================================================
The MIT License
Copyright (C) 2016-present the uvloop authors and contributors.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
================================================
FILE: MANIFEST.in
================================================
recursive-include docs *.py *.rst
recursive-include examples *.py
recursive-include tests *.py *.pem
recursive-include uvloop *.pyx *.pxd *.pxi *.py *.c *.h *.pyi py.typed
recursive-include vendor/libuv *
recursive-exclude vendor/libuv/.git *
recursive-exclude vendor/libuv/docs *
recursive-exclude vendor/libuv/img *
include LICENSE-MIT LICENSE-APACHE README.rst Makefile performance.png .flake8 mypy.ini
================================================
FILE: Makefile
================================================
.PHONY: _default clean clean-libuv distclean compile debug docs test testinstalled release setup-build ci-clean
PYTHON ?= python
ROOT = $(dir $(realpath $(firstword $(MAKEFILE_LIST))))
_default: compile
clean:
rm -fr dist/ doc/_build/ *.egg-info uvloop/loop.*.pyd uvloop/loop_d.*.pyd
rm -fr uvloop/*.c uvloop/*.html uvloop/*.so
rm -fr uvloop/handles/*.html uvloop/includes/*.html
find . -name '__pycache__' | xargs rm -rf
ci-clean: clean
rm -fr build/lib.* build/temp.* build/libuv
clean-libuv:
(cd vendor/libuv; git clean -dfX)
distclean: clean clean-libuv
rm -fr build/
setup-build:
$(PYTHON) setup.py build_ext --inplace --cython-always
compile: clean setup-build
debug: clean
$(PYTHON) setup.py build_ext --inplace --debug \
--cython-always \
--cython-annotate \
--cython-directives="linetrace=True" \
--define UVLOOP_DEBUG,CYTHON_TRACE,CYTHON_TRACE_NOGIL
docs:
$(PYTHON) setup.py build_ext --inplace build_sphinx
test:
PYTHONASYNCIODEBUG=1 $(PYTHON) -m unittest discover -v tests
$(PYTHON) -m unittest discover -v tests
testinstalled:
cd "$${HOME}" && $(PYTHON) -m unittest discover -v $(ROOT)/tests
================================================
FILE: README.rst
================================================
.. image:: https://img.shields.io/github/actions/workflow/status/MagicStack/uvloop/tests.yml?branch=master
:target: https://github.com/MagicStack/uvloop/actions/workflows/tests.yml?query=branch%3Amaster
.. image:: https://img.shields.io/pypi/v/uvloop.svg
:target: https://pypi.python.org/pypi/uvloop
.. image:: https://pepy.tech/badge/uvloop
:target: https://pepy.tech/project/uvloop
:alt: PyPI - Downloads
uvloop is a fast, drop-in replacement of the built-in asyncio
event loop. uvloop is implemented in Cython and uses libuv
under the hood.
The project documentation can be found
`here <http://uvloop.readthedocs.org/>`_. Please also check out the
`wiki <https://github.com/MagicStack/uvloop/wiki>`_.
Performance
-----------
uvloop makes asyncio 2-4x faster.
.. image:: https://raw.githubusercontent.com/MagicStack/uvloop/master/performance.png
:target: http://magic.io/blog/uvloop-blazing-fast-python-networking/
The above chart shows the performance of an echo server with different
message sizes. The *sockets* benchmark uses ``loop.sock_recv()`` and
``loop.sock_sendall()`` methods; the *streams* benchmark uses asyncio
high-level streams, created by the ``asyncio.start_server()`` function;
and the *protocol* benchmark uses ``loop.create_server()`` with a simple
echo protocol. Read more about uvloop in a
`blog post <http://magic.io/blog/uvloop-blazing-fast-python-networking/>`_
about it.
Installation
------------
uvloop requires Python 3.8 or greater and is available on PyPI.
Use pip to install it::
$ pip install uvloop
Note that it is highly recommended to **upgrade pip before** installing
uvloop with::
$ pip install -U pip
Using uvloop
------------
As of uvloop 0.18, the preferred way of using it is via the
``uvloop.run()`` helper function:
.. code:: python
import uvloop
async def main():
# Main entry-point.
...
uvloop.run(main())
``uvloop.run()`` works by simply configuring ``asyncio.run()``
to use uvloop, passing all of the arguments to it, such as ``debug``,
e.g. ``uvloop.run(main(), debug=True)``.
With Python 3.11 and earlier the following alternative
snippet can be used:
.. code:: python
import asyncio
import sys
import uvloop
async def main():
# Main entry-point.
...
if sys.version_info >= (3, 11):
with asyncio.Runner(loop_factory=uvloop.new_event_loop) as runner:
runner.run(main())
else:
uvloop.install()
asyncio.run(main())
Building From Source
--------------------
To build uvloop, you'll need Python 3.8 or greater:
1. Clone the repository:
.. code::
$ git clone --recursive git@github.com:MagicStack/uvloop.git
$ cd uvloop
2. Create a virtual environment and activate it:
.. code::
$ python3 -m venv uvloop-dev
$ source uvloop-dev/bin/activate
3. Install development dependencies:
.. code::
$ pip install -e .[dev]
4. Build and run tests:
.. code::
$ make
$ make test
License
-------
uvloop is dual-licensed under MIT and Apache 2.0 licenses.
================================================
FILE: docs/.gitignore
================================================
_build
_static
_templates
================================================
FILE: docs/api/index.rst
================================================
API
===
If you are looking for information on a specific function, class or method,
this part of the documentation is for you.
uvloop
------
.. autoclass:: uvloop.EventLoopPolicy
:members:
.. autofunction:: uvloop.new_event_loop
.. autoclass:: uvloop.Loop
:members:
:undoc-members:
:inherited-members:
================================================
FILE: docs/conf.py
================================================
#!/usr/bin/env python3
import alabaster
import os
import sys
sys.path.insert(0, os.path.abspath('..'))
version_file = os.path.join(os.path.dirname(os.path.dirname(__file__)),
'uvloop', '_version.py')
with open(version_file, 'r') as f:
for line in f:
if line.startswith('__version__ ='):
_, _, version = line.partition('=')
version = version.strip(" \n'\"")
break
else:
raise RuntimeError(
'unable to read the version from uvloop/_version.py')
# -- General configuration ------------------------------------------------
extensions = [
'sphinx.ext.autodoc',
'alabaster',
]
templates_path = ['_templates']
source_suffix = '.rst'
master_doc = 'index'
project = 'uvloop'
copyright = '2016-present, MagicStack, Inc'
author = 'Yury Selivanov'
release = version
language = None
exclude_patterns = ['_build']
pygments_style = 'sphinx'
todo_include_todos = False
# -- Options for HTML output ----------------------------------------------
html_theme = 'alabaster'
html_theme_options = {
'description': 'uvloop is an ultra fast implementation of the '
'asyncio event loop on top of libuv.',
'show_powered_by': False,
}
html_theme_path = [alabaster.get_path()]
html_title = 'uvloop Documentation'
html_short_title = 'uvloop'
html_static_path = []
html_sidebars = {
'**': [
'about.html',
'navigation.html',
]
}
html_show_sourcelink = False
html_show_sphinx = False
html_show_copyright = True
htmlhelp_basename = 'uvloopdoc'
# -- Options for LaTeX output ---------------------------------------------
latex_elements = {}
latex_documents = [
(master_doc, 'uvloop.tex', 'uvloop Documentation',
'Yury Selivanov', 'manual'),
]
# -- Options for manual page output ---------------------------------------
man_pages = [
(master_doc, 'uvloop', 'uvloop Documentation',
[author], 1)
]
# -- Options for Texinfo output -------------------------------------------
texinfo_documents = [
(master_doc, 'uvloop', 'uvloop Documentation',
author, 'uvloop', 'One line description of project.',
'Miscellaneous'),
]
================================================
FILE: docs/dev/index.rst
================================================
Developers Guide
================
The project is hosted on `GitHub <https://github.com/MagicStack/uvloop>`_.
and uses `GitHub Actions <https://github.com/MagicStack/uvloop/actions>`_ for
Continuous Integration.
A goal for the `uvloop` project is to provide a drop in replacement for the
`asyncio` event loop. Any deviation from the behavior of the reference
`asyncio` event loop is considered a bug.
If you have found a bug or have an idea for an enhancement that would
improve the library, use the
`bug tracker <https://github.com/MagicStack/uvloop/issues>`_.
Get the source
--------------
.. code-block:: console
$ git clone --recursive git@github.com:MagicStack/uvloop.git
The ``--recursive`` argument is important. It will fetch the ``libuv`` source
from the `libuv` Github repository.
Build
-----
To build `uvloop`, you'll need ``Cython`` and Python 3.8.
.. note::
The best way to work on `uvloop` is to create a virtual env, so that
you'll have Cython and Python commands pointing to the correct
tools.
.. code-block:: console
$ python3 -m venv myvenv
$ source myvenv/bin/activate
Install Cython if not already present.
.. code-block:: console
$ pip install Cython
Build `uvloop` by running the ``make`` rule from the top level directory.
.. code-block:: console
$ cd uvloop
$ make
Test
----
The easiest method to run all of the unit tests is to run the ``make test``
rule from the top level directory. This runs the standard library
``unittest`` tool which discovers all the unit tests and runs them.
It actually runs them twice, once with the `PYTHONASYNCIODEBUG` enabled and
once without.
.. code-block:: console
$ cd uvloop
$ make test
Individual Tests
++++++++++++++++
Individual unit tests can be run using the standard library ``unittest``
or ``pytest`` package.
The easiest approach to ensure that ``uvloop`` can be found by Python is to
install the package using ``pip``:
.. code-block:: console
$ cd uvloop
$ pip install -e .
You can then run the unit tests individually from the tests directory using
``unittest``:
.. code-block:: console
$ cd uvloop/tests
$ python -m unittest test_tcp
or using ``pytest``:
.. code-block:: console
$ cd uvloop/tests
$ py.test -k test_signals_sigint_uvcode
Documentation
-------------
To rebuild the project documentation, developers should run the ``make docs``
rule from the top level directory. It performs a number of steps to create
a new set of `sphinx <http://sphinx-doc.org/>`_ html content.
This step requires Sphinx to be installed. Sphinx can be installed using
pip:
.. code-block:: console
$ pip install sphinx
Once Sphinx is available you can make the documentation using:
.. code-block:: console
$ make docs
================================================
FILE: docs/index.rst
================================================
.. image:: https://img.shields.io/github/actions/workflow/status/MagicStack/uvloop/tests.yml?branch=master
:target: https://github.com/MagicStack/uvloop/actions/workflows/tests.yml?query=branch%3Amaster
.. image:: https://img.shields.io/pypi/status/uvloop.svg?maxAge=2592000?style=plastic
:target: https://pypi.python.org/pypi/uvloop
.. image:: https://img.shields.io/github/stars/magicstack/uvloop.svg?style=social&label=GitHub
:target: https://github.com/MagicStack/uvloop
uvloop
======
`uvloop` is a fast, drop-in replacement of the built-in asyncio event loop.
`uvloop` is released under the MIT license.
`uvloop` and asyncio, combined with the power of async/await in Python 3.7,
makes it easier than ever to write high-performance networking code in Python.
`uvloop` makes asyncio fast. In fact, it is at least 2x faster than nodejs,
gevent, as well as any other Python asynchronous framework. The performance of
uvloop-based asyncio is close to that of Go programs.
You can read more about uvloop in this
`blog post <http://magic.io/blog/uvloop-blazing-fast-python-networking/>`_.
Architecture
------------
The asyncio module, introduced by PEP 3156, is a collection of network
transports, protocols, and streams abstractions, with a pluggable event loop.
The event loop is the heart of asyncio. It provides APIs for:
- scheduling calls,
- transmitting data over the network,
- performing DNS queries,
- handling OS signals,
- convenient abstractions to create servers and connections,
- working with subprocesses asynchronously.
`uvloop` implements the :class:`asyncio.AbstractEventLoop` interface which
means that it provides a drop-in replacement of the asyncio event loop.
`uvloop` is written in Cython and is built on top of libuv.
libuv is a high performance, multiplatform asynchronous I/O library used by
nodejs. Because of how wide-spread and popular nodejs is, libuv is fast and
stable.
`uvloop` implements all asyncio event loop APIs. High-level Python objects
wrap low-level libuv structs and functions. Inheritance is used to keep the
code DRY and ensure that any manual memory management is in sync with libuv
primitives' lifespans.
Contents
--------
.. toctree::
:maxdepth: 1
user/index
dev/index
================================================
FILE: docs/user/index.rst
================================================
User Guide
==========
This section of the documentation provides information about how to use
uvloop.
Installation
------------
`uvloop` is available from PyPI. It requires Python 3.8.
Use pip to install it.
.. code-block:: console
$ pip install uvloop
Using uvloop
------------
To make asyncio use the event loop provided by `uvloop`, you install the
`uvloop` event loop policy:
.. code-block:: python
import asyncio
import uvloop
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
Alternatively, you can create an instance of the loop manually, using:
.. code-block:: python
import asyncio
import uvloop
loop = uvloop.new_event_loop()
asyncio.set_event_loop(loop)
================================================
FILE: examples/bench/echoclient.py
================================================
# Copied with minimal modifications from curio
# https://github.com/dabeaz/curio
import argparse
import concurrent.futures
import socket
import ssl
import time
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('--msize', default=1000, type=int,
help='message size in bytes')
parser.add_argument('--mpr', default=1, type=int,
help='messages per request')
parser.add_argument('--num', default=200000, type=int,
help='number of messages')
parser.add_argument('--times', default=1, type=int,
help='number of times to run the test')
parser.add_argument('--workers', default=3, type=int,
help='number of workers')
parser.add_argument('--addr', default='127.0.0.1:25000', type=str,
help='address:port of echoserver')
parser.add_argument('--ssl', default=False, action='store_true')
args = parser.parse_args()
client_context = None
if args.ssl:
print('with SSL')
if hasattr(ssl, 'PROTOCOL_TLS'):
client_context = ssl.SSLContext(ssl.PROTOCOL_TLS)
else:
client_context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
if hasattr(client_context, 'check_hostname'):
client_context.check_hostname = False
client_context.verify_mode = ssl.CERT_NONE
unix = False
if args.addr.startswith('file:'):
unix = True
addr = args.addr[5:]
else:
addr = args.addr.split(':')
addr[1] = int(addr[1])
addr = tuple(addr)
print('will connect to: {}'.format(addr))
MSGSIZE = args.msize
REQSIZE = MSGSIZE * args.mpr
msg = b'x' * (MSGSIZE - 1) + b'\n'
if args.mpr:
msg *= args.mpr
def run_test(n):
print('Sending', NMESSAGES, 'messages')
if args.mpr:
n //= args.mpr
if unix:
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
else:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
except (OSError, NameError):
pass
if client_context:
sock = client_context.wrap_socket(sock)
sock.connect(addr)
while n > 0:
sock.sendall(msg)
nrecv = 0
while nrecv < REQSIZE:
resp = sock.recv(REQSIZE)
if not resp:
raise SystemExit()
nrecv += len(resp)
n -= 1
TIMES = args.times
N = args.workers
NMESSAGES = args.num
start = time.time()
for _ in range(TIMES):
with concurrent.futures.ProcessPoolExecutor(max_workers=N) as e:
for _ in range(N):
e.submit(run_test, NMESSAGES)
end = time.time()
duration = end - start
print(NMESSAGES * N * TIMES, 'in', duration)
print(NMESSAGES * N * TIMES / duration, 'requests/sec')
================================================
FILE: examples/bench/echoserver.py
================================================
import argparse
import asyncio
import gc
import os.path
import pathlib
import socket
import ssl
PRINT = 0
async def echo_server(loop, address, unix):
if unix:
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
else:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(address)
sock.listen(5)
sock.setblocking(False)
if PRINT:
print('Server listening at', address)
with sock:
while True:
client, addr = await loop.sock_accept(sock)
if PRINT:
print('Connection from', addr)
loop.create_task(echo_client(loop, client))
async def echo_client(loop, client):
try:
client.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
except (OSError, NameError):
pass
with client:
while True:
data = await loop.sock_recv(client, 1000000)
if not data:
break
await loop.sock_sendall(client, data)
if PRINT:
print('Connection closed')
async def echo_client_streams(reader, writer):
sock = writer.get_extra_info('socket')
try:
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
except (OSError, NameError):
pass
if PRINT:
print('Connection from', sock.getpeername())
while True:
data = await reader.read(1000000)
if not data:
break
writer.write(data)
if PRINT:
print('Connection closed')
writer.close()
class EchoProtocol(asyncio.Protocol):
def connection_made(self, transport):
self.transport = transport
def connection_lost(self, exc):
self.transport = None
def data_received(self, data):
self.transport.write(data)
class EchoBufferedProtocol(asyncio.BufferedProtocol):
def connection_made(self, transport):
self.transport = transport
# Here the buffer is intended to be copied, so that the outgoing buffer
# won't be wrongly updated by next read
self.buffer = bytearray(256 * 1024)
def connection_lost(self, exc):
self.transport = None
def get_buffer(self, sizehint):
return self.buffer
def buffer_updated(self, nbytes):
self.transport.write(self.buffer[:nbytes])
async def print_debug(loop):
while True:
print(chr(27) + "[2J") # clear screen
loop.print_debug_info()
await asyncio.sleep(0.5)
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('--uvloop', default=False, action='store_true')
parser.add_argument('--streams', default=False, action='store_true')
parser.add_argument('--proto', default=False, action='store_true')
parser.add_argument('--addr', default='127.0.0.1:25000', type=str)
parser.add_argument('--print', default=False, action='store_true')
parser.add_argument('--ssl', default=False, action='store_true')
parser.add_argument('--buffered', default=False, action='store_true')
args = parser.parse_args()
if args.uvloop:
import uvloop
loop = uvloop.new_event_loop()
print('using UVLoop')
else:
loop = asyncio.new_event_loop()
print('using asyncio loop')
asyncio.set_event_loop(loop)
loop.set_debug(False)
if args.print:
PRINT = 1
if hasattr(loop, 'print_debug_info'):
loop.create_task(print_debug(loop))
PRINT = 0
unix = False
if args.addr.startswith('file:'):
unix = True
addr = args.addr[5:]
if os.path.exists(addr):
os.remove(addr)
else:
addr = args.addr.split(':')
addr[1] = int(addr[1])
addr = tuple(addr)
print('serving on: {}'.format(addr))
server_context = None
if args.ssl:
print('with SSL')
if hasattr(ssl, 'PROTOCOL_TLS'):
server_context = ssl.SSLContext(ssl.PROTOCOL_TLS)
else:
server_context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
server_context.load_cert_chain(
(pathlib.Path(__file__).parent.parent.parent /
'tests' / 'certs' / 'ssl_cert.pem'),
(pathlib.Path(__file__).parent.parent.parent /
'tests' / 'certs' / 'ssl_key.pem'))
if hasattr(server_context, 'check_hostname'):
server_context.check_hostname = False
server_context.verify_mode = ssl.CERT_NONE
if args.streams:
if args.proto:
print('cannot use --stream and --proto simultaneously')
exit(1)
if args.buffered:
print('cannot use --stream and --buffered simultaneously')
exit(1)
print('using asyncio/streams')
if unix:
coro = asyncio.start_unix_server(echo_client_streams,
addr,
ssl=server_context)
else:
coro = asyncio.start_server(echo_client_streams,
*addr,
ssl=server_context)
srv = loop.run_until_complete(coro)
elif args.proto:
if args.streams:
print('cannot use --stream and --proto simultaneously')
exit(1)
if args.buffered:
print('using buffered protocol')
protocol = EchoBufferedProtocol
else:
print('using simple protocol')
protocol = EchoProtocol
if unix:
coro = loop.create_unix_server(protocol, addr,
ssl=server_context)
else:
coro = loop.create_server(protocol, *addr,
ssl=server_context)
srv = loop.run_until_complete(coro)
else:
if args.ssl:
print('cannot use SSL for loop.sock_* methods')
exit(1)
print('using sock_recv/sock_sendall')
loop.create_task(echo_server(loop, addr, unix))
try:
loop.run_forever()
finally:
if hasattr(loop, 'print_debug_info'):
gc.collect()
print(chr(27) + "[2J")
loop.print_debug_info()
loop.close()
================================================
FILE: examples/bench/rlserver.py
================================================
import argparse
import asyncio
import gc
import os.path
import socket as stdsock
PRINT = 0
async def echo_client_streams(reader, writer):
sock = writer.get_extra_info('socket')
try:
sock.setsockopt(
stdsock.IPPROTO_TCP, stdsock.TCP_NODELAY, 1)
except (OSError, NameError):
pass
if PRINT:
print('Connection from', sock.getpeername())
while True:
data = await reader.readline()
if not data:
break
writer.write(data)
if PRINT:
print('Connection closed')
writer.close()
async def print_debug(loop):
while True:
print(chr(27) + "[2J") # clear screen
loop.print_debug_info()
await asyncio.sleep(0.5)
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('--uvloop', default=False, action='store_true')
parser.add_argument('--addr', default='127.0.0.1:25000', type=str)
parser.add_argument('--print', default=False, action='store_true')
args = parser.parse_args()
if args.uvloop:
import uvloop
loop = uvloop.new_event_loop()
print('using UVLoop')
else:
loop = asyncio.new_event_loop()
print('using asyncio loop')
asyncio.set_event_loop(loop)
loop.set_debug(False)
if args.print:
PRINT = 1
if hasattr(loop, 'print_debug_info'):
loop.create_task(print_debug(loop))
PRINT = 0
unix = False
if args.addr.startswith('file:'):
unix = True
addr = args.addr[5:]
if os.path.exists(addr):
os.remove(addr)
else:
addr = args.addr.split(':')
addr[1] = int(addr[1])
addr = tuple(addr)
print('readline performance test')
print('serving on: {}'.format(addr))
print('using asyncio/streams')
if unix:
coro = asyncio.start_unix_server(echo_client_streams,
addr, limit=256000)
else:
coro = asyncio.start_server(echo_client_streams,
*addr, limit=256000)
srv = loop.run_until_complete(coro)
try:
loop.run_forever()
finally:
if hasattr(loop, 'print_debug_info'):
gc.collect()
print(chr(27) + "[2J")
loop.print_debug_info()
loop.close()
================================================
FILE: mypy.ini
================================================
[mypy]
incremental = True
strict = True
[mypy-uvloop._testbase]
ignore_errors = True
================================================
FILE: pyproject.toml
================================================
[project]
name = "uvloop"
description = "Fast implementation of asyncio event loop on top of libuv"
authors = [{name = "Yury Selivanov", email = "yury@magic.io"}]
requires-python = '>=3.8.1'
readme = "README.rst"
license = {text = "MIT License"}
dynamic = ["version"]
keywords = [
"asyncio",
"networking",
]
classifiers = [
"Development Status :: 5 - Production/Stable",
"Framework :: AsyncIO",
"Intended Audience :: Developers",
"License :: OSI Approved :: Apache Software License",
"License :: OSI Approved :: MIT License",
"Operating System :: POSIX",
"Operating System :: MacOS :: MacOS X",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.8",
"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",
"Programming Language :: Python :: Implementation :: CPython",
"Topic :: System :: Networking",
]
[project.urls]
github = "https://github.com/MagicStack/uvloop"
[project.optional-dependencies]
test = [
# pycodestyle is a dependency of flake8, but it must be frozen because
# their combination breaks too often
# (example breakage: https://gitlab.com/pycqa/flake8/issues/427)
'aiohttp>=3.10.5',
'flake8~=6.1',
'psutil',
'pycodestyle~=2.11.0',
'pyOpenSSL~=25.3.0',
'mypy>=0.800',
]
dev = [
'setuptools>=60',
'Cython~=3.0',
]
docs = [
'Sphinx~=4.1.2',
'sphinxcontrib-asyncio~=0.3.0',
'sphinx_rtd_theme~=0.5.2',
]
[build-system]
requires = [
"setuptools>=60",
"wheel",
"Cython~=3.1",
]
build-backend = "setuptools.build_meta"
[tool.setuptools]
zip-safe = false
packages = ["uvloop"]
[tool.setuptools.exclude-package-data]
"*" = ["*.c", "*.h"]
[tool.cibuildwheel]
build-frontend = "build"
test-extras = "test"
test-command = "python -m unittest discover -v {project}/tests"
[tool.pytest.ini_options]
addopts = "--capture=no --assert=plain --strict-markers --tb=native --import-mode=importlib"
testpaths = "tests"
filterwarnings = "default"
================================================
FILE: setup.py
================================================
import sys
vi = sys.version_info
if vi < (3, 8):
raise RuntimeError('uvloop requires Python 3.8 or greater')
if sys.platform in ('win32', 'cygwin', 'cli'):
raise RuntimeError('uvloop does not support Windows at the moment')
import os
import os.path
import pathlib
import platform
import re
import shutil
import subprocess
import sys
from setuptools import setup, Extension
from setuptools.command.build_ext import build_ext
from setuptools.command.sdist import sdist
CYTHON_DEPENDENCY = 'Cython~=3.0'
MACHINE = platform.machine()
MODULES_CFLAGS = [os.getenv('UVLOOP_OPT_CFLAGS', '-O2')]
_ROOT = pathlib.Path(__file__).parent
LIBUV_DIR = str(_ROOT / 'vendor' / 'libuv')
LIBUV_BUILD_DIR = str(_ROOT / 'build' / 'libuv-{}'.format(MACHINE))
def _libuv_build_env():
env = os.environ.copy()
cur_cflags = env.get('CFLAGS', '')
if not re.search(r'-O\d', cur_cflags):
cur_cflags += ' -O2'
env['CFLAGS'] = (cur_cflags + ' -fPIC ' + env.get('ARCHFLAGS', ''))
return env
def _libuv_autogen(env):
if os.path.exists(os.path.join(LIBUV_DIR, 'configure')):
# No need to use autogen, the configure script is there.
return
if not os.path.exists(os.path.join(LIBUV_DIR, 'autogen.sh')):
raise RuntimeError(
'the libuv submodule has not been checked out; '
'try running "git submodule init; git submodule update"')
subprocess.run(
['/bin/sh', 'autogen.sh'], cwd=LIBUV_DIR, env=env, check=True)
class uvloop_sdist(sdist):
def run(self):
# Make sure sdist archive contains configure
# to avoid the dependency on autotools.
_libuv_autogen(_libuv_build_env())
super().run()
class uvloop_build_ext(build_ext):
user_options = build_ext.user_options + [
('cython-always', None,
'run cythonize() even if .c files are present'),
('cython-annotate', None,
'Produce a colorized HTML version of the Cython source.'),
('cython-directives=', None,
'Cythion compiler directives'),
('use-system-libuv', None,
'Use the system provided libuv, instead of the bundled one'),
]
boolean_options = build_ext.boolean_options + [
'cython-always',
'cython-annotate',
'use-system-libuv',
]
def initialize_options(self):
super().initialize_options()
self.use_system_libuv = False
self.cython_always = False
self.cython_annotate = None
self.cython_directives = None
def finalize_options(self):
need_cythonize = self.cython_always
cfiles = {}
for extension in self.distribution.ext_modules:
for i, sfile in enumerate(extension.sources):
if sfile.endswith('.pyx'):
prefix, ext = os.path.splitext(sfile)
cfile = prefix + '.c'
if os.path.exists(cfile) and not self.cython_always:
extension.sources[i] = cfile
else:
if os.path.exists(cfile):
cfiles[cfile] = os.path.getmtime(cfile)
else:
cfiles[cfile] = 0
need_cythonize = True
if need_cythonize:
import pkg_resources
# Double check Cython presence in case setup_requires
# didn't go into effect (most likely because someone
# imported Cython before setup_requires injected the
# correct egg into sys.path.
try:
import Cython
except ImportError:
raise RuntimeError(
'please install {} to compile uvloop from source'.format(
CYTHON_DEPENDENCY))
cython_dep = pkg_resources.Requirement.parse(CYTHON_DEPENDENCY)
if Cython.__version__ not in cython_dep:
raise RuntimeError(
'uvloop requires {}, got Cython=={}'.format(
CYTHON_DEPENDENCY, Cython.__version__
))
from Cython.Build import cythonize
directives = {}
if self.cython_directives:
for directive in self.cython_directives.split(','):
k, _, v = directive.partition('=')
if v.lower() == 'false':
v = False
if v.lower() == 'true':
v = True
directives[k] = v
self.cython_directives = directives
self.distribution.ext_modules[:] = cythonize(
self.distribution.ext_modules,
compiler_directives=directives,
annotate=self.cython_annotate,
compile_time_env=dict(DEFAULT_FREELIST_SIZE=250),
emit_linenums=self.debug)
super().finalize_options()
def build_libuv(self):
env = _libuv_build_env()
# Make sure configure and friends are present in case
# we are building from a git checkout.
_libuv_autogen(env)
# Copy the libuv tree to build/ so that its build
# products don't pollute sdist accidentally.
if os.path.exists(LIBUV_BUILD_DIR):
shutil.rmtree(LIBUV_BUILD_DIR)
shutil.copytree(LIBUV_DIR, LIBUV_BUILD_DIR)
# Sometimes pip fails to preserve the timestamps correctly,
# in which case, make will try to run autotools again.
subprocess.run(
['touch', 'configure.ac', 'aclocal.m4', 'configure',
'Makefile.am', 'Makefile.in'],
cwd=LIBUV_BUILD_DIR, env=env, check=True)
if 'LIBUV_CONFIGURE_HOST' in env:
cmd = ['./configure', '--host=' + env['LIBUV_CONFIGURE_HOST']]
else:
cmd = ['./configure']
subprocess.run(
cmd,
cwd=LIBUV_BUILD_DIR, env=env, check=True)
try:
njobs = len(os.sched_getaffinity(0))
except AttributeError:
njobs = os.cpu_count()
j_flag = '-j{}'.format(njobs or 1)
c_flag = "CFLAGS={}".format(env['CFLAGS'])
subprocess.run(
['make', j_flag, c_flag],
cwd=LIBUV_BUILD_DIR, env=env, check=True)
def build_extensions(self):
if self.use_system_libuv:
self.compiler.add_library('uv')
if sys.platform == 'darwin' and \
os.path.exists('/opt/local/include'):
# Support macports on Mac OS X.
self.compiler.add_include_dir('/opt/local/include')
else:
libuv_lib = os.path.join(LIBUV_BUILD_DIR, '.libs', 'libuv.a')
if not os.path.exists(libuv_lib):
self.build_libuv()
if not os.path.exists(libuv_lib):
raise RuntimeError('failed to build libuv')
self.extensions[-1].extra_objects.extend([libuv_lib])
self.compiler.add_include_dir(os.path.join(LIBUV_DIR, 'include'))
if sys.platform.startswith('linux'):
self.compiler.add_library('rt')
elif sys.platform.startswith(('freebsd', 'dragonfly')):
self.compiler.add_library('kvm')
elif sys.platform.startswith('sunos'):
self.compiler.add_library('kstat')
self.compiler.add_library('pthread')
super().build_extensions()
with open(str(_ROOT / 'uvloop' / '_version.py')) as f:
for line in f:
if line.startswith('__version__ ='):
_, _, version = line.partition('=')
VERSION = version.strip(" \n'\"")
break
else:
raise RuntimeError(
'unable to read the version from uvloop/_version.py')
setup_requires = []
if not (_ROOT / 'uvloop' / 'loop.c').exists() or '--cython-always' in sys.argv:
# No Cython output, require Cython to build.
setup_requires.append(CYTHON_DEPENDENCY)
setup(
version=VERSION,
cmdclass={
'sdist': uvloop_sdist,
'build_ext': uvloop_build_ext
},
ext_modules=[
Extension(
"uvloop.loop",
sources=[
"uvloop/loop.pyx",
],
extra_compile_args=MODULES_CFLAGS
),
],
setup_requires=setup_requires,
)
================================================
FILE: tests/__init__.py
================================================
================================================
FILE: tests/__main__.py
================================================
import os.path
import sys
import unittest
import unittest.runner
def suite():
test_loader = unittest.TestLoader()
test_suite = test_loader.discover(os.path.dirname(__file__))
return test_suite
if __name__ == '__main__':
runner = unittest.runner.TextTestRunner()
result = runner.run(suite())
sys.exit(not result.wasSuccessful())
================================================
FILE: tests/certs/ssl_cert.pem
================================================
-----BEGIN CERTIFICATE-----
MIIF8TCCBFmgAwIBAgIJAMstgJlaaVJcMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNV
BAYTAlhZMSYwJAYDVQQKDB1QeXRob24gU29mdHdhcmUgRm91bmRhdGlvbiBDQTEW
MBQGA1UEAwwNb3VyLWNhLXNlcnZlcjAeFw0xODA4MjkxNDIzMTZaFw0yODA3MDcx
NDIzMTZaMF8xCzAJBgNVBAYTAlhZMRcwFQYDVQQHDA5DYXN0bGUgQW50aHJheDEj
MCEGA1UECgwaUHl0aG9uIFNvZnR3YXJlIEZvdW5kYXRpb24xEjAQBgNVBAMMCWxv
Y2FsaG9zdDCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBAJ8oLzdB739k
YxZiFukBFGIpyjqYkj0I015p/sDz1MT7DljcZLBLy7OqnkLpB5tnM8256DwdihPA
3zlnfEzTfr9DD0qFBW2H5cMCoz7X17koeRhzGDd3dkjUeBjXvR5qRosG8wM3lQug
U7AizY+3Azaj1yN3mZ9K5a20jr58Kqinz+Xxx6sb2JfYYff2neJbBahNm5id0AD2
pi/TthZqO5DURJYo+MdgZOcy+7jEjOJsLWZd3Yzq78iM07qDjbpIoVpENZCTHTWA
hX8LIqz0OBmh4weQpm4+plU7E4r4D82uauocWw8iyuznCTtABWO7n9fWySmf9QZC
WYxHAFpBQs6zUVqAD7nhFdTqpQ9bRiaEnjE4HiAccPW+MAoSxFnv/rNzEzI6b4zU
NspFMfg1aNVamdjxdpUZ1GG1Okf0yPJykqEX4PZl3La1Be2q7YZ1wydR523Xd+f3
EO4/g+imETSKn8gyCf6Rvib175L4r2WV1CXQH7gFwZYCod6WHYq5TQIDAQABo4IB
wDCCAbwwFAYDVR0RBA0wC4IJbG9jYWxob3N0MA4GA1UdDwEB/wQEAwIFoDAdBgNV
HSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDAYDVR0TAQH/BAIwADAdBgNVHQ4E
FgQUj+od4zNcABazi29rb9NMy7XLfFUwfQYDVR0jBHYwdIAU3b/K2ubRNLo3dSHK
b5oIKPI1tkihUaRPME0xCzAJBgNVBAYTAlhZMSYwJAYDVQQKDB1QeXRob24gU29m
dHdhcmUgRm91bmRhdGlvbiBDQTEWMBQGA1UEAwwNb3VyLWNhLXNlcnZlcoIJAMst
gJlaaVJbMIGDBggrBgEFBQcBAQR3MHUwPAYIKwYBBQUHMAKGMGh0dHA6Ly90ZXN0
Y2EucHl0aG9udGVzdC5uZXQvdGVzdGNhL3B5Y2FjZXJ0LmNlcjA1BggrBgEFBQcw
AYYpaHR0cDovL3Rlc3RjYS5weXRob250ZXN0Lm5ldC90ZXN0Y2Evb2NzcC8wQwYD
VR0fBDwwOjA4oDagNIYyaHR0cDovL3Rlc3RjYS5weXRob250ZXN0Lm5ldC90ZXN0
Y2EvcmV2b2NhdGlvbi5jcmwwDQYJKoZIhvcNAQELBQADggGBACf1jFkQ9MbnKAC/
uo17EwPxHKZfswZVpCK527LVRr33DN1DbrR5ZWchDCpV7kCOhZ+fR7sKKk22ZHSY
oH+u3PEu20J3GOB1iyY1aMNB7WvId3JvappdVWkC/VpUyFfLsGUDFuIPADmZZqCb
iJMX4loteTVfl1d4xK/1mV6Gq9MRrRqiDfpSELn+v53OM9mGspwW+NZ1CIrbCuW0
KxZ/tPkqn8PSd9fNZR70bB7rWbnwrl+kH8xKxLl6qdlrMmg74WWwhLeQxK7+9DdP
IaDenzqx5cwWBGY/C0HcQj0gPuy3lSs1V/q+f7Y6uspPWP51PgiJLIywXS75iRAr
+UFGTzwAtyfTZSQoFyMmMULqfk6T5HtoVMqfRvPvK+mFDLWEstU1NIB1K/CRI7gI
AY65ClTU+zRS/tlF8IA7tsFvgtEf8jsI9kamlidhS1gyeg4dWcVErV4aeTPB1AUv
StPYQkKNM+NjytWHl5tNuBoDNLsc0gI/WSPiI4CIY8LwomOoiw==
-----END CERTIFICATE-----
================================================
FILE: tests/certs/ssl_key.pem
================================================
-----BEGIN PRIVATE KEY-----
MIIG/QIBADANBgkqhkiG9w0BAQEFAASCBucwggbjAgEAAoIBgQCfKC83Qe9/ZGMW
YhbpARRiKco6mJI9CNNeaf7A89TE+w5Y3GSwS8uzqp5C6QebZzPNueg8HYoTwN85
Z3xM036/Qw9KhQVth+XDAqM+19e5KHkYcxg3d3ZI1HgY170eakaLBvMDN5ULoFOw
Is2PtwM2o9cjd5mfSuWttI6+fCqop8/l8cerG9iX2GH39p3iWwWoTZuYndAA9qYv
07YWajuQ1ESWKPjHYGTnMvu4xIzibC1mXd2M6u/IjNO6g426SKFaRDWQkx01gIV/
CyKs9DgZoeMHkKZuPqZVOxOK+A/NrmrqHFsPIsrs5wk7QAVju5/X1skpn/UGQlmM
RwBaQULOs1FagA+54RXU6qUPW0YmhJ4xOB4gHHD1vjAKEsRZ7/6zcxMyOm+M1DbK
RTH4NWjVWpnY8XaVGdRhtTpH9MjycpKhF+D2Zdy2tQXtqu2GdcMnUedt13fn9xDu
P4PophE0ip/IMgn+kb4m9e+S+K9lldQl0B+4BcGWAqHelh2KuU0CAwEAAQKCAYEA
lKiWIYjmyRjdLKUGPTES9vWNvNmRjozV0RQ0LcoSbMMLDZkeO0UwyWqOVHUQ8+ib
jIcfEjeNJxI57oZopeHOO5vJhpNlFH+g7ltiW2qERqA1K88lSXm99Bzw6FNqhCRE
K8ub5N9fyfJA+P4o/xm0WK8EXk5yIUV17p/9zJJxzgKgv2jsVTi3QG2OZGvn4Oug
ByomMZEGHkBDzdxz8c/cP1Tlk1RFuwSgews178k2xq7AYSM/s0YmHi7b/RSvptX6
1v8P8kXNUe4AwTaNyrlvF2lwIadZ8h1hA7tCE2n44b7a7KfhAkwcbr1T59ioYh6P
zxsyPT678uD51dbtD/DXJCcoeeFOb8uzkR2KNcrnQzZpCJnRq4Gp5ybxwsxxuzpr
gz0gbNlhuWtE7EoSzmIK9t+WTS7IM2CvZymd6/OAh1Fuw6AQhSp64XRp3OfMMAAC
Ie2EPtKj4islWGT8VoUjuRYGmdRh4duAH1dkiAXOWA3R7y5a1/y/iE8KE8BtxocB
AoHBAM8aiURgpu1Fs0Oqz6izec7KSLL3l8hmW+MKUOfk/Ybng6FrTFsL5YtzR+Ap
wW4wwWnnIKEc1JLiZ7g8agRETK8hr5PwFXUn/GSWC0SMsazLJToySQS5LOV0tLzK
kJ3jtNU7tnlDGNkCHTHSoVL2T/8t+IkZI/h5Z6wjlYPvU2Iu0nVIXtiG+alv4A6M
Hrh9l5or4mjB6rGnVXeYohLkCm6s/W97ahVxLMcEdbsBo1prm2JqGnSoiR/tEFC/
QHQnbQKBwQDEu7kW0Yg9sZ89QtYtVQ1YpixFZORaUeRIRLnpEs1w7L1mCbOZ2Lj9
JHxsH05cYAc7HJfPwwxv3+3aGAIC/dfu4VSwEFtatAzUpzlhzKS5+HQCWB4JUNNU
MQ3+FwK2xQX4Ph8t+OzrFiYcK2g0An5UxWMa2HWIAWUOhnTOydAVsoH6yP31cVm4
0hxoABCwflaNLNGjRUyfBpLTAcNu/YtcE+KREy7YAAgXXrhRSO4XpLsSXwLnLT7/
YOkoBWDcTWECgcBPWnSUDZCIQ3efithMZJBciqd2Y2X19Dpq8O31HImD4jtOY0V7
cUB/wSkeHAGwjd/eCyA2e0x8B2IEdqmMfvr+86JJxekC3dJYXCFvH5WIhsH53YCa
3bT1KlWCLP9ib/g+58VQC0R/Cc9T4sfLePNH7D5ZkZd1wlbV30CPr+i8KwKay6MD
xhvtLx+jk07GE+E9wmjbCMo7TclyrLoVEOlqZMAqshgApT+p9eyCPetwXuDHwa3n
WxhHclcZCV7R4rUCgcAkdGSnxcvpIrDPOUNWwxvmAWTStw9ZbTNP8OxCNCm9cyDl
d4bAS1h8D/a+Uk7C70hnu7Sl2w7C7Eu2zhwRUdhhe3+l4GINPK/j99i6NqGPlGpq
xMlMEJ4YS768BqeKFpg0l85PRoEgTsphDeoROSUPsEPdBZ9BxIBlYKTkbKESZDGR
twzYHljx1n1NCDYPflmrb1KpXn4EOcObNghw2KqqNUUWfOeBPwBA1FxzM4BrAStp
DBINpGS4Dc0mjViVegECgcA3hTtm82XdxQXj9LQmb/E3lKx/7H87XIOeNMmvjYuZ
iS9wKrkF+u42vyoDxcKMCnxP5056wpdST4p56r+SBwVTHcc3lGBSGcMTIfwRXrj3
thOA2our2n4ouNIsYyTlcsQSzifwmpRmVMRPxl9fYVdEWUgB83FgHT0D9avvZnF9
t9OccnGJXShAIZIBADhVj/JwG4FbaX42NijD5PNpVLk1Y17OV0I576T9SfaQoBjJ
aH1M/zC4aVaS0DYB/Gxq7v8=
-----END PRIVATE KEY-----
================================================
FILE: tests/test_aiohttp.py
================================================
try:
import aiohttp
import aiohttp.web
except ImportError:
skip_tests = True
else:
skip_tests = False
import asyncio
import sys
import unittest
import weakref
from uvloop import _testbase as tb
class _TestAioHTTP:
def test_aiohttp_basic_1(self):
PAYLOAD = '<h1>It Works!</h1>' * 10000
async def on_request(request):
return aiohttp.web.Response(text=PAYLOAD)
asyncio.set_event_loop(self.loop)
app = aiohttp.web.Application()
app.router.add_get('/', on_request)
runner = aiohttp.web.AppRunner(app)
self.loop.run_until_complete(runner.setup())
site = aiohttp.web.TCPSite(runner, '0.0.0.0', '0')
self.loop.run_until_complete(site.start())
port = site._server.sockets[0].getsockname()[1]
async def test():
# Make sure we're using the correct event loop.
self.assertIs(asyncio.get_event_loop(), self.loop)
for addr in (('localhost', port),
('127.0.0.1', port)):
async with aiohttp.ClientSession() as client:
async with client.get('http://{}:{}'.format(*addr)) as r:
self.assertEqual(r.status, 200)
result = await r.text()
self.assertEqual(result, PAYLOAD)
self.loop.run_until_complete(test())
self.loop.run_until_complete(runner.cleanup())
def test_aiohttp_graceful_shutdown(self):
if self.implementation == 'asyncio' and sys.version_info >= (3, 12, 0):
# In Python 3.12.0, asyncio.Server.wait_closed() waits for all
# existing connections to complete, before aiohttp sends
# on_shutdown signals.
# https://github.com/aio-libs/aiohttp/issues/7675#issuecomment-1752143748
# https://github.com/python/cpython/pull/98582
raise unittest.SkipTest('bug in aiohttp: #7675')
async def websocket_handler(request):
ws = aiohttp.web.WebSocketResponse()
await ws.prepare(request)
request.app['websockets'].add(ws)
try:
async for msg in ws:
await ws.send_str(msg.data)
finally:
request.app['websockets'].discard(ws)
return ws
async def on_shutdown(app):
for ws in set(app['websockets']):
await ws.close(
code=aiohttp.WSCloseCode.GOING_AWAY,
message='Server shutdown')
asyncio.set_event_loop(self.loop)
app = aiohttp.web.Application()
app.router.add_get('/', websocket_handler)
app.on_shutdown.append(on_shutdown)
app['websockets'] = weakref.WeakSet()
runner = aiohttp.web.AppRunner(app)
self.loop.run_until_complete(runner.setup())
site = aiohttp.web.TCPSite(
runner,
'0.0.0.0',
0,
# https://github.com/aio-libs/aiohttp/pull/7188
shutdown_timeout=0.1,
)
self.loop.run_until_complete(site.start())
port = site._server.sockets[0].getsockname()[1]
async def client():
async with aiohttp.ClientSession() as client:
async with client.ws_connect(
'http://127.0.0.1:{}'.format(port)) as ws:
await ws.send_str("hello")
async for msg in ws:
assert msg.data == "hello"
client_task = asyncio.ensure_future(client())
async def stop():
await asyncio.sleep(0.1)
try:
await asyncio.wait_for(runner.cleanup(), timeout=0.5)
finally:
try:
client_task.cancel()
await client_task
except asyncio.CancelledError:
pass
self.loop.run_until_complete(stop())
@unittest.skipIf(skip_tests, "no aiohttp module")
class Test_UV_AioHTTP(_TestAioHTTP, tb.UVTestCase):
pass
@unittest.skipIf(skip_tests, "no aiohttp module")
class Test_AIO_AioHTTP(_TestAioHTTP, tb.AIOTestCase):
pass
================================================
FILE: tests/test_base.py
================================================
import asyncio
import fcntl
import logging
import os
import random
import sys
import subprocess
import threading
import time
import uvloop
import unittest
import weakref
from unittest import mock
from uvloop._testbase import UVTestCase, AIOTestCase
class _TestBase:
def test_close(self):
self.assertFalse(self.loop._closed)
self.assertFalse(self.loop.is_closed())
self.loop.close()
self.assertTrue(self.loop._closed)
self.assertTrue(self.loop.is_closed())
# it should be possible to call close() more than once
self.loop.close()
self.loop.close()
# operation blocked when the loop is closed
f = asyncio.Future()
self.assertRaises(RuntimeError, self.loop.run_forever)
self.assertRaises(RuntimeError, self.loop.run_until_complete, f)
def test_handle_weakref(self):
wd = weakref.WeakValueDictionary()
h = self.loop.call_soon(lambda: None)
wd['h'] = h # Would fail without __weakref__ slot.
def test_call_soon_1(self):
calls = []
def cb(inc):
calls.append(inc)
self.loop.stop()
self.loop.call_soon(cb, 10)
h = self.loop.call_soon(cb, 100)
self.assertIn('.cb', repr(h))
h.cancel()
self.assertIn('cancelled', repr(h))
self.loop.call_soon(cb, 1)
self.loop.run_forever()
self.assertEqual(calls, [10, 1])
def test_call_soon_2(self):
waiter = self.loop.create_future()
waiter_r = weakref.ref(waiter)
self.loop.call_soon(lambda f: f.set_result(None), waiter)
self.loop.run_until_complete(waiter)
del waiter
self.assertIsNone(waiter_r())
def test_call_soon_3(self):
waiter = self.loop.create_future()
waiter_r = weakref.ref(waiter)
self.loop.call_soon(lambda f=waiter: f.set_result(None))
self.loop.run_until_complete(waiter)
del waiter
self.assertIsNone(waiter_r())
def test_call_soon_base_exc(self):
def cb():
raise KeyboardInterrupt()
self.loop.call_soon(cb)
with self.assertRaises(KeyboardInterrupt):
self.loop.run_forever()
self.assertFalse(self.loop.is_closed())
def test_calls_debug_reporting(self):
def run_test(debug, meth, stack_adj):
context = None
def handler(loop, ctx):
nonlocal context
context = ctx
self.loop.set_debug(debug)
self.loop.set_exception_handler(handler)
def cb():
1 / 0
meth(cb)
self.assertIsNone(context)
self.loop.run_until_complete(asyncio.sleep(0.05))
self.assertIs(type(context['exception']), ZeroDivisionError)
self.assertTrue(context['message'].startswith(
'Exception in callback'))
if debug:
tb = context['source_traceback']
self.assertEqual(tb[-1 + stack_adj].name, 'run_test')
else:
self.assertFalse('source_traceback' in context)
del context
for debug in (True, False):
for meth_name, meth, stack_adj in (
('call_soon',
self.loop.call_soon, 0),
('call_later', # `-1` accounts for lambda
lambda *args: self.loop.call_later(0.01, *args), -1)
):
with self.subTest(debug=debug, meth_name=meth_name):
run_test(debug, meth, stack_adj)
def test_now_update(self):
async def run():
st = self.loop.time()
time.sleep(0.05)
return self.loop.time() - st
delta = self.loop.run_until_complete(run())
self.assertTrue(delta > 0.049 and delta < 0.6)
def test_call_later_1(self):
calls = []
def cb(inc=10, stop=False):
calls.append(inc)
self.assertTrue(self.loop.is_running())
if stop:
self.loop.call_soon(self.loop.stop)
self.loop.call_later(0.05, cb)
# canceled right away
h = self.loop.call_later(0.05, cb, 100, True)
self.assertIn('.cb', repr(h))
h.cancel()
self.assertIn('cancelled', repr(h))
self.loop.call_later(0.05, cb, 1, True)
self.loop.call_later(1000, cb, 1000) # shouldn't be called
started = time.monotonic()
self.loop.run_forever()
finished = time.monotonic()
self.assertEqual(calls, [10, 1])
self.assertFalse(self.loop.is_running())
self.assertLess(finished - started, 0.3)
self.assertGreater(finished - started, 0.04)
def test_call_later_2(self):
# Test that loop.call_later triggers an update of
# libuv cached time.
async def main():
await asyncio.sleep(0.001)
time.sleep(0.01)
await asyncio.sleep(0.01)
started = time.monotonic()
self.loop.run_until_complete(main())
delta = time.monotonic() - started
self.assertGreater(delta, 0.019)
def test_call_later_3(self):
# a memory leak regression test
waiter = self.loop.create_future()
waiter_r = weakref.ref(waiter)
self.loop.call_later(0.01, lambda f: f.set_result(None), waiter)
self.loop.run_until_complete(waiter)
del waiter
self.assertIsNone(waiter_r())
def test_call_later_4(self):
# a memory leak regression test
waiter = self.loop.create_future()
waiter_r = weakref.ref(waiter)
self.loop.call_later(0.01, lambda f=waiter: f.set_result(None))
self.loop.run_until_complete(waiter)
del waiter
self.assertIsNone(waiter_r())
def test_call_later_negative(self):
calls = []
def cb(arg):
calls.append(arg)
self.loop.stop()
self.loop.call_later(-1, cb, 'a')
self.loop.run_forever()
self.assertEqual(calls, ['a'])
def test_call_later_rounding(self):
# Refs #233, call_later() and call_at() shouldn't call cb early
def cb():
self.loop.stop()
for i in range(8):
self.loop.call_later(0.06 + 0.01, cb) # 0.06999999999999999
started = int(round(self.loop.time() * 1000))
self.loop.run_forever()
finished = int(round(self.loop.time() * 1000))
self.assertGreaterEqual(finished - started, 69)
def test_call_at(self):
if (os.environ.get('TRAVIS_OS_NAME')
or os.environ.get('GITHUB_WORKFLOW')):
# Time seems to be really unpredictable on Travis.
raise unittest.SkipTest('time is not monotonic on CI')
i = 0
def cb(inc):
nonlocal i
i += inc
self.loop.stop()
at = self.loop.time() + 0.05
self.loop.call_at(at, cb, 100).cancel()
self.loop.call_at(at, cb, 10)
started = time.monotonic()
self.loop.run_forever()
finished = time.monotonic()
self.assertEqual(i, 10)
self.assertLess(finished - started, 0.07)
self.assertGreater(finished - started, 0.045)
def test_check_thread(self):
def check_thread(loop, debug):
def cb():
pass
loop.set_debug(debug)
if debug:
msg = ("Non-thread-safe operation invoked on an "
"event loop other than the current one")
with self.assertRaisesRegex(RuntimeError, msg):
loop.call_soon(cb)
with self.assertRaisesRegex(RuntimeError, msg):
loop.call_later(60, cb)
with self.assertRaisesRegex(RuntimeError, msg):
loop.call_at(loop.time() + 60, cb)
else:
loop.call_soon(cb)
loop.call_later(60, cb)
loop.call_at(loop.time() + 60, cb)
def check_in_thread(loop, event, debug, create_loop, fut):
# wait until the event loop is running
event.wait()
try:
if create_loop:
loop2 = self.new_loop()
try:
asyncio.set_event_loop(loop2)
check_thread(loop, debug)
finally:
asyncio.set_event_loop(None)
loop2.close()
else:
check_thread(loop, debug)
except Exception as exc:
loop.call_soon_threadsafe(fut.set_exception, exc)
else:
loop.call_soon_threadsafe(fut.set_result, None)
def test_thread(loop, debug, create_loop=False):
event = threading.Event()
fut = asyncio.Future(loop=loop)
loop.call_soon(event.set)
args = (loop, event, debug, create_loop, fut)
thread = threading.Thread(target=check_in_thread, args=args)
thread.start()
loop.run_until_complete(fut)
thread.join()
# raise RuntimeError if the thread has no event loop
test_thread(self.loop, True)
# check disabled if debug mode is disabled
test_thread(self.loop, False)
# raise RuntimeError if the event loop of the thread is not the called
# event loop
test_thread(self.loop, True, create_loop=True)
# check disabled if debug mode is disabled
test_thread(self.loop, False, create_loop=True)
def test_run_once_in_executor_plain(self):
called = []
def cb(arg):
called.append(arg)
async def runner():
await self.loop.run_in_executor(None, cb, 'a')
self.loop.run_until_complete(runner())
self.assertEqual(called, ['a'])
def test_set_debug(self):
self.loop.set_debug(True)
self.assertTrue(self.loop.get_debug())
self.loop.set_debug(False)
self.assertFalse(self.loop.get_debug())
def test_run_until_complete_type_error(self):
self.assertRaises(
TypeError, self.loop.run_until_complete, 'blah')
def test_run_until_complete_loop(self):
task = asyncio.Future()
other_loop = self.new_loop()
self.addCleanup(other_loop.close)
self.assertRaises(
ValueError, other_loop.run_until_complete, task)
def test_run_until_complete_error(self):
async def foo():
raise ValueError('aaa')
with self.assertRaisesRegex(ValueError, 'aaa'):
self.loop.run_until_complete(foo())
def test_run_until_complete_loop_orphan_future_close_loop(self):
async def foo(delay):
await asyncio.sleep(delay)
def throw():
raise KeyboardInterrupt
self.loop.call_soon(throw)
try:
self.loop.run_until_complete(foo(0.1))
except KeyboardInterrupt:
pass
# This call fails if run_until_complete does not clean up
# done-callback for the previous future.
self.loop.run_until_complete(foo(0.2))
def test_run_until_complete_keyboard_interrupt(self):
# Issue #336: run_until_complete() must not schedule a pending
# call to stop() if the future raised a KeyboardInterrupt
async def raise_keyboard_interrupt():
raise KeyboardInterrupt
self.loop._process_events = mock.Mock()
with self.assertRaises(KeyboardInterrupt):
self.loop.run_until_complete(raise_keyboard_interrupt())
def func():
self.loop.stop()
func.called = True
func.called = False
self.loop.call_later(0.01, func)
self.loop.run_forever()
self.assertTrue(func.called)
def test_debug_slow_callbacks(self):
logger = logging.getLogger('asyncio')
self.loop.set_debug(True)
self.loop.slow_callback_duration = 0.2
self.loop.call_soon(lambda: time.sleep(0.3))
with mock.patch.object(logger, 'warning') as log:
self.loop.run_until_complete(asyncio.sleep(0))
self.assertEqual(log.call_count, 1)
# format message
msg = log.call_args[0][0] % log.call_args[0][1:]
self.assertIn('Executing <Handle', msg)
self.assertIn('test_debug_slow_callbacks', msg)
def test_debug_slow_timer_callbacks(self):
logger = logging.getLogger('asyncio')
self.loop.set_debug(True)
self.loop.slow_callback_duration = 0.2
self.loop.call_later(0.01, lambda: time.sleep(0.3))
with mock.patch.object(logger, 'warning') as log:
self.loop.run_until_complete(asyncio.sleep(0.02))
self.assertEqual(log.call_count, 1)
# format message
msg = log.call_args[0][0] % log.call_args[0][1:]
self.assertIn('Executing <TimerHandle', msg)
self.assertIn('test_debug_slow_timer_callbacks', msg)
def test_debug_slow_task_callbacks(self):
logger = logging.getLogger('asyncio')
self.loop.set_debug(True)
self.loop.slow_callback_duration = 0.2
async def foo():
time.sleep(0.3)
with mock.patch.object(logger, 'warning') as log:
self.loop.run_until_complete(foo())
self.assertEqual(log.call_count, 1)
# format message
msg = log.call_args[0][0] % log.call_args[0][1:]
self.assertIn('Executing <Task finished', msg)
self.assertIn('test_debug_slow_task_callbacks', msg)
def test_default_exc_handler_callback(self):
self.loop.set_exception_handler(None)
self.loop._process_events = mock.Mock()
def zero_error(fut):
fut.set_result(True)
1 / 0
logger = logging.getLogger('asyncio')
# Test call_soon (events.Handle)
with mock.patch.object(logger, 'error') as log:
fut = asyncio.Future()
self.loop.call_soon(zero_error, fut)
fut.add_done_callback(lambda fut: self.loop.stop())
self.loop.run_forever()
log.assert_called_with(
self.mock_pattern('Exception in callback.*zero'),
exc_info=mock.ANY)
# Test call_later (events.TimerHandle)
with mock.patch.object(logger, 'error') as log:
fut = asyncio.Future()
self.loop.call_later(0.01, zero_error, fut)
fut.add_done_callback(lambda fut: self.loop.stop())
self.loop.run_forever()
log.assert_called_with(
self.mock_pattern('Exception in callback.*zero'),
exc_info=mock.ANY)
def test_set_exc_handler_custom(self):
self.loop.set_exception_handler(None)
logger = logging.getLogger('asyncio')
def run_loop():
def zero_error():
self.loop.stop()
1 / 0
self.loop.call_soon(zero_error)
self.loop.run_forever()
errors = []
def handler(loop, exc):
errors.append(exc)
self.loop.set_debug(True)
self.assertIsNone(self.loop.get_exception_handler())
self.loop.set_exception_handler(handler)
if hasattr(self.loop, 'get_exception_handler'):
self.assertIs(self.loop.get_exception_handler(), handler)
run_loop()
self.assertEqual(len(errors), 1)
self.assertRegex(errors[-1]['message'],
'Exception in callback.*zero_error')
self.loop.set_exception_handler(None)
with mock.patch.object(logger, 'error') as log:
run_loop()
log.assert_called_with(
self.mock_pattern('Exception in callback.*zero'),
exc_info=mock.ANY)
self.assertEqual(len(errors), 1)
def test_set_exc_handler_broken(self):
logger = logging.getLogger('asyncio')
def run_loop():
def zero_error():
self.loop.stop()
1 / 0
self.loop.call_soon(zero_error)
self.loop.run_forever()
def handler(loop, context):
raise AttributeError('spam')
self.loop._process_events = mock.Mock()
self.loop.set_exception_handler(handler)
with mock.patch.object(logger, 'error') as log:
run_loop()
log.assert_called_with(
self.mock_pattern('Unhandled error in exception handler'),
exc_info=mock.ANY)
def test_set_task_factory_invalid(self):
with self.assertRaisesRegex(
TypeError,
'task factory must be a callable or None'):
self.loop.set_task_factory(1)
self.assertIsNone(self.loop.get_task_factory())
def test_set_task_factory(self):
self.loop._process_events = mock.Mock()
class MyTask(asyncio.Task):
pass
async def coro():
pass
factory = lambda loop, coro, **kwargs: MyTask(
coro, loop=loop, **kwargs
)
self.assertIsNone(self.loop.get_task_factory())
self.loop.set_task_factory(factory)
self.assertIs(self.loop.get_task_factory(), factory)
task = self.loop.create_task(coro())
self.assertTrue(isinstance(task, MyTask))
self.loop.run_until_complete(task)
self.loop.set_task_factory(None)
self.assertIsNone(self.loop.get_task_factory())
task = self.loop.create_task(coro())
self.assertTrue(isinstance(task, asyncio.Task))
self.assertFalse(isinstance(task, MyTask))
self.loop.run_until_complete(task)
def test_set_task_name(self):
self.loop._process_events = mock.Mock()
result = None
class MyTask(asyncio.Task):
def set_name(self, name):
nonlocal result
result = name + "!"
def get_name(self):
return result
async def coro():
pass
def factory(loop, coro, **kwargs):
task = MyTask(coro, loop=loop, **kwargs)
# Python moved the responsibility to set the name to the Task
# class constructor, so MyTask.set_name is never called by
# Python's create_task. Compensate for that here.
if self.is_asyncio_loop() and "name" in kwargs:
task.set_name(kwargs["name"])
return task
self.assertIsNone(self.loop.get_task_factory())
task = self.loop.create_task(coro(), name="mytask")
self.assertFalse(isinstance(task, MyTask))
self.assertEqual(task.get_name(), "mytask")
self.loop.run_until_complete(task)
self.loop.set_task_factory(factory)
self.assertIs(self.loop.get_task_factory(), factory)
task = self.loop.create_task(coro(), name="mytask")
self.assertTrue(isinstance(task, MyTask))
self.assertEqual(result, "mytask!")
self.assertEqual(task.get_name(), "mytask!")
self.loop.run_until_complete(task)
self.loop.set_task_factory(None)
self.assertIsNone(self.loop.get_task_factory())
def test_shutdown_asyncgens_01(self):
finalized = list()
if not hasattr(self.loop, 'shutdown_asyncgens'):
raise unittest.SkipTest()
async def waiter(timeout, finalized):
try:
await asyncio.sleep(timeout)
yield 1
finally:
await asyncio.sleep(0)
finalized.append(1)
async def wait():
async for _ in waiter(1, finalized):
pass
t1 = self.loop.create_task(wait())
t2 = self.loop.create_task(wait())
self.loop.run_until_complete(asyncio.sleep(0.1))
t1.cancel()
t2.cancel()
self.loop.run_until_complete(self.loop.shutdown_asyncgens())
self.assertEqual(finalized, [1, 1])
for t in {t1, t2}:
try:
self.loop.run_until_complete(t)
except asyncio.CancelledError:
pass
def test_shutdown_asyncgens_02(self):
if not hasattr(self.loop, 'shutdown_asyncgens'):
raise unittest.SkipTest()
logged = 0
def logger(loop, context):
nonlocal logged
expected = 'an error occurred during closing of asynchronous'
if expected in context['message']:
self.assertIn('asyncgen', context)
logged += 1
async def waiter(timeout):
try:
await asyncio.sleep(timeout)
yield 1
finally:
1 / 0
async def wait():
async for _ in waiter(1):
pass
t = self.loop.create_task(wait())
self.loop.run_until_complete(asyncio.sleep(0.1))
self.loop.set_exception_handler(logger)
self.loop.run_until_complete(self.loop.shutdown_asyncgens())
self.assertEqual(logged, 1)
# Silence warnings
t.cancel()
self.loop.run_until_complete(asyncio.sleep(0.1))
def test_shutdown_asyncgens_03(self):
if not hasattr(self.loop, 'shutdown_asyncgens'):
raise unittest.SkipTest()
async def waiter():
yield 1
yield 2
async def foo():
# We specifically want to hit _asyncgen_finalizer_hook
# method.
await waiter().asend(None)
self.loop.run_until_complete(foo())
self.loop.run_until_complete(asyncio.sleep(0.01))
def test_inf_wait_for(self):
async def foo():
await asyncio.sleep(0.1)
return 123
res = self.loop.run_until_complete(
asyncio.wait_for(foo(), timeout=float('inf')))
self.assertEqual(res, 123)
def test_shutdown_default_executor(self):
if not hasattr(self.loop, "shutdown_default_executor"):
raise unittest.SkipTest()
async def foo():
await self.loop.run_in_executor(None, time.sleep, .1)
self.loop.run_until_complete(foo())
self.loop.run_until_complete(
self.loop.shutdown_default_executor())
def test_call_soon_threadsafe_safety(self):
ITERATIONS = 4096
counter = [0]
def cb():
counter[0] += 1
if counter[0] < ITERATIONS - 512:
h = self.loop.call_later(0.01, lambda: None)
self.loop.call_later(
0.0005 + random.random() * 0.0005, h.cancel
)
def scheduler():
loop = self.loop
for i in range(ITERATIONS):
if loop.is_running():
loop.call_soon_threadsafe(cb)
time.sleep(0.001)
loop.call_soon_threadsafe(loop.stop)
thread = threading.Thread(target=scheduler)
self.loop.call_soon(thread.start)
self.loop.run_forever()
thread.join()
self.assertEqual(counter[0], ITERATIONS)
def test_freethreading(self):
if not hasattr(sys, "_is_gil_enabled"):
raise unittest.SkipTest("No sys._is_gil_enabled()")
if os.cpu_count() < 2:
raise unittest.SkipTest("Flaky on single CPU machines")
prog = """\
import asyncio
import os
import sys
import threading
import time
counter = 0
def job(barrier):
global counter
barrier.wait()
start_time = time.monotonic()
rv = 0
while time.monotonic() - start_time < 1:
for _i in range(10**4):
counter += 1
rv += 1
return rv
async def main():
if sys._is_gil_enabled():
print("{impl} turned on GIL")
return False
loop = asyncio.get_running_loop()
n_jobs = os.cpu_count()
barrier = threading.Barrier(n_jobs)
fs = [loop.run_in_executor(None, job, barrier) for _ in range(n_jobs)]
result = sum(await asyncio.gather(*fs))
if counter == result:
print("Expected race condition did not happen")
return False
return True
if __name__ == "__main__":
if sys._is_gil_enabled():
print("Not running with GIL disabled")
sys.exit(2)
import {impl}
if not {impl}.run(main()):
sys.exit(1)
"""
result = subprocess.run(
[sys.executable, '-c', prog.format(impl=self.implementation)],
stdout=subprocess.PIPE,
text=True,
)
if result.returncode == 2:
raise unittest.SkipTest(result.stdout.strip())
elif result.returncode != 0:
self.fail(result.stdout.strip())
class TestBaseUV(_TestBase, UVTestCase):
def test_loop_create_future(self):
fut = self.loop.create_future()
self.assertTrue(isinstance(fut, asyncio.Future))
self.assertIs(fut._loop, self.loop)
fut.cancel()
def test_loop_call_soon_handle_cancelled(self):
cb = lambda: False # NoQA
handle = self.loop.call_soon(cb)
self.assertFalse(handle.cancelled())
handle.cancel()
self.assertTrue(handle.cancelled())
handle = self.loop.call_soon(cb)
self.assertFalse(handle.cancelled())
self.run_loop_briefly()
self.assertFalse(handle.cancelled())
def test_loop_call_later_handle_cancelled(self):
cb = lambda: False # NoQA
handle = self.loop.call_later(0.01, cb)
self.assertFalse(handle.cancelled())
handle.cancel()
self.assertTrue(handle.cancelled())
handle = self.loop.call_later(0.01, cb)
self.assertFalse(handle.cancelled())
self.run_loop_briefly(delay=0.05)
self.assertFalse(handle.cancelled())
def test_loop_std_files_cloexec(self):
# See https://github.com/MagicStack/uvloop/issues/40 for details.
for fd in {0, 1, 2}:
flags = fcntl.fcntl(fd, fcntl.F_GETFD)
self.assertFalse(flags & fcntl.FD_CLOEXEC)
def test_default_exc_handler_broken(self):
logger = logging.getLogger('asyncio')
_context = None
class Loop(uvloop.Loop):
_selector = mock.Mock()
_process_events = mock.Mock()
def default_exception_handler(self, context):
nonlocal _context
_context = context
# Simulates custom buggy "default_exception_handler"
raise ValueError('spam')
loop = Loop()
self.addCleanup(loop.close)
self.addCleanup(lambda: asyncio.set_event_loop(None))
asyncio.set_event_loop(loop)
def run_loop():
def zero_error():
loop.stop()
1 / 0
loop.call_soon(zero_error)
loop.run_forever()
with mock.patch.object(logger, 'error') as log:
run_loop()
log.assert_called_with(
'Exception in default exception handler',
exc_info=True)
def custom_handler(loop, context):
raise ValueError('ham')
_context = None
loop.set_exception_handler(custom_handler)
with mock.patch.object(logger, 'error') as log:
run_loop()
log.assert_called_with(
self.mock_pattern('Exception in default exception.*'
'while handling.*in custom'),
exc_info=True)
# Check that original context was passed to default
# exception handler.
self.assertIn('context', _context)
self.assertIs(type(_context['context']['exception']),
ZeroDivisionError)
def test_big_call_later_timeout(self):
OK, NOT_OK = 0, 0
async def sleep(delay_name, delay):
nonlocal OK, NOT_OK
try:
await asyncio.sleep(delay)
except asyncio.CancelledError:
OK += 1
except Exception:
NOT_OK += 1
async def main():
tests = [
sleep("infinity", float("inf")),
sleep("sys.maxsize", float(sys.maxsize)),
sleep("sys.maxsize", sys.maxsize),
sleep("2**55", 2**55),
sleep("2**54", 2**54),
]
tasks = [self.loop.create_task(test) for test in tests]
await asyncio.sleep(0.1)
for task in tasks:
task.cancel()
await task
self.loop.run_until_complete(main())
self.assertEqual(OK, 5)
self.assertEqual(NOT_OK, 0)
def test_loop_call_later_handle_when(self):
cb = lambda: False # NoQA
delay = 1.0
loop_t = self.loop.time()
handle = self.loop.call_later(delay, cb)
self.assertAlmostEqual(handle.when(), loop_t + delay, places=2)
handle.cancel()
self.assertTrue(handle.cancelled())
self.assertAlmostEqual(handle.when(), loop_t + delay, places=2)
def test_loop_call_later_handle_when_after_fired(self):
fut = self.loop.create_future()
handle = self.loop.call_later(0.05, fut.set_result, None)
when = handle.when()
self.loop.run_until_complete(fut)
self.assertEqual(handle.when(), when)
class TestBaseAIO(_TestBase, AIOTestCase):
pass
class TestPolicy(unittest.TestCase):
def test_uvloop_policy(self):
try:
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
loop = asyncio.new_event_loop()
try:
self.assertIsInstance(loop, uvloop.Loop)
finally:
loop.close()
finally:
asyncio.set_event_loop_policy(None)
@unittest.skipUnless(hasattr(asyncio, '_get_running_loop'),
'No asyncio._get_running_loop')
def test_running_loop_within_a_loop(self):
async def runner(loop):
loop.run_forever()
try:
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
loop = asyncio.new_event_loop()
outer_loop = asyncio.new_event_loop()
try:
with self.assertRaisesRegex(RuntimeError,
'while another loop is running'):
outer_loop.run_until_complete(runner(loop))
finally:
loop.close()
outer_loop.close()
finally:
asyncio.set_event_loop_policy(None)
@unittest.skipUnless(hasattr(asyncio, '_get_running_loop'),
'No asyncio._get_running_loop')
def test_get_event_loop_returns_running_loop(self):
class Policy(asyncio.DefaultEventLoopPolicy):
def get_event_loop(self):
raise NotImplementedError
loop = None
old_policy = asyncio.get_event_loop_policy()
try:
asyncio.set_event_loop_policy(Policy())
loop = uvloop.new_event_loop()
self.assertIs(asyncio._get_running_loop(), None)
async def func():
self.assertIs(asyncio.get_event_loop(), loop)
self.assertIs(asyncio._get_running_loop(), loop)
loop.run_until_complete(func())
finally:
asyncio.set_event_loop_policy(old_policy)
if loop is not None:
loop.close()
self.assertIs(asyncio._get_running_loop(), None)
================================================
FILE: tests/test_context.py
================================================
import asyncio
import contextvars
import decimal
import itertools
import random
import socket
import ssl
import sys
import tempfile
import unittest
import weakref
from uvloop import _testbase as tb
class _BaseProtocol(asyncio.BaseProtocol):
def __init__(self, cvar, *, loop=None):
self.cvar = cvar
self.transport = None
self.connection_made_fut = asyncio.Future(loop=loop)
self.buffered_ctx = None
self.data_received_fut = asyncio.Future(loop=loop)
self.eof_received_fut = asyncio.Future(loop=loop)
self.pause_writing_fut = asyncio.Future(loop=loop)
self.resume_writing_fut = asyncio.Future(loop=loop)
self.pipe_ctx = {0, 1, 2}
self.pipe_connection_lost_fut = asyncio.Future(loop=loop)
self.process_exited_fut = asyncio.Future(loop=loop)
self.error_received_fut = asyncio.Future(loop=loop)
self.connection_lost_ctx = None
self.done = asyncio.Future(loop=loop)
def connection_made(self, transport):
self.transport = transport
self.connection_made_fut.set_result(self.cvar.get())
def connection_lost(self, exc):
self.connection_lost_ctx = self.cvar.get()
if exc is None:
self.done.set_result(None)
else:
self.done.set_exception(exc)
def eof_received(self):
self.eof_received_fut.set_result(self.cvar.get())
def pause_writing(self):
self.pause_writing_fut.set_result(self.cvar.get())
def resume_writing(self):
self.resume_writing_fut.set_result(self.cvar.get())
class _Protocol(_BaseProtocol, asyncio.Protocol):
def data_received(self, data):
self.data_received_fut.set_result(self.cvar.get())
class _BufferedProtocol(_BaseProtocol, asyncio.BufferedProtocol):
def get_buffer(self, sizehint):
if self.buffered_ctx is None:
self.buffered_ctx = self.cvar.get()
elif self.cvar.get() != self.buffered_ctx:
self.data_received_fut.set_exception(ValueError("{} != {}".format(
self.buffered_ctx, self.cvar.get(),
)))
return bytearray(65536)
def buffer_updated(self, nbytes):
if not self.data_received_fut.done():
if self.cvar.get() == self.buffered_ctx:
self.data_received_fut.set_result(self.cvar.get())
else:
self.data_received_fut.set_exception(
ValueError("{} != {}".format(
self.buffered_ctx, self.cvar.get(),
))
)
class _DatagramProtocol(_BaseProtocol, asyncio.DatagramProtocol):
def datagram_received(self, data, addr):
self.data_received_fut.set_result(self.cvar.get())
def error_received(self, exc):
self.error_received_fut.set_result(self.cvar.get())
class _SubprocessProtocol(_BaseProtocol, asyncio.SubprocessProtocol):
def pipe_data_received(self, fd, data):
self.data_received_fut.set_result(self.cvar.get())
def pipe_connection_lost(self, fd, exc):
self.pipe_ctx.remove(fd)
val = self.cvar.get()
self.pipe_ctx.add(val)
if not any(isinstance(x, int) for x in self.pipe_ctx):
if len(self.pipe_ctx) == 1:
self.pipe_connection_lost_fut.set_result(val)
else:
self.pipe_connection_lost_fut.set_exception(
AssertionError(str(list(self.pipe_ctx))))
def process_exited(self):
self.process_exited_fut.set_result(self.cvar.get())
class _SSLSocketOverSSL:
# because wrap_socket() doesn't work correctly on
# SSLSocket, we have to do the 2nd level SSL manually
def __init__(self, ssl_sock, ctx, **kwargs):
self.sock = ssl_sock
self.incoming = ssl.MemoryBIO()
self.outgoing = ssl.MemoryBIO()
self.sslobj = ctx.wrap_bio(
self.incoming, self.outgoing, **kwargs)
self.do(self.sslobj.do_handshake)
def do(self, func, *args):
while True:
try:
rv = func(*args)
break
except ssl.SSLWantReadError:
if self.outgoing.pending:
self.sock.send(self.outgoing.read())
self.incoming.write(self.sock.recv(65536))
if self.outgoing.pending:
self.sock.send(self.outgoing.read())
return rv
def send(self, data):
self.do(self.sslobj.write, data)
def unwrap(self):
self.do(self.sslobj.unwrap)
def close(self):
self.sock.unwrap()
self.sock.close()
class _ContextBaseTests(tb.SSLTestCase):
ONLYCERT = tb._cert_fullname(__file__, 'ssl_cert.pem')
ONLYKEY = tb._cert_fullname(__file__, 'ssl_key.pem')
def test_task_decimal_context(self):
async def fractions(t, precision, x, y):
with decimal.localcontext() as ctx:
ctx.prec = precision
a = decimal.Decimal(x) / decimal.Decimal(y)
await asyncio.sleep(t)
b = decimal.Decimal(x) / decimal.Decimal(y ** 2)
return a, b
async def main():
r1, r2 = await asyncio.gather(
fractions(0.1, 3, 1, 3), fractions(0.2, 6, 1, 3))
return r1, r2
r1, r2 = self.loop.run_until_complete(main())
self.assertEqual(str(r1[0]), '0.333')
self.assertEqual(str(r1[1]), '0.111')
self.assertEqual(str(r2[0]), '0.333333')
self.assertEqual(str(r2[1]), '0.111111')
def test_task_context_1(self):
cvar = contextvars.ContextVar('cvar', default='nope')
async def sub():
await asyncio.sleep(0.01)
self.assertEqual(cvar.get(), 'nope')
cvar.set('something else')
async def main():
self.assertEqual(cvar.get(), 'nope')
subtask = self.loop.create_task(sub())
cvar.set('yes')
self.assertEqual(cvar.get(), 'yes')
await subtask
self.assertEqual(cvar.get(), 'yes')
task = self.loop.create_task(main())
self.loop.run_until_complete(task)
def test_task_context_2(self):
cvar = contextvars.ContextVar('cvar', default='nope')
async def main():
def fut_on_done(fut):
# This change must not pollute the context
# of the "main()" task.
cvar.set('something else')
self.assertEqual(cvar.get(), 'nope')
for j in range(2):
fut = self.loop.create_future()
fut.add_done_callback(fut_on_done)
cvar.set('yes{}'.format(j))
self.loop.call_soon(fut.set_result, None)
await fut
self.assertEqual(cvar.get(), 'yes{}'.format(j))
for i in range(3):
# Test that task passed its context to add_done_callback:
cvar.set('yes{}-{}'.format(i, j))
await asyncio.sleep(0.001)
self.assertEqual(cvar.get(), 'yes{}-{}'.format(i, j))
task = self.loop.create_task(main())
self.loop.run_until_complete(task)
self.assertEqual(cvar.get(), 'nope')
def test_task_context_3(self):
cvar = contextvars.ContextVar('cvar', default=-1)
# Run 100 Tasks in parallel, each modifying cvar.
async def sub(num):
for i in range(10):
cvar.set(num + i)
await asyncio.sleep(random.uniform(0.001, 0.05))
self.assertEqual(cvar.get(), num + i)
async def main():
tasks = []
for i in range(100):
task = self.loop.create_task(sub(random.randint(0, 10)))
tasks.append(task)
await asyncio.gather(*tasks, return_exceptions=True)
self.loop.run_until_complete(main())
self.assertEqual(cvar.get(), -1)
def test_task_context_4(self):
cvar = contextvars.ContextVar('cvar', default='nope')
class TrackMe:
pass
tracked = TrackMe()
ref = weakref.ref(tracked)
async def sub():
cvar.set(tracked) # NoQA
self.loop.call_soon(lambda: None)
async def main():
await self.loop.create_task(sub())
await asyncio.sleep(0.01)
task = self.loop.create_task(main())
self.loop.run_until_complete(task)
del tracked
self.assertIsNone(ref())
def _run_test(self, method, **switches):
switches.setdefault('use_tcp', 'both')
use_ssl = switches.setdefault('use_ssl', 'no') in {'yes', 'both'}
names = ['factory']
options = [(_Protocol, _BufferedProtocol)]
for k, v in switches.items():
if v == 'yes':
options.append((True,))
elif v == 'no':
options.append((False,))
elif v == 'both':
options.append((True, False))
else:
raise ValueError(f"Illegal {k}={v}, can only be yes/no/both")
names.append(k)
for combo in itertools.product(*options):
values = dict(zip(names, combo))
with self.subTest(**values):
cvar = contextvars.ContextVar('cvar', default='outer')
values['proto'] = values.pop('factory')(cvar, loop=self.loop)
async def test():
self.assertEqual(cvar.get(), 'outer')
cvar.set('inner')
tmp_dir = tempfile.TemporaryDirectory()
if use_ssl:
values['sslctx'] = self._create_server_ssl_context(
self.ONLYCERT, self.ONLYKEY)
values['client_sslctx'] = \
self._create_client_ssl_context()
else:
values['sslctx'] = values['client_sslctx'] = None
if values['use_tcp']:
values['addr'] = ('127.0.0.1', tb.find_free_port())
values['family'] = socket.AF_INET
else:
values['addr'] = tmp_dir.name + '/test.sock'
values['family'] = socket.AF_UNIX
try:
await method(cvar=cvar, **values)
finally:
tmp_dir.cleanup()
self.loop.run_until_complete(test())
def _run_server_test(self, method, async_sock=False, **switches):
async def test(sslctx, client_sslctx, addr, family, **values):
if values['use_tcp']:
srv = await self.loop.create_server(
lambda: values['proto'], *addr, ssl=sslctx)
else:
srv = await self.loop.create_unix_server(
lambda: values['proto'], addr, ssl=sslctx)
s = socket.socket(family)
if async_sock:
s.setblocking(False)
await self.loop.sock_connect(s, addr)
else:
await self.loop.run_in_executor(
None, s.connect, addr)
if values['use_ssl']:
values['ssl_sock'] = await self.loop.run_in_executor(
None, client_sslctx.wrap_socket, s)
try:
await method(s=s, **values)
finally:
if values['use_ssl']:
values['ssl_sock'].close()
s.close()
srv.close()
await srv.wait_closed()
return self._run_test(test, **switches)
def test_create_server_protocol_factory_context(self):
async def test(cvar, proto, use_tcp, family, addr, **_):
factory_called_future = self.loop.create_future()
def factory():
try:
self.assertEqual(cvar.get(), 'inner')
except Exception as e:
factory_called_future.set_exception(e)
else:
factory_called_future.set_result(None)
return proto
if use_tcp:
srv = await self.loop.create_server(factory, *addr)
else:
srv = await self.loop.create_unix_server(factory, addr)
s = socket.socket(family)
with s:
s.setblocking(False)
await self.loop.sock_connect(s, addr)
try:
await factory_called_future
finally:
srv.close()
await proto.done
await srv.wait_closed()
self._run_test(test)
def test_create_server_connection_protocol(self):
async def test(proto, s, **_):
inner = await proto.connection_made_fut
self.assertEqual(inner, "inner")
await self.loop.sock_sendall(s, b'data')
inner = await proto.data_received_fut
self.assertEqual(inner, "inner")
s.shutdown(socket.SHUT_WR)
inner = await proto.eof_received_fut
self.assertEqual(inner, "inner")
s.close()
await proto.done
self.assertEqual(proto.connection_lost_ctx, "inner")
self._run_server_test(test, async_sock=True)
def test_create_ssl_server_connection_protocol(self):
async def test(cvar, proto, ssl_sock, **_):
def resume_reading(transport):
cvar.set("resume_reading")
transport.resume_reading()
try:
inner = await proto.connection_made_fut
self.assertEqual(inner, "inner")
await self.loop.run_in_executor(None, ssl_sock.send, b'data')
inner = await proto.data_received_fut
self.assertEqual(inner, "inner")
if self.implementation != 'asyncio':
# this seems to be a bug in asyncio
proto.data_received_fut = self.loop.create_future()
proto.transport.pause_reading()
await self.loop.run_in_executor(None,
ssl_sock.send, b'data')
self.loop.call_soon(resume_reading, proto.transport)
inner = await proto.data_received_fut
self.assertEqual(inner, "inner")
await self.loop.run_in_executor(None, ssl_sock.unwrap)
else:
ssl_sock.shutdown(socket.SHUT_WR)
inner = await proto.eof_received_fut
self.assertEqual(inner, "inner")
await self.loop.run_in_executor(None, ssl_sock.close)
await proto.done
self.assertEqual(proto.connection_lost_ctx, "inner")
finally:
if self.implementation == 'asyncio':
# mute resource warning in asyncio
proto.transport.close()
self._run_server_test(test, use_ssl='yes')
def test_create_server_manual_connection_lost(self):
if self.implementation == 'asyncio':
raise unittest.SkipTest('this seems to be a bug in asyncio')
async def test(proto, cvar, **_):
def close():
cvar.set('closing')
proto.transport.close()
inner = await proto.connection_made_fut
self.assertEqual(inner, "inner")
self.loop.call_soon(close)
await proto.done
self.assertEqual(proto.connection_lost_ctx, "inner")
self._run_server_test(test, async_sock=True)
def test_create_ssl_server_manual_connection_lost(self):
if self.implementation == 'asyncio' and sys.version_info >= (3, 11, 0):
# TODO(fantix): fix for 3.11
raise unittest.SkipTest('should pass on 3.11')
async def test(proto, cvar, ssl_sock, **_):
def close():
cvar.set('closing')
proto.transport.close()
inner = await proto.connection_made_fut
self.assertEqual(inner, "inner")
if self.implementation == 'asyncio':
self.loop.call_soon(close)
else:
# asyncio doesn't have the flushing phase
# put the incoming data on-hold
proto.transport.pause_reading()
# send data
await self.loop.run_in_executor(None,
ssl_sock.send, b'hello')
# schedule a proactive transport close which will trigger
# the flushing process to retrieve the remaining data
self.loop.call_soon(close)
# turn off the reading lock now (this also schedules a
# resume operation after transport.close, therefore it
# won't affect our test)
proto.transport.resume_reading()
await asyncio.sleep(0)
await self.loop.run_in_executor(None, ssl_sock.unwrap)
await proto.done
self.assertEqual(proto.connection_lost_ctx, "inner")
self.assertFalse(proto.data_received_fut.done())
self._run_server_test(test, use_ssl='yes')
def test_create_connection_protocol(self):
async def test(cvar, proto, addr, sslctx, client_sslctx, family,
use_sock, use_ssl, use_tcp):
ss = socket.socket(family)
ss.bind(addr)
ss.listen(1)
def accept():
sock, _ = ss.accept()
if use_ssl:
sock = sslctx.wrap_socket(sock, server_side=True)
return sock
async def write_over():
cvar.set("write_over")
count = 0
if use_ssl:
proto.transport.set_write_buffer_limits(high=256, low=128)
while not proto.transport.get_write_buffer_size():
proto.transport.write(b'q' * 16384)
count += 1
else:
proto.transport.set_write_buffer_limits(high=256, low=128)
while not proto.transport.get_write_buffer_size():
proto.transport.write(b'q' * 16384)
count += 1
return count
s = self.loop.run_in_executor(None, accept)
try:
method = ('create_connection' if use_tcp
else 'create_unix_connection')
params = {}
if use_sock:
cs = socket.socket(family)
cs.connect(addr)
params['sock'] = cs
if use_ssl:
params['server_hostname'] = '127.0.0.1'
elif use_tcp:
params['host'] = addr[0]
params['port'] = addr[1]
else:
params['path'] = addr
if use_ssl:
params['server_hostname'] = '127.0.0.1'
if use_ssl:
params['ssl'] = client_sslctx
await getattr(self.loop, method)(lambda: proto, **params)
s = await s
inner = await proto.connection_made_fut
self.assertEqual(inner, "inner")
await self.loop.run_in_executor(None, s.send, b'data')
inner = await proto.data_received_fut
self.assertEqual(inner, "inner")
if self.implementation != 'asyncio':
# asyncio bug
count = await self.loop.create_task(write_over())
inner = await proto.pause_writing_fut
self.assertEqual(inner, "inner")
for i in range(count):
await self.loop.run_in_executor(None, s.recv, 16384)
inner = await proto.resume_writing_fut
self.assertEqual(inner, "inner")
if use_ssl and self.implementation != 'asyncio':
await self.loop.run_in_executor(None, s.unwrap)
else:
s.shutdown(socket.SHUT_WR)
inner = await proto.eof_received_fut
self.assertEqual(inner, "inner")
s.close()
await proto.done
self.assertEqual(proto.connection_lost_ctx, "inner")
finally:
ss.close()
proto.transport.close()
self._run_test(test, use_sock='both', use_ssl='both')
def test_start_tls(self):
if self.implementation == 'asyncio':
raise unittest.SkipTest('this seems to be a bug in asyncio')
async def test(cvar, proto, addr, sslctx, client_sslctx, family,
ssl_over_ssl, use_tcp, **_):
ss = socket.socket(family)
ss.bind(addr)
ss.listen(1)
def accept():
sock, _ = ss.accept()
sock = sslctx.wrap_socket(sock, server_side=True)
if ssl_over_ssl:
sock = _SSLSocketOverSSL(sock, sslctx, server_side=True)
return sock
s = self.loop.run_in_executor(None, accept)
transport = None
try:
if use_tcp:
await self.loop.create_connection(lambda: proto, *addr)
else:
await self.loop.create_unix_connection(lambda: proto, addr)
inner = await proto.connection_made_fut
self.assertEqual(inner, "inner")
cvar.set('start_tls')
transport = await self.loop.start_tls(
proto.transport, proto, client_sslctx,
server_hostname='127.0.0.1',
)
if ssl_over_ssl:
cvar.set('start_tls_over_tls')
transport = await self.loop.start_tls(
transport, proto, client_sslctx,
server_hostname='127.0.0.1',
)
s = await s
await self.loop.run_in_executor(None, s.send, b'data')
inner = await proto.data_received_fut
self.assertEqual(inner, "inner")
await self.loop.run_in_executor(None, s.unwrap)
inner = await proto.eof_received_fut
self.assertEqual(inner, "inner")
s.close()
await proto.done
self.assertEqual(proto.connection_lost_ctx, "inner")
finally:
ss.close()
if transport:
transport.close()
self._run_test(test, use_ssl='yes', ssl_over_ssl='both')
def test_connect_accepted_socket(self):
async def test(proto, addr, family, sslctx, client_sslctx,
use_ssl, **_):
ss = socket.socket(family)
ss.bind(addr)
ss.listen(1)
s = self.loop.run_in_executor(None, ss.accept)
cs = socket.socket(family)
cs.connect(addr)
s, _ = await s
try:
if use_ssl:
cs = self.loop.run_in_executor(
None, client_sslctx.wrap_socket, cs)
await self.loop.connect_accepted_socket(lambda: proto, s,
ssl=sslctx)
cs = await cs
else:
await self.loop.connect_accepted_socket(lambda: proto, s)
inner = await proto.connection_made_fut
self.assertEqual(inner, "inner")
await self.loop.run_in_executor(None, cs.send, b'data')
inner = await proto.data_received_fut
self.assertEqual(inner, "inner")
if use_ssl and self.implementation != 'asyncio':
await self.loop.run_in_executor(None, cs.unwrap)
else:
cs.shutdown(socket.SHUT_WR)
inner = await proto.eof_received_fut
self.assertEqual(inner, "inner")
cs.close()
await proto.done
self.assertEqual(proto.connection_lost_ctx, "inner")
finally:
proto.transport.close()
ss.close()
self._run_test(test, use_ssl='both')
def test_subprocess_protocol(self):
cvar = contextvars.ContextVar('cvar', default='outer')
proto = _SubprocessProtocol(cvar, loop=self.loop)
async def test():
self.assertEqual(cvar.get(), 'outer')
cvar.set('inner')
await self.loop.subprocess_exec(
lambda: proto, sys.executable, b'-c',
b';'.join((b'import sys',
b'data = sys.stdin.buffer.read()',
b'sys.stdout.buffer.write(data)')))
try:
inner = await proto.connection_made_fut
self.assertEqual(inner, "inner")
proto.transport.get_pipe_transport(0).write(b'data')
proto.transport.get_pipe_transport(0).write_eof()
inner = await proto.data_received_fut
self.assertEqual(inner, "inner")
inner = await proto.pipe_connection_lost_fut
self.assertEqual(inner, "inner")
inner = await proto.process_exited_fut
if self.implementation != 'asyncio':
# bug in asyncio
self.assertEqual(inner, "inner")
await proto.done
if self.implementation != 'asyncio':
# bug in asyncio
self.assertEqual(proto.connection_lost_ctx, "inner")
finally:
proto.transport.close()
self.loop.run_until_complete(test())
def test_datagram_protocol(self):
cvar = contextvars.ContextVar('cvar', default='outer')
proto = _DatagramProtocol(cvar, loop=self.loop)
server_addr = ('127.0.0.1', 8888)
client_addr = ('127.0.0.1', 0)
async def run():
self.assertEqual(cvar.get(), 'outer')
cvar.set('inner')
def close():
cvar.set('closing')
proto.transport.close()
try:
await self.loop.create_datagram_endpoint(
lambda: proto, local_addr=server_addr)
inner = await proto.connection_made_fut
self.assertEqual(inner, "inner")
s = socket.socket(socket.AF_INET, type=socket.SOCK_DGRAM)
s.bind(client_addr)
s.sendto(b'data', server_addr)
inner = await proto.data_received_fut
self.assertEqual(inner, "inner")
self.loop.call_soon(close)
await proto.done
if self.implementation != 'asyncio':
# bug in asyncio
self.assertEqual(proto.connection_lost_ctx, "inner")
finally:
proto.transport.close()
s.close()
# let transports close
await asyncio.sleep(0.1)
self.loop.run_until_complete(run())
class Test_UV_Context(_ContextBaseTests, tb.UVTestCase):
pass
class Test_AIO_Context(_ContextBaseTests, tb.AIOTestCase):
pass
================================================
FILE: tests/test_cython.py
================================================
import asyncio
from uvloop._testbase import UVTestCase
class TestCythonIntegration(UVTestCase):
def test_cython_coro_is_coroutine(self):
from uvloop.loop import _test_coroutine_1
from asyncio.coroutines import _format_coroutine
coro = _test_coroutine_1()
coro_fmt = _format_coroutine(coro)
self.assertTrue(
coro_fmt.startswith('_test_coroutine_1() done')
or coro_fmt.startswith('_test_coroutine_1() running')
)
self.assertEqual(_test_coroutine_1.__qualname__, '_test_coroutine_1')
self.assertEqual(_test_coroutine_1.__name__, '_test_coroutine_1')
self.assertTrue(asyncio.iscoroutine(coro))
fut = asyncio.ensure_future(coro)
self.assertTrue(isinstance(fut, asyncio.Future))
self.assertTrue(isinstance(fut, asyncio.Task))
fut.cancel()
with self.assertRaises(asyncio.CancelledError):
self.loop.run_until_complete(fut)
try:
_format_coroutine(coro) # This line checks against Cython segfault
except TypeError:
# TODO: Fix Cython to not reset __name__/__qualname__ to None
pass
coro.close()
================================================
FILE: tests/test_dealloc.py
================================================
import asyncio
import subprocess
import sys
from uvloop import _testbase as tb
class TestDealloc(tb.UVTestCase):
def test_dealloc_1(self):
# Somewhere between Cython 0.25.2 and 0.26.0 uvloop programs
# started to trigger the following output:
#
# $ python prog.py
# Error in sys.excepthook:
#
# Original exception was:
#
# Upon some debugging, it appeared that Handle.__dealloc__ was
# called at a time where some CPython objects become non-functional,
# and any exception in __dealloc__ caused CPython to output the
# above.
#
# This regression test starts an event loop in debug mode,
# lets it run for a brief period of time, and exits the program.
# This will trigger Handle.__dealloc__, CallbackHandle.__dealloc__,
# and Loop.__dealloc__ methods. The test will fail if they produce
# any unwanted output.
async def test():
prog = '''\
import uvloop
async def foo():
return 42
def main():
loop = uvloop.new_event_loop()
loop.set_debug(True)
loop.run_until_complete(foo())
# Do not close the loop on purpose: let __dealloc__ methods run.
if __name__ == '__main__':
main()
'''
cmd = sys.executable
proc = await asyncio.create_subprocess_exec(
cmd, b'-W', b'ignore', b'-c', prog,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
await proc.wait()
out = await proc.stdout.read()
err = await proc.stderr.read()
return out, err
out, err = self.loop.run_until_complete(test())
self.assertEqual(out, b'', 'stdout is not empty')
self.assertEqual(err, b'', 'stderr is not empty')
================================================
FILE: tests/test_dns.py
================================================
import asyncio
import socket
import unittest
from uvloop import _testbase as tb
def patched_getaddrinfo(*args, **kwargs):
# corrected socket.getaddrinfo() behavior: ai_canonname always follows the
# flag AI_CANONNAME, even if `host` is an IP
rv = []
result = socket.getaddrinfo(*args, **kwargs)
first = True
for af, sk, proto, canon_name, addr in result:
if kwargs.get('flags', 0) & socket.AI_CANONNAME:
if not canon_name and first:
first = False
canon_name = args[0]
if not isinstance(canon_name, str):
canon_name = canon_name.decode('ascii')
elif canon_name:
canon_name = ''
rv.append((af, sk, proto, canon_name, addr))
return rv
class BaseTestDNS:
def _test_getaddrinfo(self, *args, _patch=False, _sorted=False, **kwargs):
err = None
try:
if _patch:
a1 = patched_getaddrinfo(*args, **kwargs)
else:
a1 = socket.getaddrinfo(*args, **kwargs)
except (socket.gaierror, UnicodeError) as ex:
err = ex
try:
a2 = self.loop.run_until_complete(
self.loop.getaddrinfo(*args, **kwargs))
except (socket.gaierror, UnicodeError) as ex:
if err is not None:
self.assertEqual(ex.args, err.args)
else:
ex.__context__ = err
raise ex
except OSError as ex:
ex.__context__ = err
raise ex
else:
if err is not None:
raise err
if _sorted:
if kwargs.get('flags', 0) & socket.AI_CANONNAME and a1 and a2:
# The API doesn't guarantee the ai_canonname value if
# multiple results are returned, but both implementations
# must return the same value for the first result.
self.assertEqual(a1[0][3], a2[0][3])
a1 = [(af, sk, pr, addr) for af, sk, pr, _, addr in a1]
a2 = [(af, sk, pr, addr) for af, sk, pr, _, addr in a2]
self.assertEqual(sorted(a1), sorted(a2))
else:
self.assertEqual(a1, a2)
def _test_getnameinfo(self, *args, **kwargs):
err = None
try:
a1 = socket.getnameinfo(*args, **kwargs)
except Exception as ex:
err = ex
try:
a2 = self.loop.run_until_complete(
self.loop.getnameinfo(*args, **kwargs))
except Exception as ex:
if err is not None:
if ex.__class__ is not err.__class__:
print(ex, err)
self.assertIs(ex.__class__, err.__class__)
self.assertEqual(ex.args, err.args)
else:
raise
else:
if err is not None:
raise err
self.assertEqual(a1, a2)
def test_getaddrinfo_1(self):
self._test_getaddrinfo('example.com', 80, _sorted=True)
self._test_getaddrinfo('example.com', 80, type=socket.SOCK_STREAM,
_sorted=True)
def test_getaddrinfo_2(self):
self._test_getaddrinfo('example.com', 80, flags=socket.AI_CANONNAME,
_sorted=True)
def test_getaddrinfo_3(self):
self._test_getaddrinfo('a' + '1' * 50 + '.wat', 800)
def test_getaddrinfo_4(self):
self._test_getaddrinfo('example.com', 80, family=-1)
self._test_getaddrinfo('example.com', 80, type=socket.SOCK_STREAM,
family=-1)
def test_getaddrinfo_5(self):
self._test_getaddrinfo('example.com', '80', _sorted=True)
self._test_getaddrinfo('example.com', '80', type=socket.SOCK_STREAM,
_sorted=True)
def test_getaddrinfo_6(self):
self._test_getaddrinfo(b'example.com', b'80', _sorted=True)
self._test_getaddrinfo(b'example.com', b'80', type=socket.SOCK_STREAM,
_sorted=True)
def test_getaddrinfo_7(self):
self._test_getaddrinfo(None, 0)
self._test_getaddrinfo(None, 0, type=socket.SOCK_STREAM)
def test_getaddrinfo_8(self):
self._test_getaddrinfo('', 0)
self._test_getaddrinfo('', 0, type=socket.SOCK_STREAM)
def test_getaddrinfo_9(self):
self._test_getaddrinfo(b'', 0)
self._test_getaddrinfo(b'', 0, type=socket.SOCK_STREAM)
def test_getaddrinfo_10(self):
self._test_getaddrinfo(None, None)
self._test_getaddrinfo(None, None, type=socket.SOCK_STREAM)
def test_getaddrinfo_11(self):
self._test_getaddrinfo(b'example.com', '80', _sorted=True)
self._test_getaddrinfo(b'example.com', '80', type=socket.SOCK_STREAM,
_sorted=True)
def test_getaddrinfo_12(self):
# musl always returns ai_canonname but we don't
patch = self.implementation != 'asyncio'
self._test_getaddrinfo('127.0.0.1', '80')
self._test_getaddrinfo('127.0.0.1', '80', type=socket.SOCK_STREAM,
_patch=patch)
def test_getaddrinfo_13(self):
# musl always returns ai_canonname but we don't
patch = self.implementation != 'asyncio'
self._test_getaddrinfo(b'127.0.0.1', b'80')
self._test_getaddrinfo(b'127.0.0.1', b'80', type=socket.SOCK_STREAM,
_patch=patch)
def test_getaddrinfo_14(self):
# musl always returns ai_canonname but we don't
patch = self.implementation != 'asyncio'
self._test_getaddrinfo(b'127.0.0.1', b'http')
self._test_getaddrinfo(b'127.0.0.1', b'http', type=socket.SOCK_STREAM,
_patch=patch)
def test_getaddrinfo_15(self):
# musl always returns ai_canonname but we don't
patch = self.implementation != 'asyncio'
self._test_getaddrinfo('127.0.0.1', 'http')
self._test_getaddrinfo('127.0.0.1', 'http', type=socket.SOCK_STREAM,
_patch=patch)
def test_getaddrinfo_16(self):
self._test_getaddrinfo('localhost', 'http')
self._test_getaddrinfo('localhost', 'http', type=socket.SOCK_STREAM)
def test_getaddrinfo_17(self):
self._test_getaddrinfo(b'localhost', 'http')
self._test_getaddrinfo(b'localhost', 'http', type=socket.SOCK_STREAM)
def test_getaddrinfo_18(self):
self._test_getaddrinfo('localhost', b'http')
self._test_getaddrinfo('localhost', b'http', type=socket.SOCK_STREAM)
def test_getaddrinfo_19(self):
# musl always returns ai_canonname while macOS never return for IPs,
# but we strictly follow the docs to use the AI_CANONNAME flag in a
# shortcut __static_getaddrinfo_pyaddr()
patch = self.implementation != 'asyncio'
self._test_getaddrinfo('::1', 80)
self._test_getaddrinfo('::1', 80, type=socket.SOCK_STREAM,
_patch=patch)
self._test_getaddrinfo('::1', 80, type=socket.SOCK_STREAM,
flags=socket.AI_CANONNAME, _patch=patch)
def test_getaddrinfo_20(self):
# musl always returns ai_canonname while macOS never return for IPs,
# but we strictly follow the docs to use the AI_CANONNAME flag in a
# shortcut __static_getaddrinfo_pyaddr()
patch = self.implementation != 'asyncio'
self._test_getaddrinfo('127.0.0.1', 80)
self._test_getaddrinfo('127.0.0.1', 80, type=socket.SOCK_STREAM,
_patch=patch)
self._test_getaddrinfo('127.0.0.1', 80, type=socket.SOCK_STREAM,
flags=socket.AI_CANONNAME, _patch=patch)
# https://github.com/libuv/libuv/security/advisories/GHSA-f74f-cvh7-c6q6
# See also: https://github.com/MagicStack/uvloop/pull/600
def test_getaddrinfo_21(self):
payload = f'0x{"0" * 246}7f000001.example.com'.encode('ascii')
self._test_getaddrinfo(payload, 80)
self._test_getaddrinfo(payload, 80, type=socket.SOCK_STREAM)
def test_getaddrinfo_22(self):
payload = f'0x{"0" * 246}7f000001.example.com'
self._test_getaddrinfo(payload, 80)
self._test_getaddrinfo(payload, 80, type=socket.SOCK_STREAM)
def test_getaddrinfo_broadcast(self):
self._test_getaddrinfo('<broadcast>', 80)
self._test_getaddrinfo('<broadcast>', 80, type=socket.SOCK_STREAM)
######
def test_getnameinfo_1(self):
self._test_getnameinfo(('127.0.0.1', 80), 0)
def test_getnameinfo_2(self):
self._test_getnameinfo(('127.0.0.1', 80, 1231231231213), 0)
def test_getnameinfo_3(self):
self._test_getnameinfo(('127.0.0.1', 80, 0, 0), 0)
def test_getnameinfo_4(self):
self._test_getnameinfo(('::1', 80), 0)
def test_getnameinfo_5(self):
self._test_getnameinfo(('localhost', 8080), 0)
class Test_UV_DNS(BaseTestDNS, tb.UVTestCase):
def test_getaddrinfo_close_loop(self):
# Test that we can close the loop with a running
# DNS query.
try:
# Check that we have internet connection
socket.getaddrinfo('example.com', 80)
except socket.error:
raise unittest.SkipTest
async def run():
fut = self.loop.create_task(
self.loop.getaddrinfo('example.com', 80))
await asyncio.sleep(0)
fut.cancel()
self.loop.stop()
try:
self.loop.run_until_complete(run())
finally:
self.loop.close()
class Test_AIO_DNS(BaseTestDNS, tb.AIOTestCase):
pass
================================================
FILE: tests/test_executors.py
================================================
import asyncio
import concurrent.futures
import multiprocessing
import unittest
from uvloop import _testbase as tb
def fib(n):
if n < 2:
return 1
return fib(n - 2) + fib(n - 1)
class _TestExecutors:
def run_pool_test(self, pool_factory):
async def run():
pool = pool_factory()
with pool:
coros = []
for i in range(0, 10):
coros.append(self.loop.run_in_executor(pool, fib, i))
res = await asyncio.gather(*coros)
self.assertEqual(res, fib10)
await asyncio.sleep(0.01)
fib10 = [fib(i) for i in range(10)]
self.loop.run_until_complete(run())
@unittest.skipIf(
multiprocessing.get_start_method(False) == 'spawn',
'no need to test on macOS where spawn is used instead of fork')
def test_executors_process_pool_01(self):
self.run_pool_test(concurrent.futures.ProcessPoolExecutor)
def test_executors_process_pool_02(self):
self.run_pool_test(concurrent.futures.ThreadPoolExecutor)
class TestUVExecutors(_TestExecutors, tb.UVTestCase):
pass
class TestAIOExecutors(_TestExecutors, tb.AIOTestCase):
pass
================================================
FILE: tests/test_fs_event.py
================================================
import asyncio
import contextlib
import os.path
import tempfile
from uvloop import _testbase as tb
from uvloop.loop import FileSystemEvent
class Test_UV_FS_Event(tb.UVTestCase):
def setUp(self):
super().setUp()
self.exit_stack = contextlib.ExitStack()
self.tmp_dir = self.exit_stack.enter_context(
tempfile.TemporaryDirectory()
)
def tearDown(self):
self.exit_stack.close()
super().tearDown()
def test_fs_event_change(self):
change_event_count = 0
filename = "fs_event_change.txt"
path = os.path.join(self.tmp_dir, filename)
q = asyncio.Queue()
with open(path, 'wt') as f:
async def file_writer():
while True:
f.write('hello uvloop\n')
f.flush()
x = await q.get()
if x is None:
return
def event_cb(ev_fname: bytes, evt: FileSystemEvent):
nonlocal change_event_count
self.assertEqual(ev_fname, filename.encode())
self.assertEqual(evt, FileSystemEvent.CHANGE)
change_event_count += 1
if change_event_count < 4:
q.put_nowait(0)
else:
q.put_nowait(None)
h = self.loop._monitor_fs(path, event_cb)
self.loop.run_until_complete(
asyncio.sleep(0.1) # let monitor start
)
self.assertFalse(h.cancelled())
self.loop.run_until_complete(asyncio.wait_for(file_writer(), 4))
h.cancel()
self.assertTrue(h.cancelled())
self.assertEqual(change_event_count, 4)
def test_fs_event_rename(self):
orig_name = "hello_fs_event.txt"
new_name = "hello_fs_event_rename.txt"
changed_set = {orig_name, new_name}
event = asyncio.Event()
async def file_renamer():
os.rename(os.path.join(self.tmp_dir, orig_name),
os.path.join(self.tmp_dir, new_name))
await event.wait()
def event_cb(ev_fname: bytes, evt: FileSystemEvent):
ev_fname = ev_fname.decode()
self.assertEqual(evt, FileSystemEvent.RENAME)
changed_set.discard(ev_fname)
if len(changed_set) == 0:
event.set()
with open(os.path.join(self.tmp_dir, orig_name), 'wt') as f:
f.write('hello!')
h = self.loop._monitor_fs(self.tmp_dir, event_cb)
self.loop.run_until_complete(asyncio.sleep(0.5)) # let monitor start
self.assertFalse(h.cancelled())
self.loop.run_until_complete(asyncio.wait_for(file_renamer(), 4))
h.cancel()
self.assertTrue(h.cancelled())
self.assertEqual(len(changed_set), 0)
================================================
FILE: tests/test_libuv_api.py
================================================
from uvloop import _testbase as tb
from uvloop.loop import libuv_get_loop_t_ptr, libuv_get_version
from uvloop.loop import _testhelper_unwrap_capsuled_pointer as unwrap
class Test_UV_libuv(tb.UVTestCase):
def test_libuv_get_loop_t_ptr(self):
loop1 = self.new_loop()
cap1 = libuv_get_loop_t_ptr(loop1)
cap2 = libuv_get_loop_t_ptr(loop1)
loop2 = self.new_loop()
cap3 = libuv_get_loop_t_ptr(loop2)
try:
self.assertEqual(unwrap(cap1), unwrap(cap2))
self.assertNotEqual(unwrap(cap1), unwrap(cap3))
finally:
loop1.close()
loop2.close()
def test_libuv_get_version(self):
self.assertGreater(libuv_get_version(), 0)
================================================
FILE: tests/test_pipes.py
================================================
import asyncio
import io
import os
import socket
from uvloop import _testbase as tb
# All tests are copied from asyncio (mostly as-is)
class MyReadPipeProto(asyncio.Protocol):
done = None
def __init__(self, loop=None):
self.state = ['INITIAL']
self.nbytes = 0
self.transport = None
if loop is not None:
self.done = asyncio.Future(loop=loop)
def connection_made(self, transport):
self.transport = transport
assert self.state == ['INITIAL'], self.state
self.state.append('CONNECTED')
def data_received(self, data):
assert self.state == ['INITIAL', 'CONNECTED'], self.state
self.nbytes += len(data)
def eof_received(self):
assert self.state == ['INITIAL', 'CONNECTED'], self.state
self.state.append('EOF')
def connection_lost(self, exc):
if 'EOF' not in self.state:
self.state.append('EOF') # It is okay if EOF is missed.
assert self.state == ['INITIAL', 'CONNECTED', 'EOF'], self.state
self.state.append('CLOSED')
if self.done:
self.done.set_result(None)
class MyWritePipeProto(asyncio.BaseProtocol):
done = None
paused = False
def __init__(self, loop=None):
self.state = 'INITIAL'
self.transport = None
if loop is not None:
self.done = asyncio.Future(loop=loop)
def connection_made(self, transport):
self.transport = transport
assert self.state == 'INITIAL', self.state
self.state = 'CONNECTED'
def connection_lost(self, exc):
assert self.state == 'CONNECTED', self.state
self.state = 'CLOSED'
if self.done:
self.done.set_result(None)
def pause_writing(self):
self.paused = True
def resume_writing(self):
self.paused = False
class _BasePipeTest:
def test_read_pipe(self):
proto = MyReadPipeProto(loop=self.loop)
rpipe, wpipe = os.pipe()
pipeobj = io.open(rpipe, 'rb', 1024)
async def connect():
t, p = await self.loop.connect_read_pipe(
lambda: proto, pipeobj)
self.assertIs(p, proto)
self.assertIs(t, proto.transport)
self.assertEqual(['INITIAL', 'CONNECTED'], proto.state)
self.assertEqual(0, proto.nbytes)
self.loop.run_until_complete(connect())
os.write(wpipe, b'1')
tb.run_until(self.loop, lambda: proto.nbytes >= 1)
self.assertEqual(1, proto.nbytes)
os.write(wpipe, b'2345')
tb.run_until(self.loop, lambda: proto.nbytes >= 5)
self.assertEqual(['INITIAL', 'CONNECTED'], proto.state)
self.assertEqual(5, proto.nbytes)
os.close(wpipe)
self.loop.run_until_complete(proto.done)
self.assertEqual(
['INITIAL', 'CONNECTED', 'EOF', 'CLOSED'], proto.state)
# extra info is available
self.assertIsNotNone(proto.transport.get_extra_info('pipe'))
def test_read_pty_output(self):
proto = MyReadPipeProto(loop=self.loop)
master, slave = os.openpty()
master_read_obj = io.open(master, 'rb', 0)
async def connect():
t, p = await self.loop.connect_read_pipe(
lambda: proto, master_read_obj)
self.assertIs(p, proto)
self.assertIs(t, proto.transport)
self.assertEqual(['INITIAL', 'CONNECTED'], proto.state)
self.assertEqual(0, proto.nbytes)
self.loop.run_until_complete(connect())
os.write(slave, b'1')
tb.run_until(self.loop, lambda: proto.nbytes)
self.assertEqual(1, proto.nbytes)
os.write(slave, b'2345')
tb.run_until(self.loop, lambda: proto.nbytes >= 5)
self.assertEqual(['INITIAL', 'CONNECTED'], proto.state)
self.assertEqual(5, proto.nbytes)
# On Linux, transport raises EIO when slave is closed --
# ignore it.
self.loop.set_exception_handler(lambda loop, ctx: None)
os.close(slave)
proto.transport.close()
self.loop.run_until_complete(proto.done)
self.assertEqual(
['INITIAL', 'CONNECTED', 'EOF', 'CLOSED'], proto.state)
# extra info is available
self.assertIsNotNone(proto.transport.get_extra_info('pipe'))
def test_write_pipe(self):
rpipe, wpipe = os.pipe()
os.set_blocking(rpipe, False)
pipeobj = io.open(wpipe, 'wb', 1024)
proto = MyWritePipeProto(loop=self.loop)
connect = self.loop.connect_write_pipe(lambda: proto, pipeobj)
transport, p = self.loop.run_until_complete(connect)
self.assertIs(p, proto)
self.assertIs(transport, proto.transport)
self.assertEqual('CONNECTED', proto.state)
transport.write(b'1')
data = bytearray()
def reader(data):
try:
chunk = os.read(rpipe, 1024)
except BlockingIOError:
return len(data)
data += chunk
return len(data)
tb.run_until(self.loop, lambda: reader(data) >= 1)
self.assertEqual(b'1', data)
transport.write(b'2345')
tb.run_until(self.loop, lambda: reader(data) >= 5)
self.assertEqual(b'12345', data)
self.assertEqual('CONNECTED', proto.state)
os.close(rpipe)
# extra info is available
self.assertIsNotNone(proto.transport.get_extra_info('pipe'))
# close connection
proto.transport.close()
self.loop.run_until_complete(proto.done)
self.assertEqual('CLOSED', proto.state)
def test_write_pipe_disconnect_on_close(self):
rsock, wsock = socket.socketpair()
rsock.setblocking(False)
pipeobj = io.open(wsock.detach(), 'wb', 1024)
proto = MyWritePipeProto(loop=self.loop)
connect = self.loop.connect_write_pipe(lambda: proto, pipeobj)
transport, p = self.loop.run_until_complete(connect)
self.assertIs(p, proto)
self.assertIs(transport, proto.transport)
self.assertEqual('CONNECTED', proto.state)
transport.write(b'1')
data = self.loop.run_until_complete(self.loop.sock_recv(rsock, 1024))
self.assertEqual(b'1', data)
rsock.close()
self.loop.run_until_complete(proto.done)
self.assertEqual('CLOSED', proto.state)
def test_write_pty(self):
master, slave = os.openpty()
os.set_blocking(master, False)
slave_write_obj = io.open(slave, 'wb', 0)
proto = MyWritePipeProto(loop=self.loop)
connect = self.loop.connect_write_pipe(lambda: proto, slave_write_obj)
transport, p = self.loop.run_until_complete(connect)
self.assertIs(p, proto)
self.assertIs(transport, proto.transport)
self.assertEqual('CONNECTED', proto.state)
transport.write(b'1')
data = bytearray()
def reader(data):
try:
chunk = os.read(master, 1024)
except BlockingIOError:
return len(data)
data += chunk
return len(data)
tb.run_until(self.loop, lambda: reader(data) >= 1,
timeout=10)
self.assertEqual(b'1', data)
transport.write(b'2345')
tb.run_until(self.loop, lambda: reader(data) >= 5,
timeout=10)
self.assertEqual(b'12345', data)
self.assertEqual('CONNECTED', proto.state)
os.close(master)
# extra info is available
self.assertIsNotNone(proto.transport.get_extra_info('pipe'))
# close connection
proto.transport.close()
self.loop.run_until_complete(proto.done)
self.assertEqual('CLOSED', proto.state)
def test_write_buffer_full(self):
rpipe, wpipe = os.pipe()
pipeobj = io.open(wpipe, 'wb', 1024)
proto = MyWritePipeProto(loop=self.loop)
connect = self.loop.connect_write_pipe(lambda: proto, pipeobj)
transport, p = self.loop.run_until_complete(connect)
self.assertIs(p, proto)
self.assertIs(transport, proto.transport)
self.assertEqual('CONNECTED', proto.state)
for i in range(32):
transport.write(b'x' * 32768)
if proto.paused:
transport.write(b'x' * 32768)
break
else:
self.fail("Didn't reach a full buffer")
os.close(rpipe)
self.loop.run_until_complete(asyncio.wait_for(proto.done, 1))
self.assertEqual('CLOSED', proto.state)
class Test_UV_Pipes(_BasePipeTest, tb.UVTestCase):
pass
class Test_AIO_Pipes(_BasePipeTest, tb.AIOTestCase):
pass
================================================
FILE: tests/test_process.py
================================================
import asyncio
import contextlib
import gc
import os
import pathlib
import signal
import subprocess
import sys
import tempfile
import textwrap
import time
import unittest
import psutil
from uvloop import _testbase as tb
class _RedirectFD(contextlib.AbstractContextManager):
def __init__(self, old_file, new_file):
self._old_fd = old_file.fileno()
self._old_fd_save = os.dup(self._old_fd)
self._new_fd = new_file.fileno()
def __enter__(self):
os.dup2(self._new_fd, self._old_fd)
def __exit__(self, exc_type, exc_val, exc_tb):
os.dup2(self._old_fd_save, self._old_fd)
os.close(self._old_fd_save)
class _TestProcess:
def get_num_fds(self):
return psutil.Process(os.getpid()).num_fds()
def test_process_env_1(self):
async def test():
cmd = 'echo $FOO$BAR'
env = {'FOO': 'sp', 'BAR': 'am'}
proc = await asyncio.create_subprocess_shell(
cmd,
env=env,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
out, _ = await proc.communicate()
self.assertEqual(out, b'spam\n')
self.assertEqual(proc.returncode, 0)
self.loop.run_until_complete(test())
def test_process_env_2(self):
async def test():
cmd = 'env'
env = {} # empty environment
proc = await asyncio.create_subprocess_exec(
cmd,
env=env,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
out, _ = await proc.communicate()
self.assertEqual(out, b'')
self.assertEqual(proc.returncode, 0)
self.loop.run_until_complete(test())
def test_process_cwd_1(self):
async def test():
cmd = 'pwd'
env = {}
cwd = '/'
proc = await asyncio.create_subprocess_shell(
cmd,
cwd=cwd,
env=env,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
out, _ = await proc.communicate()
self.assertEqual(out, b'/\n')
self.assertEqual(proc.returncode, 0)
self.loop.run_until_complete(test())
@unittest.skipUnless(hasattr(os, 'fspath'), 'no os.fspath()')
def test_process_cwd_2(self):
async def test():
cmd = 'pwd'
env = {}
cwd = pathlib.Path('/')
proc = await asyncio.create_subprocess_shell(
cmd,
cwd=cwd,
env=env,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
out, _ = await proc.communicate()
self.assertEqual(out, b'/\n')
self.assertEqual(proc.returncode, 0)
self.loop.run_until_complete(test())
def test_process_preexec_fn_1(self):
# Copied from CPython/test_suprocess.py
# DISCLAIMER: Setting environment variables is *not* a good use
# of a preexec_fn. This is merely a test.
async def test():
cmd = sys.executable
proc = await asyncio.create_subprocess_exec(
cmd, b'-W', b'ignore', '-c',
'import os,sys;sys.stdout.write(os.getenv("FRUIT"))',
stdout=subprocess.PIPE,
preexec_fn=lambda: os.putenv("FRUIT", "apple"))
out, _ = await proc.communicate()
self.assertEqual(out, b'apple')
self.assertEqual(proc.returncode, 0)
self.loop.run_until_complete(test())
def test_process_preexec_fn_2(self):
# Copied from CPython/test_suprocess.py
def raise_it():
raise ValueError("spam")
async def test():
cmd = sys.executable
proc = await asyncio.create_subprocess_exec(
cmd, b'-W', b'ignore', '-c', 'import time; time.sleep(10)',
preexec_fn=raise_it)
await proc.communicate()
started = time.time()
try:
self.loop.run_until_complete(test())
except subprocess.SubprocessError as ex:
self.assertIn('preexec_fn', ex.args[0])
if ex.__cause__ is not None:
# uvloop will set __cause__
self.assertIs(type(ex.__cause__), ValueError)
self.assertEqual(ex.__cause__.args[0], 'spam')
else:
self.fail(
'exception in preexec_fn did not propagate to the parent')
if time.time() - started > 5:
self.fail(
'exception in preexec_fn did not kill the child process')
def test_process_executable_1(self):
async def test():
proc = await asyncio.create_subprocess_exec(
b'doesnotexist', b'-W', b'ignore', b'-c', b'print("spam")',
executable=sys.executable,
stdout=subprocess.PIPE)
out, err = await proc.communicate()
self.assertEqual(out, b'spam\n')
self.loop.run_until_complete(test())
def test_process_executable_2(self):
async def test():
proc = await asyncio.create_subprocess_exec(
pathlib.Path(sys.executable),
b'-W', b'ignore', b'-c', b'print("spam")',
stdout=subprocess.PIPE)
out, err = await proc.communicate()
self.assertEqual(out, b'spam\n')
self.loop.run_until_complete(test())
def test_process_pid_1(self):
async def test():
prog = '''\
import os
print(os.getpid())
'''
cmd = sys.executable
proc = await asyncio.create_subprocess_exec(
cmd, b'-W', b'ignore', b'-c', prog,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE)
pid = proc.pid
expected_result = '{}\n'.format(pid).encode()
out, err = await proc.communicate()
self.assertEqual(out, expected_result)
self.loop.run_until_complete(test())
def test_process_send_signal_1(self):
async def test():
prog = '''\
import signal
def handler(signum, frame):
if signum == signal.SIGUSR1:
print('WORLD')
signal.signal(signal.SIGUSR1, handler)
a = input()
print(a)
a = input()
print(a)
exit(11)
'''
cmd = sys.executable
proc = await asyncio.create_subprocess_exec(
cmd, b'-W', b'ignore', b'-c', prog,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
proc.stdin.write(b'HELLO\n')
await proc.stdin.drain()
self.assertEqual(await proc.stdout.readline(), b'HELLO\n')
proc.send_signal(signal.SIGUSR1)
proc.stdin.write(b'!\n')
await proc.stdin.drain()
self.assertEqual(await proc.stdout.readline(), b'WORLD\n')
self.assertEqual(await proc.stdout.readline(), b'!\n')
self.assertEqual(await proc.wait(), 11)
self.loop.run_until_complete(test())
def test_process_streams_basic_1(self):
async def test():
prog = '''\
import sys
while True:
a = input()
if a == 'stop':
exit(20)
elif a == 'stderr':
print('OUCH', file=sys.stderr)
else:
print('>' + a + '<')
'''
cmd = sys.executable
proc = await asyncio.create_subprocess_exec(
cmd, b'-W', b'ignore', b'-c', prog,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
self.assertGreater(proc.pid, 0)
self.assertIs(proc.returncode, None)
transp = proc._transport
with self.assertRaises(NotImplementedError):
# stdin is WriteTransport
transp.get_pipe_transport(0).pause_reading()
with self.assertRaises((NotImplementedError, AttributeError)):
# stdout is ReadTransport
transp.get_pipe_transport(1).write(b'wat')
proc.stdin.write(b'foobar\n')
await proc.stdin.drain()
out = await proc.stdout.readline()
self.assertEqual(out, b'>foobar<\n')
proc.stdin.write(b'stderr\n')
await proc.stdin.drain()
out = await proc.stderr.readline()
self.assertEqual(out, b'OUCH\n')
proc.stdin.write(b'stop\n')
await proc.stdin.drain()
exitcode = await proc.wait()
self.assertEqual(exitcode, 20)
self.loop.run_until_complete(test())
def test_process_streams_stderr_to_stdout(self):
async def test():
prog = '''\
import sys
print('out', flush=True)
print('err', file=sys.stderr, flush=True)
'''
proc = await asyncio.create_subprocess_exec(
sys.executable, b'-W', b'ignore', b'-c', prog,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
out, err = await proc.communicate()
self.assertIsNone(err)
self.assertEqual(out, b'out\nerr\n')
self.loop.run_until_complete(test())
def test_process_streams_devnull(self):
async def test():
prog = '''\
import sys
print('out', flush=True)
print('err', file=sys.stderr, flush=True)
'''
proc = await asyncio.create_subprocess_exec(
sys.executable, b'-W', b'ignore', b'-c', prog,
stdin=subprocess.DEVNULL,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL)
out, err = await proc.communicate()
self.assertIsNone(err)
self.assertIsNone(out)
self.loop.run_until_complete(test())
def test_process_streams_pass_fds(self):
async def test():
prog = '''\
import sys, os
assert sys.argv[1] == '--'
inherited = int(sys.argv[2])
non_inherited = int(sys.argv[3])
os.fstat(inherited)
try:
os.fstat(non_inherited)
except:
pass
else:
raise RuntimeError()
print("OK")
'''
with tempfile.TemporaryFile() as inherited, \
tempfile.TemporaryFile() as non_inherited:
proc = await asyncio.create_subprocess_exec(
sys.executable, b'-W', b'ignore', b'-c', prog, '--',
str(inherited.fileno()),
str(non_inherited.fileno()),
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
pass_fds=(inherited.fileno(),))
out, err = await proc.communicate()
self.assertEqual(err, b'')
self.assertEqual(out, b'OK\n')
self.loop.run_until_complete(test())
def test_subprocess_fd_leak_1(self):
async def main(n):
for i in range(n):
try:
await asyncio.create_subprocess_exec(
'nonexistant',
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL)
except FileNotFoundError:
pass
await asyncio.sleep(0)
self.loop.run_until_complete(main(10))
num_fd_1 = self.get_num_fds()
self.loop.run_until_complete(main(10))
num_fd_2 = self.get_num_fds()
self.assertEqual(num_fd_1, num_fd_2)
def test_subprocess_fd_leak_2(self):
async def main(n):
for i in range(n):
try:
p = await asyncio.create_subprocess_exec(
'ls',
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL)
finally:
await p.wait()
await asyncio.sleep(0)
self.loop.run_until_complete(main(10))
num_fd_1 = self.get_num_fds()
self.loop.run_until_complete(main(10))
num_fd_2 = self.get_num_fds()
self.assertEqual(num_fd_1, num_fd_2)
def test_subprocess_invalid_stdin(self):
fd = None
for tryfd in range(10000, 1000, -1):
try:
tryfd = os.dup(tryfd)
except OSError:
fd = tryfd
break
else:
os.close(tryfd)
else:
self.fail('could not find a free FD')
async def main():
with self.assertRaises(OSError):
await asyncio.create_subprocess_exec(
'ls',
stdin=fd)
with self.assertRaises(OSError):
await asyncio.create_subprocess_exec(
'ls',
stdout=fd)
with self.assertRaises(OSError):
await asyncio.create_subprocess_exec(
'ls',
stderr=fd)
self.loop.run_until_complete(main())
def test_process_streams_redirect(self):
async def test():
prog = bR'''
import sys
print('out', flush=True)
print('err', file=sys.stderr, flush=True)
'''
proc = await asyncio.create_subprocess_exec(
sys.executable, b'-W', b'ignore', b'-c', prog)
out, err = await proc.communicate()
self.assertIsNone(out)
self.assertIsNone(err)
with tempfile.NamedTemporaryFile('w') as stdout:
with tempfile.NamedTemporaryFile('w') as stderr:
with _RedirectFD(sys.stdout, stdout):
with _RedirectFD(sys.stderr, stderr):
self.loop.run_until_complete(test())
stdout.flush()
stderr.flush()
with open(stdout.name, 'rb') as so:
self.assertEqual(so.read(), b'out\n')
with open(stderr.name, 'rb') as se:
self.assertEqual(se.read(), b'err\n')
class _AsyncioTests:
# Program blocking
PROGRAM_BLOCKED = [sys.executable, b'-W', b'ignore',
b'-c', b'import time; time.sleep(3600)']
# Program copying input to output
PROGRAM_CAT = [
sys.executable, b'-c',
b';'.join((b'import sys',
b'data = sys.stdin.buffer.read()',
b'sys.stdout.buffer.write(data)'))]
PROGRAM_ERROR = [
sys.executable, b'-W', b'ignore', b'-c', b'1/0'
]
def test_stdin_not_inheritable(self):
# asyncio issue #209: stdin must not be inheritable, otherwise
# the Process.communicate() hangs
async def len_message(message):
code = 'import sys; data = sys.stdin.read(); print(len(data))'
proc = await asyncio.create_subprocess_exec(
sys.executable, b'-W', b'ignore', b'-c', code,
stdin=asyncio.subprocess.PIPE,
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE,
close_fds=False)
stdout, stderr = await proc.communicate(message)
exitcode = await proc.wait()
return (stdout, exitcode)
output, exitcode = self.loop.run_until_complete(len_message(b'abc'))
self.assertEqual(output.rstrip(), b'3')
self.assertEqual(exitcode, 0)
def test_stdin_stdout_pipe(self):
args = self.PROGRAM_CAT
async def run(data):
proc = await asyncio.create_subprocess_exec(
*args,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE)
# feed data
proc.stdin.write(data)
await proc.stdin.drain()
proc.stdin.close()
# get output and exitcode
data = await proc.stdout.read()
exitcode = await proc.wait()
return (exitcode, data)
task = run(b'some data')
task = asyncio.wait_for(task, 60.0)
exitcode, stdout = self.loop.run_until_complete(task)
self.assertEqual(exitcode, 0)
self.assertEqual(stdout, b'some data')
def test_stdin_stdout_file(self):
args = self.PROGRAM_CAT
async def run(data, stdout):
proc = await asyncio.create_subprocess_exec(
*args,
stdin=subprocess.PIPE,
stdout=stdout)
# feed data
proc.stdin.write(data)
await proc.stdin.drain()
proc.stdin.close()
exitcode = await proc.wait()
return exitcode
with tempfile.TemporaryFile('w+b') as new_stdout:
task = run(b'some data', new_stdout)
task = asyncio.wait_for(task, 60.0)
exitcode = self.loop.run_until_complete(task)
self.assertEqual(exitcode, 0)
new_stdout.seek(0)
self.assertEqual(new_stdout.read(), b'some data')
def test_stdin_stderr_file(self):
args = self.PROGRAM_ERROR
async def run(stderr):
proc = await asyncio.create_subprocess_exec(
*args,
stdin=subprocess.PIPE,
stderr=stderr)
exitcode = await proc.wait()
return exitcode
with tempfile.TemporaryFile('w+b') as new_stderr:
task = run(new_stderr)
task = asyncio.wait_for(task, 60.0)
exitcode = self.loop.run_until_complete(task)
self.assertEqual(exitcode, 1)
new_stderr.seek(0)
self.assertIn(b'ZeroDivisionError', new_stderr.read())
def test_communicate(self):
args = self.PROGRAM_CAT
async def run(data):
proc = await asyncio.create_subprocess_exec(
*args,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE)
stdout, stderr = await proc.communicate(data)
return proc.returncode, stdout
task = run(b'some data')
task = asyncio.wait_for(task, 60.0)
exitcode, stdout = self.loop.run_until_complete(task)
self.assertEqual(exitcode, 0)
self.assertEqual(stdout, b'some data')
def test_start_new_session(self):
# start the new process in a new session
create = asyncio.create_subprocess_shell('exit 8',
start_new_session=True)
proc = self.loop.run_until_complete(create)
exitcode = self.loop.run_until_complete(proc.wait())
self.assertEqual(exitcode, 8)
def test_shell(self):
create = asyncio.create_subprocess_shell('exit 7')
proc = self.loop.run_until_complete(create)
exitcode = self.loop.run_until_complete(proc.wait())
self.assertEqual(exitcode, 7)
def test_kill(self):
args = self.PROGRAM_BLOCKED
create = asyncio.create_subprocess_exec(*args)
proc = self.loop.run_until_complete(create)
proc.kill()
returncode = self.loop.run_until_complete(proc.wait())
self.assertEqual(-signal.SIGKILL, returncode)
def test_terminate(self):
args = self.PROGRAM_BLOCKED
create = asyncio.create_subprocess_exec(*args)
proc = self.loop.run_until_complete(create)
proc.terminate()
returncode = self.loop.run_until_complete(proc.wait())
self.assertEqual(-signal.SIGTERM, returncode)
def test_send_signal(self):
code = 'import time; print("sleeping", flush=True); time.sleep(3600)'
args = [sys.executable, b'-W', b'ignore', b'-c', code]
create = asyncio.create_subprocess_exec(*args,
stdout=subprocess.PIPE)
proc = self.loop.run_until_complete(create)
async def send_signal(proc):
# basic synchronization to wait until the program is sleeping
line = await proc.stdout.readline()
self.assertEqual(line, b'sleeping\n')
proc.send_signal(signal.SIGHUP)
returncode = (await proc.wait())
return returncode
returncode = self.loop.run_until_complete(send_signal(proc))
self.assertEqual(-signal.SIGHUP, returncode)
def test_cancel_process_wait(self):
# Issue #23140: cancel Process.wait()
async def cancel_wait():
proc = await asyncio.create_subprocess_exec(
*self.PROGRAM_BLOCKED)
# Create an internal future waiting on the process exit
task = self.loop.create_task(proc.wait())
self.loop.call_soon(task.cancel)
try:
await task
except asyncio.CancelledError:
pass
# Cancel the future
task.cancel()
# Kill the process and wait until it is done
proc.kill()
await proc.wait()
self.loop.run_until_complete(cancel_wait())
def test_cancel_make_subprocess_transport_exec(self):
async def cancel_make_transport():
coro = asyncio.create_subprocess_exec(*self.PROGRAM_BLOCKED)
task = self.loop.create_task(coro)
self.loop.call_soon(task.cancel)
try:
await task
except asyncio.CancelledError:
pass
# Give the process handler some time to close itself
await asyncio.sleep(0.3)
gc.collect()
# ignore the log:
# "Exception during subprocess creation, kill the subprocess"
with tb.disable_logger():
self.loop.run_until_complete(cancel_make_transport())
def test_cancel_post_init(self):
if sys.version_info >= (3, 13) and self.implementation == 'asyncio':
# https://github.com/python/cpython/issues/103847#issuecomment-3736561321
# This test started to flake on CPython 3.13 and later,
# so we skip it for asyncio tests until the issue is resolved.
self.skipTest('flaky test on CPython 3.13+')
async def cancel_make_transport():
coro = self.loop.subprocess_exec(asyncio.SubprocessProtocol,
*self.PROGRAM_BLOCKED)
task = self.loop.create_task(coro)
self.loop.call_soon(task.cancel)
try:
await task
except asyncio.CancelledError:
pass
# Give the process handler some time to close itself
await asyncio.sleep(0.3)
gc.collect()
# ignore the log:
# "Exception during subprocess creation, kill the subprocess"
with tb.disable_logger():
self.loop.run_until_complete(cancel_make_transport())
tb.run_briefly(self.loop)
def test_close_gets_process_closed(self):
loop = self.loop
class Protocol(asyncio.SubprocessProtocol):
def __init__(self):
self.closed = loop.create_future()
def connection_lost(self, exc):
self.closed.set_result(1)
async def test_subprocess():
transport, protocol = await loop.subprocess_exec(
Protocol, *self.PROGRAM_BLOCKED)
pid = transport.get_pid()
transport.close()
self.assertIsNone(transport.get_returncode())
await protocol.closed
self.assertIsNotNone(transport.get_returncode())
with self.assertRaises(ProcessLookupError):
os.kill(pid, 0)
loop.run_until_complete(test_subprocess())
def test_communicate_large_stdout_65536(self):
self._test_communicate_large_stdout(65536)
def test_communicate_large_stdout_65537(self):
self._test_communicate_large_stdout(65537)
def test_communicate_large_stdout_1000000(self):
self._test_communicate_large_stdout(1000000)
def _test_communicate_large_stdout(self, size):
async def copy_stdin_to_stdout(stdin):
# See https://github.com/MagicStack/uvloop/issues/363
# A program that copies stdin to stdout character by character
code = ('import sys, shutil; '
'shutil.copyfileobj(sys.stdin, sys.stdout, 1)')
proc = await asyncio.create_subprocess_exec(
sys.executable, b'-W', b'ignore', b'-c', code,
stdin=asyncio.subprocess.PIPE,
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE)
stdout, _stderr = await asyncio.wait_for(proc.communicate(stdin),
60.0)
return stdout
stdin = b'x' * size
stdout = self.loop.run_until_complete(copy_stdin_to_stdout(stdin))
self.assertEqual(stdout, stdin)
def test_write_huge_stdin_8192(self):
self._test_write_huge_stdin(8192)
def test_write_huge_stdin_8193(self):
self._test_write_huge_stdin(8193)
def test_write_huge_stdin_219263(self):
self._test_write_huge_stdin(219263)
def test_write_huge_stdin_219264(self):
self._test_write_huge_stdin(219264)
def _test_write_huge_stdin(self, buf_size):
code = '''
import sys
n = 0
while True:
line = sys.stdin.readline()
if not line:
print("unexpected EOF", file=sys.stderr)
break
if line == "END\\n":
break
n+=1
print(n)'''
num_lines = buf_size - len(b"END\n")
args = [sys.executable, b'-W', b'ignore', b'-c', code]
async def test():
proc = await asyncio.create_subprocess_exec(
*args,
stdout=asyncio.subprocess.PIPE,
stdin=asyncio.subprocess.PIPE)
data = b"\n" * num_lines + b"END\n"
self.assertEqual(len(data), buf_size)
proc.stdin.write(data)
await asyncio.wait_for(proc.stdin.drain(), timeout=5.0)
try:
await asyncio.wait_for(proc.wait(), timeout=5.0)
except asyncio.TimeoutError:
proc.kill()
proc.stdin.close()
await proc.wait()
raise
out = await proc.stdout.read()
self.assertEqual(int(out), num_lines)
self.loop.run_until_complete(test())
class Test_UV_Process(_TestProcess, tb.UVTestCase):
def test_process_double_close(self):
script = textwrap.dedent("""
import os
import sys
from unittest import mock
import asyncio
pipes = []
original_os_pipe = os.pipe
def log_pipes():
pipe = original_os_pipe()
pipes.append(pipe)
return pipe
dups = []
original_os_dup = os.dup
def log_dups(*args, **kwargs):
dup = original_os_dup(*args, **kwargs)
dups.append(dup)
return dup
with mock.patch(
"os.close", wraps=os.close
) as os_close, mock.patch(
"os.pipe", new=log_pipes
), mock.patch(
"os.dup", new=log_dups
):
import uvloop
async def test():
proc = await asyncio.create_subprocess_exec(
sys.executable, "-c", "pass"
)
await proc.communicate()
uvloop.run(test())
stdin, stdout, stderr = dups
(r, w), = pipes
assert os_close.mock_calls == [
mock.call(w),
mock.call(r),
mock.call(stderr),
mock.call(stdout),
mock.call(stdin),
]
""")
subprocess.run([sys.executable, '-c', script], check=True)
class Test_AIO_Process(_TestProcess, tb.AIOTestCase):
pass
class TestAsyncio_UV_Process(_AsyncioTests, tb.UVTestCase):
pass
class TestAsyncio_AIO_Process(_AsyncioTests, tb.AIOTestCase):
pass
class Test_UV_Process_Delayed(tb.UVTestCase):
class TestProto:
def __init__(self):
self.lost = 0
self.stages = []
def connection_made(self, transport):
self.stages.append(('CM', transport))
def pipe_data_received(self, fd, data):
if fd == 1:
self.stages.append(('STDOUT', data))
def pipe_connection_lost(self, fd, exc):
if fd == 1:
self.stages.append(('STDOUT', 'LOST'))
def process_exited(self):
self.stages.append('PROC_EXIT')
def connection_lost(self, exc):
self.stages.append(('CL', self.lost, exc))
self.lost += 1
async def run_sub(self, **kwargs):
return await self.loop.subprocess_shell(
lambda: self.TestProto(),
'echo 1',
**kwargs)
def test_process_delayed_stdio__paused__stdin_pipe(self):
transport, proto = self.loop.run_until_complete(
self.run_sub(
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
__uvloop_sleep_after_fork=True))
self.assertIsNot(transport, None)
self.assertEqual(transport.get_returncode(), 0)
self.assertEqual(
set(proto.stages),
{
('CM', transport),
'PROC_EXIT',
('STDOUT', b'1\n'),
('STDOUT', 'LOST'),
('CL', 0, None)
})
def test_process_delayed_stdio__paused__no_stdin(self):
transport, proto = self.loop.run_until_complete(
self.run_sub(
stdin=None,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
__uvloop_sleep_after_fork=True))
self.assertIsNot(transport, None)
self.assertEqual(transport.get_returncode(), 0)
self.assertEqual(
set(proto.stages),
{
('CM', transport),
'PROC_EXIT',
('STDOUT', b'1\n'),
('STDOUT', 'LOST'),
('CL', 0, None)
})
def test_process_delayed_stdio__not_paused__no_stdin(self):
if ((os.environ.get('TRAVIS_OS_NAME')
or os.environ.get('GITHUB_WORKFLOW'))
and sys.platform == 'darwin'):
# Randomly crashes on Travis, can't reproduce locally.
raise unittest.SkipTest()
transport, proto = self.loop.run_until_complete(
self.run_sub(
stdin=None,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE))
self.loop.run_until_complete(transport._wait())
self.assertEqual(transport.get_returncode(), 0)
self.assertIsNot(transport, None)
self.assertEqual(
set(proto.stages),
{
('CM', transport),
'PROC_EXIT',
('STDOUT', b'1\n'),
('STDOUT', 'LOST'),
('CL', 0, None)
})
================================================
FILE: tests/test_process_spawning.py
================================================
import asyncio
import ctypes.util
import logging
from concurrent.futures import ThreadPoolExecutor
from threading import Thread
from unittest import TestCase
import uvloop
class ProcessSpawningTestCollection(TestCase):
def test_spawning_external_process(self):
"""Test spawning external process (using `popen` system call) that
cause loop freeze."""
async def run(loop):
event = asyncio.Event()
dummy_workers = [simulate_loop_activity(loop, event)
for _ in range(5)]
spawn_worker = spawn_external_process(loop, event)
done, pending = await asyncio.wait([
asyncio.ensure_future(fut)
for fut in ([spawn_worker] + dummy_workers)
])
exceptions = [result.exception()
for result in done if result.exception()]
if exceptions:
raise exceptions[0]
return True
async def simulate_loop_activity(loop, done_event):
"""Simulate loop activity by busy waiting for event."""
while True:
try:
await asyncio.wait_for(done_event.wait(), timeout=0.1)
except asyncio.TimeoutError:
pass
if done_event.is_set():
return None
async def spawn_external_process(loop, event):
executor = ThreadPoolExecutor()
try:
call = loop.run_in_executor(executor, spawn_process)
await asyncio.wait_for(call, timeout=3600)
finally:
event.set()
executor.shutdown(wait=False)
return True
BUFFER_LENGTH = 1025
BufferType = ctypes.c_char * (BUFFER_LENGTH - 1)
def run_echo(popen, fread, pclose):
fd = popen('echo test'.encode('ASCII'), 'r'.encode('ASCII'))
try:
while True:
buffer = BufferType()
data = ctypes.c_void_p(ctypes.addressof(buffer))
# -> this call will freeze whole loop in case of bug
read = fread(data, 1, BUFFER_LENGTH, fd)
if not read:
break
except Exception:
logging.getLogger().exception('read error')
raise
finally:
pclose(fd)
def spawn_process():
"""Spawn external process via `popen` system call."""
stdio = ctypes.CDLL(ctypes.util.find_library('c'))
# popen system call
popen = stdio.popen
popen.argtypes = (ctypes.c_char_p, ctypes.c_char_p)
popen.restype = ctypes.c_void_p
# pclose system call
pclose = stdio.pclose
pclose.argtypes = (ctypes.c_void_p,)
pclose.restype = ctypes.c_int
# fread system call
fread = stdio.fread
fread.argtypes = (ctypes.c_void_p, ctypes.c_size_t,
ctypes.c_size_t, ctypes.c_void_p)
fread.restype = ctypes.c_size_t
for iteration in range(1000):
t = Thread(target=run_echo,
args=(popen, fread, pclose),
daemon=True)
t.start()
t.join(timeout=10.0)
if t.is_alive():
raise Exception('process freeze detected at {}'
.format(iteration))
return True
loop = uvloop.new_event_loop()
proc = loop.run_until_complete(run(loop))
self.assertTrue(proc)
================================================
FILE: tests/test_regr1.py
================================================
import asyncio
import queue
import multiprocessing
import signal
import threading
import unittest
import uvloop
from uvloop import _testbase as tb
class EchoServerProtocol(asyncio.Protocol):
def connection_made(self, transport):
transport.write(b'z')
class EchoClientProtocol(asyncio.Protocol):
def __init__(self, loop):
self.loop = loop
def connection_made(self, transport):
self.transport = transport
def data_received(self, data):
self.transport.close()
def connection_lost(self, exc):
self.loop.stop()
class FailedTestError(BaseException):
pass
def run_server(quin, qout):
server_loop = None
def server_thread():
nonlocal server_loop
loop = server_loop = uvloop.new_event_loop()
asyncio.set_event_loop(loop)
coro = loop.create_server(EchoServerProtocol, '127.0.0.1', 0)
server = loop.run_until_complete(coro)
addr = server.sockets[0].getsockname()
qout.put(addr)
loop.run_forever()
server.close()
loop.run_until_complete(server.wait_closed())
try:
loop.close()
except Exception as exc:
print(exc)
qout.put('stopped')
thread = threading.Thread(target=server_thread, daemon=True)
thread.start()
quin.get()
server_loop.call_soon_threadsafe(server_loop.stop)
thread.join(1)
class TestIssue39Regr(tb.UVTestCase):
"""See https://github.com/MagicStack/uvloop/issues/39 for details.
Original code to reproduce the bug is by Jim Fulton.
"""
def on_alarm(self, sig, fr):
if self.running:
raise FailedTestError
def run_test(self):
for i in range(10):
for threaded in [True, False]:
if threaded:
qin, qout = queue.Queue(), queue.Queue()
threading.Thread(
target=run_server,
args=(qin, qout),
daemon=True).start()
else:
qin = multiprocessing.Queue()
qout = multiprocessing.Queue()
multiprocessing.Process(
target=run_server,
args=(qin, qout),
daemon=True).start()
addr = qout.get()
loop = self.new_loop()
asyncio.set_event_loop(loop)
loop.create_task(
loop.create_connection(
lambda: EchoClientProtocol(loop),
host=addr[0], port=addr[1]))
loop.run_forever()
loop.close()
qin.put('stop')
qout.get()
@unittest.skipIf(
multiprocessing.get_start_method(False) == 'spawn',
'no need to test on macOS where spawn is used instead of fork')
def test_issue39_regression(self):
signal.signal(signal.SIGALRM, self.on_alarm)
signal.alarm(5)
try:
self.running = True
self.run_test()
except FailedTestError:
self.fail('deadlocked in libuv')
finally:
self.running = False
signal.signal(signal.SIGALRM, signal.SIG_IGN)
================================================
FILE: tests/test_runner.py
================================================
import asyncio
import unittest
import uvloop
class TestSourceCode(unittest.TestCase):
def test_uvloop_run_1(self):
CNT = 0
async def main():
nonlocal CNT
CNT += 1
loop = asyncio.get_running_loop()
self.assertTrue(isinstance(loop, uvloop.Loop))
self.assertTrue(loop.get_debug())
return 'done'
result = uvloop.run(main(), debug=True)
self.assertEqual(result, 'done')
self.assertEqual(CNT, 1)
def test_uvloop_run_2(self):
async def main():
pass
coro = main()
with self.assertRaisesRegex(TypeError, ' a non-uvloop event loop'):
uvloop.run(
coro,
loop_factory=asyncio.DefaultEventLoopPolicy().new_event_loop,
)
coro.close()
================================================
FILE: tests/test_signals.py
================================================
import asyncio
import signal
import subprocess
import sys
import time
from uvloop import _testbase as tb
DELAY = 0.1
class _TestSignal:
NEW_LOOP = None
@tb.silence_long_exec_warning()
def test_signals_sigint_pycode_stop(self):
async def runner():
PROG = R"""\
import asyncio
import uvloop
import time
from uvloop import _testbase as tb
async def worker():
print('READY', flush=True)
time.sleep(200)
@tb.silence_long_exec_warning()
def run():
loop = """ + self.NEW_LOOP + """
asyncio.set_event_loop(loop)
try:
loop.run_until_complete(worker())
finally:
loop.close()
run()
"""
proc = await asyncio.create_subprocess_exec(
sys.executable, b'-W', b'ignore', b'-c', PROG,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
await proc.stdout.readline()
time.sleep(DELAY)
proc.send_signal(signal.SIGINT)
out, err = await proc.communicate()
self.assertIn(b'KeyboardInterrupt', err)
self.assertEqual(out, b'')
self.loop.run_until_complete(runner())
@tb.silence_long_exec_warning()
def test_signals_sigint_pycode_continue(self):
async def runner():
PROG = R"""\
import asyncio
import uvloop
import time
from uvloop import _testbase as tb
async def worker():
print('READY', flush=True)
try:
time.sleep(200)
except KeyboardInterrupt:
print("oups")
await asyncio.sleep(0.5)
print('done')
@tb.silence_long_exec_warning()
def run():
loop = """ + self.NEW_LOOP + """
asyncio.set_event_loop(loop)
try:
loop.run_until_complete(worker())
finally:
loop.close()
run()
"""
proc = await asyncio.create_subprocess_exec(
sys.executable, b'-W', b'ignore', b'-c', PROG,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
await proc.stdout.readline()
time.sleep(DELAY)
proc.send_signal(signal.SIGINT)
out, err = await proc.communicate()
self.assertEqual(err, b'')
self.assertEqual(out, b'oups\ndone\n')
self.loop.run_until_complete(runner())
@tb.silence_long_exec_warning()
def test_signals_sigint_uvcode(self):
async def runner():
PROG = R"""\
import asyncio
import uvloop
srv = None
async def worker():
g
gitextract_3ml8fczj/
├── .editorconfig
├── .flake8
├── .github/
│ ├── ISSUE_TEMPLATE.md
│ ├── release_log.py
│ └── workflows/
│ ├── release.yml
│ └── tests.yml
├── .gitignore
├── .gitmodules
├── LICENSE-APACHE
├── LICENSE-MIT
├── MANIFEST.in
├── Makefile
├── README.rst
├── docs/
│ ├── .gitignore
│ ├── api/
│ │ └── index.rst
│ ├── conf.py
│ ├── dev/
│ │ └── index.rst
│ ├── index.rst
│ └── user/
│ └── index.rst
├── examples/
│ └── bench/
│ ├── echoclient.py
│ ├── echoserver.py
│ └── rlserver.py
├── mypy.ini
├── pyproject.toml
├── setup.py
├── tests/
│ ├── __init__.py
│ ├── __main__.py
│ ├── certs/
│ │ ├── ssl_cert.pem
│ │ └── ssl_key.pem
│ ├── test_aiohttp.py
│ ├── test_base.py
│ ├── test_context.py
│ ├── test_cython.py
│ ├── test_dealloc.py
│ ├── test_dns.py
│ ├── test_executors.py
│ ├── test_fs_event.py
│ ├── test_libuv_api.py
│ ├── test_pipes.py
│ ├── test_process.py
│ ├── test_process_spawning.py
│ ├── test_regr1.py
│ ├── test_runner.py
│ ├── test_signals.py
│ ├── test_sockets.py
│ ├── test_sourcecode.py
│ ├── test_tcp.py
│ ├── test_testbase.py
│ ├── test_udp.py
│ └── test_unix.py
└── uvloop/
├── .gitignore
├── __init__.py
├── _noop.py
├── _testbase.py
├── _version.py
├── cbhandles.pxd
├── cbhandles.pyx
├── dns.pyx
├── errors.pyx
├── handles/
│ ├── async_.pxd
│ ├── async_.pyx
│ ├── basetransport.pxd
│ ├── basetransport.pyx
│ ├── check.pxd
│ ├── check.pyx
│ ├── fsevent.pxd
│ ├── fsevent.pyx
│ ├── handle.pxd
│ ├── handle.pyx
│ ├── idle.pxd
│ ├── idle.pyx
│ ├── pipe.pxd
│ ├── pipe.pyx
│ ├── poll.pxd
│ ├── poll.pyx
│ ├── process.pxd
│ ├── process.pyx
│ ├── stream.pxd
│ ├── stream.pyx
│ ├── streamserver.pxd
│ ├── streamserver.pyx
│ ├── tcp.pxd
│ ├── tcp.pyx
│ ├── timer.pxd
│ ├── timer.pyx
│ ├── udp.pxd
│ └── udp.pyx
├── includes/
│ ├── __init__.py
│ ├── compat.h
│ ├── consts.pxi
│ ├── debug.h
│ ├── debug.pxd
│ ├── flowcontrol.pxd
│ ├── fork_handler.h
│ ├── python.pxd
│ ├── stdlib.pxi
│ ├── system.pxd
│ └── uv.pxd
├── loop.pxd
├── loop.pyi
├── loop.pyx
├── lru.pyx
├── pseudosock.pyx
├── py.typed
├── request.pxd
├── request.pyx
├── server.pxd
├── server.pyx
├── sslproto.pxd
└── sslproto.pyx
SYMBOL INDEX (609 symbols across 33 files)
FILE: .github/release_log.py
function main (line 13) | def main():
FILE: examples/bench/echoclient.py
function run_test (line 57) | def run_test(n):
FILE: examples/bench/echoserver.py
function echo_server (line 13) | async def echo_server(loop, address, unix):
function echo_client (line 32) | async def echo_client(loop, client):
function echo_client_streams (line 48) | async def echo_client_streams(reader, writer):
class EchoProtocol (line 66) | class EchoProtocol(asyncio.Protocol):
method connection_made (line 67) | def connection_made(self, transport):
method connection_lost (line 70) | def connection_lost(self, exc):
method data_received (line 73) | def data_received(self, data):
class EchoBufferedProtocol (line 77) | class EchoBufferedProtocol(asyncio.BufferedProtocol):
method connection_made (line 78) | def connection_made(self, transport):
method connection_lost (line 84) | def connection_lost(self, exc):
method get_buffer (line 87) | def get_buffer(self, sizehint):
method buffer_updated (line 90) | def buffer_updated(self, nbytes):
function print_debug (line 94) | async def print_debug(loop):
FILE: examples/bench/rlserver.py
function echo_client_streams (line 11) | async def echo_client_streams(reader, writer):
function print_debug (line 30) | async def print_debug(loop):
FILE: setup.py
function _libuv_build_env (line 32) | def _libuv_build_env():
function _libuv_autogen (line 44) | def _libuv_autogen(env):
class uvloop_sdist (line 58) | class uvloop_sdist(sdist):
method run (line 59) | def run(self):
class uvloop_build_ext (line 66) | class uvloop_build_ext(build_ext):
method initialize_options (line 84) | def initialize_options(self):
method finalize_options (line 91) | def finalize_options(self):
method build_libuv (line 154) | def build_libuv(self):
method build_extensions (line 192) | def build_extensions(self):
FILE: tests/__main__.py
function suite (line 7) | def suite():
FILE: tests/test_aiohttp.py
class _TestAioHTTP (line 17) | class _TestAioHTTP:
method test_aiohttp_basic_1 (line 19) | def test_aiohttp_basic_1(self):
method test_aiohttp_graceful_shutdown (line 51) | def test_aiohttp_graceful_shutdown(self):
class Test_UV_AioHTTP (line 120) | class Test_UV_AioHTTP(_TestAioHTTP, tb.UVTestCase):
class Test_AIO_AioHTTP (line 125) | class Test_AIO_AioHTTP(_TestAioHTTP, tb.AIOTestCase):
FILE: tests/test_base.py
class _TestBase (line 18) | class _TestBase:
method test_close (line 20) | def test_close(self):
method test_handle_weakref (line 36) | def test_handle_weakref(self):
method test_call_soon_1 (line 41) | def test_call_soon_1(self):
method test_call_soon_2 (line 61) | def test_call_soon_2(self):
method test_call_soon_3 (line 69) | def test_call_soon_3(self):
method test_call_soon_base_exc (line 77) | def test_call_soon_base_exc(self):
method test_calls_debug_reporting (line 88) | def test_calls_debug_reporting(self):
method test_now_update (line 128) | def test_now_update(self):
method test_call_later_1 (line 137) | def test_call_later_1(self):
method test_call_later_2 (line 167) | def test_call_later_2(self):
method test_call_later_3 (line 181) | def test_call_later_3(self):
method test_call_later_4 (line 190) | def test_call_later_4(self):
method test_call_later_negative (line 199) | def test_call_later_negative(self):
method test_call_later_rounding (line 210) | def test_call_later_rounding(self):
method test_call_at (line 223) | def test_call_at(self):
method test_check_thread (line 250) | def test_check_thread(self):
method test_run_once_in_executor_plain (line 313) | def test_run_once_in_executor_plain(self):
method test_set_debug (line 326) | def test_set_debug(self):
method test_run_until_complete_type_error (line 332) | def test_run_until_complete_type_error(self):
method test_run_until_complete_loop (line 336) | def test_run_until_complete_loop(self):
method test_run_until_complete_error (line 343) | def test_run_until_complete_error(self):
method test_run_until_complete_loop_orphan_future_close_loop (line 349) | def test_run_until_complete_loop_orphan_future_close_loop(self):
method test_run_until_complete_keyboard_interrupt (line 366) | def test_run_until_complete_keyboard_interrupt(self):
method test_debug_slow_callbacks (line 386) | def test_debug_slow_callbacks(self):
method test_debug_slow_timer_callbacks (line 402) | def test_debug_slow_timer_callbacks(self):
method test_debug_slow_task_callbacks (line 418) | def test_debug_slow_task_callbacks(self):
method test_default_exc_handler_callback (line 436) | def test_default_exc_handler_callback(self):
method test_set_exc_handler_custom (line 467) | def test_set_exc_handler_custom(self):
method test_set_exc_handler_broken (line 503) | def test_set_exc_handler_broken(self):
method test_set_task_factory_invalid (line 526) | def test_set_task_factory_invalid(self):
method test_set_task_factory (line 535) | def test_set_task_factory(self):
method test_set_task_name (line 564) | def test_set_task_name(self):
method test_shutdown_asyncgens_01 (line 607) | def test_shutdown_asyncgens_01(self):
method test_shutdown_asyncgens_02 (line 641) | def test_shutdown_asyncgens_02(self):
method test_shutdown_asyncgens_03 (line 677) | def test_shutdown_asyncgens_03(self):
method test_inf_wait_for (line 693) | def test_inf_wait_for(self):
method test_shutdown_default_executor (line 701) | def test_shutdown_default_executor(self):
method test_call_soon_threadsafe_safety (line 712) | def test_call_soon_threadsafe_safety(self):
method test_freethreading (line 739) | def test_freethreading(self):
class TestBaseUV (line 803) | class TestBaseUV(_TestBase, UVTestCase):
method test_loop_create_future (line 805) | def test_loop_create_future(self):
method test_loop_call_soon_handle_cancelled (line 811) | def test_loop_call_soon_handle_cancelled(self):
method test_loop_call_later_handle_cancelled (line 823) | def test_loop_call_later_handle_cancelled(self):
method test_loop_std_files_cloexec (line 835) | def test_loop_std_files_cloexec(self):
method test_default_exc_handler_broken (line 841) | def test_default_exc_handler_broken(self):
method test_big_call_later_timeout (line 893) | def test_big_call_later_timeout(self):
method test_loop_call_later_handle_when (line 924) | def test_loop_call_later_handle_when(self):
method test_loop_call_later_handle_when_after_fired (line 934) | def test_loop_call_later_handle_when_after_fired(self):
class TestBaseAIO (line 942) | class TestBaseAIO(_TestBase, AIOTestCase):
class TestPolicy (line 946) | class TestPolicy(unittest.TestCase):
method test_uvloop_policy (line 948) | def test_uvloop_policy(self):
method test_running_loop_within_a_loop (line 961) | def test_running_loop_within_a_loop(self):
method test_get_event_loop_returns_running_loop (line 984) | def test_get_event_loop_returns_running_loop(self):
FILE: tests/test_context.py
class _BaseProtocol (line 16) | class _BaseProtocol(asyncio.BaseProtocol):
method __init__ (line 17) | def __init__(self, cvar, *, loop=None):
method connection_made (line 33) | def connection_made(self, transport):
method connection_lost (line 37) | def connection_lost(self, exc):
method eof_received (line 44) | def eof_received(self):
method pause_writing (line 47) | def pause_writing(self):
method resume_writing (line 50) | def resume_writing(self):
class _Protocol (line 54) | class _Protocol(_BaseProtocol, asyncio.Protocol):
method data_received (line 55) | def data_received(self, data):
class _BufferedProtocol (line 59) | class _BufferedProtocol(_BaseProtocol, asyncio.BufferedProtocol):
method get_buffer (line 60) | def get_buffer(self, sizehint):
method buffer_updated (line 69) | def buffer_updated(self, nbytes):
class _DatagramProtocol (line 81) | class _DatagramProtocol(_BaseProtocol, asyncio.DatagramProtocol):
method datagram_received (line 82) | def datagram_received(self, data, addr):
method error_received (line 85) | def error_received(self, exc):
class _SubprocessProtocol (line 89) | class _SubprocessProtocol(_BaseProtocol, asyncio.SubprocessProtocol):
method pipe_data_received (line 90) | def pipe_data_received(self, fd, data):
method pipe_connection_lost (line 93) | def pipe_connection_lost(self, fd, exc):
method process_exited (line 104) | def process_exited(self):
class _SSLSocketOverSSL (line 108) | class _SSLSocketOverSSL:
method __init__ (line 112) | def __init__(self, ssl_sock, ctx, **kwargs):
method do (line 120) | def do(self, func, *args):
method send (line 133) | def send(self, data):
method unwrap (line 136) | def unwrap(self):
method close (line 139) | def close(self):
class _ContextBaseTests (line 144) | class _ContextBaseTests(tb.SSLTestCase):
method test_task_decimal_context (line 149) | def test_task_decimal_context(self):
method test_task_context_1 (line 172) | def test_task_context_1(self):
method test_task_context_2 (line 191) | def test_task_context_2(self):
method test_task_context_3 (line 221) | def test_task_context_3(self):
method test_task_context_4 (line 244) | def test_task_context_4(self):
method _run_test (line 266) | def _run_test(self, method, **switches):
method _run_server_test (line 314) | def _run_server_test(self, method, async_sock=False, **switches):
method test_create_server_protocol_factory_context (line 344) | def test_create_server_protocol_factory_context(self):
method test_create_server_connection_protocol (line 376) | def test_create_server_connection_protocol(self):
method test_create_ssl_server_connection_protocol (line 395) | def test_create_ssl_server_connection_protocol(self):
method test_create_server_manual_connection_lost (line 435) | def test_create_server_manual_connection_lost(self):
method test_create_ssl_server_manual_connection_lost (line 454) | def test_create_ssl_server_manual_connection_lost(self):
method test_create_connection_protocol (line 493) | def test_create_connection_protocol(self):
method test_start_tls (line 579) | def test_start_tls(self):
method test_connect_accepted_socket (line 640) | def test_connect_accepted_socket(self):
method test_subprocess_protocol (line 684) | def test_subprocess_protocol(self):
method test_datagram_protocol (line 723) | def test_datagram_protocol(self):
class Test_UV_Context (line 763) | class Test_UV_Context(_ContextBaseTests, tb.UVTestCase):
class Test_AIO_Context (line 767) | class Test_AIO_Context(_ContextBaseTests, tb.AIOTestCase):
FILE: tests/test_cython.py
class TestCythonIntegration (line 6) | class TestCythonIntegration(UVTestCase):
method test_cython_coro_is_coroutine (line 8) | def test_cython_coro_is_coroutine(self):
FILE: tests/test_dealloc.py
class TestDealloc (line 8) | class TestDealloc(tb.UVTestCase):
method test_dealloc_1 (line 10) | def test_dealloc_1(self):
FILE: tests/test_dns.py
function patched_getaddrinfo (line 8) | def patched_getaddrinfo(*args, **kwargs):
class BaseTestDNS (line 27) | class BaseTestDNS:
method _test_getaddrinfo (line 29) | def _test_getaddrinfo(self, *args, _patch=False, _sorted=False, **kwar...
method _test_getnameinfo (line 68) | def _test_getnameinfo(self, *args, **kwargs):
method test_getaddrinfo_1 (line 92) | def test_getaddrinfo_1(self):
method test_getaddrinfo_2 (line 97) | def test_getaddrinfo_2(self):
method test_getaddrinfo_3 (line 101) | def test_getaddrinfo_3(self):
method test_getaddrinfo_4 (line 104) | def test_getaddrinfo_4(self):
method test_getaddrinfo_5 (line 109) | def test_getaddrinfo_5(self):
method test_getaddrinfo_6 (line 114) | def test_getaddrinfo_6(self):
method test_getaddrinfo_7 (line 119) | def test_getaddrinfo_7(self):
method test_getaddrinfo_8 (line 123) | def test_getaddrinfo_8(self):
method test_getaddrinfo_9 (line 127) | def test_getaddrinfo_9(self):
method test_getaddrinfo_10 (line 131) | def test_getaddrinfo_10(self):
method test_getaddrinfo_11 (line 135) | def test_getaddrinfo_11(self):
method test_getaddrinfo_12 (line 140) | def test_getaddrinfo_12(self):
method test_getaddrinfo_13 (line 148) | def test_getaddrinfo_13(self):
method test_getaddrinfo_14 (line 156) | def test_getaddrinfo_14(self):
method test_getaddrinfo_15 (line 164) | def test_getaddrinfo_15(self):
method test_getaddrinfo_16 (line 172) | def test_getaddrinfo_16(self):
method test_getaddrinfo_17 (line 176) | def test_getaddrinfo_17(self):
method test_getaddrinfo_18 (line 180) | def test_getaddrinfo_18(self):
method test_getaddrinfo_19 (line 184) | def test_getaddrinfo_19(self):
method test_getaddrinfo_20 (line 196) | def test_getaddrinfo_20(self):
method test_getaddrinfo_21 (line 210) | def test_getaddrinfo_21(self):
method test_getaddrinfo_22 (line 215) | def test_getaddrinfo_22(self):
method test_getaddrinfo_broadcast (line 220) | def test_getaddrinfo_broadcast(self):
method test_getnameinfo_1 (line 226) | def test_getnameinfo_1(self):
method test_getnameinfo_2 (line 229) | def test_getnameinfo_2(self):
method test_getnameinfo_3 (line 232) | def test_getnameinfo_3(self):
method test_getnameinfo_4 (line 235) | def test_getnameinfo_4(self):
method test_getnameinfo_5 (line 238) | def test_getnameinfo_5(self):
class Test_UV_DNS (line 242) | class Test_UV_DNS(BaseTestDNS, tb.UVTestCase):
method test_getaddrinfo_close_loop (line 244) | def test_getaddrinfo_close_loop(self):
class Test_AIO_DNS (line 267) | class Test_AIO_DNS(BaseTestDNS, tb.AIOTestCase):
FILE: tests/test_executors.py
function fib (line 9) | def fib(n):
class _TestExecutors (line 15) | class _TestExecutors:
method run_pool_test (line 17) | def run_pool_test(self, pool_factory):
method test_executors_process_pool_01 (line 34) | def test_executors_process_pool_01(self):
method test_executors_process_pool_02 (line 37) | def test_executors_process_pool_02(self):
class TestUVExecutors (line 41) | class TestUVExecutors(_TestExecutors, tb.UVTestCase):
class TestAIOExecutors (line 45) | class TestAIOExecutors(_TestExecutors, tb.AIOTestCase):
FILE: tests/test_fs_event.py
class Test_UV_FS_Event (line 10) | class Test_UV_FS_Event(tb.UVTestCase):
method setUp (line 11) | def setUp(self):
method tearDown (line 18) | def tearDown(self):
method test_fs_event_change (line 22) | def test_fs_event_change(self):
method test_fs_event_rename (line 59) | def test_fs_event_rename(self):
FILE: tests/test_libuv_api.py
class Test_UV_libuv (line 6) | class Test_UV_libuv(tb.UVTestCase):
method test_libuv_get_loop_t_ptr (line 7) | def test_libuv_get_loop_t_ptr(self):
method test_libuv_get_version (line 22) | def test_libuv_get_version(self):
FILE: tests/test_pipes.py
class MyReadPipeProto (line 12) | class MyReadPipeProto(asyncio.Protocol):
method __init__ (line 15) | def __init__(self, loop=None):
method connection_made (line 22) | def connection_made(self, transport):
method data_received (line 27) | def data_received(self, data):
method eof_received (line 31) | def eof_received(self):
method connection_lost (line 35) | def connection_lost(self, exc):
class MyWritePipeProto (line 44) | class MyWritePipeProto(asyncio.BaseProtocol):
method __init__ (line 48) | def __init__(self, loop=None):
method connection_made (line 54) | def connection_made(self, transport):
method connection_lost (line 59) | def connection_lost(self, exc):
method pause_writing (line 65) | def pause_writing(self):
method resume_writing (line 68) | def resume_writing(self):
class _BasePipeTest (line 72) | class _BasePipeTest:
method test_read_pipe (line 73) | def test_read_pipe(self):
method test_read_pty_output (line 105) | def test_read_pty_output(self):
method test_write_pipe (line 142) | def test_write_pipe(self):
method test_write_pipe_disconnect_on_close (line 184) | def test_write_pipe_disconnect_on_close(self):
method test_write_pty (line 206) | def test_write_pty(self):
method test_write_buffer_full (line 251) | def test_write_buffer_full(self):
class Test_UV_Pipes (line 275) | class Test_UV_Pipes(_BasePipeTest, tb.UVTestCase):
class Test_AIO_Pipes (line 279) | class Test_AIO_Pipes(_BasePipeTest, tb.AIOTestCase):
FILE: tests/test_process.py
class _RedirectFD (line 19) | class _RedirectFD(contextlib.AbstractContextManager):
method __init__ (line 20) | def __init__(self, old_file, new_file):
method __enter__ (line 25) | def __enter__(self):
method __exit__ (line 28) | def __exit__(self, exc_type, exc_val, exc_tb):
class _TestProcess (line 33) | class _TestProcess:
method get_num_fds (line 34) | def get_num_fds(self):
method test_process_env_1 (line 37) | def test_process_env_1(self):
method test_process_env_2 (line 53) | def test_process_env_2(self):
method test_process_cwd_1 (line 69) | def test_process_cwd_1(self):
method test_process_cwd_2 (line 88) | def test_process_cwd_2(self):
method test_process_preexec_fn_1 (line 106) | def test_process_preexec_fn_1(self):
method test_process_preexec_fn_2 (line 126) | def test_process_preexec_fn_2(self):
method test_process_executable_1 (line 157) | def test_process_executable_1(self):
method test_process_executable_2 (line 169) | def test_process_executable_2(self):
method test_process_pid_1 (line 181) | def test_process_pid_1(self):
method test_process_send_signal_1 (line 202) | def test_process_send_signal_1(self):
method test_process_streams_basic_1 (line 242) | def test_process_streams_basic_1(self):
method test_process_streams_stderr_to_stdout (line 293) | def test_process_streams_stderr_to_stdout(self):
method test_process_streams_devnull (line 312) | def test_process_streams_devnull(self):
method test_process_streams_pass_fds (line 332) | def test_process_streams_pass_fds(self):
method test_subprocess_fd_leak_1 (line 369) | def test_subprocess_fd_leak_1(self):
method test_subprocess_fd_leak_2 (line 388) | def test_subprocess_fd_leak_2(self):
method test_subprocess_invalid_stdin (line 407) | def test_subprocess_invalid_stdin(self):
method test_process_streams_redirect (line 438) | def test_process_streams_redirect(self):
class _AsyncioTests (line 469) | class _AsyncioTests:
method test_stdin_not_inheritable (line 486) | def test_stdin_not_inheritable(self):
method test_stdin_stdout_pipe (line 505) | def test_stdin_stdout_pipe(self):
method test_stdin_stdout_file (line 530) | def test_stdin_stdout_file(self):
method test_stdin_stderr_file (line 556) | def test_stdin_stderr_file(self):
method test_communicate (line 577) | def test_communicate(self):
method test_start_new_session (line 594) | def test_start_new_session(self):
method test_shell (line 602) | def test_shell(self):
method test_kill (line 608) | def test_kill(self):
method test_terminate (line 616) | def test_terminate(self):
method test_send_signal (line 624) | def test_send_signal(self):
method test_cancel_process_wait (line 643) | def test_cancel_process_wait(self):
method test_cancel_make_subprocess_transport_exec (line 667) | def test_cancel_make_subprocess_transport_exec(self):
method test_cancel_post_init (line 687) | def test_cancel_post_init(self):
method test_close_gets_process_closed (line 715) | def test_close_gets_process_closed(self):
method test_communicate_large_stdout_65536 (line 740) | def test_communicate_large_stdout_65536(self):
method test_communicate_large_stdout_65537 (line 743) | def test_communicate_large_stdout_65537(self):
method test_communicate_large_stdout_1000000 (line 746) | def test_communicate_large_stdout_1000000(self):
method _test_communicate_large_stdout (line 749) | def _test_communicate_large_stdout(self, size):
method test_write_huge_stdin_8192 (line 768) | def test_write_huge_stdin_8192(self):
method test_write_huge_stdin_8193 (line 771) | def test_write_huge_stdin_8193(self):
method test_write_huge_stdin_219263 (line 774) | def test_write_huge_stdin_219263(self):
method test_write_huge_stdin_219264 (line 777) | def test_write_huge_stdin_219264(self):
method _test_write_huge_stdin (line 780) | def _test_write_huge_stdin(self, buf_size):
class Test_UV_Process (line 818) | class Test_UV_Process(_TestProcess, tb.UVTestCase):
method test_process_double_close (line 819) | def test_process_double_close(self):
class Test_AIO_Process (line 872) | class Test_AIO_Process(_TestProcess, tb.AIOTestCase):
class TestAsyncio_UV_Process (line 876) | class TestAsyncio_UV_Process(_AsyncioTests, tb.UVTestCase):
class TestAsyncio_AIO_Process (line 880) | class TestAsyncio_AIO_Process(_AsyncioTests, tb.AIOTestCase):
class Test_UV_Process_Delayed (line 884) | class Test_UV_Process_Delayed(tb.UVTestCase):
class TestProto (line 886) | class TestProto:
method __init__ (line 887) | def __init__(self):
method connection_made (line 891) | def connection_made(self, transport):
method pipe_data_received (line 894) | def pipe_data_received(self, fd, data):
method pipe_connection_lost (line 898) | def pipe_connection_lost(self, fd, exc):
method process_exited (line 902) | def process_exited(self):
method connection_lost (line 905) | def connection_lost(self, exc):
method run_sub (line 909) | async def run_sub(self, **kwargs):
method test_process_delayed_stdio__paused__stdin_pipe (line 915) | def test_process_delayed_stdio__paused__stdin_pipe(self):
method test_process_delayed_stdio__paused__no_stdin (line 934) | def test_process_delayed_stdio__paused__no_stdin(self):
method test_process_delayed_stdio__not_paused__no_stdin (line 953) | def test_process_delayed_stdio__not_paused__no_stdin(self):
FILE: tests/test_process_spawning.py
class ProcessSpawningTestCollection (line 11) | class ProcessSpawningTestCollection(TestCase):
method test_spawning_external_process (line 13) | def test_spawning_external_process(self):
FILE: tests/test_regr1.py
class EchoServerProtocol (line 13) | class EchoServerProtocol(asyncio.Protocol):
method connection_made (line 15) | def connection_made(self, transport):
class EchoClientProtocol (line 19) | class EchoClientProtocol(asyncio.Protocol):
method __init__ (line 21) | def __init__(self, loop):
method connection_made (line 24) | def connection_made(self, transport):
method data_received (line 27) | def data_received(self, data):
method connection_lost (line 30) | def connection_lost(self, exc):
class FailedTestError (line 34) | class FailedTestError(BaseException):
function run_server (line 38) | def run_server(quin, qout):
class TestIssue39Regr (line 66) | class TestIssue39Regr(tb.UVTestCase):
method on_alarm (line 72) | def on_alarm(self, sig, fr):
method run_test (line 76) | def run_test(self):
method test_issue39_regression (line 108) | def test_issue39_regression(self):
FILE: tests/test_runner.py
class TestSourceCode (line 6) | class TestSourceCode(unittest.TestCase):
method test_uvloop_run_1 (line 8) | def test_uvloop_run_1(self):
method test_uvloop_run_2 (line 27) | def test_uvloop_run_2(self):
FILE: tests/test_signals.py
class _TestSignal (line 12) | class _TestSignal:
method test_signals_sigint_pycode_stop (line 16) | def test_signals_sigint_pycode_stop(self):
method test_signals_sigint_pycode_continue (line 56) | def test_signals_sigint_pycode_continue(self):
method test_signals_sigint_uvcode (line 101) | def test_signals_sigint_uvcode(self):
method test_signals_sigint_uvcode_two_loop_runs (line 140) | def test_signals_sigint_uvcode_two_loop_runs(self):
method test_signals_sigint_and_custom_handler (line 179) | def test_signals_sigint_and_custom_handler(self):
method test_signals_and_custom_handler_1 (line 232) | def test_signals_and_custom_handler_1(self):
method test_signals_invalid_signal (line 298) | def test_signals_invalid_signal(self):
method test_signals_coro_callback (line 305) | def test_signals_coro_callback(self):
method test_signals_wakeup_fd_unchanged (line 311) | def test_signals_wakeup_fd_unchanged(self):
method test_signals_fork_in_thread (line 350) | def test_signals_fork_in_thread(self):
class Test_UV_Signals (line 387) | class Test_UV_Signals(_TestSignal, tb.UVTestCase):
method test_signals_no_SIGCHLD (line 390) | def test_signals_no_SIGCHLD(self):
class Test_AIO_Signals (line 397) | class Test_AIO_Signals(_TestSignal, tb.AIOTestCase):
FILE: tests/test_sockets.py
class _TestSockets (line 15) | class _TestSockets:
method recv_all (line 17) | async def recv_all(self, sock, nbytes):
method test_socket_accept_recv_send (line 23) | def test_socket_accept_recv_send(self):
method test_socket_failed_connect (line 51) | def test_socket_failed_connect(self):
method test_socket_ipv6_addr (line 67) | def test_socket_ipv6_addr(self):
method test_socket_ipv4_nameaddr (line 89) | def test_socket_ipv4_nameaddr(self):
method test_socket_blocking_error (line 105) | def test_socket_blocking_error(self):
method test_socket_fileno (line 126) | def test_socket_fileno(self):
method test_socket_sync_remove_and_immediately_close (line 145) | def test_socket_sync_remove_and_immediately_close(self):
method test_sock_cancel_add_reader_race (line 162) | def test_sock_cancel_add_reader_race(self):
method test_sock_send_before_cancel (line 218) | def test_sock_send_before_cancel(self):
class TestUVSockets (line 268) | class TestUVSockets(_TestSockets, tb.UVTestCase):
method test_socket_sync_remove (line 271) | def test_socket_sync_remove(self):
method test_add_reader_or_writer_transport_fd (line 294) | def test_add_reader_or_writer_transport_fd(self):
method test_pseudosocket (line 338) | def test_pseudosocket(self):
method test_socket_connect_and_close (line 413) | def test_socket_connect_and_close(self):
method test_socket_recv_and_close (line 432) | def test_socket_recv_and_close(self):
method test_socket_recv_into_and_close (line 461) | def test_socket_recv_into_and_close(self):
method test_socket_send_and_close (line 493) | def test_socket_send_and_close(self):
method test_socket_close_loop_and_close (line 525) | def test_socket_close_loop_and_close(self):
method test_socket_close_remove_reader (line 563) | def test_socket_close_remove_reader(self):
method test_socket_close_remove_writer (line 581) | def test_socket_close_remove_writer(self):
method test_socket_cancel_sock_recv_1 (line 599) | def test_socket_cancel_sock_recv_1(self):
method test_socket_cancel_sock_recv_2 (line 628) | def test_socket_cancel_sock_recv_2(self):
method test_socket_cancel_sock_sendall (line 668) | def test_socket_cancel_sock_sendall(self):
method test_socket_close_many_add_readers (line 701) | def test_socket_close_many_add_readers(self):
method test_socket_close_many_remove_writers (line 722) | def test_socket_close_many_remove_writers(self):
class TestAIOSockets (line 744) | class TestAIOSockets(_TestSockets, tb.AIOTestCase):
FILE: tests/test_sourcecode.py
function find_uvloop_root (line 7) | def find_uvloop_root():
class TestSourceCode (line 11) | class TestSourceCode(unittest.TestCase):
method test_flake8 (line 13) | def test_flake8(self):
method test_mypy (line 40) | def test_mypy(self):
FILE: tests/test_tcp.py
class MyBaseProto (line 21) | class MyBaseProto(asyncio.Protocol):
method __init__ (line 25) | def __init__(self, loop=None):
method connection_made (line 33) | def connection_made(self, transport):
method data_received (line 40) | def data_received(self, data):
method eof_received (line 44) | def eof_received(self):
method connection_lost (line 48) | def connection_lost(self, exc):
class _TestTCP (line 55) | class _TestTCP:
method test_create_server_1 (line 56) | def test_create_server_1(self):
method test_create_server_2 (line 201) | def test_create_server_2(self):
method test_create_server_3 (line 205) | def test_create_server_3(self):
method test_create_server_4 (line 243) | def test_create_server_4(self):
method test_create_server_5 (line 258) | def test_create_server_5(self):
method test_create_server_6 (line 275) | def test_create_server_6(self):
method test_create_server_7 (line 301) | def test_create_server_7(self):
method test_create_server_8 (line 345) | def test_create_server_8(self):
method test_create_server_9 (line 353) | def test_create_server_9(self):
method test_create_server_10 (line 377) | def test_create_server_10(self):
method test_create_connection_open_con_addr (line 400) | def test_create_connection_open_con_addr(self):
method test_create_connection_open_con_sock (line 427) | def test_create_connection_open_con_sock(self):
method _test_create_connection_1 (line 450) | def _test_create_connection_1(self, client):
method test_create_connection_2 (line 485) | def test_create_connection_2(self):
method test_create_connection_3 (line 502) | def test_create_connection_3(self):
method test_create_connection_4 (line 542) | def test_create_connection_4(self):
method test_create_connection_5 (line 557) | def test_create_connection_5(self):
method test_create_connection_6 (line 579) | def test_create_connection_6(self):
method test_transport_shutdown (line 587) | def test_transport_shutdown(self):
method test_tcp_handle_exception_in_connection_made (line 643) | def test_tcp_handle_exception_in_connection_made(self):
method test_resume_writing_write_different_transport (line 687) | def test_resume_writing_write_different_transport(self):
class Test_UV_TCP (line 741) | class Test_UV_TCP(_TestTCP, tb.UVTestCase):
method test_create_server_buffered_1 (line 743) | def test_create_server_buffered_1(self):
method test_create_server_buffered_2 (line 790) | def test_create_server_buffered_2(self):
method test_transport_get_extra_info (line 900) | def test_transport_get_extra_info(self):
method test_create_server_float_backlog (line 995) | def test_create_server_float_backlog(self):
method test_many_small_writes (line 1008) | def test_many_small_writes(self):
method test_tcp_handle_abort_in_connection_made (line 1069) | def test_tcp_handle_abort_in_connection_made(self):
method test_connect_accepted_socket_ssl_args (line 1102) | def test_connect_accepted_socket_ssl_args(self):
method test_connect_accepted_socket (line 1114) | def test_connect_accepted_socket(self, server_ssl=None, client_ssl=None):
method test_create_connection_wrong_sock (line 1185) | def test_create_connection_wrong_sock(self):
method test_create_server_wrong_sock (line 1194) | def test_create_server_wrong_sock(self):
method test_create_server_stream_bittype (line 1204) | def test_create_server_stream_bittype(self):
method test_flowcontrol_mixin_set_write_limits (line 1213) | def test_flowcontrol_mixin_set_write_limits(self):
class Test_AIO_TCP (line 1249) | class Test_AIO_TCP(_TestTCP, tb.AIOTestCase):
class _TestSSL (line 1253) | class _TestSSL(tb.SSLTestCase):
method test_create_server_ssl_1 (line 1261) | def test_create_server_ssl_1(self):
method test_create_connection_ssl_1 (line 1353) | def test_create_connection_ssl_1(self):
method test_create_connection_ssl_slow_handshake (line 1445) | def test_create_connection_ssl_slow_handshake(self):
method test_create_connection_ssl_failed_certificate (line 1481) | def test_create_connection_ssl_failed_certificate(self):
method test_start_tls_wrong_args (line 1518) | def test_start_tls_wrong_args(self):
method test_ssl_handshake_timeout (line 1533) | def test_ssl_handshake_timeout(self):
method test_ssl_handshake_connection_lost (line 1581) | def test_ssl_handshake_connection_lost(self):
method test_ssl_connect_accepted_socket (line 1630) | def test_ssl_connect_accepted_socket(self):
method test_start_tls_client_corrupted_ssl (line 1654) | def test_start_tls_client_corrupted_ssl(self):
method test_start_tls_client_reg_proto_1 (line 1703) | def test_start_tls_client_reg_proto_1(self):
method test_create_connection_memory_leak (line 1767) | def test_create_connection_memory_leak(self):
method test_start_tls_client_buf_proto_1 (line 1833) | def test_start_tls_client_buf_proto_1(self):
method test_start_tls_slow_client_cancel (line 1932) | def test_start_tls_slow_client_cancel(self):
method test_start_tls_server_1 (line 1995) | def test_start_tls_server_1(self):
method test_create_server_ssl_over_ssl (line 2077) | def test_create_server_ssl_over_ssl(self):
method test_renegotiation (line 2223) | def test_renegotiation(self):
method test_shutdown_timeout (line 2342) | def test_shutdown_timeout(self):
method test_shutdown_cleanly (line 2440) | def test_shutdown_cleanly(self):
method test_write_to_closed_transport (line 2504) | def test_write_to_closed_transport(self):
method test_flush_before_shutdown (line 2583) | def test_flush_before_shutdown(self):
method test_remote_shutdown_receives_trailing_data (line 2650) | def test_remote_shutdown_receives_trailing_data(self):
method test_connect_timeout_warning (line 2784) | def test_connect_timeout_warning(self):
method test_handshake_timeout_handler_leak (line 2812) | def test_handshake_timeout_handler_leak(self):
method test_shutdown_timeout_handler_leak (line 2841) | def test_shutdown_timeout_handler_leak(self):
method test_shutdown_timeout_handler_not_set (line 2879) | def test_shutdown_timeout_handler_not_set(self):
method test_shutdown_while_pause_reading (line 2937) | def test_shutdown_while_pause_reading(self):
method test_bpo_39951_discard_trailing_data (line 3019) | def test_bpo_39951_discard_trailing_data(self):
method test_first_data_after_wakeup (line 3101) | def test_first_data_after_wakeup(self):
class Test_UV_TCPSSL (line 3193) | class Test_UV_TCPSSL(_TestSSL, tb.UVTestCase):
class Test_AIO_TCPSSL (line 3197) | class Test_AIO_TCPSSL(_TestSSL, tb.AIOTestCase):
FILE: tests/test_testbase.py
class TestBaseTest (line 6) | class TestBaseTest(unittest.TestCase):
method test_duplicate_methods (line 8) | def test_duplicate_methods(self):
method test_duplicate_methods_parent_1 (line 21) | def test_duplicate_methods_parent_1(self):
method test_duplicate_methods_parent_2 (line 37) | def test_duplicate_methods_parent_2(self):
FILE: tests/test_udp.py
class MyDatagramProto (line 12) | class MyDatagramProto(asyncio.DatagramProtocol):
method __init__ (line 15) | def __init__(self, loop=None):
method connection_made (line 21) | def connection_made(self, transport):
method datagram_received (line 26) | def datagram_received(self, data, addr):
method error_received (line 30) | def error_received(self, exc):
method connection_lost (line 34) | def connection_lost(self, exc):
class _TestUDP (line 41) | class _TestUDP:
method _test_create_datagram_endpoint_addrs (line 43) | def _test_create_datagram_endpoint_addrs(self, family, lc_addr):
method test_create_datagram_endpoint_addrs_ipv4 (line 129) | def test_create_datagram_endpoint_addrs_ipv4(self):
method test_create_datagram_endpoint_addrs_ipv4_nameaddr (line 133) | def test_create_datagram_endpoint_addrs_ipv4_nameaddr(self):
method _test_create_datagram_endpoint_addrs_ipv6 (line 137) | def _test_create_datagram_endpoint_addrs_ipv6(self):
method test_create_datagram_endpoint_ipv6_family (line 141) | def test_create_datagram_endpoint_ipv6_family(self):
method test_create_datagram_endpoint_sock (line 162) | def test_create_datagram_endpoint_sock(self):
method test_create_datagram_endpoint_sock_unix_domain (line 188) | def test_create_datagram_endpoint_sock_unix_domain(self):
method test_create_datagram_1 (line 254) | def test_create_datagram_1(self):
method test_socketpair (line 278) | def test_socketpair(self):
method _skip_create_datagram_endpoint_reuse_addr (line 316) | def _skip_create_datagram_endpoint_reuse_addr(self):
method test_create_datagram_endpoint_reuse_address_error (line 323) | def test_create_datagram_endpoint_reuse_address_error(self):
method test_create_datagram_endpoint_reuse_address_warning (line 337) | def test_create_datagram_endpoint_reuse_address_warning(self):
class Test_UV_UDP (line 354) | class Test_UV_UDP(_TestUDP, tb.UVTestCase):
method test_create_datagram_endpoint_wrong_sock (line 356) | def test_create_datagram_endpoint_wrong_sock(self):
method test_udp_sendto_dns (line 364) | def test_udp_sendto_dns(self):
method test_udp_sendto_broadcast (line 381) | def test_udp_sendto_broadcast(self):
method test_send_after_close (line 397) | def test_send_after_close(self):
method test_create_datagram_endpoint_addrs_ipv6 (line 411) | def test_create_datagram_endpoint_addrs_ipv6(self):
class Test_AIO_UDP (line 415) | class Test_AIO_UDP(_TestUDP, tb.AIOTestCase):
method test_create_datagram_endpoint_addrs_ipv6 (line 417) | def test_create_datagram_endpoint_addrs_ipv6(self):
FILE: tests/test_unix.py
class _TestUnix (line 16) | class _TestUnix:
method test_create_unix_server_1 (line 17) | def test_create_unix_server_1(self):
method test_create_unix_server_2 (line 177) | def test_create_unix_server_2(self):
method test_create_unix_server_3 (line 190) | def test_create_unix_server_3(self):
method test_create_unix_server_existing_path_sock (line 198) | def test_create_unix_server_existing_path_sock(self):
method test_create_unix_connection_open_unix_con_addr (line 211) | def test_create_unix_connection_open_unix_con_addr(self):
method test_create_unix_connection_open_unix_con_sock (line 226) | def test_create_unix_connection_open_unix_con_sock(self):
method test_create_unix_connection_open_con_sock (line 243) | def test_create_unix_connection_open_con_sock(self):
method _test_create_unix_connection_1 (line 260) | def _test_create_unix_connection_1(self, client):
method test_create_unix_connection_2 (line 298) | def test_create_unix_connection_2(self):
method test_create_unix_connection_3 (line 313) | def test_create_unix_connection_3(self):
method test_create_unix_connection_4 (line 356) | def test_create_unix_connection_4(self):
method test_create_unix_connection_5 (line 371) | def test_create_unix_connection_5(self):
method test_create_unix_connection_6 (line 399) | def test_create_unix_connection_6(self):
class Test_UV_Unix (line 408) | class Test_UV_Unix(_TestUnix, tb.UVTestCase):
method test_create_unix_connection_pathlib (line 411) | def test_create_unix_connection_pathlib(self):
method test_create_unix_server_pathlib (line 422) | def test_create_unix_server_pathlib(self):
method test_transport_fromsock_get_extra_info (line 430) | def test_transport_fromsock_get_extra_info(self):
method test_create_unix_server_path_dgram (line 453) | def test_create_unix_server_path_dgram(self):
method test_create_unix_server_path_stream_bittype (line 464) | def test_create_unix_server_path_stream_bittype(self):
method test_epollhup (line 478) | def test_epollhup(self):
class Test_AIO_Unix (line 529) | class Test_AIO_Unix(_TestUnix, tb.AIOTestCase):
class _TestSSL (line 533) | class _TestSSL(tb.SSLTestCase):
method test_create_unix_server_ssl_1 (line 538) | def test_create_unix_server_ssl_1(self):
method test_create_unix_connection_ssl_1 (line 638) | def test_create_unix_connection_ssl_1(self):
class Test_UV_UnixSSL (line 701) | class Test_UV_UnixSSL(_TestSSL, tb.UVTestCase):
class Test_AIO_UnixSSL (line 705) | class Test_AIO_UnixSSL(_TestSSL, tb.AIOTestCase):
FILE: uvloop/__init__.py
class Loop (line 18) | class Loop(__BaseLoop, _AbstractEventLoop): # type: ignore[misc]
function new_event_loop (line 22) | def new_event_loop() -> Loop:
function run (line 28) | def run(
function run (line 38) | def run(main, *, loop_factory=new_event_loop, debug=None, **run_kwargs):
function _cancel_all_tasks (line 104) | def _cancel_all_tasks(loop: _AbstractEventLoop) -> None:
function __getattr__ (line 136) | def __getattr__(name: str) -> _typing.Any:
FILE: uvloop/_noop.py
function noop (line 1) | def noop() -> None:
FILE: uvloop/_testbase.py
class MockPattern (line 24) | class MockPattern(str):
method __eq__ (line 25) | def __eq__(self, other):
class TestCaseDict (line 29) | class TestCaseDict(collections.UserDict):
method __init__ (line 31) | def __init__(self, name):
method __setitem__ (line 35) | def __setitem__(self, key, value):
class BaseTestCaseMeta (line 42) | class BaseTestCaseMeta(type):
method __prepare__ (line 45) | def __prepare__(mcls, name, bases):
method __new__ (line 48) | def __new__(mcls, name, bases, dct):
class BaseTestCase (line 62) | class BaseTestCase(unittest.TestCase, metaclass=BaseTestCaseMeta):
method new_loop (line 64) | def new_loop(self):
method new_policy (line 67) | def new_policy(self):
method mock_pattern (line 70) | def mock_pattern(self, str):
method wait_closed (line 73) | async def wait_closed(self, obj):
method is_asyncio_loop (line 81) | def is_asyncio_loop(self):
method run_loop_briefly (line 84) | def run_loop_briefly(self, *, delay=0.01):
method loop_exception_handler (line 87) | def loop_exception_handler(self, loop, context):
method setUp (line 91) | def setUp(self):
method tearDown (line 100) | def tearDown(self):
method skip_unclosed_handles_check (line 157) | def skip_unclosed_handles_check(self):
method tcp_server (line 160) | def tcp_server(self, server_prog, *,
method tcp_client (line 192) | def tcp_client(self, client_prog,
method unix_server (line 207) | def unix_server(self, *args, **kwargs):
method unix_client (line 210) | def unix_client(self, *args, **kwargs):
method unix_sock_name (line 214) | def unix_sock_name(self):
method _abort_socket_test (line 225) | def _abort_socket_test(self, ex):
function _cert_fullname (line 232) | def _cert_fullname(test_file_name, cert_file_name):
function silence_long_exec_warning (line 240) | def silence_long_exec_warning():
function find_free_port (line 256) | def find_free_port(start_from=50000):
class SSLTestCase (line 269) | class SSLTestCase:
method _create_server_ssl_context (line 271) | def _create_server_ssl_context(self, certfile, keyfile=None):
method _create_client_ssl_context (line 282) | def _create_client_ssl_context(self, *, disable_verify=True):
method _silence_eof_received_warning (line 290) | def _silence_eof_received_warning(self):
class UVTestCase (line 301) | class UVTestCase(BaseTestCase):
method new_loop (line 305) | def new_loop(self):
method new_policy (line 308) | def new_policy(self):
class AIOTestCase (line 312) | class AIOTestCase(BaseTestCase):
method setUp (line 316) | def setUp(self):
method tearDown (line 324) | def tearDown(self):
method new_loop (line 329) | def new_loop(self):
method new_policy (line 332) | def new_policy(self):
function has_IPv6 (line 336) | def has_IPv6():
class TestSocketWrapper (line 355) | class TestSocketWrapper:
method __init__ (line 357) | def __init__(self, sock):
method recv_all (line 360) | def recv_all(self, n):
method starttls (line 369) | def starttls(self, ssl_context, *,
method __getattr__ (line 387) | def __getattr__(self, name):
method __repr__ (line 390) | def __repr__(self):
class SocketThread (line 394) | class SocketThread(threading.Thread):
method stop (line 396) | def stop(self):
method __enter__ (line 400) | def __enter__(self):
method __exit__ (line 404) | def __exit__(self, *exc):
class TestThreadedClient (line 408) | class TestThreadedClient(SocketThread):
method __init__ (line 410) | def __init__(self, test, sock, prog, timeout):
method run (line 420) | def run(self):
class TestThreadedServer (line 429) | class TestThreadedServer(SocketThread):
method __init__ (line 431) | def __init__(self, test, sock, prog, timeout, max_clients):
method stop (line 449) | def stop(self):
method run (line 459) | def run(self):
method _run (line 468) | def _run(self):
method _handle_client (line 504) | def _handle_client(self, sock):
method addr (line 508) | def addr(self):
function run_briefly (line 517) | def run_briefly(loop):
function run_until (line 531) | def run_until(loop, pred, timeout=30):
function disable_logger (line 542) | def disable_logger():
FILE: uvloop/includes/compat.h
type epoll_event (line 27) | struct epoll_event {}
function epoll_ctl (line 28) | int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event) {
function PyObject (line 34) | PyObject *
function PyObject (line 60) | PyObject * Context_CopyCurrent(void) {
function Context_Enter (line 64) | int Context_Enter(PyObject *ctx) {
function Context_Exit (line 68) | int Context_Exit(PyObject *ctx) {
function PyObject (line 74) | PyObject * Context_CopyCurrent(void) {
function Context_Enter (line 78) | int Context_Enter(PyObject *ctx) {
function Context_Exit (line 82) | int Context_Exit(PyObject *ctx) {
function _Py_RestoreSignals (line 93) | void
FILE: uvloop/includes/fork_handler.h
function handleAtFork (line 16) | void handleAtFork(void) {
function setForkHandler (line 27) | void setForkHandler(OnForkHandler handler)
function resetForkHandler (line 33) | void resetForkHandler(void)
function setMainThreadID (line 38) | void setMainThreadID(uint64_t id) {
FILE: uvloop/loop.pyi
class Loop (line 27) | class Loop:
method call_soon (line 28) | def call_soon(
method call_soon_threadsafe (line 31) | def call_soon_threadsafe(
method call_later (line 34) | def call_later(
method call_at (line 37) | def call_at(
method time (line 40) | def time(self) -> float: ...
method stop (line 41) | def stop(self) -> None: ...
method run_forever (line 42) | def run_forever(self) -> None: ...
method close (line 43) | def close(self) -> None: ...
method get_debug (line 44) | def get_debug(self) -> bool: ...
method set_debug (line 45) | def set_debug(self, enabled: bool) -> None: ...
method is_running (line 46) | def is_running(self) -> bool: ...
method is_closed (line 47) | def is_closed(self) -> bool: ...
method create_future (line 48) | def create_future(self) -> asyncio.Future[Any]: ...
method create_task (line 49) | def create_task(
method set_task_factory (line 55) | def set_task_factory(
method get_task_factory (line 61) | def get_task_factory(
method run_until_complete (line 67) | def run_until_complete(self, future: Generator[Any, None, _T]) -> _T: ...
method run_until_complete (line 69) | def run_until_complete(self, future: Awaitable[_T]) -> _T: ...
method getaddrinfo (line 70) | async def getaddrinfo(
method getnameinfo (line 88) | async def getnameinfo(
method start_tls (line 97) | async def start_tls(
method create_server (line 109) | async def create_server(
method create_server (line 127) | async def create_server(
method create_connection (line 145) | async def create_connection(
method create_connection (line 162) | async def create_connection(
method create_unix_server (line 178) | async def create_unix_server(
method create_unix_connection (line 190) | async def create_unix_connection(
method default_exception_handler (line 201) | def default_exception_handler(self, context: _Context) -> None: ...
method get_exception_handler (line 202) | def get_exception_handler(self) -> Optional[_ExceptionHandler]: ...
method set_exception_handler (line 203) | def set_exception_handler(self, handler: Optional[_ExceptionHandler]) ...
method call_exception_handler (line 204) | def call_exception_handler(self, context: _Context) -> None: ...
method add_reader (line 205) | def add_reader(self, fd: Any, callback: Callable[..., Any], *args: Any...
method remove_reader (line 206) | def remove_reader(self, fd: Any) -> None: ...
method add_writer (line 207) | def add_writer(self, fd: Any, callback: Callable[..., Any], *args: Any...
method remove_writer (line 208) | def remove_writer(self, fd: Any) -> None: ...
method sock_recv (line 209) | async def sock_recv(self, sock: socket, nbytes: int) -> bytes: ...
method sock_recv_into (line 210) | async def sock_recv_into(self, sock: socket, buf: bytearray) -> int: ...
method sock_sendall (line 211) | async def sock_sendall(self, sock: socket, data: bytes) -> None: ...
method sock_accept (line 212) | async def sock_accept(self, sock: socket) -> Tuple[socket, _RetAddress...
method sock_connect (line 213) | async def sock_connect(self, sock: socket, address: _Address) -> None:...
method sock_recvfrom (line 214) | async def sock_recvfrom(self, sock: socket, bufsize: int) -> bytes: ...
method sock_recvfrom_into (line 215) | async def sock_recvfrom_into(self, sock: socket, buf: bytearray, nbyte...
method sock_sendto (line 216) | async def sock_sendto(self, sock: socket, data: bytes, address: _Addre...
method connect_accepted_socket (line 217) | async def connect_accepted_socket(
method run_in_executor (line 226) | async def run_in_executor(
method set_default_executor (line 229) | def set_default_executor(self, executor: Any) -> None: ...
method subprocess_shell (line 230) | async def subprocess_shell(
method subprocess_exec (line 240) | async def subprocess_exec(
method connect_read_pipe (line 249) | async def connect_read_pipe(
method connect_write_pipe (line 252) | async def connect_write_pipe(
method add_signal_handler (line 255) | def add_signal_handler(
method remove_signal_handler (line 258) | def remove_signal_handler(self, sig: int) -> bool: ...
method create_datagram_endpoint (line 259) | async def create_datagram_endpoint(
method shutdown_asyncgens (line 273) | async def shutdown_asyncgens(self) -> None: ...
method shutdown_default_executor (line 274) | async def shutdown_default_executor(
method sendfile (line 280) | async def sendfile(
method sock_sendfile (line 289) | async def sock_sendfile(
Condensed preview — 110 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (825K chars).
[
{
"path": ".editorconfig",
"chars": 173,
"preview": "root = true\n\n[*]\ntrim_trailing_whitespace = true\ninsert_final_newline = true\n\n[Makefile]\nindent_style = tab\n\n[*.{py,pyx,"
},
{
"path": ".flake8",
"chars": 351,
"preview": "[flake8]\nfilename = *.py,*.pyi\nignore = E402,E731,D100,D101,D102,D103,D104,D105,W503,W504,E252\nexclude = .git,__pycache_"
},
{
"path": ".github/ISSUE_TEMPLATE.md",
"chars": 512,
"preview": "<!--\nThanks for wanting to report an issue you've found in uvloop. Please fill in\nthe template below.\n\nIt will be much e"
},
{
"path": ".github/release_log.py",
"chars": 1239,
"preview": "#!/usr/bin/env python3\n\n\nimport argparse\nimport json\nimport requests\nimport re\n\n\nBASE_URL = 'https://api.github.com/repo"
},
{
"path": ".github/workflows/release.yml",
"chars": 5140,
"preview": "name: Release\n\non:\n pull_request:\n branches:\n - \"master\"\n - \"ci\"\n - \"[0-9]+.[0-9x]+*\"\n paths:\n "
},
{
"path": ".github/workflows/tests.yml",
"chars": 2031,
"preview": "name: Tests\n\non:\n push:\n branches:\n - master\n - ci\n pull_request:\n branches:\n - master\n\njobs:\n t"
},
{
"path": ".gitignore",
"chars": 346,
"preview": "*._*\n*.pyc\n*.pyo\n*.ymlc\n*.ymlc~\n*.scssc\n*.so\n*~\n.#*\n.DS_Store\n.project\n.pydevproject\n.settings\n.idea\n/.ropeproject\n\\#*#\n"
},
{
"path": ".gitmodules",
"chars": 90,
"preview": "[submodule \"vendor/libuv\"]\n\tpath = vendor/libuv\n\turl = https://github.com/libuv/libuv.git\n"
},
{
"path": "LICENSE-APACHE",
"chars": 11439,
"preview": "Copyright (C) 2016-present the uvloop authors and contributors.\n\n Apache License\n "
},
{
"path": "LICENSE-MIT",
"chars": 1105,
"preview": "The MIT License\n\nCopyright (C) 2016-present the uvloop authors and contributors.\n\nPermission is hereby granted, free of "
},
{
"path": "MANIFEST.in",
"chars": 406,
"preview": "recursive-include docs *.py *.rst\nrecursive-include examples *.py\nrecursive-include tests *.py *.pem\nrecursive-include u"
},
{
"path": "Makefile",
"chars": 1150,
"preview": ".PHONY: _default clean clean-libuv distclean compile debug docs test testinstalled release setup-build ci-clean\n\n\nPYTHON"
},
{
"path": "README.rst",
"chars": 3112,
"preview": ".. image:: https://img.shields.io/github/actions/workflow/status/MagicStack/uvloop/tests.yml?branch=master\n :target: "
},
{
"path": "docs/.gitignore",
"chars": 26,
"preview": "_build\n_static\n_templates\n"
},
{
"path": "docs/api/index.rst",
"chars": 317,
"preview": "API\n===\n\nIf you are looking for information on a specific function, class or method,\nthis part of the documentation is f"
},
{
"path": "docs/conf.py",
"chars": 2191,
"preview": "#!/usr/bin/env python3\n\nimport alabaster\nimport os\nimport sys\n\nsys.path.insert(0, os.path.abspath('..'))\n\nversion_file ="
},
{
"path": "docs/dev/index.rst",
"chars": 2808,
"preview": "Developers Guide\n================\n\nThe project is hosted on `GitHub <https://github.com/MagicStack/uvloop>`_.\nand uses `"
},
{
"path": "docs/index.rst",
"chars": 2259,
"preview": ".. image:: https://img.shields.io/github/actions/workflow/status/MagicStack/uvloop/tests.yml?branch=master\n :target: "
},
{
"path": "docs/user/index.rst",
"chars": 719,
"preview": "User Guide\n==========\n\nThis section of the documentation provides information about how to use\nuvloop.\n\n\nInstallation\n--"
},
{
"path": "examples/bench/echoclient.py",
"chars": 3057,
"preview": "# Copied with minimal modifications from curio\n# https://github.com/dabeaz/curio\n\n\nimport argparse\nimport concurrent.fut"
},
{
"path": "examples/bench/echoserver.py",
"chars": 6317,
"preview": "import argparse\nimport asyncio\nimport gc\nimport os.path\nimport pathlib\nimport socket\nimport ssl\n\n\nPRINT = 0\n\n\nasync def "
},
{
"path": "examples/bench/rlserver.py",
"chars": 2352,
"preview": "import argparse\nimport asyncio\nimport gc\nimport os.path\nimport socket as stdsock\n\n\nPRINT = 0\n\n\nasync def echo_client_str"
},
{
"path": "mypy.ini",
"chars": 86,
"preview": "[mypy]\nincremental = True\nstrict = True\n\n[mypy-uvloop._testbase]\nignore_errors = True\n"
},
{
"path": "pyproject.toml",
"chars": 2174,
"preview": "[project]\nname = \"uvloop\"\ndescription = \"Fast implementation of asyncio event loop on top of libuv\"\nauthors = [{name = \""
},
{
"path": "setup.py",
"chars": 8360,
"preview": "import sys\n\nvi = sys.version_info\nif vi < (3, 8):\n raise RuntimeError('uvloop requires Python 3.8 or greater')\n\nif sy"
},
{
"path": "tests/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "tests/__main__.py",
"chars": 356,
"preview": "import os.path\nimport sys\nimport unittest\nimport unittest.runner\n\n\ndef suite():\n test_loader = unittest.TestLoader()\n"
},
{
"path": "tests/certs/ssl_cert.pem",
"chars": 2122,
"preview": "-----BEGIN CERTIFICATE-----\nMIIF8TCCBFmgAwIBAgIJAMstgJlaaVJcMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNV\nBAYTAlhZMSYwJAYDVQQKDB1QeXR"
},
{
"path": "tests/certs/ssl_key.pem",
"chars": 2484,
"preview": "-----BEGIN PRIVATE KEY-----\nMIIG/QIBADANBgkqhkiG9w0BAQEFAASCBucwggbjAgEAAoIBgQCfKC83Qe9/ZGMW\nYhbpARRiKco6mJI9CNNeaf7A89T"
},
{
"path": "tests/test_aiohttp.py",
"chars": 4200,
"preview": "try:\n import aiohttp\n import aiohttp.web\nexcept ImportError:\n skip_tests = True\nelse:\n skip_tests = False\n\ni"
},
{
"path": "tests/test_base.py",
"chars": 31654,
"preview": "import asyncio\nimport fcntl\nimport logging\nimport os\nimport random\nimport sys\nimport subprocess\nimport threading\nimport "
},
{
"path": "tests/test_context.py",
"chars": 27825,
"preview": "import asyncio\nimport contextvars\nimport decimal\nimport itertools\nimport random\nimport socket\nimport ssl\nimport sys\nimpo"
},
{
"path": "tests/test_cython.py",
"chars": 1206,
"preview": "import asyncio\n\nfrom uvloop._testbase import UVTestCase\n\n\nclass TestCythonIntegration(UVTestCase):\n\n def test_cython_"
},
{
"path": "tests/test_dealloc.py",
"chars": 1843,
"preview": "import asyncio\nimport subprocess\nimport sys\n\nfrom uvloop import _testbase as tb\n\n\nclass TestDealloc(tb.UVTestCase):\n\n "
},
{
"path": "tests/test_dns.py",
"chars": 9808,
"preview": "import asyncio\nimport socket\nimport unittest\n\nfrom uvloop import _testbase as tb\n\n\ndef patched_getaddrinfo(*args, **kwar"
},
{
"path": "tests/test_executors.py",
"chars": 1218,
"preview": "import asyncio\nimport concurrent.futures\nimport multiprocessing\nimport unittest\n\nfrom uvloop import _testbase as tb\n\n\nde"
},
{
"path": "tests/test_fs_event.py",
"chars": 2866,
"preview": "import asyncio\nimport contextlib\nimport os.path\nimport tempfile\n\nfrom uvloop import _testbase as tb\nfrom uvloop.loop imp"
},
{
"path": "tests/test_libuv_api.py",
"chars": 732,
"preview": "from uvloop import _testbase as tb\nfrom uvloop.loop import libuv_get_loop_t_ptr, libuv_get_version\nfrom uvloop.loop impo"
},
{
"path": "tests/test_pipes.py",
"chars": 8736,
"preview": "import asyncio\nimport io\nimport os\nimport socket\n\nfrom uvloop import _testbase as tb\n\n\n# All tests are copied from async"
},
{
"path": "tests/test_process.py",
"chars": 31322,
"preview": "import asyncio\nimport contextlib\nimport gc\nimport os\nimport pathlib\nimport signal\nimport subprocess\nimport sys\nimport te"
},
{
"path": "tests/test_process_spawning.py",
"chars": 3737,
"preview": "import asyncio\nimport ctypes.util\nimport logging\nfrom concurrent.futures import ThreadPoolExecutor\nfrom threading import"
},
{
"path": "tests/test_regr1.py",
"chars": 3295,
"preview": "import asyncio\nimport queue\nimport multiprocessing\nimport signal\nimport threading\nimport unittest\n\nimport uvloop\n\nfrom u"
},
{
"path": "tests/test_runner.py",
"chars": 852,
"preview": "import asyncio\nimport unittest\nimport uvloop\n\n\nclass TestSourceCode(unittest.TestCase):\n\n def test_uvloop_run_1(self)"
},
{
"path": "tests/test_signals.py",
"chars": 10250,
"preview": "import asyncio\nimport signal\nimport subprocess\nimport sys\nimport time\n\nfrom uvloop import _testbase as tb\n\nDELAY = 0.1\n\n"
},
{
"path": "tests/test_sockets.py",
"chars": 25071,
"preview": "import asyncio\nimport pickle\nimport select\nimport socket\nimport sys\nimport time\nimport unittest\n\nfrom uvloop import _tes"
},
{
"path": "tests/test_sourcecode.py",
"chars": 2312,
"preview": "import os\nimport subprocess\nimport sys\nimport unittest\n\n\ndef find_uvloop_root():\n return os.path.dirname(os.path.dirn"
},
{
"path": "tests/test_tcp.py",
"chars": 104201,
"preview": "import asyncio\nimport asyncio.sslproto\nimport gc\nimport os\nimport select\nimport socket\nimport unittest.mock\nimport ssl\ni"
},
{
"path": "tests/test_testbase.py",
"chars": 1374,
"preview": "import unittest\n\nfrom uvloop import _testbase as tb\n\n\nclass TestBaseTest(unittest.TestCase):\n\n def test_duplicate_met"
},
{
"path": "tests/test_udp.py",
"chars": 14686,
"preview": "import asyncio\nimport os\nimport socket\nimport sys\nimport tempfile\nimport unittest\nimport uuid\n\nfrom uvloop import _testb"
},
{
"path": "tests/test_unix.py",
"chars": 23346,
"preview": "import asyncio\nimport os\nimport pathlib\nimport socket\nimport tempfile\nimport time\nimport unittest\nimport sys\n\nfrom uvloo"
},
{
"path": "uvloop/.gitignore",
"chars": 11,
"preview": "*.c\n*.html\n"
},
{
"path": "uvloop/__init__.py",
"chars": 7558,
"preview": "import asyncio as __asyncio\nimport typing as _typing\nimport sys as _sys\nimport warnings as _warnings\n\nfrom . import incl"
},
{
"path": "uvloop/_noop.py",
"chars": 86,
"preview": "def noop() -> None:\n \"\"\"Empty function to invoke CPython ceval loop.\"\"\"\n return\n"
},
{
"path": "uvloop/_testbase.py",
"chars": 15570,
"preview": "\"\"\"Test utilities. Don't use outside of the uvloop project.\"\"\"\n\n\nimport asyncio\nimport asyncio.events\nimport collections"
},
{
"path": "uvloop/_version.py",
"chars": 576,
"preview": "# This file MUST NOT contain anything but the __version__ assignment.\n#\n# When making a release, change the value of __v"
},
{
"path": "uvloop/cbhandles.pxd",
"chars": 752,
"preview": "cdef class Handle:\n cdef:\n Loop loop\n object context\n bint _cancelled\n\n str meth_name\n "
},
{
"path": "uvloop/cbhandles.pyx",
"chars": 12706,
"preview": "@cython.no_gc_clear\n@cython.freelist(DEFAULT_FREELIST_SIZE)\ncdef class Handle:\n def __cinit__(self):\n self._ca"
},
{
"path": "uvloop/dns.pyx",
"chars": 14562,
"preview": "cdef __port_to_int(port, proto):\n if type(port) is int:\n return port\n\n if port is None or port == '' or por"
},
{
"path": "uvloop/errors.pyx",
"chars": 2774,
"preview": "cdef str __strerr(int errno):\n return strerror(errno).decode()\n\n\ncdef __convert_python_error(int uverr):\n # XXX Wo"
},
{
"path": "uvloop/handles/async_.pxd",
"chars": 252,
"preview": "cdef class UVAsync(UVHandle):\n cdef:\n method_t callback\n object ctx\n\n cdef _init(self, Loop loop, me"
},
{
"path": "uvloop/handles/async_.pyx",
"chars": 1516,
"preview": "@cython.no_gc_clear\ncdef class UVAsync(UVHandle):\n cdef _init(self, Loop loop, method_t callback, object ctx):\n "
},
{
"path": "uvloop/handles/basetransport.pxd",
"chars": 1322,
"preview": "cdef class UVBaseTransport(UVSocketHandle):\n\n cdef:\n readonly bint _closing\n\n bint _protocol_connected\n"
},
{
"path": "uvloop/handles/basetransport.pyx",
"chars": 9553,
"preview": "cdef class UVBaseTransport(UVSocketHandle):\n\n def __cinit__(self):\n # Flow control\n self._high_water = "
},
{
"path": "uvloop/handles/check.pxd",
"chars": 276,
"preview": "cdef class UVCheck(UVHandle):\n cdef:\n Handle h\n bint running\n\n # All \"inline\" methods are final\n\n "
},
{
"path": "uvloop/handles/check.pyx",
"chars": 1881,
"preview": "@cython.no_gc_clear\ncdef class UVCheck(UVHandle):\n cdef _init(self, Loop loop, Handle h):\n cdef int err\n\n "
},
{
"path": "uvloop/handles/fsevent.pxd",
"chars": 325,
"preview": "cdef class UVFSEvent(UVHandle):\n cdef:\n object callback\n bint running\n\n cdef _init(self, Loop loop, "
},
{
"path": "uvloop/handles/fsevent.pyx",
"chars": 2823,
"preview": "import enum\n\n\nclass FileSystemEvent(enum.IntEnum):\n RENAME = uv.UV_RENAME\n CHANGE = uv.UV_CHANGE\n RENAME_CHANGE"
},
{
"path": "uvloop/handles/handle.pxd",
"chars": 1189,
"preview": "cdef class UVHandle:\n cdef:\n uv.uv_handle_t *_handle\n Loop _loop\n readonly _source_traceback\n "
},
{
"path": "uvloop/handles/handle.pyx",
"chars": 13248,
"preview": "cdef class UVHandle:\n \"\"\"A base class for all libuv handles.\n\n Automatically manages memory deallocation and closi"
},
{
"path": "uvloop/handles/idle.pxd",
"chars": 274,
"preview": "cdef class UVIdle(UVHandle):\n cdef:\n Handle h\n bint running\n\n # All \"inline\" methods are final\n\n "
},
{
"path": "uvloop/handles/idle.pyx",
"chars": 1859,
"preview": "@cython.no_gc_clear\ncdef class UVIdle(UVHandle):\n cdef _init(self, Loop loop, Handle h):\n cdef int err\n\n "
},
{
"path": "uvloop/handles/pipe.pxd",
"chars": 933,
"preview": "cdef class UnixServer(UVStreamServer):\n\n cdef bind(self, str path)\n\n @staticmethod\n cdef UnixServer new(Loop lo"
},
{
"path": "uvloop/handles/pipe.pyx",
"chars": 7688,
"preview": "cdef __pipe_init_uv_handle(UVStream handle, Loop loop):\n cdef int err\n\n handle._handle = <uv.uv_handle_t*>PyMem_Ra"
},
{
"path": "uvloop/handles/poll.pxd",
"chars": 575,
"preview": "cdef class UVPoll(UVHandle):\n cdef:\n int fd\n Handle reading_handle\n Handle writing_handle\n\n c"
},
{
"path": "uvloop/handles/poll.pyx",
"chars": 6511,
"preview": "@cython.no_gc_clear\ncdef class UVPoll(UVHandle):\n cdef _init(self, Loop loop, int fd):\n cdef int err\n\n "
},
{
"path": "uvloop/handles/process.pxd",
"chars": 2314,
"preview": "cdef class UVProcess(UVHandle):\n cdef:\n object _returncode\n object _pid\n\n object _errpipe_read\n "
},
{
"path": "uvloop/handles/process.pyx",
"chars": 26919,
"preview": "@cython.no_gc_clear\ncdef class UVProcess(UVHandle):\n \"\"\"Abstract class; wrapper over uv_process_t handle.\"\"\"\n\n def"
},
{
"path": "uvloop/handles/stream.pxd",
"chars": 1846,
"preview": "cdef enum ProtocolType:\n SIMPLE = 0 # User Protocol doesn't support asyncio.BufferedProtocol\n BUFFERED = "
},
{
"path": "uvloop/handles/stream.pyx",
"chars": 33232,
"preview": "cdef enum:\n __PREALLOCED_BUFS = 4\n\n\n@cython.no_gc_clear\n@cython.freelist(DEFAULT_FREELIST_SIZE)\ncdef class _StreamWri"
},
{
"path": "uvloop/handles/streamserver.pxd",
"chars": 786,
"preview": "cdef class UVStreamServer(UVSocketHandle):\n cdef:\n int backlog\n object ssl\n object ssl_handshake"
},
{
"path": "uvloop/handles/streamserver.pyx",
"chars": 4632,
"preview": "@cython.no_gc_clear\ncdef class UVStreamServer(UVSocketHandle):\n\n def __cinit__(self):\n self.opened = 0\n "
},
{
"path": "uvloop/handles/tcp.pxd",
"chars": 892,
"preview": "cdef class TCPServer(UVStreamServer):\n cdef bind(self, system.sockaddr* addr, unsigned int flags=*)\n\n @staticmetho"
},
{
"path": "uvloop/handles/tcp.pyx",
"chars": 7291,
"preview": "cdef __tcp_init_uv_handle(UVStream handle, Loop loop, unsigned int flags):\n cdef int err\n\n handle._handle = <uv.uv"
},
{
"path": "uvloop/handles/timer.pxd",
"chars": 440,
"preview": "cdef class UVTimer(UVHandle):\n cdef:\n method_t callback\n object ctx\n bint running\n uint64"
},
{
"path": "uvloop/handles/timer.pyx",
"chars": 2416,
"preview": "@cython.no_gc_clear\ncdef class UVTimer(UVHandle):\n cdef _init(self, Loop loop, method_t callback, object ctx,\n "
},
{
"path": "uvloop/handles/udp.pxd",
"chars": 671,
"preview": "cdef class UDPTransport(UVBaseTransport):\n cdef:\n bint __receiving\n int _family\n object _address"
},
{
"path": "uvloop/handles/udp.pyx",
"chars": 12252,
"preview": "@cython.no_gc_clear\n@cython.freelist(DEFAULT_FREELIST_SIZE)\ncdef class _UDPSendContext:\n # used to hold additional wr"
},
{
"path": "uvloop/includes/__init__.py",
"chars": 361,
"preview": "# flake8: noqa\n\n# These have to be synced with the stdlib.pxi\nimport asyncio\nimport collections\nimport concurrent.future"
},
{
"path": "uvloop/includes/compat.h",
"chars": 2166,
"preview": "#include <errno.h>\n#include <stddef.h>\n#include <signal.h>\n#include <sys/socket.h>\n#include <sys/un.h>\n#include \"Python."
},
{
"path": "uvloop/includes/consts.pxi",
"chars": 843,
"preview": "cdef enum:\n UV_STREAM_RECV_BUF_SIZE = 256000 # 250kb\n\n FLOW_CONTROL_HIGH_WATER = 64 # KiB\n FLOW_CONTROL_HIGH_"
},
{
"path": "uvloop/includes/debug.h",
"chars": 51,
"preview": "#ifndef UVLOOP_DEBUG\n#define UVLOOP_DEBUG 0\n#endif\n"
},
{
"path": "uvloop/includes/debug.pxd",
"chars": 64,
"preview": "cdef extern from \"includes/debug.h\":\n\n cdef int UVLOOP_DEBUG\n"
},
{
"path": "uvloop/includes/flowcontrol.pxd",
"chars": 458,
"preview": "# flake8: noqa\n\n\ncdef inline add_flowcontrol_defaults(high, low, int kb):\n cdef int h, l\n if high is None:\n "
},
{
"path": "uvloop/includes/fork_handler.h",
"chars": 937,
"preview": "#ifndef UVLOOP_FORK_HANDLER_H_\n#define UVLOOP_FORK_HANDLER_H_\n\nvolatile uint64_t MAIN_THREAD_ID = 0;\nvolatile int8_t MAI"
},
{
"path": "uvloop/includes/python.pxd",
"chars": 846,
"preview": "cdef extern from \"Python.h\":\n int PY_VERSION_HEX\n\n unicode PyUnicode_FromString(const char *)\n\n void* PyMem_Raw"
},
{
"path": "uvloop/includes/stdlib.pxi",
"chars": 6381,
"preview": "# flake8: noqa\n\n\nimport asyncio, asyncio.log, asyncio.base_events, \\\n asyncio.sslproto, asyncio.coroutines, \\\n "
},
{
"path": "uvloop/includes/system.pxd",
"chars": 2405,
"preview": "from libc.stdint cimport int8_t, uint64_t\n\ncdef extern from \"arpa/inet.h\" nogil:\n\n int ntohl(int)\n int htonl(int)\n"
},
{
"path": "uvloop/includes/uv.pxd",
"chars": 16080,
"preview": "from libc.stdint cimport uint16_t, uint32_t, uint64_t, int64_t\nfrom posix.types cimport gid_t, uid_t\nfrom posix.unistd c"
},
{
"path": "uvloop/loop.pxd",
"chars": 6194,
"preview": "# cython: language_level=3\n\n\nfrom .includes cimport uv\nfrom .includes cimport system\n\nfrom libc.stdint cimport uint64_t,"
},
{
"path": "uvloop/loop.pyi",
"chars": 10504,
"preview": "import asyncio\nimport ssl\nimport sys\nfrom socket import AddressFamily, SocketKind, _Address, _RetAddress, socket\nfrom ty"
},
{
"path": "uvloop/loop.pyx",
"chars": 118251,
"preview": "# cython: language_level=3, embedsignature=True, freethreading_compatible=True\n\nimport asyncio\ncimport cython\n\nfrom .inc"
},
{
"path": "uvloop/lru.pyx",
"chars": 2279,
"preview": "cdef object _LRU_MARKER = object()\n\n\n@cython.final\ncdef class LruCache:\n\n cdef:\n object _dict\n int _max"
},
{
"path": "uvloop/pseudosock.pyx",
"chars": 5383,
"preview": "cdef class PseudoSocket:\n cdef:\n int _family\n int _type\n int _proto\n int _fd\n obje"
},
{
"path": "uvloop/py.typed",
"chars": 0,
"preview": ""
},
{
"path": "uvloop/request.pxd",
"chars": 143,
"preview": "cdef class UVRequest:\n cdef:\n uv.uv_req_t *request\n bint done\n Loop loop\n\n cdef on_done(self)"
},
{
"path": "uvloop/request.pyx",
"chars": 2259,
"preview": "cdef class UVRequest:\n \"\"\"A base class for all libuv requests (uv_getaddrinfo_t, etc).\n\n Important: it's a respons"
},
{
"path": "uvloop/server.pxd",
"chars": 394,
"preview": "cdef class Server:\n cdef:\n list _servers\n list _waiters\n int _active_count\n Loop _loop\n "
},
{
"path": "uvloop/server.pyx",
"chars": 3623,
"preview": "import asyncio\n\n\ncdef class Server:\n def __cinit__(self, Loop loop):\n self._loop = loop\n self._servers "
},
{
"path": "uvloop/sslproto.pxd",
"chars": 3983,
"preview": "cdef enum SSLProtocolState:\n UNWRAPPED = 0\n DO_HANDSHAKE = 1\n WRAPPED = 2\n FLUSHING = 3\n SHUTDOWN = 4\n\n\nc"
},
{
"path": "uvloop/sslproto.pyx",
"chars": 38090,
"preview": "cdef _create_transport_context(server_side, server_hostname):\n if server_side:\n raise ValueError('Server side "
}
]
About this extraction
This page contains the full source code of the MagicStack/uvloop GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 110 files (774.9 KB), approximately 177.9k tokens, and a symbol index with 609 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.