1
0
mirror of https://github.com/lightning/bolts.git synced 2024-11-19 01:50:03 +01:00

tools: Update formatting of python tools

This commit is contained in:
Christian Decker 2017-07-11 11:29:12 +02:00
parent 22544d7789
commit d67a28227c
2 changed files with 84 additions and 48 deletions

View File

@ -1,19 +1,20 @@
#! /usr/bin/python3 #! /usr/bin/python3
# Simple script to parse specs and produce CSV files. # Simple script to parse specs and produce CSV files.
# Released by Rusty Russell under CC0: https://creativecommons.org/publicdomain/zero/1.0/ # Released by Rusty Russell under CC0:
# https://creativecommons.org/publicdomain/zero/1.0/
from optparse import OptionParser from optparse import OptionParser
import sys import sys
import re import re
import fileinput import fileinput
# Figure out if we can determine type from size.
def guess_alignment(message,name,sizestr):
# Figure out if we can determine type from size.
def guess_alignment(message, name, sizestr):
# Exceptions: # Exceptions:
# - Padding has no alignment requirements. # - Padding has no alignment requirements.
# - channel-id is size 8, but has alignment 4. # - channel-id is size 8, but has alignment 4.
# - node_announcement.ipv6 has size 16, but alignment 4 (to align IPv4 addr). # - node_announcement.ipv6 has size 16, but alignment 4 (to align IPv4).
# - node_announcement.alias is a string, so alignment 1 # - node_announcement.alias is a string, so alignment 1
# - signatures have no alignment requirement. # - signatures have no alignment requirement.
if name.startswith('pad'): if name.startswith('pad'):
@ -29,7 +30,7 @@ def guess_alignment(message,name,sizestr):
return 1 return 1
if 'signature' in name: if 'signature' in name:
return 1 return 1
# Size can be variable. # Size can be variable.
try: try:
@ -51,6 +52,7 @@ def guess_alignment(message,name,sizestr):
return 1 return 1
def main(options, args=None, output=sys.stdout, lines=None): def main(options, args=None, output=sys.stdout, lines=None):
# Example inputs: # Example inputs:
# 1. type: 17 (`error`) # 1. type: 17 (`error`)
@ -62,23 +64,28 @@ def main(options, args=None, output=sys.stdout, lines=None):
# 1. type: PERM|NODE|3 (`required_node_feature_missing`) # 1. type: PERM|NODE|3 (`required_node_feature_missing`)
message = None message = None
havedata = None havedata = None
typeline = re.compile('1\. type: (?P<value>[-0-9A-Za-z_|]+) \(`(?P<name>[A-Za-z_]+)`\)') typeline = re.compile(
dataline = re.compile('\s+\* \[`(?P<size>[_a-z0-9*+]+)`:`(?P<name>[_a-z0-9]+)`\]') '1\. type: (?P<value>[-0-9A-Za-z_|]+) \(`(?P<name>[A-Za-z_]+)`\)')
dataline = re.compile(
'\s+\* \[`(?P<size>[_a-z0-9*+]+)`:`(?P<name>[_a-z0-9]+)`\]')
if lines is None: if lines is None:
lines = fileinput.input(args) lines = fileinput.input(args)
for i,line in enumerate(lines): for i, line in enumerate(lines):
line = line.rstrip() line = line.rstrip()
linenum = i+1 linenum = i+1
match = typeline.fullmatch(line) match = typeline.fullmatch(line)
if match: if match:
if message is not None: if message is not None:
raise ValueError('{}:Found a message while I was already in a message'.format(linenum)) raise ValueError('{}:Found a message while I was already in a '
'message'.format(linenum))
message = match.group('name') message = match.group('name')
if options.output_types: if options.output_types:
print("{},{}".format(match.group('name'), match.group('value')), file=output) print("{},{}".format(
match.group('name'),
match.group('value')), file=output)
havedata = None havedata = None
alignoff = False alignoff = False
elif message is not None and havedata is None: elif message is not None and havedata is None:
@ -87,11 +94,11 @@ def main(options, args=None, output=sys.stdout, lines=None):
havedata = True havedata = True
dataoff = 0 dataoff = 0
off_extraterms = "" off_extraterms = ""
maxalign = 1
elif message is not None and havedata is not None: elif message is not None and havedata is not None:
match = dataline.fullmatch(line) match = dataline.fullmatch(line)
if match: if match:
align = guess_alignment(message, match.group('name'), match.group('size')) align = guess_alignment(message, match.group('name'),
match.group('size'))
# Do not check alignment if we previously had a variable # Do not check alignment if we previously had a variable
# length field in the message # length field in the message
@ -99,10 +106,21 @@ def main(options, args=None, output=sys.stdout, lines=None):
alignoff = True alignoff = True
if not alignoff and options.check_alignment and dataoff % align != 0: if not alignoff and options.check_alignment and dataoff % align != 0:
raise ValueError('{}:message {} field {} Offset {} not aligned on {} boundary:'.format(linenum, message, match.group('name'), dataoff, align)) raise ValueError('{}:message {} field {} Offset {} not '
'aligned on {} boundary:'.format(
linenum,
message,
match.group('name'),
dataoff,
align))
if options.output_fields: if options.output_fields:
print("{},{}{},{},{}".format(message,dataoff,off_extraterms,match.group('name'),match.group('size')), file=output) print("{},{}{},{},{}".format(
message,
dataoff,
off_extraterms,
match.group('name'),
match.group('size')), file=output)
# Size can be variable. # Size can be variable.
try: try:
@ -113,17 +131,30 @@ def main(options, args=None, output=sys.stdout, lines=None):
else: else:
message = None message = None
if __name__=="__main__":
if __name__ == "__main__":
parser = OptionParser() parser = OptionParser()
parser.add_option("--message-types", parser.add_option(
action="store_true", dest="output_types", default=False, "--message-types",
help="Output MESSAGENAME,VALUE for every message") action="store_true",
parser.add_option("--check-alignment", dest="output_types",
action="store_true", dest="check_alignment", default=False, default=False,
help="Check alignment for every member of each message") help="Output MESSAGENAME,VALUE for every message"
parser.add_option("--message-fields", )
action="store_true", dest="output_fields", default=False, parser.add_option(
help="Output MESSAGENAME,OFFSET,FIELDNAME,SIZE for every message") "--check-alignment",
action="store_true",
dest="check_alignment",
default=False,
help="Check alignment for every member of each message"
)
parser.add_option(
"--message-fields",
action="store_true",
dest="output_fields",
default=False,
help="Output MESSAGENAME,OFFSET,FIELDNAME,SIZE for every message"
)
(options, args) = parser.parse_args() (options, args) = parser.parse_args()

