Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ethPM] Update deployments to work when only abi available #1417

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 4 additions & 25 deletions ethpm/deployments.py
Original file line number Diff line number Diff line change
@@ -4,9 +4,6 @@
List,
)

from ethpm.exceptions import (
EthPMValidationError,
)
from ethpm.validation.package import (
validate_contract_name,
)
@@ -25,11 +22,11 @@ class Deployments:
def __init__(
self,
deployment_data: Dict[str, Dict[str, str]],
contract_factories: Dict[str, Contract],
contract_instances: Dict[str, Contract],
w3: Web3,
) -> None:
self.deployment_data = deployment_data
self.contract_factories = contract_factories
self.contract_instances = contract_instances
self.w3 = w3

def __getitem__(self, key: str) -> Dict[str, str]:
@@ -56,30 +53,12 @@ def get_instance(self, contract_name: str) -> None:
after validating contract name.
"""
self._validate_name_and_references(contract_name)
# Use a deployment's "contract_type" to lookup contract factory
# in case the deployment uses a contract alias
contract_type = self.deployment_data[contract_name]["contract_type"]
factory = self.contract_factories[contract_type]
address = self.deployment_data[contract_name]["address"]
contract_kwargs = {
"abi": factory.abi,
"bytecode": factory.bytecode,
"bytecode_runtime": factory.bytecode_runtime,
}
return self.w3.eth.contract(address=address, **contract_kwargs)
return self.contract_instances[contract_name]

def _validate_name_and_references(self, name: str) -> None:
validate_contract_name(name)

if name not in self.deployment_data:
raise KeyError(
"Contract name not found in deployment data. "
f"Contract deployment: {name} not found in deployment data. "
f"Available deployments include: {list(sorted(self.deployment_data.keys()))}."
)

contract_type = self.deployment_data[name]["contract_type"]
if contract_type not in self.contract_factories:
raise EthPMValidationError(
f"Contract type: {contract_type} for alias: {name} not found. "
f"Available contract types include: {list(sorted(self.contract_factories.keys()))}."
)
29 changes: 21 additions & 8 deletions ethpm/package.py
Original file line number Diff line number Diff line change
@@ -19,6 +19,7 @@
)
from eth_utils import (
to_canonical_address,
to_dict,
to_text,
to_tuple,
)
@@ -46,6 +47,7 @@
)
from ethpm.exceptions import (
BytecodeLinkingError,
EthPMValidationError,
FailureToFetchIPFSAssetsError,
InsufficientAssetsError,
PyEthPMError,
@@ -323,7 +325,7 @@ def build_dependencies(self) -> "Dependencies":
def deployments(self) -> Union["Deployments", Dict[None, None]]:
"""
Returns a ``Deployments`` object containing all the deployment data and contract
factories of a ``Package``'s `contract_types`. Automatically filters deployments
instances of a ``Package``'s `contract_types`. Automatically filters deployments
to only expose those available on the current ``Package.w3`` instance.

.. code:: python
@@ -337,12 +339,7 @@ def deployments(self) -> Union["Deployments", Dict[None, None]]:
matching_uri = validate_single_matching_uri(all_blockchain_uris, self.w3)

deployments = self.manifest["deployments"][matching_uri]
all_contract_factories = {
deployment_data["contract_type"]: self.get_contract_factory(
deployment_data["contract_type"]
)
for deployment_data in deployments.values()
}
all_contract_instances = self._get_all_contract_instances(deployments)
validate_deployments_tx_receipt(deployments, self.w3, allow_missing_data=True)
linked_deployments = get_linked_deployments(deployments)
if linked_deployments:
@@ -360,7 +357,23 @@ def deployments(self) -> Union["Deployments", Dict[None, None]]:
for linked_ref in resolved_linked_refs:
validate_linked_references(linked_ref, on_chain_bytecode)

return Deployments(deployments, all_contract_factories, self.w3)
return Deployments(deployments, all_contract_instances, self.w3)

@to_dict
def _get_all_contract_instances(self, deployments):
contract_types = self.manifest['contract_types'].keys()
for deployment_name, deployment_data in deployments.items():
if deployment_data['contract_type'] not in contract_types:
raise EthPMValidationError(
f"Contract type: {deployment_data['contract_type']} for alias: "
f"{deployment_name} not found. Available contract types include: "
f"{list(sorted(contract_types))}."
)
contract_instance = self.get_contract_instance(
deployment_data['contract_type'],
deployment_data['address'],
)
yield deployment_name, contract_instance

@to_tuple
def _resolve_linked_references(
30 changes: 1 addition & 29 deletions tests/ethpm/test_deployments.py
Original file line number Diff line number Diff line change
@@ -69,37 +69,16 @@ def test_deployment_getitem_without_deployment_reference_raises_exception(deploy
deployment["DoesNotExist"]


def test_deployment_getitem_without_contract_type_reference_raises_exception(
invalid_deployment
):
with pytest.raises(EthPMValidationError):
invalid_deployment["SafeMathLib"]


def test_deployment_implements_get_items(deployment):
expected_items = DEPLOYMENT_DATA.items()
assert deployment.items() == expected_items


def test_deployment_get_items_with_invalid_contract_names_raises_exception(
invalid_deployment
):
with pytest.raises(EthPMValidationError):
invalid_deployment.items()


def test_deployment_implements_get_values(deployment):
expected_values = list(DEPLOYMENT_DATA.values())
assert deployment.values() == expected_values


def test_deployment_get_values_with_invalid_contract_names_raises_exception(
invalid_deployment
):
with pytest.raises(EthPMValidationError):
invalid_deployment.values()


def test_deployment_implements_key_lookup(deployment):
key = "SafeMathLib" in deployment
assert key is True
@@ -123,13 +102,6 @@ def test_get_instance_without_reference_in_deployments_raises_exception(deployme
deployment.get_instance("InvalidContract")


def test_get_instance_without_reference_in_contract_factories_raises(
invalid_deployment
):
with pytest.raises(EthPMValidationError):
invalid_deployment.get_instance("SafeMathLib")


def test_deployments_get_instance(safe_math_lib_package):
deps = safe_math_lib_package.deployments
safe_math_instance = deps.get_instance("SafeMathLib")
@@ -166,7 +138,7 @@ def test_get_linked_deployments(escrow_package):
assert actual_linked_deployments == {"Escrow": all_deployments["Escrow"]}
# integration via package.deployments
deployments = escrow_package.deployments
assert len(deployments.contract_factories) is 2
assert len(deployments.contract_instances) is 2


@pytest.mark.parametrize(