diff --git a/.codecov.yml b/.codecov.yml index 541d3e5..4ff1bf9 100644 --- a/.codecov.yml +++ b/.codecov.yml @@ -1,3 +1,5 @@ +--- + codecov: branch: main notify: @@ -6,7 +8,7 @@ codecov: coverage: range: "95..100" status: - project: no + project: false flags: library: diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 6dd4ac6..81d0cec 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,3 +1,4 @@ +--- version: 2 updates: - package-ecosystem: pip diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index ebbb113..eaa8739 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -1,6 +1,7 @@ +--- name: CI -on: +on: # yamllint disable-line rule:truthy push: branches: ["main"] pull_request: @@ -8,7 +9,7 @@ on: release: types: [created] branches: - - 'main' + - 'main' workflow_dispatch: env: @@ -27,29 +28,29 @@ jobs: runs-on: ubuntu-latest # if: github.event_name == 'release' && github.event.action == 'created' steps: - - name: Checkout project - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - name: Set up Python - uses: actions/setup-python@v4 - with: - python-version: ${{ env.PYTHON_LATEST }} - cache: pip - - run: python -m pip install build - name: Install core libraries for build and install - - name: Build artifacts - run: python -m build - - name: Upload built artifacts for testing - uses: actions/upload-artifact@v3 - with: - name: ${{ env.sdist-artifact }} - # NOTE: Exact expected file names are specified here - # NOTE: as a safety measure — if anything weird ends - # NOTE: up being in this dir or not all dists will be - # NOTE: produced, this will fail the workflow. - path: dist/${{ env.sdist-name }} - retention-days: 15 + - name: Checkout project + uses: actions/checkout@v3 + with: + fetch-depth: 0 + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: ${{ env.PYTHON_LATEST }} + cache: pip + - run: python -m pip install build + name: Install core libraries for build and install + - name: Build artifacts + run: python -m build + - name: Upload built artifacts for testing + uses: actions/upload-artifact@v3 + with: + name: ${{ env.sdist-artifact }} + # NOTE: Exact expected file names are specified here + # NOTE: as a safety measure — if anything weird ends + # NOTE: up being in this dir or not all dists will be + # NOTE: produced, this will fail the workflow. + path: dist/${{ env.sdist-name }} + retention-days: 15 lint: uses: ./.github/workflows/lint.yml @@ -63,34 +64,34 @@ jobs: fail-fast: true matrix: python-version: - - "3.8" - - "3.9" - - "3.10" - - "3.11" + - "3.8" + - "3.9" + - "3.10" + - "3.11" experimental: [false] include: - - python-version: "~3.12.0-0" - experimental: true + - python-version: "~3.12.0-0" + experimental: true steps: - - name: Checkout the source code - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - name: Set up Python - uses: actions/setup-python@v4 - with: - python-version: ${{ matrix.python-version }} - cache: pip - cache-dependency-path: | - setup.cfg - requirements-dev.txt - - name: Install dependencies - run: | - pip install -U -r requirements-dev.txt - - name: Run tests - run: python -m pytest --cov=aiomonitor -v tests - - name: Upload coverage data - uses: codecov/codecov-action@v3 + - name: Checkout the source code + uses: actions/checkout@v3 + with: + fetch-depth: 0 + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + cache: pip + cache-dependency-path: | + setup.cfg + requirements-dev.txt + - name: Install dependencies + run: | + pip install -U -r requirements-dev.txt + - name: Run tests + run: python -m pytest --cov=aiomonitor -v tests + - name: Upload coverage data + uses: codecov/codecov-action@v3 check: # This job does nothing and is only used for the branch protection name: ✅ Ensure the required checks passing @@ -110,12 +111,12 @@ jobs: environment: pypi if: github.event_name == 'release' && github.event.action == 'created' steps: - - name: Download the sdist artifact - uses: actions/download-artifact@v3 - with: - name: ${{ env.sdist-artifact }} - path: dist - - name: Publish package to PyPI - uses: pypa/gh-action-pypi-publish@release/v1 - with: - password: ${{ secrets.PYPI_API_TOKEN }} + - name: Download the sdist artifact + uses: actions/download-artifact@v3 + with: + name: ${{ env.sdist-artifact }} + path: dist + - name: Publish package to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 + with: + password: ${{ secrets.PYPI_API_TOKEN }} diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 564a20c..218d2fc 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -1,6 +1,8 @@ +--- + name: Linters -on: +on: # yamllint disable-line rule:truthy workflow_call: workflow_dispatch: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..ecee51f --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,38 @@ +--- + +ci: + autoupdate_schedule: quarterly +repos: +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: v2.3.0 + hooks: + - id: check-yaml + - id: end-of-file-fixer + - id: trailing-whitespace +- repo: https://github.com/psf/black + rev: 23.3.0 + hooks: + - id: black +- repo: https://github.com/PyCQA/flake8 + rev: 6.0.0 + hooks: + - id: flake8 +- repo: https://github.com/PyCQA/isort + rev: 5.12.0 + hooks: + - id: isort +- repo: https://github.com/pre-commit/mirrors-mypy + rev: v1.2.0 + hooks: + - id: mypy + additional_dependencies: + - types-requests +- repo: https://github.com/adrienverge/yamllint.git + rev: v1.30.0 + hooks: + - id: yamllint + types: + - file + - yaml + args: + - --strict diff --git a/.pyup.yml b/.pyup.yml index 75f9711..bd82d36 100644 --- a/.pyup.yml +++ b/.pyup.yml @@ -1,3 +1,4 @@ +--- # Label PRs with `deps-update` label label_prs: deps-update diff --git a/.readthedocs.yml b/.readthedocs.yml index ff9b167..a3237b8 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -1,4 +1,5 @@ -# Required +--- + version: 2 # Build documentation in the docs/ directory with Sphinx diff --git a/.yamllint b/.yamllint new file mode 100644 index 0000000..68bf02c --- /dev/null +++ b/.yamllint @@ -0,0 +1,10 @@ +--- + +extends: default + +rules: + indentation: + level: error + indent-sequences: false + +... diff --git a/LICENSE b/LICENSE index f474e18..f2f47db 100644 --- a/LICENSE +++ b/LICENSE @@ -199,4 +199,3 @@ Apache License 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. - diff --git a/README.rst b/README.rst index 51d351c..d2f67d4 100644 --- a/README.rst +++ b/README.rst @@ -67,8 +67,8 @@ Now from separate terminal it is possible to connect to the application:: or the included python client:: $ python -m aiomonitor.cli - - + + Tutorial -------- @@ -122,9 +122,9 @@ Now you can type commands, for instance, ``help``:: monitor >>> help Usage: help [OPTIONS] COMMAND [ARGS]... - + To see the usage of each command, run them with "--help" option. - + Commands: cancel Cancel an indicated task console Switch to async Python REPL diff --git a/aiomonitor/task.py b/aiomonitor/task.py index 36aded4..0ee9f9c 100644 --- a/aiomonitor/task.py +++ b/aiomonitor/task.py @@ -70,12 +70,12 @@ def _trace_termination(self, _: "asyncio.Task[Any]") -> None: self_id, name=self.get_name(), coro=_format_coroutine(self._orig_coro).partition(" ")[0], - cancelled=self.cancelled(), - exc_repr=exc_repr, started_at=self._started_at, terminated_at=time.perf_counter(), + cancelled=self.cancelled(), termination_stack=self._termination_stack, canceller_stack=None, + exc_repr=exc_repr, persistent=self._persistent, ) self._termination_info_queue.put_nowait(task_info) diff --git a/aiomonitor/types.py b/aiomonitor/types.py index d73f15c..c8fe06c 100644 --- a/aiomonitor/types.py +++ b/aiomonitor/types.py @@ -1,10 +1,9 @@ import traceback +from dataclasses import dataclass from typing import List, Optional -from attrs import define - -@define +@dataclass class TerminatedTaskInfo: id: str name: str @@ -12,13 +11,13 @@ class TerminatedTaskInfo: started_at: float terminated_at: float cancelled: bool - termination_stack: Optional[List[traceback.FrameSummary]] + termination_stack: Optional[List[traceback.FrameSummary]] = None canceller_stack: Optional[List[traceback.FrameSummary]] = None exc_repr: Optional[str] = None persistent: bool = False -@define +@dataclass class CancellationChain: target_id: str canceller_id: str diff --git a/docs/Makefile b/docs/Makefile index cff0c1d..2713008 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -17,4 +17,4 @@ help: # Catch-all target: route all unknown targets to Sphinx using the new # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). %: Makefile - @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) \ No newline at end of file + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/conf.py b/docs/conf.py index 2f26626..5e1c44d 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -29,13 +29,14 @@ # needs_sphinx = '1.0' import pathlib -from importlib.metadata import version +from importlib.metadata import version as get_version +from typing import Mapping _docs_path = pathlib.Path(__file__).parent try: - _version_info = version("aiomonitor") + _version_info = get_version("aiomonitor") except IndexError: raise RuntimeError("Unable to determine version.") @@ -130,7 +131,7 @@ # -- Options for LaTeX output --------------------------------------------- -latex_elements = { +latex_elements: Mapping[str, str] = { # The paper size ('letterpaper' or 'a4paper'). # # 'papersize': 'letterpaper', diff --git a/tests/test_monitor.py b/tests/test_monitor.py index 4bc28f0..0cd2bc1 100644 --- a/tests/test_monitor.py +++ b/tests/test_monitor.py @@ -93,7 +93,6 @@ def console_enabled(request): @pytest.mark.asyncio async def test_ctor(event_loop, unused_port, console_enabled): - with Monitor(event_loop, console_enabled=console_enabled): await asyncio.sleep(0.01) with start_monitor(event_loop, console_enabled=console_enabled) as m: