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
4
49
from typing import (
5
50
Any ,
6
51
)
7
52
8
53
import solcx
9
54
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
55
+ arg_parser = argparse . ArgumentParser ()
56
+ arg_parser . add_argument (
57
+ "-v" , "--version" , help = "Solidity version for compiling contracts."
58
+ )
59
+ arg_parser . add_argument (
60
+ "-f" ,
61
+ "--filename" ,
62
+ help = "(optional) The filename if only one file is to be compiled - "
63
+ "otherwise all .sol files will be compiled at once." ,
19
64
)
65
+ user_args = arg_parser .parse_args ()
20
66
67
+ CONFIGURED_SOLIDITY_VERSION = "0.8.17"
68
+ # establish Solidity version from user-provided arg or use hard-coded version
69
+ user_sol_version = user_args .version
21
70
71
+ solidity_version = user_sol_version if user_sol_version else CONFIGURED_SOLIDITY_VERSION
22
72
solcx .install_solc (solidity_version )
23
73
solcx .set_solc_version (solidity_version )
24
74
25
75
26
- def compile_dot_sol_files (dot_sol_filename : str ) -> dict [str , Any ]:
76
+ # compile just the .sol file specified or all .sol files
77
+ all_dot_sol_files = [f for f in os .listdir (os .getcwd ()) if f .endswith (".sol" )]
78
+ user_filename = user_args .filename
79
+ files_to_compile = [user_filename ] if user_filename else all_dot_sol_files
80
+
81
+
82
+ def _compile_dot_sol_files (dot_sol_filename : str ) -> dict [str , Any ]:
27
83
compiled = solcx .compile_files (
28
84
[f"./{ dot_sol_filename } " ],
29
85
output_values = ["abi" , "bin" , "bin-runtime" ],
30
86
)
31
87
return compiled
32
88
33
89
34
- def get_compiled_contract_data (
90
+ def _get_compiled_contract_data (
35
91
sol_file_output : dict [str , dict [str , str ]],
36
92
dot_sol_filename : str ,
37
93
contract_name : str = None ,
@@ -54,8 +110,9 @@ def get_compiled_contract_data(
54
110
55
111
contracts_in_file = {}
56
112
57
- for filename in os .listdir (os .getcwd ()):
58
- if ".sol" in filename :
113
+
114
+ def compile_files (file_list : list [str ]) -> None :
115
+ for filename in file_list :
59
116
with open (os .path .join (os .getcwd (), filename ), "r" ) as f :
60
117
dot_sol_file = f .readlines ()
61
118
@@ -70,54 +127,54 @@ def get_compiled_contract_data(
70
127
71
128
contracts_in_file [filename ] = contract_names
72
129
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
-
130
+ for dot_sol_filename in contracts_in_file . keys ():
131
+ filename_no_extension = dot_sol_filename . replace ( ".sol" , "" )
132
+ split_and_lowercase = [
133
+ i . lower () for i in re . split ( r"([A-Z][a-z]*)" , filename_no_extension ) if i
134
+ ]
135
+ python_filename = f" { '_' . join ( split_and_lowercase ) } .py"
136
+ python_file_path = os . path . join (os . getcwd (), "contract_data" , python_filename )
137
+ try :
138
+ # clean up existing files
139
+ os . remove ( python_file_path )
140
+ except FileNotFoundError :
141
+ pass
142
+ print ( f"compiling { dot_sol_filename } " )
143
+ compiled_dot_sol_data = _compile_dot_sol_files ( dot_sol_filename )
144
+ with open ( python_file_path , "w" ) as f :
145
+ f . write ( f'""" \n Generated by ` { os . path . basename ( __file__ ) } ` script. \n ' )
146
+ f . write ( f'Compiled with Solidity v { solidity_version } . \n """ \n \n ' )
147
+
148
+ for c in contracts_in_file [ dot_sol_filename ] :
149
+ c_name_split_and_uppercase = [
150
+ i . upper () for i in re . split ( r"([A-Z0-9][a-z0-9]*)" , c ) if i
151
+ ]
152
+ contract_upper = "_" . join ( c_name_split_and_uppercase )
153
+
154
+ c_data = _get_compiled_contract_data (
155
+ compiled_dot_sol_data , dot_sol_filename , c
156
+ )
157
+
158
+ contract_source = (
159
+ f"# source: web3/_utils/contract_sources/ { dot_sol_filename } : { c } "
160
+ )
161
+ if len ( contract_source ) > 88 :
162
+ contract_source += " # noqa: E501"
163
+
164
+ f . write ( f" { contract_source } \n " )
165
+ f . write (
166
+ f' { contract_upper } _BYTECODE = "{ c_data [ "bin" ] } " # noqa: E501\n '
167
+ )
168
+ f .write (
169
+ f '{ contract_upper } _RUNTIME = "{ c_data ["bin-runtime " ]} " # noqa: E501\n '
170
+ )
171
+ f . write ( f" { contract_upper } _ABI = { c_data ['abi' ] } \n " )
172
+ f . write ( contract_upper + "_DATA = { \n " )
173
+ f .write (f' "bytecode": { contract_upper } _BYTECODE, \n ' )
174
+ f .write (f' "bytecode_runtime": { contract_upper } _RUNTIME, \n ' )
175
+ f .write (f' "abi ": { contract_upper } _ABI ,\n ' )
176
+ f . write ( "} \n \n \n " )
177
+
178
+
179
+ compile_files ( files_to_compile )
123
180
os .system (f"black { os .getcwd ()} " )
0 commit comments