diff --git a/hathor/simulator/tx_generator.py b/hathor/simulator/tx_generator.py index 8c977c870..81c8345d8 100644 --- a/hathor/simulator/tx_generator.py +++ b/hathor/simulator/tx_generator.py @@ -20,12 +20,12 @@ from hathor.conf.get_settings import get_global_settings from hathor.simulator.utils import NoCandidatesError, gen_new_double_spending, gen_new_tx from hathor.transaction.exceptions import RewardLocked +from hathor.types import VertexId from hathor.util import Random from hathor.wallet.exceptions import InsufficientFunds if TYPE_CHECKING: from hathor.manager import HathorManager - from hathor.transaction import Transaction logger = get_logger() @@ -62,7 +62,7 @@ def __init__(self, manager: 'HathorManager', rng: Random, *, # Most recent transactions generated here. # The lowest index has the most recent transaction. self.transactions_found: int = 0 - self.latest_transactions: deque[Transaction] = deque() + self.latest_transactions: deque[VertexId] = deque() self.double_spending_only = False diff --git a/pyproject.toml b/pyproject.toml index 7a4d67554..3f8649691 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -154,6 +154,20 @@ warn_return_any = true # disallow_subclassing_any = true # disallow_untyped_calls = true +# We also override to add disallow_untyped_defs for some specific test modules +[[tool.mypy.overrides]] +module = [ + "tests.consensus.*", + "tests.crypto.*", + "tests.event.*", + "tests.execution_manager.*", + "tests.feature_activation.*", +# "tests.p2p.*", + "tests.pubsub.*", +# "tests.simulation.*", +] +disallow_untyped_defs = true + [tool.pydantic-mypy] init_typed = true init_forbid_extra = true diff --git a/tests/consensus/test_consensus.py b/tests/consensus/test_consensus.py index 54573ff0e..5d9a9db31 100644 --- a/tests/consensus/test_consensus.py +++ b/tests/consensus/test_consensus.py @@ -3,6 +3,7 @@ from hathor.execution_manager import ExecutionManager from hathor.simulator.utils import add_new_block, add_new_blocks, gen_new_tx from hathor.transaction.storage import TransactionMemoryStorage +from hathor.util import not_none from tests import unittest from tests.utils import add_blocks_unlock_reward, add_new_double_spending, add_new_transactions @@ -10,14 +11,14 @@ class BaseConsensusTestCase(unittest.TestCase): __test__ = False - def setUp(self): + def setUp(self) -> None: super().setUp() self.tx_storage = TransactionMemoryStorage() self.genesis = self.tx_storage.get_all_genesis() self.genesis_blocks = [tx for tx in self.genesis if tx.is_block] self.genesis_txs = [tx for tx in self.genesis if not tx.is_block] - def test_unhandled_exception(self): + def test_unhandled_exception(self) -> None: manager = self.create_peer('testnet', tx_storage=self.tx_storage) # Mine a few blocks in a row with no transaction but the genesis @@ -45,7 +46,7 @@ class MyError(Exception): meta2 = tx2.get_metadata() self.assertEqual({self._settings.CONSENSUS_FAIL_ID}, meta2.voided_by) - def test_revert_block_high_weight(self): + def test_revert_block_high_weight(self) -> None: """ A conflict transaction will be propagated. At first, it will be voided. But, a new block with high weight will verify it, which will flip it to executed. """ @@ -108,7 +109,7 @@ def test_revert_block_high_weight(self): self.assertConsensusValid(manager) - def test_dont_revert_block_low_weight(self): + def test_dont_revert_block_low_weight(self) -> None: """ A conflict transaction will be propagated and voided. A new block with low weight will verify it, which won't be enough to flip to executed. So, it will remain voided. @@ -162,7 +163,7 @@ def test_dont_revert_block_low_weight(self): self.assertConsensusValid(manager) - def test_dont_revert_block_high_weight_transaction_verify_other(self): + def test_dont_revert_block_high_weight_transaction_verify_other(self) -> None: """ A conflict transaction will be propagated and voided. But this transaction verifies its conflicting transaction. So, its accumulated weight will always be smaller than the others and it will never be executed. @@ -180,8 +181,8 @@ def test_dont_revert_block_high_weight_transaction_verify_other(self): # Create a double spending transaction. conflicting_tx = add_new_double_spending(manager, tx=txs[-1]) meta = conflicting_tx.get_metadata() - self.assertEqual(len(meta.conflict_with), 1) - self.assertIn(list(meta.conflict_with)[0], conflicting_tx.parents) + self.assertEqual(len(not_none(meta.conflict_with)), 1) + self.assertIn(not_none(meta.conflict_with)[0], conflicting_tx.parents) # Add a few transactions. add_new_transactions(manager, 10, advance_clock=15) @@ -219,7 +220,7 @@ def test_dont_revert_block_high_weight_transaction_verify_other(self): self.assertConsensusValid(manager) - def test_dont_revert_block_high_weight_verify_both(self): + def test_dont_revert_block_high_weight_verify_both(self) -> None: """ A conflicting transaction will be propagated and voided. But the block with high weight verifies both the conflicting transactions, so this block will always be voided. """ diff --git a/tests/consensus/test_consensus2.py b/tests/consensus/test_consensus2.py index d8993c69e..57965252c 100644 --- a/tests/consensus/test_consensus2.py +++ b/tests/consensus/test_consensus2.py @@ -1,12 +1,15 @@ from hathor.graphviz import GraphvizVisualizer +from hathor.manager import HathorManager from hathor.simulator.utils import gen_new_tx +from hathor.transaction import Transaction +from hathor.util import not_none from tests import unittest from tests.simulation.base import SimulatorTestCase from tests.utils import add_custom_tx class BaseConsensusSimulatorTestCase(SimulatorTestCase): - def checkConflict(self, tx1, tx2): + def checkConflict(self, tx1: Transaction, tx2: Transaction) -> None: meta1 = tx1.get_metadata() meta2 = tx2.get_metadata() self.assertIn(tx1.hash, meta2.conflict_with) @@ -19,7 +22,7 @@ def checkConflict(self, tx1, tx2): cnt += 1 self.assertLessEqual(cnt, 1) - def do_step(self, i, manager1, tx_base): + def do_step(self, i: int, manager1: HathorManager, tx_base: Transaction) -> Transaction: txA = add_custom_tx(manager1, [(tx_base, 0)], n_outputs=2) self.graphviz.labels[txA.hash] = f'txA-{i}' @@ -52,7 +55,7 @@ def do_step(self, i, manager1, tx_base): return txH - def test_two_conflicts_intertwined_once(self): + def test_two_conflicts_intertwined_once(self) -> None: manager1 = self.create_peer() manager1.allow_mining_without_peers() @@ -87,7 +90,7 @@ def test_two_conflicts_intertwined_once(self): # dot = self.graphviz.dot() # dot.render('dot0') - def test_two_conflicts_intertwined_multiple_times(self): + def test_two_conflicts_intertwined_multiple_times(self) -> None: manager1 = self.create_peer() manager1.allow_mining_without_peers() @@ -113,7 +116,7 @@ def test_two_conflicts_intertwined_multiple_times(self): initial.weight = 25 initial.update_hash() manager1.propagate_tx(initial, fails_silently=False) - self.graphviz.labels[initial.hash] = 'initial' + self.graphviz.labels[not_none(initial.hash)] = 'initial' x = initial x = self.do_step(0, manager1, x) diff --git a/tests/consensus/test_consensus3.py b/tests/consensus/test_consensus3.py index 70099975c..215766bf0 100644 --- a/tests/consensus/test_consensus3.py +++ b/tests/consensus/test_consensus3.py @@ -6,14 +6,14 @@ class DoubleSpendingTestCase(unittest.TestCase): - def setUp(self): + def setUp(self) -> None: super().setUp() self.network = 'testnet' self.manager1 = self.create_peer(self.network, unlock_wallet=True, enable_sync_v1=True, enable_sync_v2=False) @pytest.mark.xfail(strict=True) - def test_double_spending_attempt_1(self): + def test_double_spending_attempt_1(self) -> None: manager = self.manager1 add_new_blocks(manager, 5, advance_clock=15) @@ -38,7 +38,7 @@ def test_double_spending_attempt_1(self): manager.cpu_mining_service.resolve(tx_fund0) self.assertTrue(manager.propagate_tx(tx_fund0)) - def do_step(tx_fund): + def do_step(tx_fund: Transaction) -> Transaction: inputs = [WalletInputInfo(tx_fund.hash, 0, manager.wallet.get_private_key(addr))] outputs = [WalletOutputInfo(decode_address(addr), 1, None)] tx1 = manager.wallet.prepare_transaction(Transaction, inputs, outputs, tx_fund.timestamp+1) @@ -105,7 +105,7 @@ def do_step(tx_fund): self.assertConsensusValid(manager) @pytest.mark.xfail(strict=True) - def test_double_spending_attempt_2(self): + def test_double_spending_attempt_2(self) -> None: manager = self.manager1 add_new_blocks(manager, 5, advance_clock=15) @@ -128,7 +128,7 @@ def test_double_spending_attempt_2(self): manager.cpu_mining_service.resolve(tx_fund0) self.assertTrue(manager.propagate_tx(tx_fund0)) - def do_step(tx_fund): + def do_step(tx_fund: Transaction) -> Transaction: inputs = [WalletInputInfo(tx_fund.hash, 0, manager.wallet.get_private_key(addr))] outputs = [WalletOutputInfo(decode_address(addr), 1, None)] tx1 = manager.wallet.prepare_transaction(Transaction, inputs, outputs, tx_fund.timestamp+1) diff --git a/tests/consensus/test_consensus4.py b/tests/consensus/test_consensus4.py index bdc3f2047..906a82b10 100644 --- a/tests/consensus/test_consensus4.py +++ b/tests/consensus/test_consensus4.py @@ -1,4 +1,7 @@ from hathor.graphviz import GraphvizVisualizer +from hathor.manager import HathorManager +from hathor.transaction import Block +from hathor.types import VertexId from tests import unittest from tests.simulation.base import SimulatorTestCase from tests.utils import gen_custom_tx @@ -6,7 +9,14 @@ class BaseConsensusSimulatorTestCase(SimulatorTestCase): - def create_chain(self, manager, first_parent_block_hash, length, prefix, tx_parents=None): + def create_chain( + self, + manager: HathorManager, + first_parent_block_hash: VertexId, + length: int, + prefix: str, + tx_parents: list[VertexId] | None = None + ) -> list[Block]: current = first_parent_block_hash v = [] for i in range(length): @@ -23,7 +33,7 @@ def create_chain(self, manager, first_parent_block_hash, length, prefix, tx_pare current = blk.hash return v - def test_conflict_with_parent_tx(self): + def test_conflict_with_parent_tx(self) -> None: manager1 = self.create_peer() manager1.allow_mining_without_peers() diff --git a/tests/consensus/test_consensus5.py b/tests/consensus/test_consensus5.py index c6e4bebc7..19feaded3 100644 --- a/tests/consensus/test_consensus5.py +++ b/tests/consensus/test_consensus5.py @@ -1,4 +1,7 @@ from hathor.graphviz import GraphvizVisualizer +from hathor.manager import HathorManager +from hathor.transaction import Block +from hathor.types import VertexId from tests import unittest from tests.simulation.base import SimulatorTestCase from tests.utils import gen_custom_tx @@ -6,7 +9,14 @@ class BaseConsensusSimulatorTestCase(SimulatorTestCase): - def create_chain(self, manager, first_parent_block_hash, length, prefix, tx_parents=None): + def create_chain( + self, + manager: HathorManager, + first_parent_block_hash: VertexId, + length: int, + prefix: str, + tx_parents: list[VertexId] | None = None + ) -> list[Block]: current = first_parent_block_hash v = [] for i in range(length): @@ -23,7 +33,7 @@ def create_chain(self, manager, first_parent_block_hash, length, prefix, tx_pare current = blk.hash return v - def test_conflict_with_parent_tx(self): + def test_conflict_with_parent_tx(self) -> None: manager1 = self.create_peer() manager1.allow_mining_without_peers() diff --git a/tests/consensus/test_soft_voided.py b/tests/consensus/test_soft_voided.py index 97bb0d562..aac80a453 100644 --- a/tests/consensus/test_soft_voided.py +++ b/tests/consensus/test_soft_voided.py @@ -1,7 +1,11 @@ +from typing import Iterator + from hathor.graphviz import GraphvizVisualizer -from hathor.simulator import FakeConnection, Simulator +from hathor.simulator import FakeConnection, RandomTransactionGenerator, Simulator from hathor.simulator.trigger import StopAfterNTransactions from hathor.simulator.utils import gen_new_tx +from hathor.transaction import Block +from hathor.types import VertexId from tests import unittest from tests.simulation.base import SimulatorTestCase from tests.utils import add_custom_tx @@ -10,14 +14,19 @@ class BaseSoftVoidedTestCase(SimulatorTestCase): seed_config = 5988775361793628170 - def assertNoParentsAreSoftVoided(self, tx): + def assertNoParentsAreSoftVoided(self, tx: Block) -> None: + assert tx.storage is not None for h in tx.parents: tx2 = tx.storage.get_transaction(h) tx2_meta = tx2.get_metadata() tx2_voided_by = tx2_meta.voided_by or set() self.assertNotIn(self._settings.SOFT_VOIDED_ID, tx2_voided_by) - def _run_test(self, simulator, soft_voided_tx_ids): + def _run_test( + self, + simulator: Simulator, + soft_voided_tx_ids: set[VertexId] + ) -> Iterator[RandomTransactionGenerator]: manager1 = self.create_peer(soft_voided_tx_ids=soft_voided_tx_ids, simulator=simulator) manager1.allow_mining_without_peers() @@ -127,7 +136,7 @@ def _run_test(self, simulator, soft_voided_tx_ids): # dot = graphviz.dot() # dot.render('dot0') - def _get_txA_hash(self): + def _get_txA_hash(self) -> VertexId: simulator = Simulator(seed=self.simulator.seed) simulator.start() @@ -140,7 +149,7 @@ def _get_txA_hash(self): return txA_hash - def test_soft_voided(self): + def test_soft_voided(self) -> None: txA_hash = self._get_txA_hash() soft_voided_tx_ids = set([ txA_hash, diff --git a/tests/consensus/test_soft_voided2.py b/tests/consensus/test_soft_voided2.py index 3e03de57a..e2ebf72e5 100644 --- a/tests/consensus/test_soft_voided2.py +++ b/tests/consensus/test_soft_voided2.py @@ -1,6 +1,12 @@ +from typing import Iterator + from hathor.graphviz import GraphvizVisualizer +from hathor.manager import HathorManager from hathor.simulator import Simulator from hathor.simulator.utils import gen_new_tx +from hathor.transaction import Block, Transaction +from hathor.types import VertexId +from hathor.wallet import HDWallet from tests import unittest from tests.simulation.base import SimulatorTestCase from tests.utils import BURN_ADDRESS, add_custom_tx @@ -9,7 +15,7 @@ class BaseConsensusSimulatorTestCase(SimulatorTestCase): seed_config = 5988775361793628169 - def assertValidConflictResolution(self, tx1, tx2): + def assertValidConflictResolution(self, tx1: Transaction, tx2: Transaction) -> None: meta1 = tx1.get_metadata() meta2 = tx2.get_metadata() @@ -28,8 +34,9 @@ def assertValidConflictResolution(self, tx1, tx2): cnt += 1 self.assertLessEqual(cnt, 1) - def do_step(self, i, manager1, tx_base): + def do_step(self, i: int, manager1: HathorManager, tx_base: Transaction) -> Transaction: wallet = manager1.wallet + assert isinstance(wallet, HDWallet) address = wallet.get_address(wallet.get_key_at_index(0)) txA = add_custom_tx(manager1, [(tx_base, 0)], n_outputs=2, address=address) @@ -86,7 +93,7 @@ def do_step(self, i, manager1, tx_base): return txH - def gen_block(self, manager1, tx, parent_block=None): + def gen_block(self, manager1: HathorManager, tx: Transaction, parent_block: Block | None = None) -> Block: parent_block_hash = parent_block.hash if parent_block else None block = manager1.generate_mining_block(parent_block_hash=parent_block_hash, address=BURN_ADDRESS) block.parents[1] = tx.hash @@ -96,8 +103,8 @@ def gen_block(self, manager1, tx, parent_block=None): self.assertTrue(manager1.propagate_tx(block, fails_silently=False)) return block - def _run_test(self, simulator, soft_voided_tx_ids): - self.txF_hashes = [] + def _run_test(self, simulator: Simulator, soft_voided_tx_ids: set[VertexId]) -> Iterator[None]: + self.txF_hashes: list[VertexId] = [] manager1 = self.create_peer(soft_voided_tx_ids=soft_voided_tx_ids, simulator=simulator) manager1.allow_mining_without_peers() @@ -180,7 +187,7 @@ def _run_test(self, simulator, soft_voided_tx_ids): # dot = self.graphviz.dot() # dot.render('dot0') - def _get_txF_hashes(self): + def _get_txF_hashes(self) -> list[VertexId]: self.skip_asserts = True simulator = Simulator(seed=self.simulator.seed) simulator.start() @@ -194,7 +201,7 @@ def _get_txF_hashes(self): return list(self.txF_hashes) - def test_soft_voided(self): + def test_soft_voided(self) -> None: txF_hashes = self._get_txF_hashes() self.assertEqual(10, len(txF_hashes)) soft_voided_tx_ids = set(txF_hashes) diff --git a/tests/consensus/test_soft_voided3.py b/tests/consensus/test_soft_voided3.py index 92af7c201..76237970b 100644 --- a/tests/consensus/test_soft_voided3.py +++ b/tests/consensus/test_soft_voided3.py @@ -1,7 +1,11 @@ +from typing import Iterator + from hathor.graphviz import GraphvizVisualizer -from hathor.simulator import FakeConnection, Simulator +from hathor.simulator import FakeConnection, RandomTransactionGenerator, Simulator from hathor.simulator.trigger import StopAfterNTransactions from hathor.simulator.utils import gen_new_tx +from hathor.transaction import Transaction +from hathor.types import VertexId from tests import unittest from tests.simulation.base import SimulatorTestCase from tests.utils import add_custom_tx, gen_custom_tx @@ -10,14 +14,19 @@ class BaseSoftVoidedTestCase(SimulatorTestCase): seed_config = 5988775361793628169 - def assertNoParentsAreSoftVoided(self, tx): + def assertNoParentsAreSoftVoided(self, tx: Transaction) -> None: + assert tx.storage is not None for h in tx.parents: tx2 = tx.storage.get_transaction(h) tx2_meta = tx2.get_metadata() tx2_voided_by = tx2_meta.voided_by or set() self.assertNotIn(self._settings.SOFT_VOIDED_ID, tx2_voided_by) - def _run_test(self, simulator, soft_voided_tx_ids): + def _run_test( + self, + simulator: Simulator, + soft_voided_tx_ids: set[VertexId] + ) -> Iterator[RandomTransactionGenerator]: manager1 = self.create_peer(soft_voided_tx_ids=soft_voided_tx_ids, simulator=simulator) manager1.allow_mining_without_peers() @@ -109,7 +118,7 @@ def _run_test(self, simulator, soft_voided_tx_ids): # dot = graphviz.dot() # dot.render('test_soft_voided3') - def _get_txA_hash(self): + def _get_txA_hash(self) -> VertexId: simulator = Simulator(seed=self.simulator.seed) simulator.start() @@ -122,7 +131,7 @@ def _get_txA_hash(self): return txA_hash - def test_soft_voided(self): + def test_soft_voided(self) -> None: txA_hash = self._get_txA_hash() soft_voided_tx_ids = set([ txA_hash, diff --git a/tests/consensus/test_soft_voided4.py b/tests/consensus/test_soft_voided4.py index bd914b341..e32a1a617 100644 --- a/tests/consensus/test_soft_voided4.py +++ b/tests/consensus/test_soft_voided4.py @@ -1,7 +1,10 @@ +from typing import Iterator + from hathor.graphviz import GraphvizVisualizer -from hathor.simulator import FakeConnection, Simulator +from hathor.simulator import FakeConnection, RandomTransactionGenerator, Simulator from hathor.simulator.trigger import StopAfterNTransactions from hathor.simulator.utils import gen_new_double_spending +from hathor.types import VertexId from tests import unittest from tests.simulation.base import SimulatorTestCase from tests.utils import add_custom_tx @@ -10,7 +13,11 @@ class BaseSoftVoidedTestCase(SimulatorTestCase): seed_config = 5988775361793628169 - def _run_test(self, simulator, soft_voided_tx_ids): + def _run_test( + self, + simulator: Simulator, + soft_voided_tx_ids: list[VertexId] + ) -> Iterator[RandomTransactionGenerator]: manager1 = self.create_peer(soft_voided_tx_ids=set(soft_voided_tx_ids), simulator=simulator) manager1.allow_mining_without_peers() @@ -54,6 +61,7 @@ def _run_test(self, simulator, soft_voided_tx_ids): gen_tx2.stop() + assert isinstance(soft_voided_tx_ids, list) self.assertEqual(2, len(soft_voided_tx_ids)) txA_hash = soft_voided_tx_ids[0] txB_hash = soft_voided_tx_ids[1] @@ -125,12 +133,12 @@ def _run_test(self, simulator, soft_voided_tx_ids): metaD = txD.get_metadata() self.assertEqual(metaD.voided_by, {tx_base.hash}) - def _get_txA_hash(self): + def _get_txA_hash(self) -> VertexId: simulator = Simulator(seed=self.simulator.seed) simulator.start() try: - it = self._run_test(simulator, set()) + it = self._run_test(simulator, []) gen_tx = next(it) txA_hash = gen_tx.latest_transactions[0] finally: @@ -138,12 +146,12 @@ def _get_txA_hash(self): return txA_hash - def _get_txB_hash(self, txA_hash): + def _get_txB_hash(self, txA_hash: VertexId) -> VertexId: simulator = Simulator(seed=self.simulator.seed) simulator.start() try: - it = self._run_test(simulator, set([txA_hash])) + it = self._run_test(simulator, [txA_hash]) _ = next(it) _ = next(it) gen_tx = next(it) @@ -153,7 +161,7 @@ def _get_txB_hash(self, txA_hash): return txB_hash - def test_soft_voided(self): + def test_soft_voided(self) -> None: txA_hash = self._get_txA_hash() txB_hash = self._get_txB_hash(txA_hash) self.assertNotEqual(txA_hash, txB_hash) diff --git a/tests/crypto/test_util.py b/tests/crypto/test_util.py index e8ba0353b..17e611037 100644 --- a/tests/crypto/test_util.py +++ b/tests/crypto/test_util.py @@ -13,22 +13,24 @@ class CryptoUtilTestCase(unittest.TestCase): - def setUp(self): + def setUp(self) -> None: super().setUp() - self.private_key = ec.generate_private_key(ec.SECP256K1(), default_backend()) + key = ec.generate_private_key(ec.SECP256K1(), default_backend()) + assert isinstance(key, ec.EllipticCurvePrivateKeyWithSerialization) + self.private_key = key self.public_key = self.private_key.public_key() - def test_privkey_serialization(self): + def test_privkey_serialization(self) -> None: private_key_bytes = get_private_key_bytes(self.private_key) self.assertEqual(self.private_key.private_numbers(), get_private_key_from_bytes(private_key_bytes).private_numbers()) - def test_address(self): + def test_address(self) -> None: address = get_address_from_public_key(self.public_key) address_b58 = get_address_b58_from_public_key(self.public_key) self.assertEqual(address, decode_address(address_b58)) - def test_invalid_address(self): + def test_invalid_address(self) -> None: from hathor.wallet.exceptions import InvalidAddress address_b58 = get_address_b58_from_public_key(self.public_key) address_b58 += '0' # 0 is invalid in base58 diff --git a/tests/event/test_base_event.py b/tests/event/test_base_event.py index 5751ae988..19459e472 100644 --- a/tests/event/test_base_event.py +++ b/tests/event/test_base_event.py @@ -23,7 +23,7 @@ @pytest.mark.parametrize('event_id', [0, 1, 1000]) @pytest.mark.parametrize('group_id', [None, 0, 1, 1000]) -def test_create_base_event(event_id, group_id): +def test_create_base_event(event_id: int, group_id: int | None) -> None: event = BaseEvent( id=event_id, timestamp=123.3, @@ -70,8 +70,8 @@ def test_create_base_event(event_id, group_id): assert event.dict() == expected -@pytest.mark.parametrize('event_id', [None, -1, -1000]) -def test_create_base_event_fail_id(event_id): +@pytest.mark.parametrize('event_id', [-1, -1000]) +def test_create_base_event_fail_id(event_id: int) -> None: with pytest.raises(ValidationError): BaseEvent( id=event_id, @@ -82,7 +82,7 @@ def test_create_base_event_fail_id(event_id): @pytest.mark.parametrize('group_id', [-1, -1000]) -def test_create_base_event_fail_group_id(group_id): +def test_create_base_event_fail_group_id(group_id: int) -> None: with pytest.raises(ValidationError): BaseEvent( id=0, @@ -93,7 +93,7 @@ def test_create_base_event_fail_group_id(group_id): ) -def test_create_base_event_fail_data_type(): +def test_create_base_event_fail_data_type() -> None: with pytest.raises(ValidationError): BaseEvent( id=0, diff --git a/tests/event/test_event_manager.py b/tests/event/test_event_manager.py index e8a09c83b..289d5b0f5 100644 --- a/tests/event/test_event_manager.py +++ b/tests/event/test_event_manager.py @@ -1,13 +1,14 @@ from hathor.event.model.event_type import EventType from hathor.event.storage.memory_storage import EventMemoryStorage from hathor.pubsub import HathorEvents +from hathor.util import not_none from tests import unittest class BaseEventManagerTest(unittest.TestCase): __test__ = False - def setUp(self): + def setUp(self) -> None: super().setUp() self.network = 'testnet' self.event_storage = EventMemoryStorage() @@ -18,37 +19,37 @@ def setUp(self): event_storage=self.event_storage ) - def test_if_event_is_persisted(self): + def test_if_event_is_persisted(self) -> None: block = self.manager.tx_storage.get_best_block() self.manager.pubsub.publish(HathorEvents.NETWORK_NEW_TX_ACCEPTED, tx=block) self.run_to_completion() self.assertIsNotNone(self.event_storage.get_event(0)) - def _fake_reorg_started(self): + def _fake_reorg_started(self) -> None: block = self.manager.tx_storage.get_best_block() # XXX: since we're faking these events, they don't neet to be consistent self.manager.pubsub.publish(HathorEvents.REORG_STARTED, old_best_height=1, old_best_block=block, new_best_height=1, new_best_block=block, reorg_size=1, common_block=block) - def _fake_reorg_finished(self): + def _fake_reorg_finished(self) -> None: self.manager.pubsub.publish(HathorEvents.REORG_FINISHED) - def test_event_group(self): + def test_event_group(self) -> None: self._fake_reorg_started() self._fake_reorg_finished() self._fake_reorg_started() self._fake_reorg_finished() self.run_to_completion() - event0 = self.event_storage.get_event(0) - event1 = self.event_storage.get_event(1) - event2 = self.event_storage.get_event(2) - event3 = self.event_storage.get_event(3) - event4 = self.event_storage.get_event(4) - event5 = self.event_storage.get_event(5) - event6 = self.event_storage.get_event(6) - event7 = self.event_storage.get_event(7) - event8 = self.event_storage.get_event(8) + event0 = not_none(self.event_storage.get_event(0)) + event1 = not_none(self.event_storage.get_event(1)) + event2 = not_none(self.event_storage.get_event(2)) + event3 = not_none(self.event_storage.get_event(3)) + event4 = not_none(self.event_storage.get_event(4)) + event5 = not_none(self.event_storage.get_event(5)) + event6 = not_none(self.event_storage.get_event(6)) + event7 = not_none(self.event_storage.get_event(7)) + event8 = not_none(self.event_storage.get_event(8)) self.assertEqual(EventType(event0.type), EventType.LOAD_STARTED) self.assertEqual(EventType(event1.type), EventType.NEW_VERTEX_ACCEPTED) @@ -66,19 +67,19 @@ def test_event_group(self): self.assertIsNotNone(event7.group_id) self.assertEqual(event7.group_id, event8.group_id) - def test_cannot_start_group_twice(self): + def test_cannot_start_group_twice(self) -> None: self._fake_reorg_started() self.run_to_completion() with self.assertRaises(AssertionError): self._fake_reorg_started() self.run_to_completion() - def test_cannot_finish_group_that_was_not_started(self): + def test_cannot_finish_group_that_was_not_started(self) -> None: with self.assertRaises(AssertionError): self._fake_reorg_finished() self.run_to_completion() - def test_cannot_finish_group_twice(self): + def test_cannot_finish_group_twice(self) -> None: self._fake_reorg_started() self._fake_reorg_finished() self.run_to_completion() diff --git a/tests/event/test_event_reorg.py b/tests/event/test_event_reorg.py index 81648f456..97606e8e9 100644 --- a/tests/event/test_event_reorg.py +++ b/tests/event/test_event_reorg.py @@ -8,7 +8,7 @@ class BaseEventReorgTest(unittest.TestCase): __test__ = False - def setUp(self): + def setUp(self) -> None: super().setUp() self.network = 'testnet' self.event_storage = EventMemoryStorage() @@ -23,7 +23,7 @@ def setUp(self): self.genesis_private_key = get_genesis_key() self.genesis_public_key = self.genesis_private_key.public_key() - def test_reorg_events(self): + def test_reorg_events(self) -> None: assert self._settings.REWARD_SPEND_MIN_BLOCKS == 10, 'this test was made with this hardcoded value in mind' # add some blocks @@ -44,7 +44,7 @@ def test_reorg_events(self): # check events actual_events = list(self.event_storage.iter_from_event(0)) - expected_events = [ + expected_events: list[tuple[EventType, dict[str, str | int]]] = [ (EventType.LOAD_STARTED, {}), (EventType.NEW_VERTEX_ACCEPTED, {'hash': self._settings.GENESIS_BLOCK_HASH.hex()}), (EventType.NEW_VERTEX_ACCEPTED, {'hash': self._settings.GENESIS_TX1_HASH.hex()}), diff --git a/tests/event/test_event_simulation_scenarios.py b/tests/event/test_event_simulation_scenarios.py index 65847491d..d3a580eff 100644 --- a/tests/event/test_event_simulation_scenarios.py +++ b/tests/event/test_event_simulation_scenarios.py @@ -64,7 +64,7 @@ def test_only_load(self) -> None: expected = _remove_timestamp(expected) assert responses == expected, f'expected: {expected}\n\nactual: {responses}' - def test_single_chain_one_block(self): + def test_single_chain_one_block(self) -> None: stream_id = self.manager._event_manager._stream_id Scenario.SINGLE_CHAIN_ONE_BLOCK.simulate(self.simulator, self.manager) self._start_stream() @@ -92,7 +92,7 @@ def test_single_chain_one_block(self): expected = _remove_timestamp(expected) assert responses == expected, f'expected: {expected}\n\nactual: {responses}' - def test_single_chain_blocks_and_transactions(self): + def test_single_chain_blocks_and_transactions(self) -> None: stream_id = self.manager._event_manager._stream_id Scenario.SINGLE_CHAIN_BLOCKS_AND_TRANSACTIONS.simulate(self.simulator, self.manager) self._start_stream() @@ -157,7 +157,7 @@ def test_single_chain_blocks_and_transactions(self): expected = _remove_timestamp(expected) assert responses == expected, f'expected: {expected}\n\nactual: {responses}' - def test_reorg(self): + def test_reorg(self) -> None: stream_id = self.manager._event_manager._stream_id Scenario.REORG.simulate(self.simulator, self.manager) self._start_stream() @@ -205,7 +205,7 @@ def test_reorg(self): expected = _remove_timestamp(expected) assert responses == expected, f'expected: {expected}\n\nactual: {responses}' - def test_unvoided_transaction(self): + def test_unvoided_transaction(self) -> None: stream_id = self.manager._event_manager._stream_id Scenario.UNVOIDED_TRANSACTION.simulate(self.simulator, self.manager) self._start_stream() diff --git a/tests/event/test_event_storage.py b/tests/event/test_event_storage.py index 1013fb25f..f9b2651a4 100644 --- a/tests/event/test_event_storage.py +++ b/tests/event/test_event_storage.py @@ -2,6 +2,7 @@ import pytest +from hathor.event.model.base_event import BaseEvent from hathor.event.model.node_state import NodeState from hathor.event.storage import EventStorage from hathor.event.storage.memory_storage import EventMemoryStorage @@ -16,18 +17,18 @@ class EventStorageBaseTest(unittest.TestCase): event_storage: EventStorage - def setUp(self): + def setUp(self) -> None: super().setUp() self.event_mocker = EventMocker(self.rng) - def test_save_event_and_retrieve(self): + def test_save_event_and_retrieve(self) -> None: event = self.event_mocker.generate_mocked_event() self.event_storage.save_event(event) event_retrieved = self.event_storage.get_event(event.id) assert event_retrieved == event - def test_save_events_and_retrieve(self): + def test_save_events_and_retrieve(self) -> None: event1 = self.event_mocker.generate_mocked_event() event2 = self.event_mocker.generate_mocked_event() self.event_storage.save_events([event1, event2]) @@ -37,7 +38,7 @@ def test_save_events_and_retrieve(self): assert event1_retrieved == event1 assert event2_retrieved == event2 - def test_get_negative_key(self): + def test_get_negative_key(self) -> None: with self.assertRaises(ValueError) as cm: self.event_storage.get_event(-1) @@ -46,20 +47,22 @@ def test_get_negative_key(self): str(cm.exception) ) - def test_get_nonexistent_event(self): + def test_get_nonexistent_event(self) -> None: assert self.event_storage.get_event(0) is None assert self.event_storage.get_event(9999) is None - def test_save_events_and_retrieve_the_last(self): - last_event = None + def test_save_events_and_retrieve_the_last(self) -> None: + last_event: BaseEvent | None = None for i in range(10): last_event = self.event_mocker.generate_mocked_event(i) self.event_storage.save_event(last_event) event_retrieved = self.event_storage.get_last_event() + assert event_retrieved is not None + assert last_event is not None assert event_retrieved.id == last_event.id - def test_save_non_sequential(self): + def test_save_non_sequential(self) -> None: for i in range(10): event = self.event_mocker.generate_mocked_event(i) self.event_storage.save_event(event) @@ -74,16 +77,16 @@ def test_save_non_sequential(self): str(cm.exception) ) - def test_iter_from_event_empty(self): + def test_iter_from_event_empty(self) -> None: self._test_iter_from_event(0) - def test_iter_from_event_single(self): + def test_iter_from_event_single(self) -> None: self._test_iter_from_event(1) - def test_iter_from_event_multiple(self): + def test_iter_from_event_multiple(self) -> None: self._test_iter_from_event(20) - def _test_iter_from_event(self, n_events): + def _test_iter_from_event(self, n_events: int) -> None: expected_events = [] for i in range(n_events): event = self.event_mocker.generate_mocked_event(i) @@ -94,7 +97,7 @@ def _test_iter_from_event(self, n_events): self.assertEqual(expected_events, actual_events) - def test_iter_from_event_negative_key(self): + def test_iter_from_event_negative_key(self) -> None: with self.assertRaises(ValueError) as cm: events = self.event_storage.iter_from_event(-10) list(events) @@ -104,7 +107,7 @@ def test_iter_from_event_negative_key(self): str(cm.exception) ) - def test_save_events_and_retrieve_last_group_id(self): + def test_save_events_and_retrieve_last_group_id(self) -> None: expected_group_id = 4 self._populate_events_and_last_group_id(n_events=10, last_group_id=expected_group_id) @@ -119,38 +122,38 @@ def _populate_events_and_last_group_id(self, n_events: int, last_group_id: int) event = self.event_mocker.generate_mocked_event(i, group_id) self.event_storage.save_event(event) - def test_get_empty_node_state(self): + def test_get_empty_node_state(self) -> None: node_state = self.event_storage.get_node_state() assert node_state is None - def test_save_node_state_and_retrieve(self): + def test_save_node_state_and_retrieve(self) -> None: self.event_storage.save_node_state(NodeState.SYNC) node_state = self.event_storage.get_node_state() assert node_state == NodeState.SYNC - def test_get_empty_event_queue_state(self): + def test_get_empty_event_queue_state(self) -> None: enabled = self.event_storage.get_event_queue_state() assert enabled is False - def test_save_event_queue_enabled_and_retrieve(self): + def test_save_event_queue_enabled_and_retrieve(self) -> None: self.event_storage.save_event_queue_state(True) enabled = self.event_storage.get_event_queue_state() assert enabled is True - def test_save_event_queue_disabled_and_retrieve(self): + def test_save_event_queue_disabled_and_retrieve(self) -> None: self.event_storage.save_event_queue_state(False) enabled = self.event_storage.get_event_queue_state() assert enabled is False - def test_reset_events_empty_database(self): + def test_reset_events_empty_database(self) -> None: self._test_reset_events() - def test_reset_all_empty_database(self): + def test_reset_all_empty_database(self) -> None: self._test_reset_events() def _test_reset_events(self) -> None: @@ -179,7 +182,7 @@ def _test_reset_all(self) -> None: assert node_state is None assert event_queue_state is False - def test_reset_events_full_database(self): + def test_reset_events_full_database(self) -> None: n_events = 10 expected_last_group_id = 4 expected_node_state = NodeState.SYNC @@ -206,7 +209,7 @@ def test_reset_events_full_database(self): assert node_state == expected_node_state assert event_queue_state is True - def test_reset_all_full_database(self): + def test_reset_all_full_database(self) -> None: n_events = 10 expected_last_group_id = 4 expected_node_state = NodeState.SYNC @@ -238,7 +241,7 @@ def test_reset_all_full_database(self): class EventStorageRocksDBTest(EventStorageBaseTest): __test__ = True - def setUp(self): + def setUp(self) -> None: super().setUp() self.directory = tempfile.mkdtemp() self.tmpdirs.append(self.directory) @@ -249,6 +252,6 @@ def setUp(self): class EventStorageMemoryTest(EventStorageBaseTest): __test__ = True - def setUp(self): + def setUp(self) -> None: super().setUp() self.event_storage = EventMemoryStorage() diff --git a/tests/event/websocket/test_factory.py b/tests/event/websocket/test_factory.py index b100fc6d5..6c703a609 100644 --- a/tests/event/websocket/test_factory.py +++ b/tests/event/websocket/test_factory.py @@ -24,7 +24,7 @@ from tests.utils import EventMocker -def test_started_register(): +def test_started_register() -> None: factory = _get_factory() connection = Mock(spec_set=EventWebsocketProtocol) connection.send_invalid_request_response = Mock() @@ -35,7 +35,7 @@ def test_started_register(): connection.send_invalid_request_response.assert_not_called() -def test_non_started_register(): +def test_non_started_register() -> None: factory = _get_factory() connection = Mock(spec_set=EventWebsocketProtocol) connection.send_invalid_request_response = Mock() @@ -45,7 +45,7 @@ def test_non_started_register(): connection.send_invalid_request_response.assert_called_once_with(InvalidRequestType.EVENT_WS_NOT_RUNNING) -def test_stopped_register(): +def test_stopped_register() -> None: factory = _get_factory() connection = Mock(spec_set=EventWebsocketProtocol) connection.send_invalid_request_response = Mock() @@ -84,7 +84,7 @@ def test_broadcast_event(can_receive_event: bool) -> None: connection.send_event_response.assert_called_once_with(response) -def test_broadcast_multiple_events_multiple_connections(): +def test_broadcast_multiple_events_multiple_connections() -> None: stream_id = 'stream_id' factory = _get_factory(10) connection1 = Mock(spec_set=EventWebsocketProtocol) diff --git a/tests/event/websocket/test_protocol.py b/tests/event/websocket/test_protocol.py index 2f3a4dcfe..afa4bab0f 100644 --- a/tests/event/websocket/test_protocol.py +++ b/tests/event/websocket/test_protocol.py @@ -13,7 +13,7 @@ # limitations under the License. from typing import Optional -from unittest.mock import ANY, Mock +from unittest.mock import ANY, Mock, patch import pytest from autobahn.websocket import ConnectionRequest @@ -27,11 +27,11 @@ @pytest.fixture -def factory(): +def factory() -> Mock: return Mock(spec_set=EventWebsocketFactory) -def test_init(): +def test_init() -> None: protocol = EventWebsocketProtocol() assert protocol.client_peer is None @@ -41,7 +41,7 @@ def test_init(): assert not protocol._stream_is_active -def test_next_expected_event_id(): +def test_next_expected_event_id() -> None: protocol = EventWebsocketProtocol() assert protocol.next_expected_event_id() == 0 @@ -51,7 +51,7 @@ def test_next_expected_event_id(): assert protocol.next_expected_event_id() == 6 -def test_on_connect(): +def test_on_connect() -> None: protocol = EventWebsocketProtocol() request = Mock(spec_set=ConnectionRequest) request.peer = 'some_peer' @@ -61,7 +61,7 @@ def test_on_connect(): assert protocol.client_peer == 'some_peer' -def test_on_open(factory): +def test_on_open(factory: Mock) -> None: protocol = EventWebsocketProtocol() protocol.factory = factory @@ -70,7 +70,7 @@ def test_on_open(factory): factory.register.assert_called_once_with(protocol) -def test_on_close(factory): +def test_on_close(factory: Mock) -> None: protocol = EventWebsocketProtocol() protocol.factory = factory @@ -79,7 +79,7 @@ def test_on_close(factory): factory.unregister.assert_called_once_with(protocol) -def test_send_event_response(): +def test_send_event_response() -> None: protocol = EventWebsocketProtocol() protocol.sendMessage = Mock() response = EventResponse( @@ -112,7 +112,11 @@ def test_send_event_response(): @pytest.mark.parametrize('_type', [InvalidRequestType.VALIDATION_ERROR, InvalidRequestType.STREAM_IS_INACTIVE]) @pytest.mark.parametrize('invalid_payload', [None, b'some_payload']) @pytest.mark.parametrize('error_message', [None, 'some error']) -def test_send_invalid_request_response(_type, invalid_payload, error_message): +def test_send_invalid_request_response( + _type: InvalidRequestType, + invalid_payload: bytes | None, + error_message: str | None +) -> None: protocol = EventWebsocketProtocol() protocol.sendMessage = Mock() @@ -173,7 +177,7 @@ def test_can_receive_event( assert result == expected_result -def test_on_valid_stop_message(): +def test_on_valid_stop_message() -> None: protocol = EventWebsocketProtocol() protocol._stream_is_active = True @@ -182,7 +186,7 @@ def test_on_valid_stop_message(): assert not protocol._stream_is_active -def test_stop_message_on_inactive(): +def test_stop_message_on_inactive() -> None: protocol = EventWebsocketProtocol() protocol.sendMessage = Mock() protocol._stream_is_active = False @@ -206,7 +210,7 @@ def test_stop_message_on_inactive(): (10, 0, 10), ] ) -def test_on_valid_ack_message(ack_event_id, window_size, last_sent_event_id): +def test_on_valid_ack_message(ack_event_id: int, window_size: int, last_sent_event_id: int) -> None: protocol = EventWebsocketProtocol() protocol._last_sent_event_id = last_sent_event_id protocol.factory = Mock() @@ -235,7 +239,7 @@ def test_on_valid_ack_message(ack_event_id, window_size, last_sent_event_id): (10, 0, 10), ] ) -def test_on_valid_start_message(ack_event_id, window_size, last_sent_event_id): +def test_on_valid_start_message(ack_event_id: int, window_size: int, last_sent_event_id: int | None) -> None: protocol = EventWebsocketProtocol() protocol._last_sent_event_id = last_sent_event_id protocol.factory = Mock() @@ -251,7 +255,7 @@ def test_on_valid_start_message(ack_event_id, window_size, last_sent_event_id): protocol.factory.send_next_event_to_connection.assert_called_once() -def test_ack_message_on_inactive(): +def test_ack_message_on_inactive() -> None: protocol = EventWebsocketProtocol() protocol.sendMessage = Mock() protocol._stream_is_active = False @@ -264,7 +268,7 @@ def test_ack_message_on_inactive(): protocol.sendMessage.assert_called_once_with(response) -def test_start_message_on_active(): +def test_start_message_on_active() -> None: protocol = EventWebsocketProtocol() protocol.sendMessage = Mock() protocol._stream_is_active = True @@ -294,17 +298,21 @@ def test_start_message_on_active(): (5, 1, 10, InvalidRequestType.ACK_TOO_LARGE), ] ) -def test_on_invalid_ack_message(_ack_event_id, last_sent_event_id, ack_event_id, _type): +def test_on_invalid_ack_message( + _ack_event_id: int, + last_sent_event_id: int | None, + ack_event_id: int, + _type: InvalidRequestType, +) -> None: protocol = EventWebsocketProtocol() protocol._ack_event_id = _ack_event_id protocol._last_sent_event_id = last_sent_event_id - protocol.send_invalid_request_response = Mock() protocol._stream_is_active = True payload = f'{{"type": "ACK", "ack_event_id": {ack_event_id}, "window_size": 0}}'.encode('utf8') - protocol.onMessage(payload, False) - - protocol.send_invalid_request_response.assert_called_once_with(_type, payload) + with patch.object(protocol, 'send_invalid_request_response') as mock: + protocol.onMessage(payload, False) + mock.assert_called_once_with(_type, payload) @pytest.mark.parametrize( @@ -318,16 +326,15 @@ def test_on_invalid_ack_message(_ack_event_id, last_sent_event_id, ack_event_id, (10, 5), ] ) -def test_on_invalid_start_message(_ack_event_id, ack_event_id): +def test_on_invalid_start_message(_ack_event_id: int, ack_event_id: int | None) -> None: protocol = EventWebsocketProtocol() protocol._ack_event_id = _ack_event_id - protocol.send_invalid_request_response = Mock() - ack_event_id = 'null' if ack_event_id is None else ack_event_id - payload = f'{{"type": "START_STREAM", "last_ack_event_id": {ack_event_id}, "window_size": 0}}'.encode('utf8') + ack_event_id_str: str = 'null' if ack_event_id is None else f'{ack_event_id}' + payload = f'{{"type": "START_STREAM", "last_ack_event_id": {ack_event_id_str}, "window_size": 0}}'.encode('utf8') - protocol.onMessage(payload, False) - - protocol.send_invalid_request_response.assert_called_once_with(InvalidRequestType.ACK_TOO_SMALL, payload) + with patch.object(protocol, 'send_invalid_request_response') as mock: + protocol.onMessage(payload, False) + mock.assert_called_once_with(InvalidRequestType.ACK_TOO_SMALL, payload) @pytest.mark.parametrize( @@ -343,11 +350,10 @@ def test_on_invalid_start_message(_ack_event_id, ack_event_id): b'{"type": "ACK", "ack_event_id": -10, "window_size": 0}', ] ) -def test_validation_error_on_message(payload): +def test_validation_error_on_message(payload: bytes) -> None: protocol = EventWebsocketProtocol() - protocol.send_invalid_request_response = Mock() protocol._stream_is_active = False - protocol.onMessage(payload, False) - - protocol.send_invalid_request_response.assert_called_once_with(InvalidRequestType.VALIDATION_ERROR, payload, ANY) + with patch.object(protocol, 'send_invalid_request_response') as mock: + protocol.onMessage(payload, False) + mock.assert_called_once_with(InvalidRequestType.VALIDATION_ERROR, payload, ANY) diff --git a/tests/feature_activation/test_bit_signaling_service.py b/tests/feature_activation/test_bit_signaling_service.py index c6aab1c18..0a929ffaa 100644 --- a/tests/feature_activation/test_bit_signaling_service.py +++ b/tests/feature_activation/test_bit_signaling_service.py @@ -258,7 +258,7 @@ def test_non_signaling_features_warning( tx_storage = Mock(spec_set=TransactionStorage) tx_storage.get_best_block = lambda: best_block - def get_bits_description_mock(block): + def get_bits_description_mock(block: Block) -> dict[Feature, FeatureDescription]: if block == best_block: return {} raise NotImplementedError diff --git a/tests/feature_activation/test_criteria.py b/tests/feature_activation/test_criteria.py index 2d8e5774a..b8ef70d2e 100644 --- a/tests/feature_activation/test_criteria.py +++ b/tests/feature_activation/test_criteria.py @@ -12,6 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. +from typing import Any + import pytest from pydantic import ValidationError @@ -43,7 +45,7 @@ ) ] ) -def test_valid_criteria(criteria): +def test_valid_criteria(criteria: dict[str, Any]) -> None: Criteria(**criteria).to_validated(evaluation_interval=1000, max_signal_bits=2) @@ -56,10 +58,10 @@ def test_valid_criteria(criteria): (10, 'bit must be lower than max_signal_bits: 10 >= 2') ] ) -def test_bit(bit, error): +def test_bit(bit: int, error: str) -> None: criteria = VALID_CRITERIA | dict(bit=bit) with pytest.raises(ValidationError) as e: - Criteria(**criteria).to_validated(evaluation_interval=1000, max_signal_bits=2) + Criteria(**criteria).to_validated(evaluation_interval=1000, max_signal_bits=2) # type: ignore[arg-type] errors = e.value.errors() assert errors[0]['msg'] == error @@ -75,10 +77,10 @@ def test_bit(bit, error): (100, 'Should be a multiple of evaluation_interval: 100 % 1000 != 0') ] ) -def test_start_height(start_height, error): +def test_start_height(start_height: int, error: str) -> None: criteria = VALID_CRITERIA | dict(start_height=start_height) with pytest.raises(ValidationError) as e: - Criteria(**criteria).to_validated(evaluation_interval=1000, max_signal_bits=2) + Criteria(**criteria).to_validated(evaluation_interval=1000, max_signal_bits=2) # type: ignore[arg-type] errors = e.value.errors() assert errors[0]['msg'] == error @@ -95,10 +97,10 @@ def test_start_height(start_height, error): (3111, 'Should be a multiple of evaluation_interval: 3111 % 1000 != 0') ] ) -def test_timeout_height(timeout_height, error): +def test_timeout_height(timeout_height: int, error: str) -> None: criteria = VALID_CRITERIA | dict(timeout_height=timeout_height) with pytest.raises(ValidationError) as e: - Criteria(**criteria).to_validated(evaluation_interval=1000, max_signal_bits=2) + Criteria(**criteria).to_validated(evaluation_interval=1000, max_signal_bits=2) # type: ignore[arg-type] errors = e.value.errors() assert errors[0]['msg'] == error @@ -113,10 +115,10 @@ def test_timeout_height(timeout_height, error): (100000, 'threshold must not be greater than evaluation_interval: 100000 > 1000') ] ) -def test_threshold(threshold, error): +def test_threshold(threshold: int, error: str) -> None: criteria = VALID_CRITERIA | dict(threshold=threshold) with pytest.raises(ValidationError) as e: - Criteria(**criteria).to_validated(evaluation_interval=1000, max_signal_bits=2) + Criteria(**criteria).to_validated(evaluation_interval=1000, max_signal_bits=2) # type: ignore[arg-type] errors = e.value.errors() assert errors[0]['msg'] == error @@ -132,10 +134,10 @@ def test_threshold(threshold, error): (100, 'Should be a multiple of evaluation_interval: 100 % 1000 != 0'), ] ) -def test_minimum_activation_height(minimum_activation_height, error): +def test_minimum_activation_height(minimum_activation_height: int, error: str) -> None: criteria = VALID_CRITERIA | dict(minimum_activation_height=minimum_activation_height) with pytest.raises(ValidationError) as e: - Criteria(**criteria).to_validated(evaluation_interval=1000, max_signal_bits=2) + Criteria(**criteria).to_validated(evaluation_interval=1000, max_signal_bits=2) # type: ignore[arg-type] errors = e.value.errors() assert errors[0]['msg'] == error @@ -149,10 +151,10 @@ def test_minimum_activation_height(minimum_activation_height, error): ('0.0', 'string does not match regex "^(\\d+\\.\\d+\\.\\d+(-rc\\.\\d+)?|nightly-[a-f0-9]{7,8})$"') ] ) -def test_version(version, error): +def test_version(version: str, error: str) -> None: criteria = VALID_CRITERIA | dict(version=version) with pytest.raises(ValidationError) as e: - Criteria(**criteria).to_validated(evaluation_interval=1000, max_signal_bits=2) + Criteria(**criteria).to_validated(evaluation_interval=1000, max_signal_bits=2) # type: ignore[arg-type] errors = e.value.errors() assert errors[0]['msg'] == error diff --git a/tests/feature_activation/test_settings.py b/tests/feature_activation/test_settings.py index 7159533a1..92b3f374e 100644 --- a/tests/feature_activation/test_settings.py +++ b/tests/feature_activation/test_settings.py @@ -56,9 +56,9 @@ ) ] ) -def test_valid_settings(features): +def test_valid_settings(features: dict) -> None: data = dict(features=features) - FeatureSettings(**data) + FeatureSettings(**data) # type: ignore[arg-type] @pytest.mark.parametrize( @@ -114,10 +114,10 @@ def test_valid_settings(features): ) ] ) -def test_conflicting_bits(features): +def test_conflicting_bits(features: list[dict]) -> None: with pytest.raises(ValidationError) as e: data = dict(features=features) - FeatureSettings(**data) + FeatureSettings(**data) # type: ignore[arg-type] errors = e.value.errors() assert errors[0]['msg'] == 'At least one pair of Features have the same bit configured for an overlapping ' \ @@ -131,10 +131,10 @@ def test_conflicting_bits(features): (100, 101, 'default_threshold must not be greater than evaluation_interval: 101 > 100') ] ) -def test_default_threshold(evaluation_interval, default_threshold, error): +def test_default_threshold(evaluation_interval: int, default_threshold: int, error: str) -> None: with pytest.raises(ValidationError) as e: data = dict(evaluation_interval=evaluation_interval, default_threshold=default_threshold) - FeatureSettings(**data) + FeatureSettings(**data) # type: ignore[arg-type] errors = e.value.errors() assert errors[0]['msg'] == error @@ -160,5 +160,5 @@ def test_default_threshold(evaluation_interval, default_threshold, error): ) ] ) -def test_find_overlap(intervals, expected): +def test_find_overlap(intervals: list[FeatureInterval], expected: tuple[FeatureInterval, FeatureInterval]) -> None: assert expected == _find_overlap(intervals) diff --git a/tests/pubsub/test_pubsub.py b/tests/pubsub/test_pubsub.py index 2d3d1ef62..b2e76e646 100644 --- a/tests/pubsub/test_pubsub.py +++ b/tests/pubsub/test_pubsub.py @@ -1,10 +1,10 @@ -from hathor.pubsub import HathorEvents, PubSubManager +from hathor.pubsub import EventArguments, HathorEvents, PubSubManager from tests.unittest import TestCase class PubSubTestCase(TestCase): - def test_duplicate_subscribe(self): - def noop(): + def test_duplicate_subscribe(self) -> None: + def noop(event: HathorEvents, args: EventArguments) -> None: pass pubsub = PubSubManager(self.clock) pubsub.subscribe(HathorEvents.NETWORK_NEW_TX_ACCEPTED, noop)