Soft Patch Panel
 help / color / mirror / Atom feed
From: Yasufumi Ogawa <yasufum.o@gmail.com>
To: spp@dpdk.org, ferruh.yigit@intel.com, yasufum.o@gmail.com
Subject: [spp] [PATCH 2/8] cli: revise composing dot script
Date: Mon, 12 Aug 2019 16:12:36 +0900	[thread overview]
Message-ID: <20190812071242.18934-3-yasufum.o@gmail.com> (raw)
In-Reply-To: <20190812071242.18934-1-yasufum.o@gmail.com>

SppTopo uses old style formatter, such as '"%s %s" % (foo, var)', for
composing dot script. It could be complex if several placeholders are
included in a string. It is better to replace latest style using
format() method.

This update is to replace all formatters for using format(), and use
labels in placeholders to be more understandable.

Signed-off-by: Yasufumi Ogawa <yasufum.o@gmail.com>
---
 src/cli/commands/topo.py | 93 +++++++++++++++++++++-------------------
 1 file changed, 50 insertions(+), 43 deletions(-)

diff --git a/src/cli/commands/topo.py b/src/cli/commands/topo.py
index 58c59d1..0d613cb 100644
--- a/src/cli/commands/topo.py
+++ b/src/cli/commands/topo.py
@@ -77,7 +77,7 @@ class SppTopo(object):
         error_codes = self.spp_ctl_cli.rest_common_error_codes
 
         for sec_id in sec_ids:
-            res = self.spp_ctl_cli.get('nfvs/%d' % sec_id)
+            res = self.spp_ctl_cli.get('nfvs/{sid}'.format(sid=sec_id))
             if res.status_code == 200:
                 res_ary.append(res.json())
             elif res.status_code in error_codes:
@@ -99,7 +99,7 @@ class SppTopo(object):
         error_codes = self.spp_ctl_cli.rest_common_error_codes
 
         for sec_id in sec_ids:
-            res = self.spp_ctl_cli.get('nfvs/%d' % sec_id)
+            res = self.spp_ctl_cli.get('nfvs/{sid}'.format(sid=sec_id))
             if res.status_code == 200:
                 res_ary.append(res.json())
             elif res.status_code in error_codes:
@@ -120,10 +120,11 @@ class SppTopo(object):
         else:
             print("Invalid file type")
             return res_ary
-        print("Create topology: '%s'" % fname)
+        print("Create topology: '{fname}'".format(fname=fname))
         return res_ary
 
     def to_dot(self, sec_list, output_fname):
+        """Output dot script."""
 
         # Graphviz params
         # TODO(yasufum) consider to move gviz params to config file.
@@ -142,7 +143,7 @@ class SppTopo(object):
 
         node_attrs = 'node[shape="rectangle", style="filled"];'
 
-        node_template = '%s' + self.delim_node + '%s'
+        node_template = '{}' + self.delim_node + '{}'
 
         phys = []
         rings = []
@@ -170,7 +171,8 @@ class SppTopo(object):
                         pass
                     else:
                         raise ValueError(
-                            "Invaid interface type: %s" % r_type)
+                            "Invaid interface type: {rtype}".format(
+                                rtype=r_type))
 
             for patch in sec['patches']:
                 if sec['status'] == 'running':
@@ -182,18 +184,18 @@ class SppTopo(object):
                     SEC_COLORS[sec["client-id"]],
                     l_style
                 )
-                link_style = node_template + ' %s ' + node_template + '%s;'
+                link_style = node_template + ' {} ' + node_template + '{};'
 
                 if self._is_valid_port(patch['src']):
                     src_type, src_id = patch['src'].split(':')
                 if self._is_valid_port(patch['dst']):
                     dst_type, dst_id = patch['dst'].split(':')
 
-                tmp = link_style % (src_type, src_id, LINK_TYPE,
+                tmp = link_style.format(src_type, src_id, LINK_TYPE,
                                     dst_type, dst_id, attrs)
                 links.append(tmp)
 
-        output = ["%s spp{" % GRAPH_TYPE]
+        output = ["{} spp{{".format(GRAPH_TYPE)]
         output.append("newrank=true;")
         output.append(node_attrs)
 
@@ -201,65 +203,65 @@ class SppTopo(object):
         for node in phys:
             r_type, r_id = node.split(':')
             phy_nodes.append(
-                node_template % (r_type, r_id))
+                node_template.format(r_type, r_id))
         phy_nodes = list(set(phy_nodes))
         for node in phy_nodes:
