diff --git a/.github/workflows/pytest.yaml b/.github/workflows/pytest.yaml index f8ffe2f6..d0dab785 100644 --- a/.github/workflows/pytest.yaml +++ b/.github/workflows/pytest.yaml @@ -47,5 +47,5 @@ jobs: env: PYTEST_NETWORK: mainnet ETHERSCAN_TOKEN: ${{ secrets.ETHERSCAN_TOKEN }} - run: pytest + run: pytest --asyncio-task-timeout=3600 diff --git a/.gitignore b/.gitignore index 3fd58aa3..a6ededca 100644 --- a/.gitignore +++ b/.gitignore @@ -6,5 +6,4 @@ dank_mids.egg-info .pytest_cache .eggs .mypy_cache -__pycache__ -*.log* \ No newline at end of file +__pycache__ \ No newline at end of file diff --git a/dank_mids/semaphores.py b/dank_mids/semaphores.py index 54adc9ff..837a507e 100644 --- a/dank_mids/semaphores.py +++ b/dank_mids/semaphores.py @@ -1,6 +1,6 @@ -import logging -from typing import TYPE_CHECKING, Literal, Union +from decimal import Decimal +from typing import TYPE_CHECKING, Literal, Optional, Union from a_sync.primitives import DummySemaphore, ThreadsafeSemaphore from a_sync.primitives.locks.prio_semaphore import ( @@ -13,6 +13,10 @@ class _BlockSemaphoreContextManager(_PrioritySemaphoreContextManager): _priority_name = "block" + def __init__(self, parent: "BlockSemaphore", priority: Union[int, float, Decimal], name: Optional[str] = None) -> None: + if not isinstance(priority, (int, float, Decimal)): + raise TypeError(priority) + super().__init__(parent, priority, name) class BlockSemaphore(_AbstractPrioritySemaphore[str, _BlockSemaphoreContextManager]): _context_manager_class = _BlockSemaphoreContextManager diff --git a/requirements-dev.txt b/requirements-dev.txt index e0842cf3..ed388947 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1 +1,3 @@ eth-brownie>1.16.0 +pytest +pytest-asyncio-cooperative \ No newline at end of file diff --git a/tests/test_brownie_patch.py b/tests/test_brownie_patch.py index 74b320e8..55dc038b 100644 --- a/tests/test_brownie_patch.py +++ b/tests/test_brownie_patch.py @@ -1,54 +1,85 @@ # sourcery skip: no-loop-in-tests import asyncio +import pytest -from brownie import Contract, web3 +import brownie +import eth_retry from decimal import Decimal -from multicall.utils import await_awaitable -from dank_mids import dank_web3, patch_contract, setup_dank_w3_from_sync +import dank_mids from dank_mids.brownie_patch.call import _patch_call -def test_patch_call(): +# must use from_explorer for gh testing workflow +# NOTE: we don't want tests to fail due to api limits +get_contract = eth_retry.auto_retry(brownie.Contract.from_explorer) +get_dank_contract = eth_retry.auto_retry(dank_mids.Contract.from_explorer) + +@pytest.mark.asyncio_cooperative +async def test_patch_call(): # must use from_explorer for gh testing workflow - weth = Contract.from_explorer('0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2') - _patch_call(weth.totalSupply, dank_web3) + weth = get_contract('0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2') + _patch_call(weth.totalSupply, dank_mids.web3) assert hasattr(weth.totalSupply, 'coroutine') - assert await_awaitable(weth.totalSupply.coroutine(block_identifier=13_000_000)) == 6620041514474872981393155 + assert await weth.totalSupply.coroutine(block_identifier=13_000_000) == 6620041514474872981393155 -def test_gather(): +@pytest.mark.asyncio_cooperative +async def test_gather(): # must use from_explorer for gh testing workflow - weth = Contract.from_explorer('0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2') - _patch_call(weth.totalSupply, dank_web3) + weth = get_contract('0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2') + _patch_call(weth.totalSupply, dank_mids.web3) assert hasattr(weth.totalSupply, 'coroutine') - for result in await_awaitable(asyncio.gather(*[weth.totalSupply.coroutine(block_identifier=13_000_000) for _ in range(10_000)])): + for result in await asyncio.gather(*[weth.totalSupply.coroutine(block_identifier=13_000_000) for _ in range(10_000)]): assert result == 6620041514474872981393155 -def test_patch_contract(): - # ContractCall - # must use from_explorer for gh testing workflow +@pytest.mark.asyncio_cooperative +async def test_patch_contract_call(): # specify w3 - weth = patch_contract(Contract.from_explorer('0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2'), dank_web3) + weth = dank_mids.patch_contract(get_contract('0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2'), dank_mids.web3) assert hasattr(weth.totalSupply, 'coroutine') - assert await_awaitable(weth.totalSupply.coroutine(block_identifier=13_000_000)) == 6620041514474872981393155 - assert await_awaitable(weth.totalSupply.coroutine(block_identifier=13_000_000, decimals=18)) == Decimal(6620041.514474872981393155) - assert await_awaitable(weth.totalSupply) + assert await weth.totalSupply.coroutine(block_identifier=13_000_000) == 6620041514474872981393155 + assert await weth.totalSupply.coroutine(block_identifier=13_000_000, decimals=18) == Decimal("6620041.514474872981393155") - # ContractTx +@pytest.mark.asyncio_cooperative +async def test_patch_contract_tx(): # must use from_explorer for gh testing workflow # dont specify w3 - uni_v3_quoter = patch_contract(Contract.from_explorer('0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6')) + uni_v3_quoter = dank_mids.patch_contract(get_contract('0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6')) + assert hasattr(uni_v3_quoter.quoteExactInput, 'coroutine') + assert await ( + uni_v3_quoter.quoteExactInput.coroutine(b"\xc0*\xaa9\xb2#\xfe\x8d\n\x0e\\O'\xea\xd9\x08