1
+ """
2
+ Arguments for the script are:
3
+ -v or --version Solidity version to be used to compile the contracts. If
4
+ blank, the script uses the latest hard-coded version
5
+ specified within the script.
6
+
7
+ -f or --filename If left blank, all .sol files will be compiled and the
8
+ respective contract data will be generated. Pass in a
9
+ specific ``.sol`` filename here to compile just one file.
10
+
11
+
12
+ To run the script, you will need the ``py-solc-x`` library for compiling the files
13
+ as well as ``black`` for linting. You can install those independently or install the
14
+ full ``[dev]`` package extra as shown below.
15
+
16
+ .. code:: sh
17
+
18
+ $ pip install "web3[dev]"
19
+
20
+ The following example compiles all the contracts and generates their respective
21
+ contract data that is used across our test files for the test suites. This data gets
22
+ generated within the ``contract_data`` subdirectory within the ``contract_sources``
23
+ folder.
24
+
25
+ .. code-block:: bash
26
+
27
+ $ cd ../web3.py/web3/_utils/contract_sources
28
+ $ python compile_contracts.py -v 0.8.17
29
+ Compiling OffchainLookup
30
+ ...
31
+ ...
32
+ reformatted ...
33
+
34
+ To compile and generate contract data for only one ``.sol`` file, specify using the
35
+ filename with the ``-f`` (or ``--filename``) argument flag.
36
+
37
+ .. code-block:: bash
38
+
39
+ $ cd ../web3.py/web3/_utils/contract_sources
40
+ $ python compile_contracts.py -v 0.8.17 -f OffchainLookup.sol
41
+ Compiling OffchainLookup.sol
42
+ reformatted ...
43
+ """
44
+
45
+
46
+ import argparse
1
47
import os
2
48
import re
3
- import sys
49
+ import warnings
4
50
from typing import (
5
51
Any ,
6
52
)
7
53
8
54
import solcx
9
55
10
- SOLIDITY_VERSION_REGEX = re . compile ( r"\d*\.\d+" ) # 0.0.0 pattern
11
- CONFIGURED_SOLIDITY_VERSION = "0.8.17"
12
-
13
- user_provided_version = sys . argv [ - 1 ]
14
-
15
- solidity_version = (
16
- user_provided_version
17
- if SOLIDITY_VERSION_REGEX . match ( user_provided_version )
18
- else CONFIGURED_SOLIDITY_VERSION
56
+ arg_parser = argparse . ArgumentParser ()
57
+ arg_parser . add_argument (
58
+ "-v" , "--version" , help = "Solidity version for compiling contracts."
59
+ )
60
+ arg_parser . add_argument (
61
+ "-f" ,
62
+ "--filename" ,
63
+ help = "(optional) The filename if only one file is to be compiled - "
64
+ "otherwise all .sol files will be compiled at once." ,
19
65
)
66
+ user_args = arg_parser .parse_args ()
20
67
68
+ CONFIGURED_SOLIDITY_VERSION = "0.8.17"
69
+ # establish Solidity version from user-provided arg or use hard-coded version
70
+ user_sol_version = user_args .version
21
71
72
+ solidity_version = user_sol_version if user_sol_version else CONFIGURED_SOLIDITY_VERSION
22
73
solcx .install_solc (solidity_version )
23
74
solcx .set_solc_version (solidity_version )
24
75
25
76
26
- def compile_dot_sol_files (dot_sol_filename : str ) -> dict [str , Any ]:
77
+ # compile just the .sol file specified or all .sol files
78
+ all_dot_sol_files = [f for f in os .listdir (os .getcwd ()) if f .endswith (".sol" )]
79
+ user_filename = user_args .filename
80
+ files_to_compile = [user_filename ] if user_filename else all_dot_sol_files
81
+
82
+
83
+ def _compile_dot_sol_files (dot_sol_filename : str ) -> dict [str , Any ]:
27
84
compiled = solcx .compile_files (
28
85
[f"./{ dot_sol_filename } " ],
29
86
output_values = ["abi" , "bin" , "bin-runtime" ],
30
87
)
31
88
return compiled
32
89
33
90
34
- def get_compiled_contract_data (
91
+ def _get_compiled_contract_data (
35
92
sol_file_output : dict [str , dict [str , str ]],
36
93
dot_sol_filename : str ,
37
94
contract_name : str = None ,
@@ -54,8 +111,9 @@ def get_compiled_contract_data(
54
111
55
112
contracts_in_file = {}
56
113
57
- for filename in os .listdir (os .getcwd ()):
58
- if ".sol" in filename :
114
+
115
+ def compile_files (file_list : list [str ]) -> None :
116
+ for filename in file_list :
59
117
with open (os .path .join (os .getcwd (), filename ), "r" ) as f :
60
118
dot_sol_file = f .readlines ()
61
119
@@ -70,54 +128,54 @@ def get_compiled_contract_data(
70
128
71
129
contracts_in_file [filename ] = contract_names
72
130
73
-
74
- for dot_sol_filename in contracts_in_file . keys ():
75
- filename_no_extension = dot_sol_filename . replace ( ".sol" , "" )
76
- split_and_lowercase = [
77
- i . lower () for i in re . split ( r"([A-Z][a-z]*)" , filename_no_extension ) if i
78
- ]
79
- python_filename = f" { '_' . join (split_and_lowercase ) } .py"
80
- python_file_path = os . path . join ( os . getcwd (), "contract_data" , python_filename )
81
-
82
- try :
83
- # clean up existing files
84
- os . remove ( python_file_path )
85
- except FileNotFoundError :
86
- pass
87
-
88
- print ( f"compiling { dot_sol_filename } " )
89
- compiled_dot_sol_data = compile_dot_sol_files ( dot_sol_filename )
90
-
91
- with open ( python_file_path , "w" ) as f :
92
- f . write ( f'""" \n Generated by ` { os . path . basename ( __file__ ) } ` script. \n ' )
93
- f . write ( f'Compiled with Solidity v { solidity_version } . \n """ \n \n ' )
94
-
95
- for c in contracts_in_file [ dot_sol_filename ]:
96
- c_name_split_and_uppercase = [
97
- i . upper () for i in re . split ( r"([A-Z0-9][a-z0-9]*)" , c ) if i
98
- ]
99
- contract_upper = "_" . join ( c_name_split_and_uppercase )
100
-
101
- c_data = get_compiled_contract_data (
102
- compiled_dot_sol_data , dot_sol_filename , c
103
- )
104
-
105
- contract_source = (
106
- f"# source: web3/_utils/contract_sources/ { dot_sol_filename } : { c } "
107
- )
108
- if len ( contract_source ) > 88 :
109
- contract_source + = " # noqa: E501"
110
-
111
- f .write (f" { contract_source } \n " )
112
- f . write ( f '{ contract_upper } _BYTECODE = "{ c_data ["bin" ]} " # noqa: E501\n ')
113
- f . write (
114
- f' { contract_upper } _RUNTIME = " { c_data ["bin-runtime" ] } " # noqa: E501 \n '
115
- )
116
- f .write (f" { contract_upper } _ABI = { c_data [ 'abi' ] } \n " )
117
- f .write (contract_upper + "_DATA = { \n " )
118
- f .write (f' "bytecode ": { contract_upper } _BYTECODE ,\n ' )
119
- f . write ( f' "bytecode_runtime": { contract_upper } _RUNTIME, \n ' )
120
- f . write ( f' "abi": { contract_upper } _ABI, \n ' )
121
- f . write ( "} \n \n \n " )
122
-
131
+ for dot_sol_filename in contracts_in_file . keys ():
132
+ filename_no_extension = dot_sol_filename . replace ( ".sol" , "" )
133
+ split_and_lowercase = [
134
+ i . lower () for i in re . split ( r"([A-Z][a-z]*)" , filename_no_extension ) if i
135
+ ]
136
+ python_filename = f" { '_' . join ( split_and_lowercase ) } .py"
137
+ python_file_path = os . path . join (os . getcwd (), "contract_data" , python_filename )
138
+ try :
139
+ # clean up existing files
140
+ os . remove ( python_file_path )
141
+ except FileNotFoundError :
142
+ pass
143
+ print ( f"compiling { dot_sol_filename } " )
144
+ compiled_dot_sol_data = _compile_dot_sol_files ( dot_sol_filename )
145
+ with open ( python_file_path , "w" ) as f :
146
+ f . write ( f'""" \n Generated by ` { os . path . basename ( __file__ ) } ` script. \n ' )
147
+ f . write ( f'Compiled with Solidity v { solidity_version } . \n """ \n \n ' )
148
+
149
+ for c in contracts_in_file [ dot_sol_filename ] :
150
+ c_name_split_and_uppercase = [
151
+ i . upper () for i in re . split ( r"([A-Z0-9][a-z0-9]*)" , c ) if i
152
+ ]
153
+ contract_upper = "_" . join ( c_name_split_and_uppercase )
154
+
155
+ c_data = _get_compiled_contract_data (
156
+ compiled_dot_sol_data , dot_sol_filename , c
157
+ )
158
+
159
+ contract_source = (
160
+ f"# source: web3/_utils/contract_sources/ { dot_sol_filename } : { c } "
161
+ )
162
+ if len ( contract_source ) > 88 :
163
+ contract_source += " # noqa: E501"
164
+
165
+ f . write ( f" { contract_source } \n " )
166
+ f . write (
167
+ f' { contract_upper } _BYTECODE = "{ c_data [ "bin" ] } " # noqa: E501\n '
168
+ )
169
+ f .write (
170
+ f '{ contract_upper } _RUNTIME = "{ c_data ["bin-runtime " ]} " # noqa: E501\n '
171
+ )
172
+ f . write ( f" { contract_upper } _ABI = { c_data ['abi' ] } \n " )
173
+ f . write ( contract_upper + "_DATA = { \n " )
174
+ f .write (f' "bytecode": { contract_upper } _BYTECODE, \n ' )
175
+ f .write (f' "bytecode_runtime": { contract_upper } _RUNTIME, \n ' )
176
+ f .write (f' "abi ": { contract_upper } _ABI ,\n ' )
177
+ f . write ( "} \n \n \n " )
178
+
179
+
180
+ compile_files ( files_to_compile )
123
181
os .system (f"black { os .getcwd ()} " )
0 commit comments