2020-03-04 04:23:09 +00:00
|
|
|
import argparse
|
|
|
|
import olefile
|
2020-03-04 06:29:02 +00:00
|
|
|
import re
|
2020-03-04 08:31:46 +00:00
|
|
|
import json
|
|
|
|
import copy
|
2020-03-04 04:23:09 +00:00
|
|
|
|
2020-03-04 08:38:19 +00:00
|
|
|
def parse(input, json_format, **kwargs):
|
2020-03-04 04:23:09 +00:00
|
|
|
fullPath = input
|
|
|
|
|
|
|
|
blah = olefile.OleFileIO(fullPath)
|
|
|
|
stream = blah.openstream('FileHeader')
|
2020-03-04 08:31:46 +00:00
|
|
|
|
|
|
|
# split binary stream into lines using a repeated 5 byte signature
|
2020-03-04 06:29:02 +00:00
|
|
|
pattern = re.compile(b'.{3}\x00\x00\|')
|
2020-03-04 08:31:46 +00:00
|
|
|
lines = pattern.split(stream.read()[5:-1]) # lopping off first 4 bytes, and last byte, since they don't seem to matter?
|
2020-03-04 06:29:02 +00:00
|
|
|
|
2020-03-04 08:31:46 +00:00
|
|
|
schematic = {}
|
|
|
|
|
|
|
|
datums = []
|
|
|
|
|
|
|
|
# loop through every "line" and parse each into a dictionary
|
2020-03-04 06:29:02 +00:00
|
|
|
for line in lines:
|
2020-03-04 08:31:46 +00:00
|
|
|
datum = {}
|
2020-03-04 06:29:02 +00:00
|
|
|
pairs = line.split(b"|")
|
|
|
|
|
|
|
|
for pair in pairs:
|
|
|
|
data = pair.split(b"=")
|
|
|
|
|
2020-03-04 08:31:46 +00:00
|
|
|
datum[data[0].decode()] = data[1].decode()
|
2020-03-04 06:29:02 +00:00
|
|
|
|
2020-03-04 08:31:46 +00:00
|
|
|
datums.append(datum)
|
2020-03-04 06:29:02 +00:00
|
|
|
|
2020-03-04 08:31:46 +00:00
|
|
|
# separate out the header dictionary from the "records" dictionaries
|
|
|
|
schematic["header"] = [x for x in datums if 'HEADER' in x.keys()]
|
|
|
|
schematic["records"] = [x for x in datums if 'RECORD' in x.keys()]
|
|
|
|
|
|
|
|
# prep a scratchpad copy of records to build hierarchy from
|
|
|
|
records_copy = copy.deepcopy(schematic["records"])
|
|
|
|
schematic["hierarchy"] = []
|
|
|
|
|
|
|
|
# loop through all "records" and organize them into owner/children
|
|
|
|
for i, current in enumerate(records_copy):
|
|
|
|
current['index'] = i
|
|
|
|
s = current.get("OWNERINDEX")
|
|
|
|
if (s is None):
|
|
|
|
schematic["hierarchy"].append(current)
|
|
|
|
else:
|
|
|
|
ownerIndex = int(s)
|
|
|
|
|
|
|
|
owner = records_copy[ownerIndex]
|
|
|
|
if (owner.get("children") == None):
|
|
|
|
owner["children"] = []
|
|
|
|
|
|
|
|
owner["children"].append(current)
|
|
|
|
|
|
|
|
if json_format == 'hierarchy':
|
|
|
|
schematic["records"] = schematic["hierarchy"]
|
|
|
|
|
|
|
|
schematic.pop("hierarchy", None)
|
|
|
|
|
2020-03-04 08:34:33 +00:00
|
|
|
return schematic
|
|
|
|
|
2020-03-04 04:23:09 +00:00
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
parser = argparse.ArgumentParser(description='Converts Altium .SchDoc files into json.')
|
|
|
|
parser.add_argument('--input', '-i', dest='input',
|
2020-03-04 08:31:46 +00:00
|
|
|
help='path/to/altiumschematic.schdoc file to parse')
|
2020-03-04 04:23:09 +00:00
|
|
|
parser.add_argument('--output', '-o', dest='output',
|
2020-03-04 08:31:46 +00:00
|
|
|
help='path/to/jsonfile.json file to output json to, otherwise prints to terminal')
|
|
|
|
parser.add_argument('json_format', default='hierarchy', nargs='?', choices=['flat', 'hierarchy'],
|
|
|
|
help='Organize records into owner/child "hierarchy" or leave as a "flat" list.')
|
2020-03-04 04:23:09 +00:00
|
|
|
|
|
|
|
args = parser.parse_args()
|
2020-03-04 08:34:33 +00:00
|
|
|
schematic = parse(**vars(args))
|
|
|
|
|
|
|
|
if args.output:
|
|
|
|
json_file = open(args.output, 'w')
|
|
|
|
json.dump(schematic, json_file)
|
|
|
|
else:
|
|
|
|
print(schematic)
|