diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 1867e88..6caed09 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -12,12 +12,9 @@ name: "CodeQL" on: - push: - branches: [ "main", "main-1.0" ] - pull_request: - branches: [ "main", "main-1.0" ] + workflow_dispatch: schedule: - - cron: '22 9 * * 6' + - cron: '22 2 * * 6' jobs: analyze: diff --git a/.github/workflows/python-package-macos-win.yml b/.github/workflows/python-package-macos-win.yml new file mode 100644 index 0000000..49f2c7e --- /dev/null +++ b/.github/workflows/python-package-macos-win.yml @@ -0,0 +1,50 @@ +# This workflow will install Python dependencies, run tests and lint with a variety of Python versions +# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python + +name: Python package MacOS & Windows + +on: + workflow_dispatch: + schedule: + - cron: '23 2 5 * *' + +# push: +# branches: [ "main", "main-1.0" ] +# pull_request: +# branches: [ "main", "main-1.0" ] + +jobs: + build: + # runs-on: [ ubuntu-latest ] + strategy: + fail-fast: false + matrix: + python-version: [ "3.11", "3.12"] + os: [ windows-latest, macos-latest ] + runs-on: ${{ matrix.os }} + + steps: + - uses: actions/checkout@v4 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + cache: 'pip' + - name: Install dependencies + run: | + python -m pip install --upgrade pip + python -m pip install . + python -m pip install ".[dev]" + - name: Lint with ruff + run: | + ruff check src tests + - name: Test with mypy + run: | + mypy src + - name: Test with pytest + run: | + pytest --cov . + - name: Upload coverage reports to Codecov + uses: codecov/codecov-action@v3 + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} # ignore diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index 9658d6f..2ff244a 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -11,13 +11,11 @@ on: jobs: build: - # runs-on: [ ubuntu-latest ] + runs-on: [ ubuntu-latest ] strategy: fail-fast: false matrix: python-version: [ "3.11", "3.12"] - os: [ ubuntu-latest, windows-latest, macos-latest ] - runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 @@ -29,22 +27,20 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - python -m pip install flake8 pytest python -m pip install . python -m pip install ".[dev]" - - name: Lint with flake8 + - name: Lint with ruff + run: | + ruff check src tests + - name: Test with mypy run: | - # stop the build if there are Python syntax errors or undefined names - flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics - # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide - flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics + mypy src - name: Test with pytest run: | pytest --cov . - - name: Test with mypy - run: | - mypy -m pyutils - name: Upload coverage reports to Codecov uses: codecov/codecov-action@v3 env: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + fail_ci_if_error: false + diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 0000000..7bba9f4 --- /dev/null +++ b/codecov.yml @@ -0,0 +1,9 @@ +coverage: + status: + project: + default: + informational: true + threshold: 1% + patch: + default: + informational: true diff --git a/pyproject.toml b/pyproject.toml index 2a50709..a40bd98 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "pyutils" -version = "1.0.0" +version = "1.0.1" authors = [{ name = "Jylpah", email = "jylpah@gmail.com" }] description = "Misc Python utils and classes" readme = "README.md" @@ -16,29 +16,30 @@ classifiers = [ "Topic :: Games/Entertainment", ] dependencies = [ - "aiofiles~=23.1", - "aiohttp~=3.9.1", - "aiodns~=3.0", - "aioconsole~=0.6", - "alive-progress~=3.1", - "Brotli~=1.1", - "Deprecated~=1.2", - "click~=8.1", - "typer~=0.9", + "aiofiles>=23.1", + "aiohttp>=3.9.1", + "aiodns>=3.0", + "aioconsole>=0.6", + "alive-progress>=3.1", + "Brotli>=1.1", + "Deprecated>=1.2", + "click>=8.1", + "typer>=0.9", ] [project.optional-dependencies] dev = [ - "build~=0.10", - "mypy~=1.7", - "pip-chill~=1.0", - "pytest~=7.4", - "pytest-asyncio~=0.23", - "pytest-datafiles~=3.0", - "pytest-cov~=4.1", - "pytest-timeout~=2.2", - "types-aiofiles~=23.1.0.1", - "types-Deprecated~=1.2.9.3", + "build>=0.10", + "mypy>=1.7", + "pip-chill>=1.0", + "pytest>=7.4", + "pytest-asyncio>=0.23", + "pytest-datafiles>=3.0", + "pytest-cov>=4.1", + "pytest-timeout>=2.2", + "ruff>=0.1.9", + "types-aiofiles>=23.1.0.1", + "types-Deprecated>=1.2.9.3", ] @@ -60,9 +61,11 @@ packages = ["src/pyutils"] exclude = ['tmp'] mypy_path = ['src'] -[tool.black] -# line-length = 100 -include = '\.pyi?$' +[tool.ruff] +include = ["pyproject.toml", "src/**/*.py", "tests/**/*.py"] +indent-width = 4 +extend-include = ["*.ipynb"] +fixable = ["ALL"] [tool.pytest.ini_options] minversion = "7.0" diff --git a/src/pyutils/__init__.py b/src/pyutils/__init__.py index eb4284d..227bbc7 100644 --- a/src/pyutils/__init__.py +++ b/src/pyutils/__init__.py @@ -8,28 +8,11 @@ from .iterablequeue import IterableQueue as IterableQueue, QueueDone as QueueDone from .multilevelformatter import MultilevelFormatter as MultilevelFormatter from .throttledclientsession import ThrottledClientSession as ThrottledClientSession -from .urlqueue import UrlQueue as UrlQueue, UrlQueueItemType, is_url +from .urlqueue import UrlQueue as UrlQueue from .utils import ( Countable as Countable, ClickHelpGen as ClickHelpGen, TyperHelpGen as TyperHelpGen, - alive_bar_monitor, - coro, - chunker, - epoch_now, - # read_config, - get_datestr, - get_subtype, - get_type, - get_url, - # get_urls, - get_url_JSON, - # get_urls_JSON, - get_temp_filename, - is_valid_obj, - post_url, - set_config, - str2path, ) diff --git a/src/pyutils/eventcounter.py b/src/pyutils/eventcounter.py index 50251fe..15a20c0 100644 --- a/src/pyutils/eventcounter.py +++ b/src/pyutils/eventcounter.py @@ -93,8 +93,9 @@ def get_value(self, category: str) -> int: assert category is not None, "param 'category' cannot be None" try: return self._log[category] - except: - logger.error(f"invalid categgory: {category}") + except Exception as err: + error(f"invalid categgory: {category}") + debug(f"{err}") return 0 def get_values(self) -> dict[str, int]: @@ -120,7 +121,7 @@ def merge(self, B: "EventCounter") -> bool: try: if not isinstance(B, EventCounter): - logger.error(f"input is not type of 'EventCounter' but: {type(B)}") + error(f"input is not type of 'EventCounter' but: {type(B)}") return False for cat in B.get_categories(): value: int = B.get_value(cat) @@ -130,7 +131,7 @@ def merge(self, B: "EventCounter") -> bool: self._error_status = self._error_status or B.get_error_status() return True except Exception as err: - logger.error(f"{err}") + error(f"{err}") return False def merge_child(self, B: "EventCounter") -> bool: @@ -148,7 +149,7 @@ def merge_child(self, B: "EventCounter") -> bool: self._error_status = self._error_status or B.get_error_status() return True except Exception as err: - logger.error(f"{err}") + error(f"{err}") return False def get_header(self) -> str: @@ -171,7 +172,7 @@ def print(self, do_print: bool = True, clean: bool = False) -> Optional[str]: ret += f"\n{self._get_str(cat)}" return ret except Exception as err: - logger.error(f"{err}") + error(f"{err}") return None async def gather_stats( diff --git a/src/pyutils/filequeue.py b/src/pyutils/filequeue.py index 109d9d8..ebcc3af 100644 --- a/src/pyutils/filequeue.py +++ b/src/pyutils/filequeue.py @@ -14,7 +14,7 @@ from pathlib import Path from typing import Optional, Sequence -from .iterablequeue import IterableQueue, QueueDone +from .iterablequeue import IterableQueue from .utils import str2path logger = logging.getLogger(__name__) diff --git a/src/pyutils/iterablequeue.py b/src/pyutils/iterablequeue.py index da8b3d9..4b681ff 100644 --- a/src/pyutils/iterablequeue.py +++ b/src/pyutils/iterablequeue.py @@ -1,4 +1,4 @@ -from asyncio import Queue, QueueFull, QueueEmpty, Event, Lock, sleep +from asyncio import Queue, QueueFull, QueueEmpty, Event, Lock from typing import AsyncIterable, TypeVar, Optional from .utils import Countable import logging @@ -206,11 +206,11 @@ def task_done(self) -> None: self.check_done() async def join(self) -> None: - debug(f"Waiting queue to be filled") + debug("Waiting queue to be filled") await self._filled.wait() - debug(f"Queue filled, waiting when queue is done") + debug("Queue filled, waiting when queue is done") await self._done.wait() - debug(f"queue is done") + debug("queue is done") return None def __aiter__(self): diff --git a/src/pyutils/multilevelformatter.py b/src/pyutils/multilevelformatter.py index 34f7ef8..3c3fa51 100644 --- a/src/pyutils/multilevelformatter.py +++ b/src/pyutils/multilevelformatter.py @@ -1,4 +1,5 @@ -import logging, sys +import logging +import sys from typing import Literal, Optional from pathlib import Path diff --git a/src/pyutils/throttledclientsession.py b/src/pyutils/throttledclientsession.py index 2e2d122..0cea4a8 100644 --- a/src/pyutils/throttledclientsession.py +++ b/src/pyutils/throttledclientsession.py @@ -193,7 +193,7 @@ async def close(self) -> None: await wait_for(self._fillerTask, timeout=0.5) except TimeoutError as err: debug(f"Timeout while cancelling bucket filler: {err}") - except CancelledError as err: + except CancelledError: debug("Cancelled") await super().close() diff --git a/src/pyutils/utils.py b/src/pyutils/utils.py index 2d8f0dc..f608fbb 100644 --- a/src/pyutils/utils.py +++ b/src/pyutils/utils.py @@ -146,7 +146,7 @@ def is_alphanum(string: str) -> bool: """test whether the string is composed of ASCII letters, numbers, hyphens or underscores only""" try: return not compile(r"[^a-zA-Z0-9_]").search(string) - except: + except Exception: error(f"Illegal characters in the table name: {string}") return False @@ -158,7 +158,7 @@ def is_valid_obj(string: str) -> bool: """ try: return not compile(r"[^a-zA-Z0-9_]").search(string) - except: + except Exception: error(f"Illegal characters in the table name: {string}") return False diff --git a/tests/test_asyncqueue.py b/tests/test_asyncqueue.py index c1759e1..8ff5f3c 100644 --- a/tests/test_asyncqueue.py +++ b/tests/test_asyncqueue.py @@ -4,12 +4,19 @@ from queue import Queue # from asyncio.queues import QueueEmpty, QueueFull -from asyncio import Task, create_task, sleep, wait_for, timeout, TimeoutError, QueueEmpty, QueueFull -import asyncio +from asyncio import ( + Task, + create_task, + sleep, + timeout, + TimeoutError, + QueueEmpty, + QueueFull, +) sys.path.insert(0, str(Path(__file__).parent.parent.resolve() / "src")) -from pyutils import AsyncQueue +from pyutils import AsyncQueue # noqa: E402 QSIZE: int = 10 N: int = 100 # N >> QSIZE @@ -86,6 +93,7 @@ async def test_2_put_get_nowait(test_asyncqueue_int: AsyncQueue[int]): await Q.join() except TimeoutError: assert False, "Queue.join() took longer than it should" + assert producer.done(), "producer has not finished" assert Q.qsize() == 0, "queue not empty" assert Q.empty(), "queue not empty" diff --git a/tests/test_bucketmapper.py b/tests/test_bucketmapper.py index 410c05c..5b7c955 100644 --- a/tests/test_bucketmapper.py +++ b/tests/test_bucketmapper.py @@ -6,8 +6,7 @@ sys.path.insert(0, str(Path(__file__).parent.parent.resolve() / "src")) -from pyutils import BucketMapper -from pyutils.bucketmapper import T +from pyutils import BucketMapper # noqa: E402 ######################################################## # @@ -96,7 +95,7 @@ def test_3_get_fails( bm_keys: list[int] = _get_keys(bm) max_key: int = max(bm_keys) for _ in range(LOOPS): - if (item := bm.get(max_key + randrange(1, N))) is None: + if (_ := bm.get(max_key + randrange(1, N))) is None: pass # OK else: assert False, "get() should always return None if key outside key range" diff --git a/tests/test_eventcounter.py b/tests/test_eventcounter.py index e715646..90f5ee5 100644 --- a/tests/test_eventcounter.py +++ b/tests/test_eventcounter.py @@ -1,11 +1,10 @@ import sys -import pytest # type: ignore -from os.path import dirname, realpath, join as pjoin +import pytest # type: ignore from pathlib import Path -sys.path.insert(0, str(Path(__file__).parent.parent.resolve() / 'src')) +sys.path.insert(0, str(Path(__file__).parent.parent.resolve() / "src")) -from pyutils import EventCounter +from pyutils import EventCounter # noqa: E402 ######################################################## @@ -19,73 +18,85 @@ # 3) Create an instance and get categories -_CATEGORIES : list[str] = [ 'one', 'two', 'three', 'four' ] +_CATEGORIES: list[str] = ["one", "two", "three", "four"] + @pytest.fixture def test_source_categories_0() -> list[str]: - return _CATEGORIES + return _CATEGORIES -def mk_eventcounter_one(name: str, cats : list[str]) -> EventCounter: - ec : EventCounter = EventCounter(name) - for c in cats: - ec.log(c) - return ec +def mk_eventcounter_one(name: str, cats: list[str]) -> EventCounter: + ec: EventCounter = EventCounter(name) + for c in cats: + ec.log(c) + return ec -def mk_eventcounter_linear(name: str, cats : list[str]) -> EventCounter: - ec : EventCounter = EventCounter(name) - for i in range(len(cats)): - ec.log(cats[i], i+1) - return ec +def mk_eventcounter_linear(name: str, cats: list[str]) -> EventCounter: + ec: EventCounter = EventCounter(name) + for i in range(len(cats)): + ec.log(cats[i], i + 1) + return ec def test_1_create(test_source_categories_0: list[str]) -> None: - """Test __init__(), log(), get_categories()""" - cats : list[str] = test_source_categories_0 - ec : EventCounter = mk_eventcounter_one('Test', cats) - assert ec.get_categories().sort() == cats.sort(), "Failed to create categories" - assert ec.sum(cats) == len(cats), "Incorrect event count" - assert ec.get_value(cats[1]) == 1, "Incorrect value" + """Test __init__(), log(), get_categories()""" + cats: list[str] = test_source_categories_0 + ec: EventCounter = mk_eventcounter_one("Test", cats) + assert ec.get_categories().sort() == cats.sort(), "Failed to create categories" + assert ec.sum(cats) == len(cats), "Incorrect event count" + assert ec.get_value(cats[1]) == 1, "Incorrect value" def test_2_create(test_source_categories_0: list[str]) -> None: - cats : list[str] = test_source_categories_0 - ec : EventCounter = mk_eventcounter_linear('Test', cats) - assert ec.get_categories().sort() == cats.sort(), "Failed to create categories" - assert ec.sum(cats) == (1 + len(cats)) / 2 * len(cats), "Incorrect event count" - assert ec.get_value(cats[1]) == 2, "Incorrect value" + cats: list[str] = test_source_categories_0 + ec: EventCounter = mk_eventcounter_linear("Test", cats) + assert ec.get_categories().sort() == cats.sort(), "Failed to create categories" + assert ec.sum(cats) == (1 + len(cats)) / 2 * len(cats), "Incorrect event count" + assert ec.get_value(cats[1]) == 2, "Incorrect value" + def test_3_merge(test_source_categories_0: list[str]) -> None: - cats : list[str] = test_source_categories_0 - ec1 : EventCounter = mk_eventcounter_linear('Test 1', cats) - ec2 : EventCounter = mk_eventcounter_linear('Test 2', cats) - ec1.merge(ec2) - assert ec1.get_categories().sort() == cats.sort(), "Merging categories failed categories" - assert ec1.sum(cats) == 2* (1 + len(cats)) / 2 * len(cats), "Incorrect event count" + cats: list[str] = test_source_categories_0 + ec1: EventCounter = mk_eventcounter_linear("Test 1", cats) + ec2: EventCounter = mk_eventcounter_linear("Test 2", cats) + ec1.merge(ec2) + assert ( + ec1.get_categories().sort() == cats.sort() + ), "Merging categories failed categories" + assert ec1.sum(cats) == 2 * (1 + len(cats)) / 2 * len(cats), "Incorrect event count" def test_4_merge_child(test_source_categories_0: list[str]) -> None: - cats : list[str] = test_source_categories_0 - ec1 : EventCounter = mk_eventcounter_linear('Test 1', cats) - ec2 : EventCounter = mk_eventcounter_linear('Test 2', cats) - ec1.merge_child(ec2) - assert len(ec1.get_categories()) == 2 * len(cats), "Incorrect category count" - assert ec1.sum(ec1.get_categories()) == 2* (1 + len(cats)) / 2 * len(cats), "Incorrect event count" + cats: list[str] = test_source_categories_0 + ec1: EventCounter = mk_eventcounter_linear("Test 1", cats) + ec2: EventCounter = mk_eventcounter_linear("Test 2", cats) + ec1.merge_child(ec2) + assert len(ec1.get_categories()) == 2 * len(cats), "Incorrect category count" + assert ec1.sum(ec1.get_categories()) == 2 * (1 + len(cats)) / 2 * len( + cats + ), "Incorrect event count" def test_5_error_categories(test_source_categories_0: list[str]) -> None: - cats : list[str] = test_source_categories_0 - ec : EventCounter = mk_eventcounter_linear('Test', cats) - assert not ec.get_error_status(), "Unintended errors logged" - assert ec.add_error_categories(cats[:2]), "Errors not logged" + cats: list[str] = test_source_categories_0 + ec: EventCounter = mk_eventcounter_linear("Test", cats) + assert not ec.get_error_status(), "Unintended errors logged" + assert ec.add_error_categories(cats[:2]), "Errors not logged" def test_6_categories(test_source_categories_0: list[str]) -> None: - """Test categories methods""" - cats : list[str] = test_source_categories_0 - ec : EventCounter = mk_eventcounter_linear('Test', cats) - assert type(ec._get_str(cats[1])) is str, f"Incorrect type returned: {type(ec._get_str(cats[1]))}" - assert type(ec.get_long_cat(cats[1])) is str, f"Incorrect type returned: {type(ec.get_long_cat(cats[1]))}" - assert issubclass(type(ec.get_values()), dict), f"Incorrect type returned: {type(ec.get_values())}" - assert type(ec.print(do_print=False)) is str, "Incorrect type returned" + """Test categories methods""" + cats: list[str] = test_source_categories_0 + ec: EventCounter = mk_eventcounter_linear("Test", cats) + assert isinstance( + ec._get_str(cats[1]), str + ), f"Incorrect type returned: {type(ec._get_str(cats[1]))}" + assert isinstance( + ec.get_long_cat(cats[1]), str + ), f"Incorrect type returned: {type(ec.get_long_cat(cats[1]))}" + assert isinstance( + ec.get_values(), dict + ), f"Incorrect type returned: {type(ec.get_values())}" + assert isinstance(ec.print(do_print=False), str), "Incorrect type returned" diff --git a/tests/test_filequeue.py b/tests/test_filequeue.py index fb961b6..53380d4 100644 --- a/tests/test_filequeue.py +++ b/tests/test_filequeue.py @@ -14,7 +14,7 @@ sys.path.insert(0, str(Path(__file__).parent.parent.resolve() / "src")) -from pyutils import FileQueue, QueueDone +from pyutils import FileQueue # noqa: E402 ######################################################## # diff --git a/tests/test_iterablequeue.py b/tests/test_iterablequeue.py index 66044a6..763c43e 100644 --- a/tests/test_iterablequeue.py +++ b/tests/test_iterablequeue.py @@ -1,14 +1,21 @@ import sys import pytest # type: ignore from pathlib import Path -from queue import Queue from asyncio.queues import QueueEmpty, QueueFull -from asyncio import Task, create_task, sleep, gather, timeout, TimeoutError, CancelledError +from asyncio import ( + Task, + create_task, + sleep, + gather, + timeout, + TimeoutError, + CancelledError, +) from random import random sys.path.insert(0, str(Path(__file__).parent.parent.resolve() / "src")) -from pyutils import IterableQueue, QueueDone +from pyutils import IterableQueue, QueueDone # noqa: E402 QSIZE: int = 10 N: int = 100 # N >> QSIZE @@ -21,7 +28,9 @@ def test_interablequeue_int() -> IterableQueue[int]: return IterableQueue[int](maxsize=QSIZE) -async def _producer_int(Q: IterableQueue[int], n: int, finish: bool = False, wait: float = 0) -> None: +async def _producer_int( + Q: IterableQueue[int], n: int, finish: bool = False, wait: float = 0 +) -> None: await Q.add_producer(N=1) await sleep(wait) try: @@ -143,7 +152,9 @@ async def test_3_multiple_producers(test_interablequeue_int: IterableQueue[int]) @pytest.mark.timeout(10) @pytest.mark.asyncio -async def test_4_multiple_producers_consumers(test_interablequeue_int: IterableQueue[int]): +async def test_4_multiple_producers_consumers( + test_interablequeue_int: IterableQueue[int], +): Q = test_interablequeue_int producers: list[Task] = list() consumers: list[Task] = list() @@ -159,7 +170,9 @@ async def test_4_multiple_producers_consumers(test_interablequeue_int: IterableQ assert not Q.has_wip, "Queue should not have any items WIP" except TimeoutError: assert False, "IterableQueue.join() took too long" - assert Q.count == THREADS * N, f"count returned wrong value {Q.count}, should be {THREADS*N}" + assert ( + Q.count == THREADS * N + ), f"count returned wrong value {Q.count}, should be {THREADS*N}" assert Q.qsize() == 0, "queue size is > 0 even it should be empty" assert Q.empty(), "queue not empty" for p in consumers: @@ -176,16 +189,21 @@ async def test_5_empty_join(test_interablequeue_int: IterableQueue[int]): try: async with timeout(3): await Q.join() - assert Q.empty(), "Queue is done after 3 secs and the join() should finish before timeout(5)" + assert ( + Q.empty() + ), "Queue is done after 3 secs and the join() should finish before timeout(5)" except TimeoutError: assert False, "await IterableQueue.join() failed with an empty queue finished" await sleep(0.1) try: consumer.cancel() - assert not consumer.cancelled(), "consumer task was cancelled and did not complete even it should have" + assert ( + not consumer.cancelled() + ), "consumer task was cancelled and did not complete even it should have" except Exception as err: assert False, f"Unknown Exception caught: {err}" + assert producer.done(), "producer has not finished" @pytest.mark.timeout(10) @@ -198,7 +216,9 @@ async def test_6_finish_full_queue(test_interablequeue_int: IterableQueue[int]): await sleep(0.5) async with timeout(3): await Q.finish(all=True, empty=True) - assert Q.empty(), f"Queue should be empty: qsize={Q._Q.qsize()}: {Q._Q.get_nowait()}, {Q._Q.get_nowait()}" + assert ( + Q.empty() + ), f"Queue should be empty: qsize={Q._Q.qsize()}: {Q._Q.get_nowait()}, {Q._Q.get_nowait()}" except TimeoutError: assert False, "await IterableQueue.join() failed with an empty queue finished" await sleep(0.1) @@ -216,7 +236,9 @@ async def test_7_aiter(test_interablequeue_int: IterableQueue[int]): await sleep(0.5) async for i in Q: assert i >= 0, "Did not receive an int" - assert True, "Queue is done after 3 secs and the join() should finish before timeout(5)" + assert ( + True + ), "Queue is done after 3 secs and the join() should finish before timeout(5)" except TimeoutError: assert False, "await IterableQueue.join() failed with an empty queue finished" @@ -236,6 +258,8 @@ async def test_8_aiter_1_item(test_interablequeue_int: IterableQueue[int]): count += 1 assert i >= 0, "Did not receive an int" assert count == 1, f"Did not receive correct number of elements {count} != 1" - assert True, "Queue is done after 3 secs and the join() should finish before timeout(5)" + assert ( + True + ), "Queue is done after 3 secs and the join() should finish before timeout(5)" except TimeoutError: assert False, "await IterableQueue.join() failed with an empty queue finished" diff --git a/tests/test_throttledclientsession.py b/tests/test_throttledclientsession.py index 9cdbd35..6b909ca 100644 --- a/tests/test_throttledclientsession.py +++ b/tests/test_throttledclientsession.py @@ -4,7 +4,6 @@ from datetime import datetime from itertools import pairwise, accumulate from functools import cached_property -from math import ceil from typing import Generator, List, Dict from multiprocessing import Process from http.server import HTTPServer, BaseHTTPRequestHandler @@ -17,12 +16,8 @@ sys.path.insert(0, str(Path(__file__).parent.parent.resolve() / "src")) -from pyutils import ( - ThrottledClientSession, - epoch_now, - get_url_JSON, - post_url, -) +from pyutils import ThrottledClientSession # noqa: E402 +from pyutils.utils import epoch_now, get_url_JSON # noqa: E402 HOST: str = "localhost" @@ -234,8 +229,8 @@ def do_GET(self) -> None: # pylint: disable=invalid-name if self.url.path == JSON_PATH: self.send_header("Content-Type", "application/json") self.end_headers() - l: int = len(self._res_json) - idx: int = epoch_now() % l + length: int = len(self._res_json) + idx: int = epoch_now() % length res: Dict[str, str | int | float | None] = self._res_json[idx] self.wfile.write(json.dumps(res).encode()) diff --git a/tests/test_utils.py b/tests/test_utils.py index 0c33a8f..a35ff38 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -13,7 +13,7 @@ sys.path.insert(0, str(Path(__file__).parent.parent.resolve() / "src")) -from pyutils.utils import ( +from pyutils.utils import ( # noqa: E402 ClickHelpGen, Countable, TyperHelpGen, @@ -22,7 +22,7 @@ get_type, get_subtype, ) -from pyutils import awrap +from pyutils import awrap # noqa: E402 logger = logging.getLogger() error = logger.error @@ -239,9 +239,9 @@ def items(self) -> List[int]: def test_3_Countable() -> None: """Test Countable""" - l = _TestCountable([1, 2, 3, 4, 5]) + list_ = _TestCountable([1, 2, 3, 4, 5]) - assert l.count == 5, f"count returned incorrect value" + assert list_.count == 5, "count returned incorrect value" def test_4_is_valid_obj() -> None: @@ -269,7 +269,7 @@ def test_5_chunker() -> None: ), "last chunk is wrong size: {len(chunk)}" i += 1 - assert i == ceil(size / chunk_size), f"incorrect number of chunks" + assert i == ceil(size / chunk_size), "incorrect number of chunks" ########################################################