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 contract types property #1440

Merged
Merged
Show file tree
Hide file tree
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
2 changes: 1 addition & 1 deletion docs/ethpm.rst
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ Properties
Each ``Package`` exposes the following properties.

.. autoclass:: ethpm.Package
:members: name, version, manifest_version, uri, __repr__, build_dependencies, deployments
:members: name, version, manifest_version, uri, __repr__, contract_types, build_dependencies, deployments

.. py:attribute:: Package.w3

Expand Down
20 changes: 15 additions & 5 deletions ethpm/package.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
Any,
Dict,
Generator,
List,
Optional,
Tuple,
Union,
Expand Down Expand Up @@ -176,6 +177,16 @@ def uri(self) -> Optional[str]:
"""
return self._uri

@property
def contract_types(self) -> List[str]:
"""
All contract types included in this package.
"""
if 'contract_types' in self.manifest:
return sorted(self.manifest['contract_types'].keys())
else:
return ValueError("No contract types found in manifest; {self.__repr__()}.")

@classmethod
def from_file(cls, file_path: Path, w3: Web3) -> "Package":
"""
Expand All @@ -202,7 +213,7 @@ def from_uri(cls, uri: URI, w3: Web3) -> "Package":
URI schemes supported:
- IPFS `ipfs://Qm...`
- HTTP `https://api.github.com/repos/:owner/:repo/git/blobs/:file_sha`
- Registry `ercXXX://registry.eth/greeter?version=1.0.0`
- Registry `erc1319://registry.eth:1/greeter?version=1.0.0`

.. code:: python

Expand Down Expand Up @@ -253,7 +264,7 @@ def get_contract_factory(self, name: ContractName) -> Contract:
raise InsufficientAssetsError(
"This package does not contain any package data to generate "
f"a contract factory for contract type: {name}. Available contract types include: "
f"{ list(self.manifest['contract_types'].keys()) }."
f"{self.contract_types}."
)

validate_minimal_contract_factory_data(contract_data)
Expand Down Expand Up @@ -361,13 +372,12 @@ def deployments(self) -> Union["Deployments", Dict[None, None]]:

@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:
if deployment_data['contract_type'] not in self.contract_types:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will you always have deployment data here? If not, it's probably worth a check:

if deployment_data and deployment_data['contract_type'] not in self.contract_types:
    ...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh good thought - but we check for deployments on line 346 / so if people are using this private method correctly (via Package.deployments and not directly ) then we should be ok

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))}."
f"{self.contract_types}."
)
contract_instance = self.get_contract_instance(
deployment_data['contract_type'],
Expand Down
1 change: 1 addition & 0 deletions newsfragments/1440.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add ``contract_types`` property to ``Package`` class.
1 change: 1 addition & 0 deletions tests/ethpm/test_package.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,4 @@ def test_package_object_properties(safe_math_package):
assert safe_math_package.manifest_version == "2"
assert safe_math_package.uri is None
assert safe_math_package.__repr__() == "<Package safe-math-lib==1.0.0>"
assert safe_math_package.contract_types == ["SafeMathLib"]
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
Package,
)
from ethpm.exceptions import (
CannotHandleURI,
EthPMValidationError,
)

Expand Down Expand Up @@ -95,3 +96,36 @@ def test_from_file_succeeds_with_valid_manifest(valid_manifest_from_path, w3):
def test_from_file_raises_type_error_with_invalid_param_type():
with pytest.raises(TypeError):
Package.from_file(1)


#
# From URI
#

VALID_IPFS_PKG = "ipfs://QmeD2s7KaBUoGYTP1eutHBmBkMMMoycdfiyGMx2DKrWXyV"


def test_package_from_uri_with_valid_uri(dummy_ipfs_backend, w3):
package = Package.from_uri(VALID_IPFS_PKG, w3)
assert package.name == "safe-math-lib"
assert isinstance(package, Package)


@pytest.mark.parametrize(
"uri",
(
# Invalid
"123",
b"123",
"ipfs://",
"http://QmTKB75Y73zhNbD3Y73xeXGjYrZHmaXXNxoZqGCagu7r8u/readme",
"ipfsQmTKB75Y73zhNbD3Y73xeXGjYrZHmaXXNxoZqGCagu7r8u/readme/",
# Unsupported
"erc111://packages.zeppelin.os/owned",
"bzz://da6adeeb4589d8652bbe5679aae6b6409ec85a20e92a8823c7c99e25dba9493d",
),
)
@pytest.mark.skipif('WEB3_INFURA_PROJECT_ID' not in os.environ, reason='Infura API key unavailable')
def test_package_from_uri_rejects_invalid_ipfs_uri(uri, w3):
with pytest.raises(CannotHandleURI):
Package.from_uri(uri, w3)
22 changes: 0 additions & 22 deletions tests/ethpm/test_package_init_from_registry_uri.py

This file was deleted.

33 changes: 0 additions & 33 deletions tests/ethpm/test_package_init_from_uri.py

This file was deleted.