Skip to content

Commit

Permalink
feat: new exception
Browse files Browse the repository at this point in the history
  • Loading branch information
antazoey committed Jul 20, 2023
1 parent 6fa531a commit ac4b66b
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 15 deletions.
20 changes: 20 additions & 0 deletions src/ape/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,26 @@ class ChainError(ApeException):
"""


class ContractNotFoundError(ChainError):
"""
Raised when a contract is not found at an address.
"""

def __init__(self, address: "AddressType", has_explorer: bool, provider_name: str):
msg = f"Failed to get contract type for address '{address}'."
msg += (
" Contract may need verification."
if has_explorer
else (
f" Current provider '{provider_name}' has no associated "
"explorer plugin. Try installing an explorer plugin using "
f"{click.style(text='ape plugins install etherscan', fg='green')}, "
"or using a network with explorer support."
)
)
super().__init__(msg)


class UnknownSnapshotError(ChainError):
"""
Raised when given an unknown snapshot ID.
Expand Down
27 changes: 14 additions & 13 deletions src/ape/managers/chain.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
from pathlib import Path
from typing import IO, Collection, Dict, Iterator, List, Optional, Set, Type, Union, cast

import click
import pandas as pd
from ethpm_types import ContractType
from rich import get_console
Expand All @@ -26,6 +25,7 @@
APINotImplementedError,
BlockNotFoundError,
ChainError,
ContractNotFoundError,
ConversionError,
CustomError,
ProviderNotConnectedError,
Expand Down Expand Up @@ -967,7 +967,12 @@ def _cache_deployment(
def __getitem__(self, address: AddressType) -> ContractType:
contract_type = self.get(address)
if not contract_type:
raise IndexError(f"No contract type found at address '{address}'.")
# Create error message from custom exception cls.
err = ContractNotFoundError(
address, self.provider.network.explorer is not None, self.provider.name
)
# Must raise IndexError.
raise IndexError(str(err))

return contract_type

Expand Down Expand Up @@ -1144,6 +1149,7 @@ def instance_at(
Raises:
TypeError: When passing an invalid type for the `contract_type` arguments
(expects `ContractType`).
:class:`~ape.exceptions.ContractNotFoundError`: When the contract type is not found.
Args:
address (Union[str, AddressType]): The address of the plugin. If you are using the ENS
Expand Down Expand Up @@ -1176,17 +1182,12 @@ def instance_at(
raise # Current exception

if not contract_type:
msg = f"Failed to get contract type for address '{contract_address}'."
if self.provider.network.explorer is None:
msg += (
f" Current provider '{self.provider.name}' has no associated "
"explorer plugin. Try installing an explorer plugin using "
f"{click.style(text='ape plugins install etherscan', fg='green')}, "
"or using a network with explorer support."
)
else:
msg += " Contract may need verification."
raise ChainError(msg)
raise ContractNotFoundError(
contract_address,
self.provider.network.explorer is not None,
self.provider.name,
)

elif not isinstance(contract_type, ContractType):
raise TypeError(
f"Expected type '{ContractType.__name__}' for argument 'contract_type'."
Expand Down
2 changes: 1 addition & 1 deletion src/ape/managers/project/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -555,7 +555,7 @@ def get_contract(self, contract_name: str) -> ContractContainer:

contract = self._get_contract(contract_name)
if not contract:
raise ValueError(f"No contract found with name '{contract_name}'.")
raise ProjectError(f"No contract found with name '{contract_name}'.")

return contract

Expand Down
31 changes: 30 additions & 1 deletion tests/functional/test_chain.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,12 @@

import ape
from ape.contracts import ContractInstance
from ape.exceptions import APINotImplementedError, ChainError, ConversionError
from ape.exceptions import (
APINotImplementedError,
ChainError,
ContractNotFoundError,
ConversionError,
)
from ape_ethereum.transactions import Receipt, TransactionStatusEnum
from tests.conftest import skip_if_plugin_installed

Expand Down Expand Up @@ -384,6 +389,30 @@ def fn(addr, default=None):
assert caplog.records[-1].message == expected_fail_message


def test_instance_at_contract_type_not_found(chain):
new_address = "0x4a986a6dCA6dbf99bC3d17F8D71aFb0d60e740f8"
expected = (
rf"Failed to get contract type for address '{new_address}'. "
r"Current provider 'test' has no associated explorer plugin. "
"Try installing an explorer plugin using .*ape plugins install etherscan.*, "
r"or using a network with explorer support\."
)
with pytest.raises(ContractNotFoundError, match=expected):
chain.contracts.instance_at(new_address)


def test_contracts_getitem_contract_not_found(chain):
new_address = "0x4a986a6dCA6dbf99bC3d17F8D71aFb0d60e740f8"
expected = (
rf"Failed to get contract type for address '{new_address}'. "
r"Current provider 'test' has no associated explorer plugin. "
"Try installing an explorer plugin using .*ape plugins install etherscan.*, "
r"or using a network with explorer support\."
)
with pytest.raises(IndexError, match=expected):
_ = chain.contracts[new_address]


def test_deployments_mapping_cache_location(chain):
# Arrange / Act
mapping_location = chain.contracts._deployments_mapping_cache
Expand Down

0 comments on commit ac4b66b

Please sign in to comment.