From a320dd600d69e7b978d5cbc376f65e82eb6a4045 Mon Sep 17 00:00:00 2001 From: Ruben de Vries Date: Mon, 20 Jun 2016 16:36:47 +0200 Subject: [PATCH 1/2] better solidity_names that doesn't fail when a contract contains a var that has 'contract' in it's name --- ethereum/_solidity.py | 58 ++++++--------------------------- ethereum/tests/test_solidity.py | 50 ++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 48 deletions(-) diff --git a/ethereum/_solidity.py b/ethereum/_solidity.py index 3b743798a..8d4222b79 100644 --- a/ethereum/_solidity.py +++ b/ethereum/_solidity.py @@ -96,57 +96,19 @@ def compiler_version(): return match.group(1) -def solidity_names(code): # pylint: disable=too-many-branches - """ Return the library and contract names in order of appearence. """ - names = [] - in_string = None - backslash = False - comment = None - - # "parse" the code by hand to handle the corner cases: - # - the contract or library can be inside a comment or string - # - multiline comments - # - the contract and library keywords could not be at the start of the line - for pos, char in enumerate(code): - if in_string: - if not backslash and in_string == char: - in_string = None - backslash = False - - if char == '\\': # pylint: disable=simplifiable-if-statement - backslash = True - else: - backslash = False - - elif comment == '//': - if char in ('\n', '\r'): - comment = None - - elif comment == '/*': - if char == '*' and code[pos + 1] == '/': - comment = None - - else: - if char == '"' or char == "'": - in_string = char +def remove_comments(string): + string = re.sub(re.compile("/\*.*?\*/",re.DOTALL ) ,"" ,string) # remove all occurance streamed comments (/*COMMENT */) from string + string = re.sub(re.compile("//.*?\n" ) ,"" ,string) # remove all occurance singleline comments (//COMMENT\n ) from string + return string - if char == '/': - if code[pos + 1] == '/': - comment = '//' - if code[pos + 1] == '*': - comment = '/*' - if char == 'c' and code[pos: pos + 8] == 'contract': - result = re.match('^contract[^_$a-zA-Z]+([_$a-zA-Z][_$a-zA-Z0-9]*)', code[pos:]) - - if result: - names.append(('contract', result.groups()[0])) - - if char == 'l' and code[pos: pos + 7] == 'library': - result = re.match('^library[^_$a-zA-Z]+([_$a-zA-Z][_$a-zA-Z0-9]*)', code[pos:]) +def solidity_names(code): + """ Return the library and contract names in order of appearence. """ + names = [] + cleancode = remove_comments(code) - if result: - names.append(('library', result.groups()[0])) + for m in re.findall(r'^\s*?(contract|library)\s+?(\S*?)\s+?', cleancode, re.MULTILINE): + names.append((m[0], m[1])) return names diff --git a/ethereum/tests/test_solidity.py b/ethereum/tests/test_solidity.py index bddf4ad8c..1c717a3c7 100644 --- a/ethereum/tests/test_solidity.py +++ b/ethereum/tests/test_solidity.py @@ -12,6 +12,56 @@ CONTRACTS_DIR = path.join(path.dirname(__file__), 'contracts') +def test_solidity_names(): + # test simple extracting names + code = ''' +contract test1 {} +contract test2 {} +''' + assert _solidity.solidity_names(code) == [('contract', 'test1'), ('contract', 'test2')] + + # test with odd comment + code = ''' +contract test1 +// odd comment here +/* more odd comments */ +{} +''' + assert _solidity.solidity_names(code) == [('contract', 'test1')] + + # test with contract in comment + code = ''' +contract test1 {} +//contract test2 {} +/*contract test3 {}*/ +/* +contract test4 {} +*/ +''' + assert _solidity.solidity_names(code) == [('contract', 'test1')] + + # test with a var named 'subcontract' + code = ''' +contract test1 { + _subcontract = new subcontract(); +} +''' + assert _solidity.solidity_names(code) == [('contract', 'test1')] + + # test with a contract named subcontract + code = ''' +contract subcontract {} +''' + assert _solidity.solidity_names(code) == [('contract', 'subcontract')] + + # test with a library + code = ''' +contract test1 {} +library test2 {} +''' + assert _solidity.solidity_names(code) == [('contract', 'test1'), ('library', 'test2')] + + @pytest.mark.skipif(not SOLIDITY_AVAILABLE, reason='solc compiler not available') def test_library_from_file(): state = tester.state() From 5b3502b071ee0f758e7ba9f494de14a86f5f17cb Mon Sep 17 00:00:00 2001 From: Ruben de Vries Date: Mon, 20 Jun 2016 17:26:30 +0200 Subject: [PATCH 2/2] print solc version in travis for debuggin --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 83ced25b8..418fea221 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,6 +6,7 @@ before_install: - sudo add-apt-repository -y ppa:ethereum/ethereum - sudo apt-get update - sudo apt-get install -y solc +- solc --version env: matrix: - TOX_ENV=py27