Skip to content

Commit 5d9437a

Browse files
authored
Merge pull request #1 from pipermerriam/piper/initial-implementation
Initial implementation
2 parents 328cc4f + c340724 commit 5d9437a

19 files changed

+623
-6
lines changed

.travis.yml

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,9 @@ sudo: required
66
before_install:
77
- travis_retry sudo add-apt-repository -y ppa:ethereum/ethereum
88
- travis_retry sudo apt-get update
9-
- travis_retry sudo apt-get install -y ethereum
10-
- mkdir -p ~/.ethash
11-
- geth makedag 0 ~/.ethash
9+
- travis_retry sudo apt-get install -y solc
1210
cache:
1311
pip: true
14-
directories:
15-
- ~/.ethash
1612
env:
1713
matrix:
1814
- TOX_ENV=py27

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ pip install py-solc
3737
},
3838
},
3939
}
40-
>>> compile_source(["/path/to/Foo.sol", "/path/to/Bar.sol"])
40+
>>> compile_files(["/path/to/Foo.sol", "/path/to/Bar.sol"])
4141
{
4242
'Foo': {
4343
'abi': [{'inputs': [], 'type': 'constructor'}],

conftest.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import pytest
2+
3+
4+
@pytest.fixture()
5+
def contracts_dir(tmpdir):
6+
return str(tmpdir.mkdir("contracts"))

requirements-dev.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
pytest>=2.9.2
2+
tox>=2.3.1

requirements.txt

Whitespace-only changes.

solc/__init__.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
from __future__ import absolute_import
2+
3+
from .main import ( # NOQA
4+
get_solc_version,
5+
compile_files,
6+
compile_source,
7+
)

solc/exceptions.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
class SolcError(Exception):
2+
pass
3+
4+
5+
class CompileError(Exception):
6+
pass

solc/main.py

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
from __future__ import absolute_import
2+
3+
import functools
4+
import json
5+
import re
6+
7+
from .exceptions import (
8+
SolcError,
9+
)
10+
11+
from .utils.formatting import (
12+
add_0x_prefix,
13+
)
14+
from .utils.filesystem import (
15+
is_executable_available,
16+
)
17+
from .wrapper import (
18+
SOLC_BINARY,
19+
solc_wrapper,
20+
)
21+
22+
23+
version_regex = re.compile('Version: ([0-9]+\.[0-9]+\.[0-9]+(-[a-f0-9]+)?)')
24+
25+
26+
is_solc_available = functools.partial(is_executable_available, SOLC_BINARY)
27+
28+
29+
def get_solc_version():
30+
stdoutdata, stderrdata = solc_wrapper(version=True)
31+
version_match = version_regex.search(stdoutdata)
32+
if version_match is None:
33+
raise SolcError(
34+
"Unable to extract version string from command output: `{0}`".format(
35+
stdoutdata,
36+
)
37+
)
38+
return version_match.groups()[0]
39+
40+
41+
def _parse_compiler_output(stdoutdata):
42+
contracts = json.loads(stdoutdata)['contracts']
43+
44+
for _, data in contracts.items():
45+
data['abi'] = json.loads(data['abi'])
46+
47+
sorted_contracts = sorted(contracts.items(), key=lambda c: c[0])
48+
49+
compiler_version = get_solc_version()
50+
51+
return {
52+
contract_name: {
53+
'abi': contract_data['abi'],
54+
'code': add_0x_prefix(contract_data['bin']),
55+
'code_runtime': add_0x_prefix(contract_data['bin-runtime']),
56+
'source': None,
57+
'meta': {
58+
'compilerVersion': compiler_version,
59+
'language': 'Solidity',
60+
'languageVersion': '0',
61+
},
62+
}
63+
for contract_name, contract_data
64+
in sorted_contracts
65+
}
66+
67+
68+
ALL_OUTPUT_VALUES = [
69+
"abi",
70+
"asm",
71+
"ast",
72+
"bin",
73+
"bin-runtime",
74+
"clone-bin",
75+
"devdoc",
76+
"interface",
77+
"opcodes",
78+
"userdoc",
79+
]
80+
81+
82+
def compile_source(source, output_values=ALL_OUTPUT_VALUES, **kwargs):
83+
if 'stdin_bytes' in kwargs:
84+
raise ValueError(
85+
"The `stdin_bytes` keyword is not allowed in the `compile_source` function"
86+
)
87+
if 'combined_json' in kwargs:
88+
raise ValueError(
89+
"The `combined_json` keyword is not allowed in the `compile_source` function"
90+
)
91+
92+
combined_json = ','.join(output_values)
93+
94+
stdoutdata, stderrdata = solc_wrapper(
95+
stdin_bytes=source,
96+
combined_json=combined_json,
97+
**kwargs
98+
)
99+
100+
contracts = _parse_compiler_output(stdoutdata)
101+
return contracts
102+
103+
104+
def compile_files(source_files, output_values=ALL_OUTPUT_VALUES, **kwargs):
105+
if 'source_files' in kwargs:
106+
raise ValueError(
107+
"The `source_files` keyword is not allowed in the `compile_files` function"
108+
)
109+
if 'combined_json' in kwargs:
110+
raise ValueError(
111+
"The `combined_json` keyword is not allowed in the `compile_files` function"
112+
)
113+
114+
combined_json = ','.join(output_values)
115+
116+
stdoutdata, stderrdata = solc_wrapper(
117+
source_files=source_files,
118+
combined_json=combined_json,
119+
**kwargs
120+
)
121+
122+
contracts = _parse_compiler_output(stdoutdata)
123+
return contracts

solc/utils/__init__.py

Whitespace-only changes.

solc/utils/filesystem.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import os
2+
3+
4+
def is_executable_available(program):
5+
def is_exe(fpath):
6+
return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
7+
8+
fpath = os.path.dirname(program)
9+
if fpath:
10+
if is_exe(program):
11+
return True
12+
else:
13+
for path in os.environ["PATH"].split(os.pathsep):
14+
path = path.strip('"')
15+
exe_file = os.path.join(path, program)
16+
if is_exe(exe_file):
17+
return True
18+
19+
return False

0 commit comments

Comments
 (0)