-            label = re.sub(r'%s' % self.delim_node, ':', node)
+            label = re.sub(r'{}'.format(self.delim_node), ':', node)
             output.append(
-                '%s[label="%s", fillcolor="%s"];' % (
-                    node, label, PORT_COLORS["phy"]))
+                '{n}[label="{l}", fillcolor="{c}"];'.format(
+                    n=node, l=label, c=PORT_COLORS["phy"]))
 
         ring_nodes = []
         for node in rings:
             r_type, r_id = node.split(':')
-            ring_nodes.append(node_template % (r_type, r_id))
+            ring_nodes.append(node_template.format(r_type, r_id))
         ring_nodes = list(set(ring_nodes))
         for node in ring_nodes:
-            label = re.sub(r'%s' % self.delim_node, ':', node)
+            label = re.sub(r'{}'.format(self.delim_node), ':', node)
             output.append(
-                '%s[label="%s", fillcolor="%s"];' % (
-                    node, label, PORT_COLORS["ring"]))
+                '{n}[label="{l}", fillcolor="{c}"];'.format(
+                    n=node, l=label, c=PORT_COLORS["ring"]))
 
         vhost_nodes = []
         for node in vhosts:
             r_type, r_id = node.split(':')
-            vhost_nodes.append(node_template % (r_type, r_id))
+            vhost_nodes.append(node_template.format(r_type, r_id))
         vhost_nodes = list(set(vhost_nodes))
         for node in vhost_nodes:
-            label = re.sub(r'%s' % self.delim_node, ':', node)
+            label = re.sub(r'{}'.format(self.delim_node), ':', node)
             output.append(
-                '%s[label="%s", fillcolor="%s"];' % (
-                    node, label, PORT_COLORS["vhost"]))
+                '{n}[label="{l}", fillcolor="{c}"];'.format(
+                    n=node, l=label, c=PORT_COLORS["vhost"]))
 
         # Align the same type of nodes with rank attribute
         output.append(
-            '{rank=same; %s}' % ("; ".join(ring_nodes)))
+            '{{rank=same; {rn}}}'.format(rn="; ".join(ring_nodes)))
         output.append(
-            '{rank=same; %s}' % ("; ".join(vhost_nodes)))
+            '{{rank=same; {vn}}}'.format(vn="; ".join(vhost_nodes)))
 
         # Decide the bottom, phy or vhost
-        rank_style = '{rank=max; %s}' % node_template
+        rank_style = '{{rank=max; ' + node_template + '}}'
         if len(phys) > 0:
             r_type, r_id = phys[0].split(':')
         elif len(vhosts) > 0:
             r_type, r_id = vhosts[0].split(':')
-        output.append(rank_style % (r_type, r_id))
+        output.append(rank_style.format(r_type, r_id))
 
         # TODO(yasufum) check if it is needed, or is not needed for vhost_nodes
         if len(phy_nodes) > 0:
             output.append(
-                '{rank=same; %s}' % ("; ".join(phy_nodes)))
+                '{{rank=same; {pn}}}'.format(pn="; ".join(phy_nodes)))
 
         # Add subgraph
         ssgs = []
         if len(self.subgraphs) > 0:
             cnt = 1
             for label, val in self.subgraphs.items():
-                cluster_id = "cluster%d" % cnt
+                cluster_id = "cluster{}".format(cnt)
                 ssg_label = label
                 ssg_ports = re.sub(r'%s' % ':', self.delim_node, val)
-                ssg = 'subgraph %s {label="%s" %s}' % (
-                    cluster_id, ssg_label, ssg_ports)
+                ssg = 'subgraph {cid} {{label="{ssgl}" {ssgp}}}'.format(
+                    cid=cluster_id, ssgl=ssg_label, ssgp=ssg_ports)
                 ssgs.append(ssg)
                 cnt += 1
 
@@ -268,13 +270,14 @@ class SppTopo(object):
         sg_ports = "; ".join(phy_nodes + ring_nodes)
         if len(ssgs) == 0:
             output.append(
-                'subgraph %s {label="%s" %s}' % (
-                    cluster_id, sg_label, sg_ports))
+                'subgraph {cid} {{label="{sgl}" {sgp}}}'.format(
+                    cid=cluster_id, sgl=sg_label, sgp=sg_ports))
         else:
-            tmp = 'label="%s" %s' % (sg_label, sg_ports)
+            tmp = 'label="{sgl}" {sgp}'.format(sgl=sg_label, sgp=sg_ports)
             contents = [tmp] + ssgs
             output.append(
-                'subgraph %s {%s}' % (cluster_id, '; '.join(contents)))
+                'subgraph {cid} {{{cont}}}'.format(
+                    cid=cluster_id, cont='; '.join(contents)))
 
         # Add links
         for link in links:
@@ -299,19 +302,21 @@ class SppTopo(object):
         f.close()
 
     def to_img(self, sec_list, output_fname):
