From bff61d99c0eb0d08dc2ad15be0c738ef80700ebc Mon Sep 17 00:00:00 2001 From: iamdefinitelyahuman Date: Tue, 9 Apr 2019 01:38:02 +0300 Subject: [PATCH 1/4] bugfix - compile_source "No input files given" on solc-v0.5.x --- CHANGELOG | 5 +++++ solcx/wrapper.py | 8 ++++++++ 2 files changed, 13 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 5a7b61d..7d6616c 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,8 @@ +0.2.0 +----- + + - Fix "No input files given" bug in `solcx.compile_source()` on v0.5.x + 0.1.1 ----- diff --git a/solcx/wrapper.py b/solcx/wrapper.py index 428a311..be47f4c 100644 --- a/solcx/wrapper.py +++ b/solcx/wrapper.py @@ -80,6 +80,7 @@ def solc_wrapper(solc_binary=None, if "v0.5" in command[0]: combined_json = combined_json.replace(',clone-bin','') command.extend(('--combined-json', combined_json)) + if gas: command.append('--gas') @@ -151,6 +152,13 @@ def solc_wrapper(solc_binary=None, if evm_version: command.extend(('--evm-version', evm_version)) + if ( + standard_json is None and + source_files is None and + "v0.5" in command[0] + ): + command.append('-') + proc = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, From 4407d332e6f32f965eb7e92e0bc268b6ce51b94b Mon Sep 17 00:00:00 2001 From: iamdefinitelyahuman Date: Tue, 9 Apr 2019 01:43:33 +0300 Subject: [PATCH 2/4] replace os.path with pathlib.Path --- CHANGELOG | 1 + solcx/__init__.py | 3 --- solcx/install.py | 68 +++++++++++++++++++++++------------------------ 3 files changed, 35 insertions(+), 37 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 7d6616c..9333f72 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,6 +2,7 @@ ----- - Fix "No input files given" bug in `solcx.compile_source()` on v0.5.x + - `install.py` - replace `os.path` with `pathlib.Path` 0.1.1 ----- diff --git a/solcx/__init__.py b/solcx/__init__.py index ab7f24e..e862995 100644 --- a/solcx/__init__.py +++ b/solcx/__init__.py @@ -21,9 +21,6 @@ # install if none found # default to latest version -if not os.path.exists(get_solc_folder()): - os.mkdir(get_solc_folder()) - if not get_installed_solc_versions(): print("Cannot find solc, installing...") install_solc() diff --git a/solcx/install.py b/solcx/install.py index 65cdc44..a8fc14b 100644 --- a/solcx/install.py +++ b/solcx/install.py @@ -3,6 +3,7 @@ """ from io import BytesIO import os +from pathlib import Path import requests import shutil import stat @@ -14,36 +15,37 @@ DOWNLOAD_BASE = "https://github.com/ethereum/solidity/releases/download/{}/{}" API = "https://api.github.com/repos/ethereum/solidity/releases/latest" -sep = "\\" if sys.platform == "win32" else "/" solc_version = None def get_solc_folder(): - return __file__[:__file__.rindex(sep)] + sep + "bin" + sep + path = Path(__file__).parent.joinpath('bin') + path.mkdir(exist_ok=True) + return path -def get_executable(version = None): +def get_executable(version=None): if not version: version = solc_version - solc_bin = "{}solc-{}".format(get_solc_folder(), version) + solc_bin = get_solc_folder().joinpath("solc-" + version) if sys.platform == "win32": - return solc_bin + sep + "solc.exe" - return solc_bin + return str(solc_bin.joinpath("solc.exe")) + return str(solc_bin) -def set_solc_version(version = None): +def set_solc_version(version=None): version = _check_version(version) - if not os.path.exists(get_executable(version)): + if not Path(get_executable(version)).exists(): install_solc(version) global solc_version solc_version = version def get_installed_solc_versions(): - return sorted([i[5:] for i in os.listdir(get_solc_folder()) if 'solc-v' in i]) + return sorted(i.name[5:] for i in get_solc_folder().glob('solc-v*')) -def install_solc(version = None): +def install_solc(version=None): version = _check_version(version) if sys.platform.startswith('linux'): _install_solc_linux(version) @@ -86,26 +88,25 @@ def _check_subprocess_call(command, message=None, verbose=True, **proc_kwargs): def _chmod_plus_x(executable_path): - current_st = os.stat(executable_path) - os.chmod(executable_path, current_st.st_mode | stat.S_IEXEC) + executable_path.chmod(executable_path.stat().st_mode | stat.S_IEXEC) def _wget(url, path): try: _check_subprocess_call( - ["wget", url, "-O", path], + ["wget", url, "-O", str(path)], "Downloading solc from {}".format(url) ) except subprocess.CalledProcessError: - if os.path.exists(path): - os.remove(path) + if path.exists(): + path.unlink() raise def _install_solc_linux(version): download = DOWNLOAD_BASE.format(version, "solc-static-linux") - binary_path = get_solc_folder()+"solc-{}".format(version) - if os.path.exists(binary_path): + binary_path = get_solc_folder().joinpath("solc-" + version) + if binary_path.exists(): print("solc {} already installed at: {}".format(version, binary_path)) return _wget(download, binary_path) @@ -114,46 +115,45 @@ def _install_solc_linux(version): def _install_solc_windows(version): download = DOWNLOAD_BASE.format(version, "solidity-windows.zip") - zip_path = get_solc_folder() + 'solc_{}.zip'.format(version[1:]) - install_folder = get_solc_folder()+"solc-{}".format(version) - if os.path.exists(install_folder): + install_folder = get_solc_folder().joinpath("solc-" + version) + if install_folder.exists(): print("solc {} already installed at: {}".format(version, install_folder)) return print("Downloading solc {} from {}".format(version, download)) request = requests.get(download) with zipfile.ZipFile(BytesIO(request.content)) as zf: - zf.extractall(install_folder) + zf.extractall(str(install_folder)) def _install_solc_osx(version): - tar_path = get_solc_folder() + "solc-{}.tar.gz".format(version) - source_folder = get_solc_folder() + "solidity_{}".format(version[1:]) + tar_path = get_solc_folder().joinpath("solc-{}.tar.gz".format(version)) + source_folder = get_solc_folder().joinpath("solidity_" + version[1:]) download = DOWNLOAD_BASE.format(version, "solidity_{}.tar.gz".format(version[1:])) - binary_path = get_solc_folder()+"solc-{}".format(version) - - if os.path.exists(binary_path): + binary_path = get_solc_folder().joinpath("solc-" + version) + + if binary_path.exists(): print("solc {} already installed at: {}".format(version, binary_path)) return _wget(download, tar_path) - with tarfile.open(tar_path, "r") as tar: - tar.extractall(get_solc_folder()) - os.remove(tar_path) + with tarfile.open(str(tar_path), "r") as tar: + tar.extractall(str(get_solc_folder())) + tar_path.unlink() _check_subprocess_call( - ["sh", source_folder+'/scripts/install_deps.sh'], + ["sh", str(source_folder.joinpath('scripts/install_deps.sh'))], message="Running dependency installation script `install_deps.sh` @ {}".format(tar_path) ) original_path = os.getcwd() - os.mkdir(source_folder+'/build') - os.chdir(source_folder+'/build') + source_folder.joinpath('build').mkdir(exist_ok=True) + os.chdir(str(source_folder.joinpath('build').resolve())) try: for cmd in (["cmake", ".."], ["make"]): _check_subprocess_call(cmd, message="Running {}".format(cmd[0])) os.chdir(original_path) - os.rename(source_folder+'/build/solc/solc', binary_path) + source_folder.joinpath('build/solc/solc').rename(binary_path) except subprocess.CalledProcessError as e: raise OSError( "{} returned non-zero exit status {}".format(cmd[0], e.returncode) + @@ -162,7 +162,7 @@ def _install_solc_osx(version): ) finally: os.chdir(original_path) - shutil.rmtree(source_folder) + shutil.rmtree(str(source_folder)) _chmod_plus_x(binary_path) From bf93157ca4c1223f44eb56073009f70d461c0eeb Mon Sep 17 00:00:00 2001 From: iamdefinitelyahuman Date: Tue, 9 Apr 2019 02:20:29 +0300 Subject: [PATCH 3/4] which solc --- CHANGELOG | 1 + solcx/__init__.py | 8 +++++--- solcx/install.py | 13 +++++++++++++ 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 9333f72..f1b29ef 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -3,6 +3,7 @@ - Fix "No input files given" bug in `solcx.compile_source()` on v0.5.x - `install.py` - replace `os.path` with `pathlib.Path` + - Linux/OSX - copy from `which solc` path to save time installing solc 0.1.1 ----- diff --git a/solcx/__init__.py b/solcx/__init__.py index e862995..0d2a143 100644 --- a/solcx/__init__.py +++ b/solcx/__init__.py @@ -11,18 +11,20 @@ link_code, ) from .install import ( + import_installed_solc, install_solc, get_installed_solc_versions, get_solc_folder, set_solc_version ) -# check for an installed version of solc -# install if none found -# default to latest version +# check for installed version of solc +import_installed_solc() +# if no installed version, download if not get_installed_solc_versions(): print("Cannot find solc, installing...") install_solc() +# default to latest version set_solc_version(get_installed_solc_versions()[-1]) \ No newline at end of file diff --git a/solcx/install.py b/solcx/install.py index a8fc14b..e315940 100644 --- a/solcx/install.py +++ b/solcx/install.py @@ -24,6 +24,19 @@ def get_solc_folder(): return path +def import_installed_solc(): + if sys.platform == "win32": + return + path = subprocess.check_output(['which','solc']).decode().strip() + if not path: + return + version = subprocess.check_output([path, '--version']).decode() + version = "v"+version[version.index("Version: ")+9:version.index('+')] + if version not in get_installed_solc_versions(): + shutil.copy(path, str(get_solc_folder().joinpath("solc-" + version))) + return version + + def get_executable(version=None): if not version: version = solc_version From 1c276ee6e482fa45ca7d3d2d51c9541b747740ba Mon Sep 17 00:00:00 2001 From: iamdefinitelyahuman Date: Tue, 9 Apr 2019 03:01:24 +0300 Subject: [PATCH 4/4] osx support for import_installed_solc, raise on install 0.4.x in OSX --- CHANGELOG | 3 ++- setup.py | 2 +- solcx/install.py | 25 +++++++++++++++++-------- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index f1b29ef..e14d4e2 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -3,7 +3,8 @@ - Fix "No input files given" bug in `solcx.compile_source()` on v0.5.x - `install.py` - replace `os.path` with `pathlib.Path` - - Linux/OSX - copy from `which solc` path to save time installing solc + - Linux - copy from `which solc` path to save time installing solc + - OSX - copy solc versions from `usr/local/Cellar`, raise when attempting v0.4.x install 0.1.1 ----- diff --git a/setup.py b/setup.py index 6abef9b..3263453 100644 --- a/setup.py +++ b/setup.py @@ -8,7 +8,7 @@ setup( name='py-solc-x', - version='0.1.1', + version='0.2.0', description="""Python wrapper around the solc binary with 0.5.x support""", long_description_markdown_filename='README.md', author='Benjamin Hauser (forked from py-solc by Piper Merriam)', diff --git a/solcx/install.py b/solcx/install.py index e315940..e3d81bf 100644 --- a/solcx/install.py +++ b/solcx/install.py @@ -25,16 +25,20 @@ def get_solc_folder(): def import_installed_solc(): - if sys.platform == "win32": - return - path = subprocess.check_output(['which','solc']).decode().strip() - if not path: + if sys.platform.startswith('linux'): + path_list = [subprocess.check_output(['which','solc']).decode().strip()] + if not path_list[0]: + return + elif sys.platform == 'darwin': + path_list = [str(i) for i in Path('/usr/local/Cellar').glob('solidity*/**/solc')] + else: return - version = subprocess.check_output([path, '--version']).decode() - version = "v"+version[version.index("Version: ")+9:version.index('+')] - if version not in get_installed_solc_versions(): + for path in path_list: + version = subprocess.check_output([path, '--version']).decode() + version = "v"+version[version.index("Version: ")+9:version.index('+')] + if version in get_installed_solc_versions(): + continue shutil.copy(path, str(get_solc_folder().joinpath("solc-" + version))) - return version def get_executable(version=None): @@ -139,6 +143,11 @@ def _install_solc_windows(version): def _install_solc_osx(version): + if "v0.4" in version: + raise ValueError( + "Py-solc-x cannot build solc versions 0.4.x on OSX. If you install solc 0.4.x\n" + "using brew and reload solcx, the installed version will be available.\n\n" + "See https://github.com/ethereum/homebrew-ethereum for installation instructions.") tar_path = get_solc_folder().joinpath("solc-{}.tar.gz".format(version)) source_folder = get_solc_folder().joinpath("solidity_" + version[1:]) download = DOWNLOAD_BASE.format(version, "solidity_{}.tar.gz".format(version[1:]))