diff options
| author | whitespace <nobody@nobody> | 2020-10-07 17:22:26 -0400 | 
|---|---|---|
| committer | Quentin Young <qlyoung@nvidia.com> | 2020-10-07 17:22:26 -0400 | 
| commit | 701a01920eee5431d2052aad92aefbdf50ac2139 (patch) | |
| tree | 2bf2339327241f59593b9583b060ebb347db1cea /python | |
| parent | bd407b54d26981f30a95bc316ea2ed965d070c53 (diff) | |
*: reformat python files
We are now using black.
Signed-off-by: Quentin Young <qlyoung@nvidia.com>
Diffstat (limited to 'python')
| -rw-r--r-- | python/callgraph-dot.py | 195 | ||||
| -rw-r--r-- | python/clidef.py | 293 | ||||
| -rw-r--r-- | python/clippy/__init__.py | 29 | ||||
| -rw-r--r-- | python/firstheader.py | 14 | ||||
| -rw-r--r-- | python/makefile.py | 118 | ||||
| -rw-r--r-- | python/makevars.py | 48 | 
6 files changed, 419 insertions, 278 deletions
diff --git a/python/callgraph-dot.py b/python/callgraph-dot.py index 4faf1dae16..f80766a080 100644 --- a/python/callgraph-dot.py +++ b/python/callgraph-dot.py @@ -20,6 +20,7 @@ import re  import sys  import json +  class FunctionNode(object):      funcs = {} @@ -39,7 +40,7 @@ class FunctionNode(object):      def define(self, attrs):          self.defined = True -        self.defs.append((attrs['filename'], attrs['line'])) +        self.defs.append((attrs["filename"], attrs["line"]))          return self      def add_call(self, called, attrs): @@ -63,11 +64,12 @@ class FunctionNode(object):              return cls.funcs[name]          return FunctionNode(name) +  class CallEdge(object):      def __init__(self, i, o, attrs):          self.i = i          self.o = o -        self.is_external = attrs['is_external'] +        self.is_external = attrs["is_external"]          self.attrs = attrs          i.out.append(self) @@ -76,11 +78,13 @@ class CallEdge(object):      def __repr__(self):          return '<"%s()" -> "%s()">' % (self.i.name, self.o.name) +  def nameclean(n): -    if '.' in n: -        return n.split('.', 1)[0] +    if "." in n: +        return n.split(".", 1)[0]      return n +  def calc_rank(queue, direction):      nextq = queue @@ -98,7 +102,7 @@ def calc_rank(queue, direction):          queue = nextq          nextq = [] -        #sys.stderr.write('rank %d\n' % currank) +        # sys.stderr.write('rank %d\n' % currank)          cont = False @@ -123,6 +127,7 @@ def calc_rank(queue, direction):      return nextq +  class Graph(dict):      class Subgraph(set):          def __init__(self): @@ -166,6 +171,7 @@ class Graph(dict):          def calls(self):              return self._calls +          def calld(self):              return self._calld @@ -245,7 +251,7 @@ class Graph(dict):                      else:                          evalset.add(evnode) -            #if len(candidates) > 1: +            # if len(candidates) > 1:              #    for candidate in candidates:              #        if candidate != node:              #            #node.merge(candidate) @@ -266,7 +272,7 @@ class Graph(dict):          self._linear_nodes = []          while len(nodes): -            sys.stderr.write('%d\n' % len(nodes)) +            sys.stderr.write("%d\n" % len(nodes))              node = nodes.pop(0)              down[node] = set() @@ -304,106 +310,90 @@ class Graph(dict):          return self._subgraphs, self._linear_nodes -with open(sys.argv[1], 'r') as fd: +with open(sys.argv[1], "r") as fd:      data = json.load(fd)  extra_info = {      # zebra - LSP WQ -    ('lsp_processq_add', 'work_queue_add'): [ -        'lsp_process', -        'lsp_processq_del', -        'lsp_processq_complete', +    ("lsp_processq_add", "work_queue_add"): [ +        "lsp_process", +        "lsp_processq_del", +        "lsp_processq_complete",      ],      # zebra - main WQ -    ('mq_add_handler', 'work_queue_add'): [ -        'meta_queue_process', -    ], -    ('meta_queue_process', 'work_queue_add'): [ -        'meta_queue_process', -    ], +    ("mq_add_handler", "work_queue_add"): ["meta_queue_process",], +    ("meta_queue_process", "work_queue_add"): ["meta_queue_process",],      # bgpd - label pool WQ -    ('bgp_lp_get', 'work_queue_add'): [ -        'lp_cbq_docallback', -    ], -    ('bgp_lp_event_chunk', 'work_queue_add'): [ -        'lp_cbq_docallback', -    ], -    ('bgp_lp_event_zebra_up', 'work_queue_add'): [ -        'lp_cbq_docallback', -    ], +    ("bgp_lp_get", "work_queue_add"): ["lp_cbq_docallback",], +    ("bgp_lp_event_chunk", "work_queue_add"): ["lp_cbq_docallback",], +    ("bgp_lp_event_zebra_up", "work_queue_add"): ["lp_cbq_docallback",],      # bgpd - main WQ -    ('bgp_process', 'work_queue_add'): [ -        'bgp_process_wq', -        'bgp_processq_del', -    ], -    ('bgp_add_eoiu_mark', 'work_queue_add'): [ -        'bgp_process_wq', -        'bgp_processq_del', -    ], +    ("bgp_process", "work_queue_add"): ["bgp_process_wq", "bgp_processq_del",], +    ("bgp_add_eoiu_mark", "work_queue_add"): ["bgp_process_wq", "bgp_processq_del",],      # clear node WQ -    ('bgp_clear_route_table', 'work_queue_add'): [ -        'bgp_clear_route_node', -        'bgp_clear_node_queue_del', -        'bgp_clear_node_complete', +    ("bgp_clear_route_table", "work_queue_add"): [ +        "bgp_clear_route_node", +        "bgp_clear_node_queue_del", +        "bgp_clear_node_complete",      ],      # rfapi WQs -    ('rfapi_close', 'work_queue_add'): [ -        'rfapi_deferred_close_workfunc', -    ], -    ('rfapiRibUpdatePendingNode', 'work_queue_add'): [ -        'rfapiRibDoQueuedCallback', -        'rfapiRibQueueItemDelete', +    ("rfapi_close", "work_queue_add"): ["rfapi_deferred_close_workfunc",], +    ("rfapiRibUpdatePendingNode", "work_queue_add"): [ +        "rfapiRibDoQueuedCallback", +        "rfapiRibQueueItemDelete",      ],  } -for func, fdata in data['functions'].items(): +for func, fdata in data["functions"].items():      func = nameclean(func)      fnode = FunctionNode.get(func).define(fdata) -    for call in fdata['calls']: -        if call.get('type') in [None, 'unnamed', 'thread_sched']: -            if call.get('target') is None: +    for call in fdata["calls"]: +        if call.get("type") in [None, "unnamed", "thread_sched"]: +            if call.get("target") is None:                  continue -            tgt = nameclean(call['target']) +            tgt = nameclean(call["target"])              fnode.add_call(FunctionNode.get(tgt), call) -            for fptr in call.get('funcptrs', []): +            for fptr in call.get("funcptrs", []):                  fnode.add_call(FunctionNode.get(nameclean(fptr)), call) -            if tgt == 'work_queue_add': +            if tgt == "work_queue_add":                  if (func, tgt) not in extra_info: -                    sys.stderr.write('%s:%d:%s(): work_queue_add() not handled\n' % ( -                        call['filename'], call['line'], func)) +                    sys.stderr.write( +                        "%s:%d:%s(): work_queue_add() not handled\n" +                        % (call["filename"], call["line"], func) +                    )                  else:                      attrs = dict(call) -                    attrs.update({'is_external': False, 'type': 'workqueue'}) +                    attrs.update({"is_external": False, "type": "workqueue"})                      for dst in extra_info[func, tgt]:                          fnode.add_call(FunctionNode.get(dst), call) -        elif call['type'] == 'install_element': -            vty_node = FunctionNode.get('VTY_NODE_%d' % call['vty_node']) -            vty_node.add_call(FunctionNode.get(nameclean(call['target'])), call) -        elif call['type'] == 'hook': +        elif call["type"] == "install_element": +            vty_node = FunctionNode.get("VTY_NODE_%d" % call["vty_node"]) +            vty_node.add_call(FunctionNode.get(nameclean(call["target"])), call) +        elif call["type"] == "hook":              # TODO: edges for hooks from data['hooks']              pass  n = FunctionNode.funcs  # fix some very low end functions cycling back very far to the top -if 'peer_free' in n: -    n['peer_free'].unlink(n['bgp_timer_set']) -    n['peer_free'].unlink(n['bgp_addpath_set_peer_type']) -if 'bgp_path_info_extra_free' in n: -    n['bgp_path_info_extra_free'].rank = 0 +if "peer_free" in n: +    n["peer_free"].unlink(n["bgp_timer_set"]) +    n["peer_free"].unlink(n["bgp_addpath_set_peer_type"]) +if "bgp_path_info_extra_free" in n: +    n["bgp_path_info_extra_free"].rank = 0 -if 'zlog_ref' in n: -    n['zlog_ref'].rank = 0 -if 'mt_checkalloc' in n: -    n['mt_checkalloc'].rank = 0 +if "zlog_ref" in n: +    n["zlog_ref"].rank = 0 +if "mt_checkalloc" in n: +    n["mt_checkalloc"].rank = 0  queue = list(FunctionNode.funcs.values())  queue = calc_rank(queue, 1)  queue = calc_rank(queue, -1) -sys.stderr.write('%d functions in cyclic set\n' % len(queue)) +sys.stderr.write("%d functions in cyclic set\n" % len(queue))  graph = Graph(queue)  graph.automerge() @@ -411,10 +401,12 @@ graph.automerge()  gv_nodes = []  gv_edges = [] -sys.stderr.write('%d groups after automerge\n' % len(graph._groups)) +sys.stderr.write("%d groups after automerge\n" % len(graph._groups)) +  def is_vnc(n): -    return n.startswith('rfapi') or n.startswith('vnc') or ('_vnc_' in n) +    return n.startswith("rfapi") or n.startswith("vnc") or ("_vnc_" in n) +  _vncstyle = ',fillcolor="#ffffcc",style=filled'  cyclic_set_names = set([fn.name for fn in graph.values()]) @@ -422,55 +414,76 @@ cyclic_set_names = set([fn.name for fn in graph.values()])  for i, group in enumerate(graph._groups):      if len(group) > 1:          group.num = i -        gv_nodes.append('\tsubgraph cluster_%d {' % i) -        gv_nodes.append('\t\tcolor=blue;') +        gv_nodes.append("\tsubgraph cluster_%d {" % i) +        gv_nodes.append("\t\tcolor=blue;")          for gn in group:              has_cycle_callers = set(gn.calld()) - group -            has_ext_callers = set([edge.i.name for edge in gn._fn.inb]) - cyclic_set_names +            has_ext_callers = ( +                set([edge.i.name for edge in gn._fn.inb]) - cyclic_set_names +            ) -            style = '' -            etext = '' +            style = "" +            etext = ""              if is_vnc(gn.name):                  style += _vncstyle              if has_cycle_callers: -                style += ',color=blue,penwidth=3' +                style += ",color=blue,penwidth=3"              if has_ext_callers:                  style += ',fillcolor="#ffeebb",style=filled' -                etext += '<br/><font point-size="10">(%d other callers)</font>' % (len(has_ext_callers)) - -            gv_nodes.append('\t\t"%s" [shape=box,label=<%s%s>%s];' % (gn.name, '<br/>'.join([fn.name for fn in gn._fns]), etext, style)) -        gv_nodes.append('\t}') +                etext += '<br/><font point-size="10">(%d other callers)</font>' % ( +                    len(has_ext_callers) +                ) + +            gv_nodes.append( +                '\t\t"%s" [shape=box,label=<%s%s>%s];' +                % (gn.name, "<br/>".join([fn.name for fn in gn._fns]), etext, style) +            ) +        gv_nodes.append("\t}")      else:          for gn in group: -            has_ext_callers = set([edge.i.name for edge in gn._fn.inb]) - cyclic_set_names +            has_ext_callers = ( +                set([edge.i.name for edge in gn._fn.inb]) - cyclic_set_names +            ) -            style = '' -            etext = '' +            style = "" +            etext = ""              if is_vnc(gn.name):                  style += _vncstyle              if has_ext_callers:                  style += ',fillcolor="#ffeebb",style=filled' -                etext += '<br/><font point-size="10">(%d other callers)</font>' % (len(has_ext_callers)) -            gv_nodes.append('\t"%s" [shape=box,label=<%s%s>%s];' % (gn.name, '<br/>'.join([fn.name for fn in gn._fns]), etext, style)) +                etext += '<br/><font point-size="10">(%d other callers)</font>' % ( +                    len(has_ext_callers) +                ) +            gv_nodes.append( +                '\t"%s" [shape=box,label=<%s%s>%s];' +                % (gn.name, "<br/>".join([fn.name for fn in gn._fns]), etext, style) +            )  edges = set()  for gn in graph.values():      for calls in gn.calls():          if gn._group == calls._group: -            gv_edges.append('\t"%s" -> "%s" [color="#55aa55",style=dashed];' % (gn.name, calls.name)) +            gv_edges.append( +                '\t"%s" -> "%s" [color="#55aa55",style=dashed];' % (gn.name, calls.name) +            )          else: +              def xname(nn):                  if len(nn._group) > 1: -                    return 'cluster_%d' % nn._group.num +                    return "cluster_%d" % nn._group.num                  else:                      return nn.name +              tup = xname(gn), calls.name              if tup[0] != tup[1] and tup not in edges:                  gv_edges.append('\t"%s" -> "%s" [weight=0.0,w=0.0,color=blue];' % tup)                  edges.add(tup) -with open(sys.argv[2], 'w') as fd: -    fd.write('''digraph { +with open(sys.argv[2], "w") as fd: +    fd.write( +        """digraph {      node [fontsize=13,fontname="Fira Sans"];  %s -}''' % '\n'.join(gv_nodes + [''] + gv_edges)) +}""" +        % "\n".join(gv_nodes + [""] + gv_edges) +    ) diff --git a/python/clidef.py b/python/clidef.py index baa6ed52b2..a47cee2d6b 100644 --- a/python/clidef.py +++ b/python/clidef.py @@ -26,39 +26,49 @@ from io import StringIO  # the various handlers generate output C code for a particular type of  # CLI token, choosing the most useful output C type. +  class RenderHandler(object):      def __init__(self, token):          pass +      def combine(self, other):          if type(self) == type(other):              return other          return StringHandler(None) -    deref = '' +    deref = ""      drop_str = False      canfail = True      canassert = False +  class StringHandler(RenderHandler): -    argtype = 'const char *' -    decl = Template('const char *$varname = NULL;') -    code = Template('$varname = (argv[_i]->type == WORD_TKN) ? argv[_i]->text : argv[_i]->arg;') +    argtype = "const char *" +    decl = Template("const char *$varname = NULL;") +    code = Template( +        "$varname = (argv[_i]->type == WORD_TKN) ? argv[_i]->text : argv[_i]->arg;" +    )      drop_str = True      canfail = False      canassert = True +  class LongHandler(RenderHandler): -    argtype = 'long' -    decl = Template('long $varname = 0;') -    code = Template('''\ +    argtype = "long" +    decl = Template("long $varname = 0;") +    code = Template( +        """\  char *_end;  $varname = strtol(argv[_i]->arg, &_end, 10); -_fail = (_end == argv[_i]->arg) || (*_end != '\\0');''') +_fail = (_end == argv[_i]->arg) || (*_end != '\\0');""" +    ) +  # A.B.C.D/M (prefix_ipv4) and  # X:X::X:X/M (prefix_ipv6) are "compatible" and can merge into a  # struct prefix: +  class PrefixBase(RenderHandler):      def combine(self, other):          if type(self) == type(other): @@ -66,23 +76,33 @@ class PrefixBase(RenderHandler):          if isinstance(other, PrefixBase):              return PrefixGenHandler(None)          return StringHandler(None) -    deref = '&' + +    deref = "&" + +  class Prefix4Handler(PrefixBase): -    argtype = 'const struct prefix_ipv4 *' -    decl = Template('struct prefix_ipv4 $varname = { };') -    code = Template('_fail = !str2prefix_ipv4(argv[_i]->arg, &$varname);') +    argtype = "const struct prefix_ipv4 *" +    decl = Template("struct prefix_ipv4 $varname = { };") +    code = Template("_fail = !str2prefix_ipv4(argv[_i]->arg, &$varname);") + +  class Prefix6Handler(PrefixBase): -    argtype = 'const struct prefix_ipv6 *' -    decl = Template('struct prefix_ipv6 $varname = { };') -    code = Template('_fail = !str2prefix_ipv6(argv[_i]->arg, &$varname);') +    argtype = "const struct prefix_ipv6 *" +    decl = Template("struct prefix_ipv6 $varname = { };") +    code = Template("_fail = !str2prefix_ipv6(argv[_i]->arg, &$varname);") + +  class PrefixEthHandler(PrefixBase): -    argtype = 'struct prefix_eth *' -    decl = Template('struct prefix_eth $varname = { };') -    code = Template('_fail = !str2prefix_eth(argv[_i]->arg, &$varname);') +    argtype = "struct prefix_eth *" +    decl = Template("struct prefix_eth $varname = { };") +    code = Template("_fail = !str2prefix_eth(argv[_i]->arg, &$varname);") + +  class PrefixGenHandler(PrefixBase): -    argtype = 'const struct prefix *' -    decl = Template('struct prefix $varname = { };') -    code = Template('_fail = !str2prefix(argv[_i]->arg, &$varname);') +    argtype = "const struct prefix *" +    decl = Template("struct prefix $varname = { };") +    code = Template("_fail = !str2prefix(argv[_i]->arg, &$varname);") +  # same for IP addresses.  result is union sockunion.  class IPBase(RenderHandler): @@ -92,18 +112,27 @@ class IPBase(RenderHandler):          if type(other) in [IP4Handler, IP6Handler, IPGenHandler]:              return IPGenHandler(None)          return StringHandler(None) + +  class IP4Handler(IPBase): -    argtype = 'struct in_addr' -    decl = Template('struct in_addr $varname = { INADDR_ANY };') -    code = Template('_fail = !inet_aton(argv[_i]->arg, &$varname);') +    argtype = "struct in_addr" +    decl = Template("struct in_addr $varname = { INADDR_ANY };") +    code = Template("_fail = !inet_aton(argv[_i]->arg, &$varname);") + +  class IP6Handler(IPBase): -    argtype = 'struct in6_addr' -    decl = Template('struct in6_addr $varname = {};') -    code = Template('_fail = !inet_pton(AF_INET6, argv[_i]->arg, &$varname);') +    argtype = "struct in6_addr" +    decl = Template("struct in6_addr $varname = {};") +    code = Template("_fail = !inet_pton(AF_INET6, argv[_i]->arg, &$varname);") + +  class IPGenHandler(IPBase): -    argtype = 'const union sockunion *' -    decl = Template('''union sockunion s__$varname = { .sa.sa_family = AF_UNSPEC }, *$varname = NULL;''') -    code = Template('''\ +    argtype = "const union sockunion *" +    decl = Template( +        """union sockunion s__$varname = { .sa.sa_family = AF_UNSPEC }, *$varname = NULL;""" +    ) +    code = Template( +        """\  if (argv[_i]->text[0] == 'X') {  	s__$varname.sa.sa_family = AF_INET6;  	_fail = !inet_pton(AF_INET6, argv[_i]->arg, &s__$varname.sin6.sin6_addr); @@ -112,26 +141,30 @@ if (argv[_i]->text[0] == 'X') {  	s__$varname.sa.sa_family = AF_INET;  	_fail = !inet_aton(argv[_i]->arg, &s__$varname.sin.sin_addr);  	$varname = &s__$varname; -}''') +}""" +    )      canassert = True +  def mix_handlers(handlers):      def combine(a, b):          if a is None:              return b          return a.combine(b) +      return reduce(combine, handlers, None) +  handlers = { -    'WORD_TKN':         StringHandler, -    'VARIABLE_TKN':     StringHandler, -    'RANGE_TKN':        LongHandler, -    'IPV4_TKN':         IP4Handler, -    'IPV4_PREFIX_TKN':  Prefix4Handler, -    'IPV6_TKN':         IP6Handler, -    'IPV6_PREFIX_TKN':  Prefix6Handler, -    'MAC_TKN':          PrefixEthHandler, -    'MAC_PREFIX_TKN':   PrefixEthHandler, +    "WORD_TKN": StringHandler, +    "VARIABLE_TKN": StringHandler, +    "RANGE_TKN": LongHandler, +    "IPV4_TKN": IP4Handler, +    "IPV4_PREFIX_TKN": Prefix4Handler, +    "IPV6_TKN": IP6Handler, +    "IPV6_PREFIX_TKN": Prefix6Handler, +    "MAC_TKN": PrefixEthHandler, +    "MAC_PREFIX_TKN": PrefixEthHandler,  }  # core template invoked for each occurence of DEFPY. @@ -139,7 +172,8 @@ handlers = {  # the "#if $..." bits are there to keep this template unified into one  # common form, without requiring a more advanced template engine (e.g.  # jinja2) -templ = Template('''/* $fnname => "$cmddef" */ +templ = Template( +    """/* $fnname => "$cmddef" */  DEFUN_CMD_FUNC_DECL($fnname)  #define funcdecl_$fnname static int ${fnname}_magic(\\  	const struct cmd_element *self __attribute__ ((unused)),\\ @@ -178,18 +212,22 @@ $argassert  	return ${fnname}_magic(self, vty, argc, argv$arglist);  } -''') +""" +)  # invoked for each named parameter -argblock = Template(''' +argblock = Template( +    """  		if (!strcmp(argv[_i]->varname, \"$varname\")) {$strblock  			$code -		}''') +		}""" +) -def get_always_args(token, always_args, args = [], stack = []): + +def get_always_args(token, always_args, args=[], stack=[]):      if token in stack:          return -    if token.type == 'END_TKN': +    if token.type == "END_TKN":          for arg in list(always_args):              if arg not in args:                  always_args.remove(arg) @@ -201,38 +239,45 @@ def get_always_args(token, always_args, args = [], stack = []):      for nexttkn in token.next():          get_always_args(nexttkn, always_args, args, stack) +  class Macros(dict):      def load(self, filename):          filedata = clippy.parse(filename) -        for entry in filedata['data']: -            if entry['type'] != 'PREPROC': +        for entry in filedata["data"]: +            if entry["type"] != "PREPROC":                  continue -            ppdir = entry['line'].lstrip().split(None, 1) -            if ppdir[0] != 'define' or len(ppdir) != 2: +            ppdir = entry["line"].lstrip().split(None, 1) +            if ppdir[0] != "define" or len(ppdir) != 2:                  continue              ppdef = ppdir[1].split(None, 1)              name = ppdef[0] -            if '(' in name: +            if "(" in name:                  continue -            val = ppdef[1] if len(ppdef) == 2 else '' +            val = ppdef[1] if len(ppdef) == 2 else "" -            val = val.strip(' \t\n\\') +            val = val.strip(" \t\n\\")              if name in self: -                sys.stderr.write('warning: macro %s redefined!\n' % (name)) +                sys.stderr.write("warning: macro %s redefined!\n" % (name))              self[name] = val +  def process_file(fn, ofd, dumpfd, all_defun, macros):      errors = 0      filedata = clippy.parse(fn) -    for entry in filedata['data']: -        if entry['type'].startswith('DEFPY') or (all_defun and entry['type'].startswith('DEFUN')): -            if len(entry['args'][0]) != 1: -                sys.stderr.write('%s:%d: DEFPY function name not parseable (%r)\n' % (fn, entry['lineno'], entry['args'][0])) +    for entry in filedata["data"]: +        if entry["type"].startswith("DEFPY") or ( +            all_defun and entry["type"].startswith("DEFUN") +        ): +            if len(entry["args"][0]) != 1: +                sys.stderr.write( +                    "%s:%d: DEFPY function name not parseable (%r)\n" +                    % (fn, entry["lineno"], entry["args"][0]) +                )                  errors += 1                  continue -            cmddef = entry['args'][2] +            cmddef = entry["args"][2]              cmddefx = []              for i in cmddef:                  while i in macros: @@ -241,13 +286,16 @@ def process_file(fn, ofd, dumpfd, all_defun, macros):                      cmddefx.append(i[1:-1])                      continue -                sys.stderr.write('%s:%d: DEFPY command string not parseable (%r)\n' % (fn, entry['lineno'], cmddef)) +                sys.stderr.write( +                    "%s:%d: DEFPY command string not parseable (%r)\n" +                    % (fn, entry["lineno"], cmddef) +                )                  errors += 1                  cmddefx = None                  break              if cmddefx is None:                  continue -            cmddef = ''.join([i for i in cmddefx]) +            cmddef = "".join([i for i in cmddefx])              graph = clippy.Graph(cmddef)              args = OrderedDict() @@ -263,12 +311,12 @@ def process_file(fn, ofd, dumpfd, all_defun, macros):              get_always_args(graph.first(), always_args) -            #print('-' * 76) -            #pprint(entry) -            #clippy.dump(graph) -            #pprint(args) +            # print('-' * 76) +            # pprint(entry) +            # clippy.dump(graph) +            # pprint(args) -            params = { 'cmddef': cmddef, 'fnname': entry['args'][0][0] } +            params = {"cmddef": cmddef, "fnname": entry["args"][0][0]}              argdefs = []              argdecls = []              arglist = [] @@ -277,63 +325,96 @@ def process_file(fn, ofd, dumpfd, all_defun, macros):              doc = []              canfail = 0 -            def do_add(handler, basename, varname, attr = ''): -                argdefs.append(',\\\n\t%s %s%s' % (handler.argtype, varname, attr)) -                argdecls.append('\t%s\n' % (handler.decl.substitute({'varname': varname}).replace('\n', '\n\t'))) -                arglist.append(', %s%s' % (handler.deref, varname)) +            def do_add(handler, basename, varname, attr=""): +                argdefs.append(",\\\n\t%s %s%s" % (handler.argtype, varname, attr)) +                argdecls.append( +                    "\t%s\n" +                    % ( +                        handler.decl.substitute({"varname": varname}).replace( +                            "\n", "\n\t" +                        ) +                    ) +                ) +                arglist.append(", %s%s" % (handler.deref, varname))                  if basename in always_args and handler.canassert: -                    argassert.append('''\tif (!%s) { +                    argassert.append( +                        """\tif (!%s) {  \t\tvty_out(vty, "Internal CLI error [%%s]\\n", "%s");  \t\treturn CMD_WARNING; -\t}\n''' % (varname, varname)) -                if attr == '': +\t}\n""" +                        % (varname, varname) +                    ) +                if attr == "":                      at = handler.argtype -                    if not at.startswith('const '): -                        at = '. . . ' + at -                    doc.append('\t%-26s %s  %s' % (at, 'alw' if basename in always_args else 'opt', varname)) +                    if not at.startswith("const "): +                        at = ". . . " + at +                    doc.append( +                        "\t%-26s %s  %s" +                        % (at, "alw" if basename in always_args else "opt", varname) +                    )              for varname in args.keys():                  handler = mix_handlers(args[varname]) -                #print(varname, handler) -                if handler is None: continue +                # print(varname, handler) +                if handler is None: +                    continue                  do_add(handler, varname, varname) -                code = handler.code.substitute({'varname': varname}).replace('\n', '\n\t\t\t') +                code = handler.code.substitute({"varname": varname}).replace( +                    "\n", "\n\t\t\t" +                )                  if handler.canfail:                      canfail = 1 -                strblock = '' +                strblock = ""                  if not handler.drop_str: -                    do_add(StringHandler(None), varname, '%s_str' % (varname), ' __attribute__ ((unused))') -                    strblock = '\n\t\t\t%s_str = argv[_i]->arg;' % (varname) -                argblocks.append(argblock.substitute({'varname': varname, 'strblock': strblock, 'code': code})) +                    do_add( +                        StringHandler(None), +                        varname, +                        "%s_str" % (varname), +                        " __attribute__ ((unused))", +                    ) +                    strblock = "\n\t\t\t%s_str = argv[_i]->arg;" % (varname) +                argblocks.append( +                    argblock.substitute( +                        {"varname": varname, "strblock": strblock, "code": code} +                    ) +                )              if dumpfd is not None:                  if len(arglist) > 0: -                    dumpfd.write('"%s":\n%s\n\n' % (cmddef, '\n'.join(doc))) +                    dumpfd.write('"%s":\n%s\n\n' % (cmddef, "\n".join(doc)))                  else:                      dumpfd.write('"%s":\n\t---- no magic arguments ----\n\n' % (cmddef)) -            params['argdefs'] = ''.join(argdefs) -            params['argdecls'] = ''.join(argdecls) -            params['arglist'] = ''.join(arglist) -            params['argblocks'] = ''.join(argblocks) -            params['canfail'] = canfail -            params['nonempty'] = len(argblocks) -            params['argassert'] = ''.join(argassert) +            params["argdefs"] = "".join(argdefs) +            params["argdecls"] = "".join(argdecls) +            params["arglist"] = "".join(arglist) +            params["argblocks"] = "".join(argblocks) +            params["canfail"] = canfail +            params["nonempty"] = len(argblocks) +            params["argassert"] = "".join(argassert)              ofd.write(templ.substitute(params))      return errors -if __name__ == '__main__': + +if __name__ == "__main__":      import argparse -    argp = argparse.ArgumentParser(description = 'FRR CLI preprocessor in Python') -    argp.add_argument('--all-defun', action = 'store_const', const = True, -            help = 'process DEFUN() statements in addition to DEFPY()') -    argp.add_argument('--show', action = 'store_const', const = True, -            help = 'print out list of arguments and types for each definition') -    argp.add_argument('-o', type = str, metavar = 'OUTFILE', -            help = 'output C file name') -    argp.add_argument('cfile', type = str) +    argp = argparse.ArgumentParser(description="FRR CLI preprocessor in Python") +    argp.add_argument( +        "--all-defun", +        action="store_const", +        const=True, +        help="process DEFUN() statements in addition to DEFPY()", +    ) +    argp.add_argument( +        "--show", +        action="store_const", +        const=True, +        help="print out list of arguments and types for each definition", +    ) +    argp.add_argument("-o", type=str, metavar="OUTFILE", help="output C file name") +    argp.add_argument("cfile", type=str)      args = argp.parse_args()      dumpfd = None @@ -349,15 +430,17 @@ if __name__ == '__main__':      basepath = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))      macros = Macros() -    macros.load('lib/route_types.h') -    macros.load(os.path.join(basepath, 'lib/command.h')) -    macros.load(os.path.join(basepath, 'bgpd/bgp_vty.h')) +    macros.load("lib/route_types.h") +    macros.load(os.path.join(basepath, "lib/command.h")) +    macros.load(os.path.join(basepath, "bgpd/bgp_vty.h"))      # sigh :( -    macros['PROTO_REDIST_STR'] = 'FRR_REDIST_STR_ISISD' +    macros["PROTO_REDIST_STR"] = "FRR_REDIST_STR_ISISD"      errors = process_file(args.cfile, ofd, dumpfd, args.all_defun, macros)      if errors != 0:          sys.exit(1)      if args.o is not None: -        clippy.wrdiff(args.o, ofd, [args.cfile, os.path.realpath(__file__), sys.executable]) +        clippy.wrdiff( +            args.o, ofd, [args.cfile, os.path.realpath(__file__), sys.executable] +        ) diff --git a/python/clippy/__init__.py b/python/clippy/__init__.py index 41aeae6b4d..d6865ff484 100644 --- a/python/clippy/__init__.py +++ b/python/clippy/__init__.py @@ -20,11 +20,12 @@ import os, stat  import _clippy  from _clippy import parse, Graph, GraphNode +  def graph_iterate(graph): -    '''iterator yielding all nodes of a graph +    """iterator yielding all nodes of a graph      nodes arrive in input/definition order, graph circles are avoided. -    ''' +    """      queue = [(graph.first(), frozenset(), 0)]      while len(queue) > 0: @@ -42,21 +43,25 @@ def graph_iterate(graph):              if n not in stop and n is not node:                  queue.insert(0, (n, stop, depth + 1)) +  def dump(graph): -    '''print out clippy.Graph''' +    """print out clippy.Graph"""      for i, depth in graph_iterate(graph): -        print('\t%s%s %r' % ('  ' * (depth * 2), i.type, i.text)) +        print("\t%s%s %r" % ("  " * (depth * 2), i.type, i.text)) + -def wrdiff(filename, buf, reffiles = []): -    '''write buffer to file if contents changed''' +def wrdiff(filename, buf, reffiles=[]): +    """write buffer to file if contents changed""" -    expl = '' -    if hasattr(buf, 'getvalue'): +    expl = "" +    if hasattr(buf, "getvalue"):          buf = buf.getvalue()      old = None -    try:    old = open(filename, 'r').read() -    except: pass +    try: +        old = open(filename, "r").read() +    except: +        pass      if old == buf:          for reffile in reffiles:              # ensure output timestamp is newer than inputs, for make @@ -67,7 +72,7 @@ def wrdiff(filename, buf, reffiles = []):          # sys.stderr.write('%s unchanged, not written\n' % (filename))          return -    newname = '%s.new-%d' % (filename, os.getpid()) -    with open(newname, 'w') as out: +    newname = "%s.new-%d" % (filename, os.getpid()) +    with open(newname, "w") as out:          out.write(buf)      os.rename(newname, filename) diff --git a/python/firstheader.py b/python/firstheader.py index 19a85b63e5..bf50f33a33 100644 --- a/python/firstheader.py +++ b/python/firstheader.py @@ -9,21 +9,21 @@ include_re = re.compile('^#\s*include\s+["<]([^ ">]+)[">]', re.M)  errors = 0 -files = subprocess.check_output(['git', 'ls-files']).decode('ASCII') +files = subprocess.check_output(["git", "ls-files"]).decode("ASCII")  for fn in files.splitlines(): -    if not fn.endswith('.c'): +    if not fn.endswith(".c"):          continue -    if fn.startswith('tools/'): +    if fn.startswith("tools/"):          continue -    with open(fn, 'r') as fd: +    with open(fn, "r") as fd:          data = fd.read()          m = include_re.search(data)          if m is None: -            #sys.stderr.write('no #include in %s?\n' % (fn)) +            # sys.stderr.write('no #include in %s?\n' % (fn))              continue -        if m.group(1) in ['config.h', 'zebra.h', 'lib/zebra.h']: +        if m.group(1) in ["config.h", "zebra.h", "lib/zebra.h"]:              continue -        sys.stderr.write('%s: %s\n' % (fn, m.group(0))) +        sys.stderr.write("%s: %s\n" % (fn, m.group(0)))          errors += 1  if errors: diff --git a/python/makefile.py b/python/makefile.py index fe20945ccc..10c73df72d 100644 --- a/python/makefile.py +++ b/python/makefile.py @@ -13,69 +13,91 @@ import argparse  from string import Template  from makevars import MakeReVars -argp = argparse.ArgumentParser(description = 'FRR Makefile extensions') -argp.add_argument('--dev-build', action = 'store_const', const = True, -            help = 'run additional developer checks') +argp = argparse.ArgumentParser(description="FRR Makefile extensions") +argp.add_argument( +    "--dev-build", +    action="store_const", +    const=True, +    help="run additional developer checks", +)  args = argp.parse_args() -with open('Makefile', 'r') as fd: +with open("Makefile", "r") as fd:      before = fd.read()  mv = MakeReVars(before) -clippy_scan = mv['clippy_scan'].strip().split() +clippy_scan = mv["clippy_scan"].strip().split()  for clippy_file in clippy_scan: -    assert clippy_file.endswith('.c') +    assert clippy_file.endswith(".c")  # check for files using clippy but not listed in clippy_scan  if args.dev_build:      basepath = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) -    if os.path.exists(os.path.join(basepath, '.git')): -        clippy_ref = subprocess.check_output([ -            'git', '-C', basepath, 'grep', '-l', '-P', '^#\s*include.*_clippy.c', '--', '**.c']).decode('US-ASCII') +    if os.path.exists(os.path.join(basepath, ".git")): +        clippy_ref = subprocess.check_output( +            [ +                "git", +                "-C", +                basepath, +                "grep", +                "-l", +                "-P", +                "^#\s*include.*_clippy.c", +                "--", +                "**.c", +            ] +        ).decode("US-ASCII")          clippy_ref = set(clippy_ref.splitlines())          missing = clippy_ref - set(clippy_scan)          if len(missing) > 0: -            sys.stderr.write('error: files seem to be using clippy, but not listed in "clippy_scan" in subdir.am:\n\t%s\n' % ('\n\t'.join(sorted(missing)))) +            sys.stderr.write( +                'error: files seem to be using clippy, but not listed in "clippy_scan" in subdir.am:\n\t%s\n' +                % ("\n\t".join(sorted(missing))) +            )              sys.exit(1) -clippydep = Template(''' +clippydep = Template( +    """  ${clippybase}.$$(OBJEXT): ${clippybase}_clippy.c  ${clippybase}.lo: ${clippybase}_clippy.c -${clippybase}_clippy.c: $$(CLIPPY_DEPS)''') +${clippybase}_clippy.c: $$(CLIPPY_DEPS)""" +) -clippyauxdep = Template('''# clippy{ +clippyauxdep = Template( +    """# clippy{  # auxiliary clippy target  ${target}: ${clippybase}_clippy.c -# }clippy''') +# }clippy""" +)  lines = before.splitlines() -autoderp = '#AUTODERP# ' +autoderp = "#AUTODERP# "  out_lines = []  bcdeps = [] -make_rule_re = re.compile('^([^:\s]+):\s*([^:\s]+)\s*($|\n)') +make_rule_re = re.compile("^([^:\s]+):\s*([^:\s]+)\s*($|\n)")  while lines:      line = lines.pop(0)      if line.startswith(autoderp): -        line = line[len(autoderp):] +        line = line[len(autoderp) :] -    if line == '# clippy{': +    if line == "# clippy{":          while lines:              line = lines.pop(0) -            if line == '# }clippy': +            if line == "# }clippy":                  break          continue -    if line.startswith('#'): +    if line.startswith("#"):          out_lines.append(line)          continue      full_line = line      full_lines = lines[:] -    while full_line.endswith('\\'): +    while full_line.endswith("\\"):          full_line = full_line[:-1] + full_lines.pop(0)      m = make_rule_re.match(full_line) @@ -87,43 +109,51 @@ while lines:      target, dep = m.group(1), m.group(2) -    if target.endswith('.lo') or target.endswith('.o'): -        if not dep.endswith('.h'): -            bcdeps.append('%s.bc: %s' % (target, target)) -            bcdeps.append('\t$(AM_V_LLVM_BC)$(COMPILE) -emit-llvm -c -o $@ %s' % (dep)) +    if target.endswith(".lo") or target.endswith(".o"): +        if not dep.endswith(".h"): +            bcdeps.append("%s.bc: %s" % (target, target)) +            bcdeps.append("\t$(AM_V_LLVM_BC)$(COMPILE) -emit-llvm -c -o $@ %s" % (dep))      if m.group(2) in clippy_scan: -        out_lines.append(clippyauxdep.substitute(target=m.group(1), clippybase=m.group(2)[:-2])) +        out_lines.append( +            clippyauxdep.substitute(target=m.group(1), clippybase=m.group(2)[:-2]) +        )      out_lines.append(line) -out_lines.append('# clippy{\n# main clippy targets') +out_lines.append("# clippy{\n# main clippy targets")  for clippy_file in clippy_scan: -    out_lines.append(clippydep.substitute(clippybase = clippy_file[:-2])) +    out_lines.append(clippydep.substitute(clippybase=clippy_file[:-2])) -out_lines.append('') +out_lines.append("")  out_lines.extend(bcdeps) -out_lines.append('') +out_lines.append("")  bc_targets = [] -for varname in ['bin_PROGRAMS', 'sbin_PROGRAMS', 'lib_LTLIBRARIES', 'module_LTLIBRARIES', 'noinst_LIBRARIES']: +for varname in [ +    "bin_PROGRAMS", +    "sbin_PROGRAMS", +    "lib_LTLIBRARIES", +    "module_LTLIBRARIES", +    "noinst_LIBRARIES", +]:      bc_targets.extend(mv[varname].strip().split())  for target in bc_targets: -    amtgt = target.replace('/', '_').replace('.', '_').replace('-', '_') -    objs = mv[amtgt + '_OBJECTS'].strip().split() -    objs = [obj + '.bc' for obj in objs] -    deps = mv.get(amtgt + '_DEPENDENCIES', '').strip().split() -    deps = [d + '.bc' for d in deps if d.endswith('.a')] +    amtgt = target.replace("/", "_").replace(".", "_").replace("-", "_") +    objs = mv[amtgt + "_OBJECTS"].strip().split() +    objs = [obj + ".bc" for obj in objs] +    deps = mv.get(amtgt + "_DEPENDENCIES", "").strip().split() +    deps = [d + ".bc" for d in deps if d.endswith(".a")]      objs.extend(deps) -    out_lines.append('%s.bc: %s' % (target, ' '.join(objs))) -    out_lines.append('\t$(AM_V_LLVM_LD)$(LLVM_LINK) -o $@ $^') -    out_lines.append('') +    out_lines.append("%s.bc: %s" % (target, " ".join(objs))) +    out_lines.append("\t$(AM_V_LLVM_LD)$(LLVM_LINK) -o $@ $^") +    out_lines.append("") -out_lines.append('# }clippy') -out_lines.append('') +out_lines.append("# }clippy") +out_lines.append("") -after = '\n'.join(out_lines) +after = "\n".join(out_lines)  if after == before:      sys.exit(0) -with open('Makefile.pyout', 'w') as fd: +with open("Makefile.pyout", "w") as fd:      fd.write(after) -os.rename('Makefile.pyout', 'Makefile') +os.rename("Makefile.pyout", "Makefile") diff --git a/python/makevars.py b/python/makevars.py index 63bf8c5eeb..951cd3438b 100644 --- a/python/makevars.py +++ b/python/makevars.py @@ -6,10 +6,12 @@ import os  import subprocess  import re +  class MakeVarsBase(object): -    ''' +    """      common code between MakeVars and MakeReVars -    ''' +    """ +      def __init__(self):          self._data = dict() @@ -18,31 +20,35 @@ class MakeVarsBase(object):              self.getvars([k])          return self._data[k] -    def get(self, k, defval = None): +    def get(self, k, defval=None):          if k not in self._data:              self.getvars([k])          return self._data.get(k) or defval +  class MakeVars(MakeVarsBase): -    ''' +    """      makevars['FOO_CFLAGS'] gets you "FOO_CFLAGS" from Makefile      This variant works by invoking make as a subprocess, i.e. Makefile must      be valid and working.  (This is sometimes a problem if depfiles have not      been generated.) -    ''' +    """ +      def getvars(self, varlist): -        ''' +        """          get a batch list of variables from make.  faster than individual calls. -        ''' +        """          rdfd, wrfd = os.pipe() -        shvars = ['shvar-%s' % s for s in varlist] -        make = subprocess.Popen(['make', '-s', 'VARFD=%d' % wrfd] + shvars, pass_fds = [wrfd]) +        shvars = ["shvar-%s" % s for s in varlist] +        make = subprocess.Popen( +            ["make", "-s", "VARFD=%d" % wrfd] + shvars, pass_fds=[wrfd] +        )          os.close(wrfd) -        data = b'' +        data = b"" -        rdf = os.fdopen(rdfd, 'rb') +        rdf = os.fdopen(rdfd, "rb")          while True:              rdata = rdf.read()              if len(rdata) == 0: @@ -52,30 +58,34 @@ class MakeVars(MakeVarsBase):          del rdf          make.wait() -        data = data.decode('US-ASCII').strip().split('\n') +        data = data.decode("US-ASCII").strip().split("\n")          for row in data: -            k, v = row.split('=', 1) +            k, v = row.split("=", 1)              v = v[1:-1]              self._data[k] = v +  class MakeReVars(MakeVarsBase): -    ''' +    """      makevars['FOO_CFLAGS'] gets you "FOO_CFLAGS" from Makefile      This variant works by regexing through Makefile.  This means the Makefile      does not need to be fully working, but on the other hand it doesn't support      fancy complicated make expressions. -    ''' -    var_re = re.compile(r'^([^=#\n\s]+)[ \t]*=[ \t]*([^#\n]*)(?:#.*)?$', flags=re.MULTILINE) -    repl_re = re.compile(r'\$(?:([A-Za-z])|\(([^\)]+)\))') +    """ + +    var_re = re.compile( +        r"^([^=#\n\s]+)[ \t]*=[ \t]*([^#\n]*)(?:#.*)?$", flags=re.MULTILINE +    ) +    repl_re = re.compile(r"\$(?:([A-Za-z])|\(([^\)]+)\))")      def __init__(self, maketext):          super(MakeReVars, self).__init__() -        self._vars = dict(self.var_re.findall(maketext.replace('\\\n', ''))) +        self._vars = dict(self.var_re.findall(maketext.replace("\\\n", "")))      def replacevar(self, match):          varname = match.group(1) or match.group(2) -        return self._vars.get(varname, '') +        return self._vars.get(varname, "")      def getvars(self, varlist):          for varname in varlist:  | 
