Skip to content

Commit d9ea35c

Browse files
committed
Ruff
1 parent f882b1c commit d9ea35c

File tree

6 files changed

+138
-52
lines changed

6 files changed

+138
-52
lines changed

src/models/service_quality_oracle.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,12 @@ def main(run_date_override: date = None):
4949
# Configuration and credentials
5050
config = load_config()
5151
slack_notifier = create_slack_notifier(config.get("SLACK_WEBHOOK_URL"))
52-
52+
5353
if slack_notifier:
5454
logger.info("Slack notifications enabled")
5555
else:
5656
logger.info("Slack notifications disabled (no webhook URL configured)")
57-
57+
5858
credential_manager.setup_google_credentials()
5959

6060
# Define the date for the current run

tests/test_blockchain_client.py

Lines changed: 46 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
import json
66
from pathlib import Path
7-
from unittest.mock import MagicMock, mock_open, patch, PropertyMock
7+
from unittest.mock import MagicMock, PropertyMock, mock_open, patch
88

99
import pytest
1010
import requests
@@ -84,6 +84,7 @@ def blockchain_client(mock_w3, mock_slack, mock_file):
8484
class TestInitializationAndConnection:
8585
"""Tests focusing on the client's initialization and RPC connection logic."""
8686

87+
8788
def test_successful_initialization(self, blockchain_client: BlockchainClient, mock_w3, mock_file):
8889
"""
8990
Tests that the BlockchainClient initializes correctly on the happy path.
@@ -103,12 +104,11 @@ def test_successful_initialization(self, blockchain_client: BlockchainClient, mo
103104
client.w3.is_connected.assert_called_once()
104105

105106
# Assert contract object was created
106-
client.mock_w3_instance.eth.contract.assert_called_once_with(
107-
address=MOCK_CONTRACT_ADDRESS, abi=MOCK_ABI
108-
)
107+
client.mock_w3_instance.eth.contract.assert_called_once_with(address=MOCK_CONTRACT_ADDRESS, abi=MOCK_ABI)
109108
assert client.w3 is not None
110109
assert client.contract is not None
111110

111+
112112
def test_initialization_fails_if_abi_not_found(self, mock_w3, mock_slack):
113113
"""
114114
Tests that BlockchainClient raises an exception if the ABI file cannot be found.
@@ -126,6 +126,7 @@ def test_initialization_fails_if_abi_not_found(self, mock_w3, mock_slack):
126126
slack_notifier=mock_slack,
127127
)
128128

129+
129130
def test_rpc_failover_mechanism(self, mock_w3, mock_slack):
130131
"""
131132
Tests that the client successfully fails over to a secondary RPC if the primary fails.
@@ -135,9 +136,7 @@ def test_rpc_failover_mechanism(self, mock_w3, mock_slack):
135136
mock_w3_instance.is_connected.side_effect = [False, True]
136137

137138
with patch("builtins.open", mock_open(read_data=json.dumps(MOCK_ABI))):
138-
with patch(
139-
"src.models.blockchain_client.Web3", MagicMock(return_value=mock_w3_instance)
140-
) as MockWeb3:
139+
with patch("src.models.blockchain_client.Web3", MagicMock(return_value=mock_w3_instance)) as MockWeb3:
141140
# Act
142141
client = BlockchainClient(
143142
rpc_providers=MOCK_RPC_PROVIDERS,
@@ -159,6 +158,7 @@ def test_rpc_failover_mechanism(self, mock_w3, mock_slack):
159158
# The client should be connected and pointing to the secondary provider index
160159
assert client.current_rpc_index == 1
161160

161+
162162
def test_connection_error_if_all_rpcs_fail(self, mock_w3, mock_slack):
163163
"""
164164
Tests that a ConnectionError is raised if the client cannot connect to any RPC provider.
@@ -183,6 +183,7 @@ def test_connection_error_if_all_rpcs_fail(self, mock_w3, mock_slack):
183183
slack_notifier=mock_slack,
184184
)
185185

