Skip to content

Commit

Permalink
Fix LibP2P-Daemon installation in setup.py (#186)
Browse files Browse the repository at this point in the history
* Rename ProtoCompileInstall and ProtoCompileDevelop to Install and Develop
* Install LibP2P-Daemon on setup install and setup develop
* Install Golang in Circle CI builds
* Add P2PD binary to gitignore
  • Loading branch information
dvmazur authored and justheuristic committed Apr 13, 2021
1 parent 4409cd6 commit 0535efe
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 32 deletions.
18 changes: 18 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
version: 2.1

parameters:
go-version:
type: string
default: 1.16.2

jobs:
build-and-test-py37:
docker:
Expand All @@ -9,6 +14,11 @@ jobs:
- restore_cache:
keys:
- py37-v1-{{ checksum "requirements.txt" }}-{{ checksum "requirements-dev.txt" }}
- v1-{{ checksum "requirements.txt" }}-{{ checksum "requirements-dev.txt" }}
- run: |
wget https://golang.org/dl/go<< pipeline.parameters.go-version >>.linux-amd64.tar.gz -O go.tar.gz
tar -C ~/ -xzf go.tar.gz
echo "export PATH=~/go/bin:$PATH" >> $BASH_ENV
- run: pip install -r requirements.txt
- run: pip install -r requirements-dev.txt
- save_cache:
Expand All @@ -29,6 +39,10 @@ jobs:
- restore_cache:
keys:
- py38-v1-{{ checksum "requirements.txt" }}-{{ checksum "requirements-dev.txt" }}
- run: |
wget https://golang.org/dl/go<< pipeline.parameters.go-version >>.linux-amd64.tar.gz -O go.tar.gz
tar -C ~/ -xzf go.tar.gz
echo "export PATH=~/go/bin:$PATH" >> $BASH_ENV
- run: pip install -r requirements.txt
- run: pip install -r requirements-dev.txt
- save_cache:
Expand All @@ -49,6 +63,10 @@ jobs:
- restore_cache:
keys:
- py39-v1-{{ checksum "requirements.txt" }}-{{ checksum "requirements-dev.txt" }}
- run: |
wget https://golang.org/dl/go<< pipeline.parameters.go-version >>.linux-amd64.tar.gz -O go.tar.gz
tar -C ~/ -xzf go.tar.gz
echo "export PATH=~/go/bin:$PATH" >> $BASH_ENV
- run: pip install -r requirements.txt
- run: pip install -r requirements-dev.txt
- save_cache:
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,6 @@ debian/files

# protobuf stuff
hivemind/proto/*_pb2*

# libp2p-daemon binary
hivemind/hivemind_cli/p2pd
67 changes: 35 additions & 32 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,26 @@
import urllib.request
import tarfile
import tempfile
import hashlib

from packaging import version
from pkg_resources import parse_requirements
from setuptools import setup, find_packages
from setuptools.command.develop import develop
from setuptools.command.install import install

P2PD_VERSION = 'v0.3.1'
P2PD_CHECKSUM = '5094d094740f4e375afe80a5683b1bb2'

here = os.path.abspath(os.path.dirname(__file__))


class cd:
"""Context manager for changing the current working directory"""
def __init__(self, newPath):
self.newPath = os.path.expanduser(newPath)

def __enter__(self):
self.savedPath = os.getcwd()
os.chdir(self.newPath)

def __exit__(self, etype, value, traceback):
os.chdir(self.savedPath)
def md5(fname, chunk_size=4096):
hash_md5 = hashlib.md5()
with open(fname, "rb") as f:
for chunk in iter(lambda: f.read(chunk_size), b""):
hash_md5.update(chunk)
return hash_md5.hexdigest()


def proto_compile(output_path):
Expand All @@ -49,56 +47,61 @@ def proto_compile(output_path):
file.truncate()


def install_libp2p_daemon():
# check go version:
def libp2p_build_install():
try:
proc = subprocess.Popen(['go', 'version'],
stdout=subprocess.PIPE)
result, _ = proc.communicate()
result = result.decode('ascii', 'replace')
_, _, v, _ = result.split(' ')
v = v.lstrip('go')

if version.parse(v) < version.parse("1.13"):
raise EnvironmentError(f'newer version of go required: must be >= 1.13, found {version}')

except FileNotFoundError:
raise FileNotFoundError('could not find golang installation')

with tempfile.TemporaryDirectory() as tempdir:
url = 'https://github.com/libp2p/go-libp2p-daemon/archive/master.tar.gz'
dest = os.path.join(tempdir, 'libp2p-daemon.tar.gz')
url = f'https://github.com/learning-at-home/go-libp2p-daemon/archive/refs/tags/{P2PD_VERSION}.tar.gz'
dest = os.path.join(tempdir, 'libp2p-daemon.tar.gz')
urllib.request.urlretrieve(url, os.path.join(tempdir, dest))

tar = tarfile.open(dest, 'r:gz')
tar.extractall(tempdir)
tar.close()

with cd(os.path.join(tempdir, 'go-libp2p-daemon-master', 'p2pd')):
status = os.system(f'go build -o {os.path.join(here, "hivemind/hivemind_cli", "p2pd")}')
if status:
raise RuntimeError('Failed to build or install libp2p-daemon:'\
f' exited with status code :{status}')

result = subprocess.run(['go', 'build', '-o', os.path.join(here, "hivemind/hivemind_cli", "p2pd")],
cwd=os.path.join(tempdir, f'go-libp2p-daemon-{P2PD_VERSION[1:]}', 'p2pd'))
if result.returncode:
raise RuntimeError('Failed to build or install libp2p-daemon:'
f' exited with status code :{result.returncode}')


def libp2p_download_install():
install_path = os.path.join(here, 'hivemind/hivemind_cli/')
binary_path = os.path.join(install_path, 'p2pd')
if 'p2pd' not in os.listdir(install_path) or md5(binary_path) != P2PD_CHECKSUM:
print('Downloading Peer to Peer Daemon')
url = f'https://github.com/learning-at-home/go-libp2p-daemon/releases/download/{P2PD_VERSION}/p2pd'
urllib.request.urlretrieve(url, binary_path)
os.chmod(binary_path, 777)

class ProtoCompileInstall(install):

class Install(install):
def run(self):
libp2p_download_install()
proto_compile(os.path.join(self.build_lib, 'hivemind', 'proto'))
super().run()


class ProtoCompileDevelop(develop):
class Develop(develop):
def run(self):
libp2p_build_install()
proto_compile(os.path.join('hivemind', 'proto'))
super().run()


class LibP2PInstall(install):
def run(self):
install_libp2p_daemon()



with open('requirements.txt') as requirements_file:
install_requires = list(map(str, parse_requirements(requirements_file)))

Expand All @@ -120,7 +123,7 @@ def run(self):
setup(
name='hivemind',
version=version_string,
cmdclass={'install': ProtoCompileInstall, 'develop': ProtoCompileDevelop, 'libp2p': LibP2PInstall},
cmdclass={'install': Install, 'develop': Develop},
description='Decentralized deep learning in PyTorch',
long_description='Decentralized deep learning in PyTorch. Built to train giant models on '
'thousands of volunteers across the world.',
Expand Down

0 comments on commit 0535efe

Please sign in to comment.