-
Notifications
You must be signed in to change notification settings - Fork 1
/
flattener.py
executable file
·86 lines (75 loc) · 3.18 KB
/
flattener.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#!/usr/bin/python3
import ast
import os
import sys
class Flattener:
def __init__(self, start):
self.file_stack = []
self.file_set = set()
self.contracts_dirs = ['', 'contracts', 'node_modules']
self.license_dirs = ['', '..']
self.license_files = ['LICENSE', 'license', 'LICENSE.MD', 'LICENSE.md', 'license.md']
self.project_root = start[0:start.rfind("contracts")]
self.add_contract(os.path.abspath(start))
def get_contract_path(self, fdir, contract_str):
cp = os.path.abspath(os.path.join(fdir, contract_str))
if os.path.exists(cp):
return cp
for contract_dir in self.contracts_dirs:
cp = os.path.abspath(os.path.join(contract_dir, contract_str))
if os.path.exists(cp):
return cp
for contract_dir in self.contracts_dirs:
cp = os.path.abspath(os.path.join(self.project_root, contract_dir, contract_str))
if os.path.exists(cp):
return cp
raise FileNotFoundError(contract_str)
def get_license_path(self, contract_dir):
for cd in self.contracts_dirs:
dest_dir = contract_dir[0:contract_dir.rfind(cd)]
for d in self.license_dirs:
p = os.path.join(dest_dir, cd, d)
for f in self.license_files:
ret = os.path.abspath(os.path.join(p, f))
if os.path.exists(ret):
return ret
def add_contract(self, contract_path):
self.file_stack.append((os.path.dirname(contract_path), open(contract_path, "r")))
self.file_set.add(os.path.basename(contract_path))
def run(self):
(main_contract_dir, _) = self.file_stack[-1]
lp = self.get_license_path(main_contract_dir)
if lp is not None:
print("/*")
with open(lp, "r") as fh:
print(fh.read()
.replace("/*", "\\/*")
.replace("*/", "*\\/"))
print("*/")
print()
# This script uses a file handle to keep the position where it processing when it recurse :(
while self.file_stack:
# Files are iterators themselves
(fdir, fh) = self.file_stack[-1]
for line in fh:
if line.startswith("import "):
include = line.strip().split()[-1].rstrip(';')
contract_str = ast.literal_eval(include)
contract = os.path.basename(contract_str)
if contract not in self.file_set:
contract_path = self.get_contract_path(fdir, contract_str)
self.add_contract(contract_path)
break
# add only the original pragmas
if line.startswith("pragma") and len(self.file_stack) != 1:
continue
if line.startswith("// SPDX"):
continue
print(line, end='')
else:
print()
self.file_stack.pop()
if len(sys.argv) != 2:
sys.exit("Usage: python3 flattener.py FILEPATH")
flattener = Flattener(sys.argv[1])
flattener.run()