Skip to content

Commit

Permalink
Implement write_to_disk for ipfs backends
Browse files Browse the repository at this point in the history
  • Loading branch information
njgheorghita committed Jun 25, 2019
1 parent 0dfc6da commit 78cbeb8
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 4 deletions.
9 changes: 9 additions & 0 deletions ethpm/backends/base.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from abc import ABC, abstractmethod
from pathlib import Path
from typing import Union

from eth_typing import URI
Expand Down Expand Up @@ -34,3 +35,11 @@ def fetch_uri_contents(self, uri: URI) -> Union[bytes, URI]:
Fetch the contents stored at a URI.
"""
pass

@abstractmethod
def write_to_disk(self, uri: URI, target_path: Path) -> None:
"""
Writes the contents of target URI to target path.
Raises exception if target path exists.
"""
pass
21 changes: 18 additions & 3 deletions ethpm/backends/http.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import base64
import json
from pathlib import Path
import shutil
import tempfile

from eth_typing import URI
import requests
Expand All @@ -18,6 +21,10 @@ class GithubOverHTTPSBackend(BaseURIBackend):
Base class for all URIs pointing to a content-addressed Github URI.
"""

@property
def base_uri(self) -> str:
return GITHUB_API_AUTHORITY

def can_resolve_uri(self, uri: URI) -> bool:
return is_valid_content_addressed_github_uri(uri)

Expand All @@ -44,6 +51,14 @@ def fetch_uri_contents(self, uri: URI) -> bytes:
validate_blob_uri_contents(decoded_contents, uri)
return decoded_contents

@property
def base_uri(self) -> str:
return GITHUB_API_AUTHORITY
def write_to_disk(self, uri: URI, target_path: Path) -> None:
contents = self.fetch_uri_contents(uri)
if target_path.exists():
raise CannotHandleURI(
f"Github blob: {uri} cannot be written to disk since target path ({target_path}) "
"already exists. Please provide a target_path that does not exist."
)
with tempfile.NamedTemporaryFile() as temp:
temp.write(contents)
temp.seek(0)
shutil.copyfile(temp.name, target_path)
22 changes: 21 additions & 1 deletion ethpm/backends/ipfs.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
from abc import abstractmethod
import os
from pathlib import Path
import shutil
import tempfile
from typing import Dict, List, Type

from eth_typing import URI
from eth_utils import import_string, to_bytes
import ipfshttpclient

Expand Down Expand Up @@ -49,6 +52,18 @@ def pin_assets(self, file_or_dir_path: Path) -> List[Dict[str, str]]:
"""
pass

def write_to_disk(self, uri: URI, target_path: Path) -> None:
contents = self.fetch_uri_contents(uri)
if target_path.exists():
raise CannotHandleURI(
f"IPFS uri: {uri} cannot be written to disk since target path ({target_path}) "
"already exists. Please provide a target_path that does not exist."
)
with tempfile.NamedTemporaryFile() as temp:
temp.write(contents)
temp.seek(0)
shutil.copyfile(temp.name, target_path)


class IPFSOverHTTPBackend(BaseIPFSBackend):
"""
Expand All @@ -59,7 +74,7 @@ class IPFSOverHTTPBackend(BaseIPFSBackend):
def __init__(self) -> None:
self.client = ipfshttpclient.connect(self.base_uri)

def fetch_uri_contents(self, uri: str) -> bytes:
def fetch_uri_contents(self, uri: URI) -> bytes:
ipfs_hash = extract_ipfs_path_from_uri(uri)
contents = self.client.cat(ipfs_hash)
validation_hash = generate_file_hash(contents)
Expand Down Expand Up @@ -108,6 +123,11 @@ def fetch_uri_contents(self, uri: str) -> bytes:
"IPFS gateway is currently disabled, please use a different IPFS backend."
)

def write_to_disk(self, uri: URI, target_path: Path) -> None:
raise CannotHandleURI(
"IPFS gateway is currently disabled, please use a different IPFS backend."
)


class InfuraIPFSBackend(IPFSOverHTTPBackend):
"""
Expand Down
8 changes: 8 additions & 0 deletions ethpm/backends/registry.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import os
from pathlib import Path

from eth_typing import URI
from web3 import Web3
from web3.providers.auto import load_provider_from_uri

from ethpm.backends.base import BaseURIBackend
from ethpm.constants import INFURA_API_KEY
from ethpm.exceptions import CannotHandleURI
from ethpm.utils.registry import fetch_standard_registry_abi
from ethpm.utils.uri import parse_registry_uri
from ethpm.validation import is_valid_registry_uri
Expand Down Expand Up @@ -41,3 +43,9 @@ def fetch_uri_contents(self, uri: str) -> URI:
self.w3.pm.set_registry(address)
_, _, manifest_uri = self.w3.pm.get_release_data(pkg_name, pkg_version)
return manifest_uri

def write_to_disk(self, uri: str, target_path: Path) -> None:
raise CannotHandleURI(
"Registry backends are not allowed to write resolved uris to disk. "
"Please use a different backend."
)
9 changes: 9 additions & 0 deletions tests/ethpm/backends/test_http_backends.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,12 @@ def test_github_over_https_backend_raises_error_with_invalid_content_hash(w3):
invalid_uri = "https://api.github.com/repos/ethpm/py-ethpm/git/blobs/a7232a93f1e9e75d606f6c1da18aa16037e03123"
with pytest.raises(HTTPError):
Package.from_uri(invalid_uri, w3)


def test_github_backend_writes_to_disk(tmp_path):
uri = "https://api.github.com/repos/ethpm/py-ethpm/git/blobs/a7232a93f1e9e75d606f6c1da18aa16037e03480"
backend = GithubOverHTTPSBackend()
contents = backend.fetch_uri_contents(uri)
target_path = tmp_path / "github_uri.txt"
backend.write_to_disk(uri, target_path)
assert target_path.read_bytes() == contents
9 changes: 9 additions & 0 deletions tests/ethpm/backends/test_ipfs_backends.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,3 +116,12 @@ def test_pin_assets_to_dummy_backend(dummy_ipfs_backend):
assert "StandardToken.sol" in dir_names
assert "QmRJHLmPVct2rbBpdGjP3xkXbF7romQigtmcs8TRfV1yC7" in dir_hashes
assert "2865" in dir_sizes


def test_ipfs_backend_write_to_disk(tmp_path):
ipfs_uri = "ipfs://QmeD2s7KaBUoGYTP1eutHBmBkMMMoycdfiyGMx2DKrWXyV"
backend = LocalIPFSBackend()
contents = backend.fetch_uri_contents(ipfs_uri)
target_path = tmp_path / "ipfs_uri.txt"
backend.write_to_disk(ipfs_uri, target_path)
assert target_path.read_bytes() == contents

0 comments on commit 78cbeb8

Please sign in to comment.