-        tmpfile = "%s.dot" % uuid.uuid4().hex
+        tmpfile = "{fn}.dot".format(fn=uuid.uuid4().hex)
         self.to_dot(sec_list, tmpfile)
         fmt = output_fname.split(".")[-1]
-        cmd = "dot -T%s %s -o %s" % (fmt, tmpfile, output_fname)
+        cmd = "dot -T{fmt} {dotf} -o {of}".format(
+                fmt=fmt, dotf=tmpfile, of=output_fname)
         subprocess.call(cmd, shell=True)
-        subprocess.call("rm -f %s" % tmpfile, shell=True)
+        subprocess.call("rm -f {tmpf}".format(tmpf=tmpfile), shell=True)
 
     def to_http(self, sec_list):
         import websocket
-        tmpfile = "%s.dot" % uuid.uuid4().hex
+        tmpfile = "{fn}.dot".format(fn=uuid.uuid4().hex)
         self.to_dot(sec_list, tmpfile)
         msg = open(tmpfile).read()
-        subprocess.call("rm -f %s" % tmpfile, shell=True)
+        subprocess.call("rm -f {tmpf}".format(tmpf=tmpfile), shell=True)
+        # TODO(yasufum) change to be able to use other than `localhost`.
         ws_url = "ws://localhost:8989/spp_ws"
         try:
             ws = websocket.create_connection(ws_url)
@@ -321,7 +326,7 @@ class SppTopo(object):
             print('Error: Connection refused! Is running websocket server?')
 
     def to_term(self, sec_list, size):
-        tmpfile = "%s.jpg" % uuid.uuid4().hex
+        tmpfile = "{fn}.jpg".format(fn=uuid.uuid4().hex)
         self.to_img(sec_list, tmpfile)
         from distutils import spawn
 
@@ -329,8 +334,8 @@ class SppTopo(object):
         if spawn.find_executable("img2sixel") is not None:
             img_cmd = "img2sixel"
         else:
-            imgcat = "%s/%s/imgcat" % (
-                os.path.dirname(__file__), '3rd_party')
+            imgcat = "{pdir}/{sdir}/imgcat".format(
+                pdir=os.path.dirname(__file__), sdir='3rd_party')
             if os.path.exists(imgcat) is True:
                 img_cmd = imgcat
             else:
@@ -339,15 +344,17 @@ class SppTopo(object):
         if img_cmd is not None:
             # Resize image to fit the terminal
             img_size = size
-            cmd = "convert -resize %s %s %s" % (img_size, tmpfile, tmpfile)
+            cmd = "convert -resize {size} {fn1} {fn2}".format(
+                    size=img_size, fn1=tmpfile, fn2=tmpfile)
             subprocess.call(cmd, shell=True)
-            subprocess.call("%s %s" % (img_cmd, tmpfile), shell=True)
+            subprocess.call("{cmd} {fn}".format(cmd=img_cmd, fn=tmpfile),
+                    shell=True)
             subprocess.call(["rm", "-f", tmpfile])
         else:
             print("img2sixel (or imgcat.sh for MacOS) not found!")
             topo_doc = "https://spp.readthedocs.io/en/latest/"
             topo_doc += "commands/experimental.html"
-            print("See '%s' for required packages." % topo_doc)
+            print("See '{url}' for required packages.".format(url=topo_doc))
 
     def format_sec_status(self, sec_id, stat):
         """Return formatted secondary status as a hash
-- 
2.17.1


  parent reply	other threads:[~2019-08-12  7:12 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-08-12  7:12 [spp] [PATCH 0/8] Update topo to support other than spp_nfv Yasufumi Ogawa
2019-08-12  7:12 ` [spp] [PATCH 1/8] cli: remove topo_resize command Yasufumi Ogawa
2019-08-12  7:12 ` Yasufumi Ogawa [this message]
2019-08-12  7:12 ` [spp] [PATCH 3/8] cli: move style params for dot to config Yasufumi Ogawa
2019-08-12  7:12 ` [spp] [PATCH 4/8] cli: add to get sec ID and procs to SppCtlClient Yasufumi Ogawa
2019-08-12  7:12 ` [spp] [PATCH 5/8] cli: support other than spp_nfv in topo command Yasufumi Ogawa
2019-08-12  7:12 ` [spp] [PATCH 6/8] cli: add port types for " Yasufumi Ogawa
2019-08-12  7:12 ` [spp] [PATCH 7/8] cli: add checking JSON objs in topo Yasufumi Ogawa
2019-08-12  7:12 ` [spp] [PATCH 8/8] cli: revise description for imgcat Yasufumi Ogawa

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190812071242.18934-3-yasufum.o@gmail.com \
    --to=yasufum.o@gmail.com \
    --cc=ferruh.yigit@intel.com \
    --cc=spp@dpdk.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).