diff --git a/.coveragerc b/.coveragerc
index d1e79c9..f70c551 100644
--- a/.coveragerc
+++ b/.coveragerc
@@ -5,6 +5,7 @@ omit =
.venv/*
[report]
+fail_under = 100
show_missing = True
skip_covered = False
exclude_lines =
diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml
new file mode 100644
index 0000000..0ce784d
--- /dev/null
+++ b/.github/workflows/main.yaml
@@ -0,0 +1,85 @@
+name: CI
+on: [push]
+jobs:
+ tests:
+ name: Python ${{ matrix.python-version }} Tests
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ python-version:
+ - '3.9'
+ - '3.10'
+ steps:
+ - uses: actions/checkout@v3
+
+ - uses: actions/setup-python@v3
+ with:
+ python-version: ${{ matrix.python-version }}
+ cache: 'pip'
+ cache-dependency-path: 'requirements/dev.txt'
+
+ - name: Upgrade packaging tools
+ run: pip install -U pip
+
+ - name: Install dependencies
+ run: pip install -U -r requirements/dev.txt
+
+ - name: Install asyncio-taskpool
+ run: pip install -e .
+
+ - name: Run tests for Python ${{ matrix.python-version }}
+ if: ${{ matrix.python-version != '3.10' }}
+ run: python -m tests
+
+ - name: Run tests for Python 3.10 and save coverage
+ if: ${{ matrix.python-version == '3.10' }}
+ run: echo "coverage=$(./coverage.sh)" >> $GITHUB_ENV
+
+ outputs:
+ coverage: ${{ env.coverage }}
+
+ update_badges:
+ needs: tests
+ name: Update Badges
+ env:
+ meta_gist_id: 3f8240a976e8781a765d9c74a583dcda
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v3
+
+ - name: Download `cloc`
+ run: sudo apt-get update -y && sudo apt-get install -y cloc
+
+ - name: Count lines of code/comments
+ run: |
+ echo "cloc_code=$(./cloc.sh -c src/)" >> $GITHUB_ENV
+ echo "cloc_comments=$(./cloc.sh -m src/)" >> $GITHUB_ENV
+ echo "cloc_commentpercent=$(./cloc.sh -p src/)" >> $GITHUB_ENV
+
+ - name: Create badge for lines of code
+ uses: Schneegans/dynamic-badges-action@v1.2.0
+ with:
+ auth: ${{ secrets.GIST_META_DATA }}
+ gistID: ${{ env.meta_gist_id }}
+ filename: cloc-code.json
+ label: Lines of Code
+ message: ${{ env.cloc_code }}
+
+ - name: Create badge for lines of comments
+ uses: Schneegans/dynamic-badges-action@v1.2.0
+ with:
+ auth: ${{ secrets.GIST_META_DATA }}
+ gistID: ${{ env.meta_gist_id }}
+ filename: cloc-comments.json
+ label: Comments
+ message: ${{ env.cloc_comments }} (${{ env.cloc_commentpercent }}%)
+
+ - name: Create badge for test coverage
+ uses: Schneegans/dynamic-badges-action@v1.2.0
+ with:
+ auth: ${{ secrets.GIST_META_DATA }}
+ gistID: ${{ env.meta_gist_id }}
+ filename: test-coverage.json
+ label: Coverage
+ message: ${{ needs.tests.outputs.coverage }}
diff --git a/README.md b/README.md
index 4f5bce2..14a6d81 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,29 @@
+[//]: # (This file is part of asyncio-taskpool.)
+
+[//]: # (asyncio-taskpool is free software: you can redistribute it and/or modify it under the terms of)
+[//]: # (version 3.0 of the GNU Lesser General Public License as published by the Free Software Foundation.)
+
+[//]: # (asyncio-taskpool is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;)
+[//]: # (without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.)
+[//]: # (See the GNU Lesser General Public License for more details.)
+
+[//]: # (You should have received a copy of the GNU Lesser General Public License along with asyncio-taskpool.)
+[//]: # (If not, see .)
+
# asyncio-taskpool
+[![GitHub last commit][github-last-commit-img]][github-last-commit]
+![Lines of code][gist-cloc-code-img]
+![Lines of comments][gist-cloc-comments-img]
+![Test coverage][gist-test-coverage-img]
+[![License: LGPL v3.0][lgpl3-img]][lgpl3]
+
**Dynamically manage pools of asyncio tasks**
+Full documentation available at [RtD](https://asyncio-taskpool.readthedocs.io/en/latest).
+
+---
+
## Contents
- [Contents](#contents)
- [Summary](#summary)
@@ -67,3 +89,11 @@ The full license texts for the [GNU GPLv3.0](COPYING) and the [GNU LGPLv3.0](COP
---
© 2022 Daniil Fajnberg
+
+[github-last-commit]: https://github.com/daniil-berg/asyncio-taskpool/commits
+[github-last-commit-img]: https://img.shields.io/github/last-commit/daniil-berg/asyncio-taskpool?label=Last%20commit&logo=git&
+[gist-cloc-code-img]: https://img.shields.io/endpoint?logo=python&color=blue&url=https://gist.githubusercontent.com/daniil-berg/3f8240a976e8781a765d9c74a583dcda/raw/cloc-code.json
+[gist-cloc-comments-img]: https://img.shields.io/endpoint?logo=sharp&color=lightgrey&url=https://gist.githubusercontent.com/daniil-berg/3f8240a976e8781a765d9c74a583dcda/raw/cloc-comments.json
+[gist-test-coverage-img]: https://img.shields.io/endpoint?logo=pytest&color=blue&url=https://gist.githubusercontent.com/daniil-berg/3f8240a976e8781a765d9c74a583dcda/raw/test-coverage.json
+[lgpl3]: https://www.gnu.org/licenses/lgpl-3.0
+[lgpl3-img]: https://img.shields.io/badge/License-LGPL_v3.0-darkgreen.svg?logo=gnu
diff --git a/cloc.sh b/cloc.sh
new file mode 100755
index 0000000..eebfc52
--- /dev/null
+++ b/cloc.sh
@@ -0,0 +1,46 @@
+#!/usr/bin/env bash
+
+# This file is part of asyncio-taskpool.
+
+# asyncio-taskpool is free software: you can redistribute it and/or modify it under the terms of
+# version 3.0 of the GNU Lesser General Public License as published by the Free Software Foundation.
+
+# asyncio-taskpool is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the GNU Lesser General Public License for more details.
+
+# You should have received a copy of the GNU Lesser General Public License along with asyncio-taskpool.
+# If not, see .
+
+typeset option
+if getopts 'bcmp' option; then
+ if [[ ${option} == [bcmp] ]]; then
+ shift
+ else
+ echo >&2 "Invalid option '$1' provided"
+ exit 1
+ fi
+fi
+
+typeset source=$1
+if [[ -z ${source} ]]; then
+ echo >&2 Source file/directory missing
+ exit 1
+fi
+
+typeset blank code comment commentpercent
+read blank comment code commentpercent < <( \
+ cloc --csv --quiet --hide-rate --include-lang Python ${source} |
+ awk -F, '$2 == "SUM" {printf ("%d %d %d %1.0f", $3, $4, $5, 100 * $4 / ($5 + $4)); exit}'
+)
+
+case ${option} in
+ b) echo ${blank} ;;
+ c) echo ${code} ;;
+ m) echo ${comment} ;;
+ p) echo ${commentpercent} ;;
+ *) echo Blank lines: ${blank}
+ echo Lines of comments: ${comment}
+ echo Lines of code: ${code}
+ echo Comment percentage: ${commentpercent} ;;
+esac
diff --git a/coverage.sh b/coverage.sh
index 786075e..c0e4597 100755
--- a/coverage.sh
+++ b/coverage.sh
@@ -1,3 +1,24 @@
-#!/usr/bin/env sh
+#!/usr/bin/env bash
-coverage erase && coverage run -m unittest discover && coverage report
+# This file is part of asyncio-taskpool.
+
+# asyncio-taskpool is free software: you can redistribute it and/or modify it under the terms of
+# version 3.0 of the GNU Lesser General Public License as published by the Free Software Foundation.
+
+# asyncio-taskpool is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the GNU Lesser General Public License for more details.
+
+# You should have received a copy of the GNU Lesser General Public License along with asyncio-taskpool.
+# If not, see .
+
+coverage erase && coverage run -m unittest discover 2> /dev/null
+
+typeset total
+total=$(coverage report | awk '$1 == "TOTAL" {print $NF}')
+
+if [[ $total == 100% ]]; then
+ echo $total
+else
+ coverage report
+fi
diff --git a/setup.cfg b/setup.cfg
index f8bb68b..f141b17 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -25,7 +25,7 @@ classifiers =
package_dir =
= src
packages = find:
-python_requires = >=3.8
+python_requires = >=3.9
[options.extras_require]
dev =
diff --git a/src/asyncio_taskpool/internals/types.py b/src/asyncio_taskpool/internals/types.py
index 69c6816..65dd98d 100644
--- a/src/asyncio_taskpool/internals/types.py
+++ b/src/asyncio_taskpool/internals/types.py
@@ -31,8 +31,8 @@ T = TypeVar('T')
ArgsT = Iterable[Any]
KwArgsT = Mapping[str, Any]
-AnyCallableT = Callable[[...], Union[T, Awaitable[T]]]
-CoroutineFunc = Callable[[...], Coroutine]
+AnyCallableT = Callable[..., Union[T, Awaitable[T]]]
+CoroutineFunc = Callable[..., Coroutine]
EndCB = Callable
CancelCB = Callable
diff --git a/src/asyncio_taskpool/pool.py b/src/asyncio_taskpool/pool.py
index 320144c..acc9522 100644
--- a/src/asyncio_taskpool/pool.py
+++ b/src/asyncio_taskpool/pool.py
@@ -640,7 +640,7 @@ class TaskPool(BaseTaskPool):
kwargs (optional):
The keyword-arguments to pass into each function call.
num (optional):
- The number of tasks to spawn with the specified parameters.
+ The number of tasks to spawn with the specified parameters. Defaults to 1.
group_name (optional):
Name of the task group to add the new tasks to. By default, a unique name is constructed in the form
:code:`'apply-{name}-group-{idx}'` (with `name` being the name of the `func` and `idx` being an
diff --git a/tests/__main__.py b/tests/__main__.py
new file mode 100644
index 0000000..3b17d90
--- /dev/null
+++ b/tests/__main__.py
@@ -0,0 +1,30 @@
+__author__ = "Daniil Fajnberg"
+__copyright__ = "Copyright © 2022 Daniil Fajnberg"
+__license__ = """GNU LGPLv3.0
+
+This file is part of asyncio-taskpool.
+
+asyncio-taskpool is free software: you can redistribute it and/or modify it under the terms of
+version 3.0 of the GNU Lesser General Public License as published by the Free Software Foundation.
+
+asyncio-taskpool is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See the GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along with asyncio-taskpool.
+If not, see ."""
+
+__doc__ = """
+Main entry point for all unit tests.
+"""
+
+
+import sys
+import unittest
+
+
+if __name__ == '__main__':
+ test_suite = unittest.defaultTestLoader.discover('.')
+ test_runner = unittest.TextTestRunner(resultclass=unittest.TextTestResult)
+ result = test_runner.run(test_suite)
+ sys.exit(not result.wasSuccessful())