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
147import os
248import re
3- import sys
449from typing import (
550 Any ,
651)
752
853import solcx
954
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." ,
1964)
65+ user_args = arg_parser .parse_args ()
2066
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
2170
71+ solidity_version = user_sol_version if user_sol_version else CONFIGURED_SOLIDITY_VERSION
2272solcx .install_solc (solidity_version )
2373solcx .set_solc_version (solidity_version )
2474
2575
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 ]:
2783 compiled = solcx .compile_files (
2884 [f"./{ dot_sol_filename } " ],
2985 output_values = ["abi" , "bin" , "bin-runtime" ],
3086 )
3187 return compiled
3288
3389
34- def get_compiled_contract_data (
90+ def _get_compiled_contract_data (
3591 sol_file_output : dict [str , dict [str , str ]],
3692 dot_sol_filename : str ,
3793 contract_name : str = None ,
@@ -54,8 +110,9 @@ def get_compiled_contract_data(
54110
55111contracts_in_file = {}
56112
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 :
59116 with open (os .path .join (os .getcwd (), filename ), "r" ) as f :
60117 dot_sol_file = f .readlines ()
61118
@@ -70,54 +127,54 @@ def get_compiled_contract_data(
70127
71128 contracts_in_file [filename ] = contract_names
72129
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 )
123180os .system (f"black { os .getcwd ()} " )
0 commit comments