3
3
import re
4
4
import subprocess
5
5
import warnings
6
+ import shlex
6
7
7
8
import yaml
8
9
@@ -45,16 +46,22 @@ def get_solidity():
45
46
return solc_wrapper
46
47
47
48
48
- def solc_arguments (libraries = None , combined = 'bin,abi' , optimize = True ):
49
+ def solc_arguments (libraries = None , combined = 'bin,abi' , optimize = True , extra_args = None ):
49
50
""" Build the arguments to call the solc binary. """
50
51
args = [
51
52
'--combined-json' , combined ,
52
- '--add-std' ,
53
+ '--add-std'
53
54
]
54
55
55
56
if optimize :
56
57
args .append ('--optimize' )
57
58
59
+ if extra_args :
60
+ try :
61
+ args .extend (shlex .split (extra_args ))
62
+ except : # if not a parseable string then treat it as a list
63
+ args .extend (extra_args )
64
+
58
65
if libraries is not None and len (libraries ):
59
66
addresses = [
60
67
'{name}:{address}' .format (name = name , address = address .decode ('utf8' ))
@@ -70,6 +77,10 @@ def solc_arguments(libraries=None, combined='bin,abi', optimize=True):
70
77
71
78
def solc_parse_output (compiler_output ):
72
79
""" Parses the compiler output. """
80
+ # At the moment some solc output like --hashes or -- gas will not output
81
+ # json at all so if used with those arguments the logic here will break.
82
+ # Perhaps solidity will slowly switch to a json only output and this comment
83
+ # can eventually go away and we will not need to add more logic here at all.
73
84
result = yaml .safe_load (compiler_output )['contracts' ]
74
85
75
86
if 'bin' in tuple (result .values ())[0 ]:
@@ -98,7 +109,7 @@ def solc_parse_output(compiler_output):
98
109
def compiler_version ():
99
110
""" Return the version of the installed solc. """
100
111
version_info = subprocess .check_output (['solc' , '--version' ])
101
- match = re .search ('^Version: ([0-9a-z.-]+)/' , version_info , re .MULTILINE )
112
+ match = re .search (b '^Version: ([0-9a-z.-]+)/' , version_info , re .MULTILINE )
102
113
103
114
if match :
104
115
return match .group (1 )
@@ -190,7 +201,7 @@ def solidity_resolve_address(hex_code, library_symbol, library_address):
190
201
raise ValueError ('Address should not contain the 0x prefix' )
191
202
192
203
try :
193
- _ = decode_hex (library_address )
204
+ decode_hex (library_address )
194
205
except TypeError :
195
206
raise ValueError ('library_address contains invalid characters, it must be hex encoded.' )
196
207
@@ -226,7 +237,7 @@ def solidity_unresolved_symbols(hex_code):
226
237
return set (re .findall (r"_.{39}" , hex_code ))
227
238
228
239
229
- def compile_file (filepath , libraries = None , combined = 'bin,abi' , optimize = True ):
240
+ def compile_file (filepath , libraries = None , combined = 'bin,abi' , optimize = True , extra_args = None ):
230
241
""" Return the compile contract code.
231
242
232
243
Args:
@@ -241,7 +252,7 @@ def compile_file(filepath, libraries=None, combined='bin,abi', optimize=True):
241
252
242
253
workdir , filename = os .path .split (filepath )
243
254
244
- args = solc_arguments (libraries = libraries , combined = combined , optimize = optimize )
255
+ args = solc_arguments (libraries = libraries , combined = combined , optimize = optimize , extra_args = extra_args )
245
256
args .insert (0 , get_compiler_path ())
246
257
args .append (filename )
247
258
@@ -250,18 +261,19 @@ def compile_file(filepath, libraries=None, combined='bin,abi', optimize=True):
250
261
return solc_parse_output (output )
251
262
252
263
253
- def compile_contract (filepath , contract_name , libraries = None , combined = 'bin,abi' , optimize = True ):
264
+ def compile_contract (filepath , contract_name , libraries = None , combined = 'bin,abi' , optimize = True , extra_args = None ):
254
265
all_contracts = compile_file (
255
266
filepath ,
256
267
libraries = libraries ,
257
268
combined = combined ,
258
269
optimize = optimize ,
270
+ extra_args = extra_args
259
271
)
260
272
261
273
return all_contracts [contract_name ]
262
274
263
275
264
- def compile_last_contract (filepath , libraries = None , combined = 'bin,abi' , optimize = True ):
276
+ def compile_last_contract (filepath , libraries = None , combined = 'bin,abi' , optimize = True , extra_args = None ):
265
277
with open (filepath ) as handler :
266
278
all_names = solidity_names (handler .read ())
267
279
@@ -278,11 +290,12 @@ def compile_last_contract(filepath, libraries=None, combined='bin,abi', optimize
278
290
libraries = libraries ,
279
291
combined = combined ,
280
292
optimize = optimize ,
293
+ extra_args = extra_args
281
294
)
282
295
283
296
284
- def compile_code (sourcecode , libraries = None , combined = 'bin,abi' , optimize = True ):
285
- args = solc_arguments (libraries = libraries , combined = combined , optimize = optimize )
297
+ def compile_code (sourcecode , libraries = None , combined = 'bin,abi' , optimize = True , extra_args = None ):
298
+ args = solc_arguments (libraries = libraries , combined = combined , optimize = optimize , extra_args = extra_args )
286
299
args .insert (0 , get_compiler_path ())
287
300
288
301
process = subprocess .Popen (args , stdin = subprocess .PIPE , stdout = subprocess .PIPE , stderr = subprocess .PIPE )
@@ -302,17 +315,17 @@ class Solc(object):
302
315
compiler_version = staticmethod (compiler_version )
303
316
304
317
@staticmethod
305
- def _code_or_path (sourcecode , path , contract_name , libraries , combined ):
318
+ def _code_or_path (sourcecode , path , contract_name , libraries , combined , extra_args ):
306
319
warnings .warn ('solc_wrapper is deprecated, please use the functions compile_file or compile_code' )
307
320
308
321
if sourcecode and path :
309
322
raise ValueError ('sourcecode and path are mutually exclusive.' )
310
323
311
324
if path and contract_name :
312
- return compile_contract (path , contract_name , libraries = libraries , combined = combined )
325
+ return compile_contract (path , contract_name , libraries = libraries , combined = combined , extra_args = extra_args )
313
326
314
327
if path :
315
- return compile_last_contract (path , libraries = libraries , combined = combined )
328
+ return compile_last_contract (path , libraries = libraries , combined = combined , extra_args = extra_args )
316
329
317
330
all_names = solidity_names (sourcecode )
318
331
all_contract_names = [
@@ -321,41 +334,44 @@ def _code_or_path(sourcecode, path, contract_name, libraries, combined):
321
334
]
322
335
last_contract = all_contract_names [- 1 ]
323
336
324
- result = compile_code (sourcecode , libraries = libraries , combined = combined )
337
+ result = compile_code (sourcecode , libraries = libraries , combined = combined , extra_args = extra_args )
325
338
return result [last_contract ]
326
339
327
340
@classmethod
328
- def compile (cls , code , path = None , libraries = None , contract_name = '' ):
341
+ def compile (cls , code , path = None , libraries = None , contract_name = '' , extra_args = None ):
329
342
""" Return the binary of last contract in code. """
330
- result = cls ._code_or_path (code , path , contract_name , libraries , 'bin' )
343
+ result = cls ._code_or_path (code , path , contract_name , libraries , 'bin' , extra_args )
331
344
return result ['bin' ]
332
345
333
346
@classmethod
334
- def mk_full_signature (cls , code , path = None , libraries = None , contract_name = '' ):
347
+ def mk_full_signature (cls , code , path = None , libraries = None , contract_name = '' , extra_args = None ):
335
348
"returns signature of last contract in code"
336
349
337
- result = cls ._code_or_path (code , path , contract_name , libraries , 'abi' )
350
+ result = cls ._code_or_path (code , path , contract_name , libraries , 'abi' , extra_args )
338
351
return result ['abi' ]
339
352
340
353
@classmethod
341
- def combined (cls , code , path = None ):
354
+ def combined (cls , code , path = None , extra_args = None ):
342
355
""" Compile combined-json with abi,bin,devdoc,userdoc.
343
356
344
357
@param code: literal solidity code as a string.
345
- @param path: absolute path to solidity-file. Note: code & path are exclusive!
358
+ @param path: absolute path to solidity-file. Note: code & path are
359
+ mutually exclusive!
360
+ @param extra_args: Either a space separated string or a list of extra
361
+ arguments to be passed to the solidity compiler.
346
362
"""
347
363
348
364
if code and path :
349
365
raise ValueError ('sourcecode and path are mutually exclusive.' )
350
366
351
367
if path :
352
- contracts = compile_file (path )
368
+ contracts = compile_file (path , extra_args = extra_args )
353
369
354
370
with open (path ) as handler :
355
371
code = handler .read ()
356
372
357
373
elif code :
358
- contracts = compile_code (code )
374
+ contracts = compile_code (code , extra_args = extra_args )
359
375
360
376
else :
361
377
raise ValueError ('either code or path needs to be supplied.' )
@@ -366,7 +382,7 @@ def combined(cls, code, path=None):
366
382
return sorted_contracts
367
383
368
384
@classmethod
369
- def compile_rich (cls , code , path = None ):
385
+ def compile_rich (cls , code , path = None , extra_args = None ):
370
386
"""full format as returned by jsonrpc"""
371
387
372
388
return {
@@ -383,7 +399,7 @@ def compile_rich(cls, code, path=None):
383
399
},
384
400
}
385
401
for contract_name , contract
386
- in cls .combined (code , path = path )
402
+ in cls .combined (code , path = path , extra_args = extra_args )
387
403
}
388
404
389
405
0 commit comments