github.com/muhammedhassanm/blockchain@v0.0.0-20200120143007-697261defd4d/sawtooth-core-master/bin/protogen (about) 1 #!/usr/bin/env python3 2 # 3 # Copyright 2017 Intel Corporation 4 # 5 # Licensed under the Apache License, Version 2.0 (the "License"); 6 # you may not use this file except in compliance with the License. 7 # You may obtain a copy of the License at 8 # 9 # http://www.apache.org/licenses/LICENSE-2.0 10 # 11 # Unless required by applicable law or agreed to in writing, software 12 # distributed under the License is distributed on an "AS IS" BASIS, 13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 # See the License for the specific language governing permissions and 15 # limitations under the License. 16 # ------------------------------------------------------------------------------ 17 18 import os 19 import tempfile 20 from glob import glob 21 import re 22 import subprocess 23 import sys 24 25 26 try: 27 from grpc.tools.protoc import main as _protoc 28 except ImportError: 29 print("Error: grpc.tools.protoc not found") 30 exit(1) 31 32 33 JOIN = os.path.join 34 TOP_DIR = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) 35 36 37 def main(args=None): 38 if args is None: 39 args = sys.argv[1:] 40 # 1. Generate and distribute top-level protos 41 proto_dir = JOIN(TOP_DIR, "protos") 42 43 protoc(proto_dir, "sdk/python", "sawtooth_sdk/protobuf") 44 protoc(proto_dir, "cli", "sawtooth_cli/protobuf") 45 protoc(proto_dir, "validator", "sawtooth_validator/protobuf") 46 protoc(proto_dir, "rest_api", "sawtooth_rest_api/protobuf") 47 protoc(proto_dir, "families/settings", "sawtooth_settings/protobuf") 48 protoc(proto_dir, "families/identity", "sawtooth_identity/protobuf") 49 protoc(proto_dir, "families/block_info", "sawtooth_block_info/protobuf") 50 51 if "javascript" in args: 52 protoc(proto_dir, "sdk/javascript", "protobuf", "javascript") 53 54 if "go" in args: 55 protoc(proto_dir, "sdk/go/src", "sawtooth_sdk/protobuf", "go") 56 57 # 2. Generate config protos 58 proto_dir = JOIN(TOP_DIR, "families/settings/protos") 59 protoc(proto_dir, "families/settings", "sawtooth_settings/protobuf") 60 protoc(proto_dir, "cli", "sawtooth_cli/protobuf") 61 62 # 3. Generate PoET protos 63 proto_dir = \ 64 JOIN( 65 TOP_DIR, 66 "consensus/poet/families/sawtooth_validator_registry/protos") 67 protoc(proto_dir, "consensus/poet/common", "sawtooth_poet_common/protobuf") 68 69 # 5. Generate identity protos 70 proto_dir = JOIN(TOP_DIR, "families/identity/protos") 71 protoc(proto_dir, "families/identity", "sawtooth_identity/protobuf") 72 protoc(proto_dir, "cli", "sawtooth_cli/protobuf") 73 74 # 6. Generate block info protos 75 proto_dir = JOIN(TOP_DIR, "families/block_info/protos") 76 protoc(proto_dir, "families/block_info", "sawtooth_block_info/protobuf") 77 78 # 7. Generate smallbank protos 79 if "go" in args: 80 proto_dir = JOIN(TOP_DIR, "families/smallbank/protos") 81 protoc(proto_dir, "families/smallbank", 82 "smallbank_go/src/protobuf", "go") 83 84 85 def protoc(src_dir, base_dir, pkg, language="python"): 86 if language == "python": 87 protoc_python(src_dir, base_dir, pkg) 88 elif language == "go": 89 protoc_go(src_dir, base_dir, pkg) 90 elif language == "javascript": 91 protoc_javascript(src_dir, base_dir, pkg) 92 93 94 def protoc_python(src_dir, base_dir, pkg): 95 # 1. Create output package directory 96 pkg_dir = JOIN(TOP_DIR, base_dir, pkg) 97 os.makedirs(pkg_dir, exist_ok=True) 98 99 # 2. 'touch' the __init__.py file if the output directory exists 100 init_py = JOIN(pkg_dir, "__init__.py") 101 if not os.path.exists(init_py): 102 with open(init_py, "w") as fd: 103 pass # Just need it to exist 104 105 # 3. Create a temp directory for building 106 with tempfile.TemporaryDirectory() as tmp_dir: 107 tmp_pkg_dir = JOIN(tmp_dir, pkg) 108 os.makedirs(tmp_pkg_dir) 109 110 # 4. Get a list of all .proto files to build 111 cwd = os.getcwd() 112 os.chdir(src_dir) 113 proto_files = glob("*.proto") 114 os.chdir(cwd) 115 116 # 5. Copy protos to temp dir and fix imports 117 for proto in proto_files: 118 src = JOIN(src_dir, proto) 119 dst = JOIN(tmp_pkg_dir, proto) 120 with open(src, encoding='utf-8') as fin: 121 with open(dst, "w", encoding='utf-8') as fout: 122 src_contents = fin.read() 123 fixed_contents = fix_import(src_contents, pkg) 124 fout.write(fixed_contents) 125 126 # 6. Compile protobuf files 127 _protoc([ 128 __file__, 129 "-I=%s" % tmp_dir, 130 "--python_out=%s" % JOIN(TOP_DIR, base_dir), 131 ] + glob("%s/*.proto" % tmp_pkg_dir)) 132 133 134 def protoc_javascript(src_dir, base_dir, pkg): 135 pkg_dir = JOIN(TOP_DIR, base_dir, pkg) 136 os.makedirs(pkg_dir, exist_ok=True) 137 138 with open(JOIN(pkg_dir, 'protobuf_bundle.json'), 'w') as out: 139 p = subprocess.Popen( 140 ['node', 'compile_protobuf.js'], 141 cwd=JOIN(TOP_DIR, base_dir), 142 stdout=out) 143 ret_code = p.wait() 144 out.flush() 145 146 if ret_code != 0: 147 raise AssertionError('Unable to compile protobuf messages for JS!') 148 149 150 def protoc_go(src_dir, base_dir, pkg): 151 # 1. Get a list of all .proto files to build 152 cwd = os.getcwd() 153 os.chdir(src_dir) 154 proto_files = glob("*.proto") 155 os.chdir(cwd) 156 157 # 2. Create a temp directory for building 158 with tempfile.TemporaryDirectory() as tmp_dir: 159 defer = [] 160 161 # 3. In order to have each protobuf file in its own namespace, 162 # directories need to be created for all of them and the .proto file 163 # copied in 164 for proto_file in proto_files: 165 proto = proto_file[:-6] 166 167 sub_pkg = JOIN(pkg, proto) 168 tmp_pkg_dir = JOIN(tmp_dir, sub_pkg + "_pb2") 169 os.makedirs(tmp_pkg_dir) 170 171 src = JOIN(src_dir, proto_file) 172 dst = JOIN(tmp_pkg_dir, proto_file) 173 with open(src, encoding='utf-8') as fin: 174 with open(dst, "w", encoding='utf-8') as fout: 175 src_contents = fin.read() 176 fixed_contents = fix_import( 177 src_contents, pkg, sub_dir=True) 178 fout.write(fixed_contents) 179 180 # Need to defer until the whole directory is setup 181 defer.append([ 182 __file__, 183 "-I=%s" % tmp_dir, 184 "--go_out=%s" % JOIN(TOP_DIR, base_dir), 185 "%s" % dst 186 ]) 187 188 for args in defer: 189 _protoc(args) 190 191 192 def fix_import(contents, pkg, sub_dir=False): 193 pattern = r'^import "(.*)\.proto\"' 194 if sub_dir: 195 template = r'import "%s/\1_pb2/\1.proto"' 196 else: 197 template = r'import "%s/\1.proto"' 198 199 return re.sub( 200 pattern, 201 lambda match: match.expand(template) % pkg, 202 contents, 203 flags=re.MULTILINE) 204 205 206 if __name__ == "__main__": 207 try: 208 main() 209 except KeyboardInterrupt: 210 exit(1)