View File

@ -1,24 +1,28 @@
formats = __import__("extract-formats")
from io import StringIO from io import StringIO
import glob import glob
import collections import collections
import json import json
formats = __import__("extract-formats")
class Options(object): class Options(object):
output_types = True output_types = True
output_fields = True output_fields = True
check_alignment = False check_alignment = False
options = Options() options = Options()
csv = [] csv = []
output = StringIO() output = StringIO()
for i in sorted(glob.glob("../??-*.md")): for i in sorted(glob.glob("../??-*.md")):
with open(i) as f: with open(i) as f:
formats.main(options, output=output, lines=f.readlines()) formats.main(options, output=output, lines=f.readlines())
csvstr = output.getvalue().strip() csvstr = output.getvalue().strip()
if csvstr == "": continue if csvstr == "":
csv += csvstr.split("\n") continue
csv += csvstr.split("\n")
resmap = collections.OrderedDict() resmap = collections.OrderedDict()
@ -26,20 +30,21 @@ currentmsgname = None
currentmsgfields = {} currentmsgfields = {}
typenum = None typenum = None
for line in csv: for line in csv:
parts = line.split(",") parts = line.split(",")
if len(parts) == 2: if len(parts) == 2:
if currentmsgname is not None: if currentmsgname is not None:
resmap[currentmsgname] = collections.OrderedDict([("type", typenum), ("payload", currentmsgfields)]) resmap[currentmsgname] = collections.OrderedDict(
currentmsgfields = collections.OrderedDict() [("type", typenum), ("payload", currentmsgfields)])
currentmsgname = parts[0] currentmsgfields = collections.OrderedDict()
typenum = parts[1] currentmsgname = parts[0]
continue typenum = parts[1]
assert currentmsgname == parts[0], line continue
assert len(parts) == 4, line assert currentmsgname == parts[0], line
position = parts[1] assert len(parts) == 4, line
length = parts[3] position = parts[1]
fieldname = parts[2] length = parts[3]
currentmsgfields[fieldname] = {"position": position, "length": length} fieldname = parts[2]
currentmsgfields[fieldname] = {"position": position, "length": length}
if __name__ == "__main__": if __name__ == "__main__":
print(json.dumps(resmap, indent=True)) print(json.dumps(resmap, indent=True))