186+
186187
def test_execute_rpc_call_with_failover(self, blockchain_client: BlockchainClient):
187188
"""
188189
Tests that _execute_rpc_call fails over to the next provider if the first one
@@ -214,6 +215,7 @@ def test_execute_rpc_call_with_failover(self, blockchain_client: BlockchainClien
214215
call_kwargs = blockchain_client.slack_notifier.send_info_notification.call_args.kwargs
215216
assert "Switching from previous RPC" in call_kwargs["message"]
216217

218+
217219
def test_execute_rpc_call_reraises_unexpected_exceptions(self, blockchain_client: BlockchainClient):
218220
"""
219221
Tests that _execute_rpc_call does not attempt to failover on unexpected,
@@ -231,6 +233,7 @@ def test_execute_rpc_call_reraises_unexpected_exceptions(self, blockchain_client
231233
assert blockchain_client.current_rpc_index == 0
232234
blockchain_client.slack_notifier.send_info_notification.assert_not_called()
233235

236+
234237
def test_initialization_fails_with_empty_rpc_provider_list(self, mock_w3, mock_slack):
235238
"""
236239
Tests that BlockchainClient raises an exception if initialized with an empty list of RPC providers.
@@ -252,6 +255,7 @@ def test_initialization_fails_with_empty_rpc_provider_list(self, mock_w3, mock_s
252255
class TestTransactionLogic:
253256
"""Tests focusing on the helper methods for building and sending a transaction."""
254257

258+
255259
def test_setup_transaction_account_success(self, blockchain_client: BlockchainClient):
256260
"""
257261
Tests that _setup_transaction_account returns the correct address and formatted key
@@ -263,12 +267,11 @@ def test_setup_transaction_account_success(self, blockchain_client: BlockchainCl
263267
address, key = blockchain_client._setup_transaction_account(MOCK_PRIVATE_KEY)
264268

265269
mock_validate.assert_called_once_with(MOCK_PRIVATE_KEY)
266-
blockchain_client.mock_w3_instance.eth.account.from_key.assert_called_once_with(
267-
MOCK_PRIVATE_KEY
268-
)
270+
blockchain_client.mock_w3_instance.eth.account.from_key.assert_called_once_with(MOCK_PRIVATE_KEY)
269271
assert address == MOCK_SENDER_ADDRESS
270272
assert key == MOCK_PRIVATE_KEY
271273

274+
272275
def test_setup_transaction_account_invalid_key_raises_key_validation_error(
273276
self, blockchain_client: BlockchainClient
274277
):
@@ -281,6 +284,7 @@ def test_setup_transaction_account_invalid_key_raises_key_validation_error(
281284
with pytest.raises(KeyValidationError, match="Invalid key"):
282285
blockchain_client._setup_transaction_account("invalid-key")
283286

287+
284288
def test_setup_transaction_account_unexpected_error(self, blockchain_client: BlockchainClient):
285289
"""
286290
Tests that _setup_transaction_account raises a generic exception for unexpected errors.
@@ -291,6 +295,7 @@ def test_setup_transaction_account_unexpected_error(self, blockchain_client: Blo
291295
with pytest.raises(Exception, match="Unexpected error"):
292296
blockchain_client._setup_transaction_account("any-key")
293297

298+
294299
def test_estimate_transaction_gas_success(self, blockchain_client: BlockchainClient):
295300
"""
296301
Tests that _estimate_transaction_gas correctly estimates gas and adds a 25% buffer.
@@ -310,9 +315,8 @@ def test_estimate_transaction_gas_success(self, blockchain_client: BlockchainCli
310315

311316
# Assert
312317
assert gas_limit == 125_000 # 100_000 * 1.25
313-
mock_contract_func.return_value.estimate_gas.assert_called_once_with(
314-
{"from": MOCK_SENDER_ADDRESS}
315-
)
318+
mock_contract_func.return_value.estimate_gas.assert_called_once_with({"from": MOCK_SENDER_ADDRESS})
319+
316320

317321
def test_estimate_transaction_gas_failure(self, blockchain_client: BlockchainClient):
318322
"""
@@ -331,6 +335,7 @@ def test_estimate_transaction_gas_failure(self, blockchain_client: BlockchainCli
331335
sender_address=MOCK_SENDER_ADDRESS,
332336
)
333337

338+
334339
def test_determine_transaction_nonce_new(self, blockchain_client: BlockchainClient):
335340
"""
336341
Tests that the next available nonce is fetched for a new transaction (replace=False).
@@ -344,9 +349,8 @@ def test_determine_transaction_nonce_new(self, blockchain_client: BlockchainClie
344349

345350
# Assert
346351
assert nonce == expected_nonce
347-
blockchain_client.mock_w3_instance.eth.get_transaction_count.assert_called_once_with(
348-
MOCK_SENDER_ADDRESS
349-
)
352+
blockchain_client.mock_w3_instance.eth.get_transaction_count.assert_called_once_with(MOCK_SENDER_ADDRESS)
353+
350354

351355
def test_determine_transaction_nonce_replace(self, blockchain_client: BlockchainClient):
352356
"""
@@ -368,15 +372,15 @@ def test_determine_transaction_nonce_replace(self, blockchain_client: Blockchain
368372

369373
# Assert
370374
assert nonce == 12
371-
blockchain_client.mock_w3_instance.eth.get_block.assert_called_once_with(
372-
"pending", full_transactions=True
373-
)
375+
blockchain_client.mock_w3_instance.eth.get_block.assert_called_once_with("pending", full_transactions=True)
376+
374377

375378
def test_determine_transaction_nonce_replace_no_pending_tx_with_nonce_gap(
376379
self, blockchain_client: BlockchainClient
377380
):
378381
"""
379-
Tests that nonce determination falls back to the latest nonce if no pending txs are found but a nonce gap exists.
382+
Tests that nonce determination falls back to the latest nonce
383+
if no pending txs are found but a nonce gap exists.
380384
"""
381385
# Arrange
382386
blockchain_client.mock_w3_instance.eth.get_block.return_value = {"transactions": []}
@@ -392,6 +396,7 @@ def test_determine_transaction_nonce_replace_no_pending_tx_with_nonce_gap(
392396
assert nonce == 9 # Should use the latest nonce from the gap
393397
assert blockchain_client.mock_w3_instance.eth.get_transaction_count.call_count == 2
394398

399+
395400
def test_determine_transaction_nonce_replace_no_pending_tx_no_gap_fallback(
396401
self, blockchain_client: BlockchainClient
397402
):
@@ -415,6 +420,7 @@ def test_determine_transaction_nonce_replace_no_pending_tx_no_gap_fallback(
415420
w3_instance.eth.get_block.assert_called_once_with("pending", full_transactions=True)
416421
assert w3_instance.eth.get_transaction_count.call_count == 3
417422

423+
418424
def test_determine_transaction_nonce_replace_handles_errors(self, blockchain_client: BlockchainClient):
419425
"""
420426
Tests that nonce determination falls back gracefully if checking for pending
@@ -433,6 +439,7 @@ def test_determine_transaction_nonce_replace_handles_errors(self, blockchain_cli
433439
w3_instance.eth.get_block.assert_called_once()
434440
w3_instance.eth.get_transaction_count.assert_called()
435441

442+
436443
def test_get_gas_prices_success(self, blockchain_client: BlockchainClient):
437444
"""
438445
Tests that _get_gas_prices successfully fetches and returns the base and priority fees.
@@ -451,6 +458,7 @@ def test_get_gas_prices_success(self, blockchain_client: BlockchainClient):
451458
assert base_fee == mock_base_fee
452459
assert max_priority_fee == mock_priority_fee
453460

461+
454462
def test_get_gas_prices_fallback_on_base_fee_error(self, blockchain_client: BlockchainClient):
455463
"""
456464
Tests that _get_gas_prices falls back to a default base fee if the RPC call fails.
@@ -466,6 +474,7 @@ def test_get_gas_prices_fallback_on_base_fee_error(self, blockchain_client: Bloc
466474
assert base_fee == 10 * 10**9
467475
blockchain_client.mock_w3_instance.to_wei.assert_called_once_with(10, "gwei")
468476

477+
469478
def test_get_gas_prices_fallback_on_priority_fee_error(self, blockchain_client: BlockchainClient):
470479
"""
471480
Tests that _get_gas_prices falls back to a default priority fee if the RPC call fails.
@@ -483,6 +492,7 @@ def test_get_gas_prices_fallback_on_priority_fee_error(self, blockchain_client:
483492
assert max_priority_fee == 2 * 10**9
484493
blockchain_client.mock_w3_instance.to_wei.assert_called_once_with(2, "gwei")
485494

495+
486496
@pytest.mark.parametrize(
487497
"replace, expected_max_fee, expected_priority_fee",
488498
[
@@ -517,6 +527,7 @@ def test_build_transaction_params(
517527
assert tx_params["from"] == MOCK_SENDER_ADDRESS
518528
assert tx_params["nonce"] == 1
519529

530+
520531
def test_build_and_sign_transaction_success(self, blockchain_client: BlockchainClient):
521532
"""
522533
Tests that _build_and_sign_transaction successfully builds and signs a transaction.
@@ -540,13 +551,12 @@ def test_build_and_sign_transaction_success(self, blockchain_client: BlockchainC
540551

541552
# Assert
542553
assert signed_tx == mock_signed_transaction
543-
mock_contract_func.return_value.build_transaction.assert_called_once_with(
544-
{"from": MOCK_SENDER_ADDRESS}
545-
)
554+
mock_contract_func.return_value.build_transaction.assert_called_once_with({"from": MOCK_SENDER_ADDRESS})
546555
blockchain_client.w3.eth.account.sign_transaction.assert_called_once_with(
547556
mock_transaction, MOCK_PRIVATE_KEY
548557
)
549558

559+
550560
def test_build_and_sign_transaction_failure(self, blockchain_client: BlockchainClient):
551561
"""
552562
Tests that _build_and_sign_transaction raises an exception if building fails.
@@ -565,6 +575,7 @@ def test_build_and_sign_transaction_failure(self, blockchain_client: BlockchainC
565575
private_key="key",
566576
)
567577

578+
568579
def test_send_signed_transaction_success(self, blockchain_client: BlockchainClient):
569580
"""
570581
Tests that a signed transaction is sent and its hash is returned on success.
@@ -588,6 +599,7 @@ def test_send_signed_transaction_success(self, blockchain_client: BlockchainClie
588599
mock_tx_hash, MOCK_TX_TIMEOUT_SECONDS
589600
)
590601

602+
591603
def test_send_signed_transaction_raises_exception_when_reverted(self, blockchain_client: BlockchainClient):
592604
"""
593605
Tests that an exception is raised if the transaction is reverted on-chain.
@@ -606,6 +618,7 @@ def test_send_signed_transaction_raises_exception_when_reverted(self, blockchain
606618
):
607619
blockchain_client._send_signed_transaction(mock_signed_tx)
608620

621+
609622
def test_send_signed_transaction_raises_exception_on_timeout(self, blockchain_client: BlockchainClient):
610623
"""
611624
Tests that an exception is raised if waiting for the transaction receipt times out.
@@ -619,7 +632,9 @@ def test_send_signed_transaction_raises_exception_on_timeout(self, blockchain_cl
619632
)
620633

621634
# Act & Assert
622-
with pytest.raises(Exception, match="Error sending transaction or waiting for receipt: All RPC providers are unreachable."):
635+
with pytest.raises(
636+
Exception, match="Error sending transaction or waiting for receipt: All RPC providers are unreachable."
637+
):
623638
blockchain_client._send_signed_transaction(mock_signed_tx)
624639

625640

@@ -665,6 +680,7 @@ def mock_full_transaction_flow(mocker: MockerFixture):
665680
class TestOrchestrationAndBatching:
666681
"""Tests focusing on the end-to-end orchestration and batch processing logic."""
667682

683+
668684
def test_execute_complete_transaction_happy_path(
669685
self,
670686
blockchain_client: BlockchainClient,
@@ -709,6 +725,7 @@ def test_execute_complete_transaction_happy_path(
709725
)
710726
mock_full_transaction_flow["send"].assert_called_once_with("signed_tx")
711727

728+
712729
def test_execute_complete_transaction_missing_params(self, blockchain_client: BlockchainClient):
713730
"""
714731
Tests that _execute_complete_transaction raises ValueError if required parameters are missing.
@@ -720,6 +737,7 @@ def test_execute_complete_transaction_missing_params(self, blockchain_client: Bl
720737
with pytest.raises(ValueError, match="Missing required parameters for transaction."):
721738
blockchain_client._execute_complete_transaction(incomplete_params)
722739

740+
723741
def test_execute_complete_transaction_invalid_function(self, blockchain_client: BlockchainClient):
724742
"""
725743
Tests that _execute_complete_transaction raises ValueError for a non-existent contract function.
@@ -742,6 +760,7 @@ def test_execute_complete_transaction_invalid_function(self, blockchain_client:
742760
):
743761
blockchain_client._execute_complete_transaction(params)
744762

763+
745764
def test_send_transaction_to_allow_indexers_orchestration(
746765
self, blockchain_client: BlockchainClient, mocker: MockerFixture
747766
):
@@ -772,6 +791,7 @@ def test_send_transaction_to_allow_indexers_orchestration(
772791
assert call_args["contract_function"] == "allow"
773792
assert call_args["replace"] is False
774793

794+
775795
def test_batch_processing_splits_correctly(self, blockchain_client: BlockchainClient):
776796
"""
777797
Tests that the batch processing logic correctly splits a list of addresses
@@ -801,6 +821,7 @@ def test_batch_processing_splits_correctly(self, blockchain_client: BlockchainCl
801821
assert blockchain_client.send_transaction_to_allow_indexers.call_args_list[1][0][0] == addresses[2:4]
802822
assert blockchain_client.send_transaction_to_allow_indexers.call_args_list[2][0][0] == addresses[4:5]
803823

824+
804825
def test_batch_processing_halts_on_failure(self, blockchain_client: BlockchainClient):
805826
"""
806827
Tests that the batch processing halts immediately if one of the transactions fails.
@@ -827,6 +848,7 @@ def test_batch_processing_halts_on_failure(self, blockchain_client: BlockchainCl
827848
# The method should have only been called twice (the first success, the second failure)
828849
assert blockchain_client.send_transaction_to_allow_indexers.call_count == 2
829850

851+
830852
def test_batch_processing_handles_empty_list(self, blockchain_client: BlockchainClient):
831853
"""
832854
Tests that batch processing handles an empty list of addresses gracefully.

0 commit comments

Comments
 (0)