From af24a947f6366c66ac4b812ba2885d2ee80c6689 Mon Sep 17 00:00:00 2001
From: Oleg Hahm <oleg@hobbykeller.org>
Date: Thu, 31 Jul 2014 16:22:53 +0200
Subject: [PATCH] pyterm: make Guido happy

---
 dist/tools/pyterm/pyterm.py | 176 +++++++++++++++++++++++-------------
 1 file changed, 113 insertions(+), 63 deletions(-)

diff --git a/dist/tools/pyterm/pyterm.py b/dist/tools/pyterm/pyterm.py
index c3fbbb9abb..4131df879d 100755
--- a/dist/tools/pyterm/pyterm.py
+++ b/dist/tools/pyterm/pyterm.py
@@ -15,7 +15,8 @@
 #
 # You should have received a copy of the GNU Lesser General Public
 # License along with this library; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301 USA
 
 
 try:
@@ -24,16 +25,18 @@ except ImportError:
     import ConfigParser as configparser
 
 
-import cmd, serial, socket, sys, threading, readline, time, logging, os, \
-       argparse, re, codecs, signal
+import cmd, serial, socket, sys, threading, readline, time, logging, \
+       os, argparse, re, codecs, signal
 
 ### import twisted if available, define dummy classes otherwise
 try:
     from twisted.internet import reactor
-    from twisted.internet.protocol import Protocol, ReconnectingClientFactory
+    from twisted.internet.protocol import Protocol, \
+                                          ReconnectingClientFactory
 except ImportError:
-    logging.getLogger("").warn("Twisted not available, please install it if you"
-                               "want to use pyterm's JSON capabilities")
+    logging.getLogger("").warn("Twisted not available, please install "
+                               "it if you want to use pyterm's JSON "
+                               "capabilities")
 
     class Protocol():
         def __init__(self):
@@ -67,11 +70,12 @@ default_fmt_str = '%(asctime)s - %(levelname)s # %(message)s'
 class SerCmd(cmd.Cmd):
     """Main class for pyterm based on Python's Cmd class.
 
-    Runs an interactive terminal that transfer between stdio and serial port.
+    Runs an interactive terminal that transfer between stdio and serial
+    port.
     """
 
-    def __init__(self, port=None, baudrate=None, tcp_serial=None, confdir=None,
-                 conffile=None, host=None, run_name=None):
+    def __init__(self, port=None, baudrate=None, tcp_serial=None,
+                 confdir=None, conffile=None, host=None, run_name=None):
         """Constructor.
 
         Args:
@@ -123,7 +127,8 @@ class SerCmd(cmd.Cmd):
 
         ### create Logging object
         my_millis = "{:.4f}".format(time.time())
-        date_str = '{}.{}'.format(time.strftime('%Y%m%d-%H:%M:%S'), my_millis[-4:])
+        date_str = '{}.{}'.format(time.strftime('%Y%m%d-%H:%M:%S'),
+                                  my_millis[-4:])
         self.startup = date_str
         # create formatter
         formatter = logging.Formatter(self.fmt_str)
@@ -131,8 +136,10 @@ class SerCmd(cmd.Cmd):
         directory = self.configdir + os.path.sep + self.host
         if not os.path.exists(directory):
             os.makedirs(directory)
-        logging.basicConfig(filename=directory + os.path.sep + self.run_name + '.log', \
-                            level=logging.DEBUG, format=self.fmt_str)
+        logging.basicConfig(filename = directory + os.path.sep +
+                                       self.run_name + '.log',
+                                       level=logging.DEBUG,
+                                       format=self.fmt_str)
         ch = logging.StreamHandler()
         ch.setLevel(logging.DEBUG)
 
@@ -152,13 +159,16 @@ class SerCmd(cmd.Cmd):
 
         # if no serial or TCP is specified use default serial port
         if not self.port and not self.tcp_serial:
-            sys.stderr.write("No port specified, using default (%s)!\n" % (defaultport))
+            sys.stderr.write("No port specified, using default (%s)!\n"
+                             % (defaultport))
             self.port = defaultport
         # if a TCP port is specified try to connect
         if self.tcp_serial:
-            self.logger.info("Connect to localhost:%s" % self.tcp_serial)
-            for res in socket.getaddrinfo('localhost', self.tcp_serial, \
-                                          socket.AF_UNSPEC, socket.SOCK_STREAM):
+            self.logger.info("Connect to localhost:%s"
+                             % self.tcp_serial)
+            for res in socket.getaddrinfo('localhost', self.tcp_serial,
+                                          socket.AF_UNSPEC, 
+                                          socket.SOCK_STREAM):
                 af, socktype, proto, canonname, sa = res
                 try:
                     s = fdsocket(af, socktype, proto)
@@ -175,15 +185,16 @@ class SerCmd(cmd.Cmd):
             if s:
                 self.ser = s
             else:
-                self.logger.error("Something went wrong connecting to localhost:%s"
-                                  % self.tcp_serial)
+                self.logger.error("Something went wrong connecting to "
+                                  "localhost:%s" % self.tcp_serial)
                 sys.exit(1)
         # otherwise go for the serial port
         elif self.port:
             self.logger.info("Connect to serial port %s" % self.port)
             self.serial_connect()
 
-        # wait until connection is established and fire startup commands to the node
+        # wait until connection is established and fire startup
+        # commands to the node
         time.sleep(1)
         for cmd in self.init_cmd:
             self.logger.debug("WRITE ----->>>>>> '" + cmd + "'\n")
@@ -195,8 +206,8 @@ class SerCmd(cmd.Cmd):
         receiver_thread.start()
 
     def precmd(self, line):
-        """Check for command prefixes to distinguish between Pyterm interal
-        commands and commands that should be send to the node.
+        """Check for command prefixes to distinguish between Pyterm
+        interal commands and commands that should be send to the node.
         """
         self.logger.debug("processing line #%s#" % line)
         if (line.startswith("/")):
@@ -204,16 +215,18 @@ class SerCmd(cmd.Cmd):
         return line
 
     def default(self, line):
-        """In case of no Pyterm specific prefix is detected, split string by
-        colons and send it to the node.
+        """In case of no Pyterm specific prefix is detected, split
+        string by colons and send it to the node.
         """
-        self.logger.debug("%s is no pyterm command, sending to default out" % line)
+        self.logger.debug("%s is no pyterm command, sending to default "
+                          "out" % line)
         for tok in line.split(';'):
             tok = self.get_alias(tok)
             self.ser.write((tok.strip() + "\n").encode("utf-8"))
 
     def do_help(self, line):
-        """Do not use Cmd's internal help function, but redirect to the node.
+        """Do not use Cmd's internal help function, but redirect to the
+        node.
         """
         self.ser.write("help\n".encode("utf-8"))
 
@@ -257,12 +270,14 @@ class SerCmd(cmd.Cmd):
             if not self.config.has_section("triggers"):
                 self.config.add_section("triggers")
             for trigger in self.triggers:
-                self.config.set("triggers", trigger.pattern, self.triggers[trigger])
+                self.config.set("triggers", trigger.pattern,
+                                self.triggers[trigger])
         if len(self.json_regs):
             if not self.config.has_section("json_regs"):
                 self.config.add_section("json_regs")
             for j in self.json_regs:
-                self.config.set("json_regs", j, self.json_regs[j].pattern)
+                self.config.set("json_regs", j,
+                                self.json_regs[j].pattern)
         if len(self.filters):
             if not self.config.has_section("filters"):
                 self.config.add_section("filters")
@@ -285,7 +300,8 @@ class SerCmd(cmd.Cmd):
                 self.config.set("init_cmd", "init_cmd%i" % i, ic)
                 i += 1
 
-        with open(self.configdir + os.path.sep + self.configfile, 'wb') as config_fd:
+        with open(self.configdir + os.path.sep + self.configfile, 'wb')\
+        as config_fd:
             self.config.write(config_fd)
             self.logger.info("Config saved")
 
@@ -296,18 +312,21 @@ class SerCmd(cmd.Cmd):
             print(str(key) + ": " + str(self.__dict__[key]))
 
     def do_PYTERM_alias(self, line):
-        """Pyterm command: Register an alias or show an list of all registered aliases.
+        """Pyterm command: Register an alias or show an list of all
+        registered aliases.
         """
         if line.endswith("list"):
             for alias in self.aliases:
-                self.logger.info("{} = {}".format(alias, self.aliases[alias]))
+                self.logger.info("{} = {}".format(alias,
+                                 self.aliases[alias]))
             return
         if not line.count("="):
             sys.stderr.write("Usage: /alias <ALIAS> = <CMD>\n")
             return
         alias = line.split('=')[0].strip()
         command = line[line.index('=')+1:].strip()
-        self.logger.info("adding command %s for alias %s" % (command, alias))
+        self.logger.info("adding command %s for alias %s"
+                         % (command, alias))
         self.aliases[alias] = command
 
     def do_PYTERM_rmalias(self, line):
@@ -332,7 +351,8 @@ class SerCmd(cmd.Cmd):
             return
         trigger = line.split('=')[0].strip()
         action = line[line.index('=')+1:].strip()
-        self.logger.info("adding action %s for trigger %s" % (action, trigger))
+        self.logger.info("adding action %s for trigger %s" % (action,
+                         trigger))
         self.triggers[re.compile(trigger)] = action
 
     def do_PYTERM_rmtrigger(self, line):
@@ -372,9 +392,11 @@ class SerCmd(cmd.Cmd):
         sys.stderr.write("Filter for %s not found\n" % line.strip())
 
     def do_PYTERM_json(self, line):
-        """Pyterm command: Transfer lines matching this Regex as JSON object.
+        """Pyterm command: Transfer lines matching this Regex as JSON
+        object.
         """
-        self.json_regs[line.split(' ')[0].strip()] = re.compile(line.partition(' ')[2].strip())
+        self.json_regs[line.split(' ')[0].strip()] = \
+        re.compile(line.partition(' ')[2].strip())
 
     def do_PYTERM_unjson(self, line):
         """Pyterm command: Remove a JSON filter.
@@ -383,7 +405,8 @@ class SerCmd(cmd.Cmd):
             sys.stderr.write("JSON regex with ID %s not found" % line)
 
     def do_PYTERM_init(self, line):
-        """Pyterm command: Add an startup command. (Only useful in addition with /save).
+        """Pyterm command: Add an startup command. (Only useful in
+        addition with /save).
         """
         self.init_cmd.append(line.strip())
 
@@ -391,25 +414,31 @@ class SerCmd(cmd.Cmd):
         """Internal function to laod configuration from file.
         """
         self.config = configparser.SafeConfigParser()
-        self.config.read([self.configdir + os.path.sep + self.configfile])
+        self.config.read([self.configdir + os.path.sep + \
+                         self.configfile])
 
         for sec in self.config.sections():
             if sec == "filters":
                 for opt in self.config.options(sec):
-                    self.filters.append(re.compile(self.config.get(sec, opt)))
+                    self.filters.append(
+                            re.compile(self.config.get(sec, opt)))
             if sec == "ignores":
                 for opt in self.config.options(sec):
-                    self.ignores.append(re.compile(self.config.get(sec, opt)))
+                    self.ignores.append(
+                            re.compile(self.config.get(sec, opt)))
             if sec == "json_regs":
                 for opt in self.config.options(sec):
-                    self.logger.info("add json regex for %s" % self.config.get(sec, opt))
-                    self.json_regs[opt] = re.compile(self.config.get(sec, opt))
+                    self.logger.info("add json regex for %s"
+                                     % self.config.get(sec, opt))
+                    self.json_regs[opt] = \
+                        re.compile(self.config.get(sec, opt))
             if sec == "aliases":
                 for opt in self.config.options(sec):
                     self.aliases[opt] = self.config.get(sec, opt)
             if sec == "triggers":
                 for opt in self.config.options(sec):
-                    self.triggers[re.compile(opt)] = self.config.get(sec, opt)
+                    self.triggers[re.compile(opt)] = \
+                        self.config.get(sec, opt)
             if sec == "init_cmd":
                 for opt in self.config.options(sec):
                     self.init_cmd.append(self.config.get(sec, opt))
@@ -419,7 +448,8 @@ class SerCmd(cmd.Cmd):
                         self.__dict__[opt] = self.config.get(sec, opt)
 
     def process_line(self, line):
-        """Processes a valid line from node that should be printed and possibly forwarded.
+        """Processes a valid line from node that should be printed and
+        possibly forwarded.
 
         Args:
             line (str): input from node.
@@ -427,13 +457,16 @@ class SerCmd(cmd.Cmd):
         self.logger.info(line)
         # check if line matches a trigger and fire the command(s)
         for trigger in self.triggers:
-            self.logger.debug("comparing input %s to trigger %s" % (line, trigger.pattern))
+            self.logger.debug("comparing input %s to trigger %s"
+                              % (line, trigger.pattern))
             m = trigger.search(line)
             if m:
                 self.onecmd(self.precmd(self.triggers[trigger]))
 
-        # ckecking if the line should be sent as JSON object to a tcp server
-        if (len(self.json_regs)) and self.factory and self.factory.myproto:
+        # ckecking if the line should be sent as JSON object to a tcp 
+        # server
+        if (len(self.json_regs)) and self.factory and \
+            self.factory.myproto:
             for j in self.json_regs:
                 m = self.json_regs[j].search(line)
                 if m:
@@ -446,9 +479,11 @@ class SerCmd(cmd.Cmd):
                     json_obj += '"date":%s, ' % int(time.time()*1000)
                     for g in m.groupdict():
                         try:
-                            json_obj += '"%s":%d, ' % (g, int(m.groupdict()[g]))
+                            json_obj += '"%s":%d, ' \
+                                        % (g, int(m.groupdict()[g]))
                         except ValueError:
-                            json_obj += '"%s":"%s", ' % (g, m.groupdict()[g])
+                            json_obj += '"%s":"%s", ' \
+                                        % (g, m.groupdict()[g])
 
                     # eliminate the superfluous last ", "
                     json_obj = json_obj[:-2]
@@ -457,7 +492,8 @@ class SerCmd(cmd.Cmd):
                     self.factory.myproto.sendMessage(json_obj)
 
     def handle_line(self, line):
-        """Handle line from node and check for further processing requirements.
+        """Handle line from node and check for further processing
+        requirements.
 
         Args:
             line (str): input line from node.
@@ -494,15 +530,18 @@ class SerCmd(cmd.Cmd):
         while (1):
             # check if serial port can be accessed.
             try:
-                sr = codecs.getreader("UTF-8")(self.ser, errors='replace')
+                sr = codecs.getreader("UTF-8")(self.ser,
+                                               errors='replace')
                 c = sr.read(1)
             # try to re-open it with a timeout of 1s otherwise
             except (serial.SerialException, ValueError) as se:
-                self.logger.warn("Serial port disconnected, waiting to get reconnected...")
+                self.logger.warn("Serial port disconnected, waiting to "
+                                 "get reconnected...")
                 self.ser.close()
                 time.sleep(1)
                 if os.path.exists(self.port):
-                    self.logger.warn("Try to reconnect to %s again..." % (self.port))
+                    self.logger.warn("Try to reconnect to %s again..."
+                                     % (self.port))
                     self.serial_connect()
                 continue
             if c == '\n' or c == '\r':
@@ -534,11 +573,13 @@ class PytermClientFactory(ReconnectingClientFactory):
     def clientConnectionLost(self, connector, reason):
         if reactor.running:
             print('Lost connection.  Reason:', reason)
-        ReconnectingClientFactory.clientConnectionLost(self, connector, reason)
+        ReconnectingClientFactory.clientConnectionLost(self, connector,
+                                                       reason)
 
     def clientConnectionFailed(self, connector, reason):
         print('Connection failed. Reason:', reason)
-        ReconnectingClientFactory.clientConnectionFailed(self, connector,
+        ReconnectingClientFactory.clientConnectionFailed(self,
+                                                         connector,
                                                          reason)
 
 def __stop_reactor(signum, stackframe):
@@ -552,29 +593,36 @@ class fdsocket(socket.socket):
         try:
             return self.sendall(string)
         except socket.error as e:
-            logging.getLogger("").warn("Error in TCP connection (%s), closing down" % str(e))
+            logging.getLogger("").warn("Error in TCP connection (%s), "
+                                       "closing down" % str(e))
             self.close()
             sys.exit(0)
 
 if __name__ == "__main__":
 
-    parser = argparse.ArgumentParser(description="Pyterm - The Python terminal program")
+    parser = argparse.ArgumentParser(description="Pyterm - The Python "
+                                                 "terminal program")
     parser.add_argument("-p", "--port",
-            help="Specifies the serial port to use, default is %s" % defaultport,
+            help="Specifies the serial port to use, default is %s"
+                 % defaultport,
             default=defaultport)
     parser.add_argument("-ts", "--tcp-serial",
             help="Connect to a TCP port instead of a serial port")
     parser.add_argument("-b", "--baudrate",
-            help="Specifies baudrate for the serial port, default is %s" % defaultbaud,
+            help="Specifies baudrate for the serial port, default is %s"
+                 % defaultbaud,
             default=defaultbaud)
     parser.add_argument('-d', '--directory',
-            help="Specify the Pyterm directory, default is %s" % defaultdir,
+            help="Specify the Pyterm directory, default is %s"
+                 % defaultdir,
             default=defaultdir)
     parser.add_argument("-c", "--config",
-            help="Specify the config filename, default is %s" % defaultfile,
+            help="Specify the config filename, default is %s"
+                 % defaultfile,
             default=defaultfile)
     parser.add_argument("-s", "--server",
-            help="Connect via TCP to this server to send output as JSON")
+            help="Connect via TCP to this server to send output as "
+                 "JSON")
     parser.add_argument("-P", "--tcp_port", type=int,
             help="Port at the JSON server")
     parser.add_argument("-H", "--host",
@@ -583,15 +631,17 @@ if __name__ == "__main__":
             help="Run name, used for logfile")
     args = parser.parse_args()
 
-    myshell = SerCmd(args.port, args.baudrate, args.tcp_serial,  args.directory, args.config, args.host, args.run_name)
+    myshell = SerCmd(args.port, args.baudrate, args.tcp_serial,
+                     args.directory, args.config, args.host, args.run_name)
     myshell.prompt = ''
 
     if args.server and args.tcp_port:
         myfactory = PytermClientFactory()
         reactor.connectTCP(args.server, args.tcp_port, myfactory)
         myshell.factory = myfactory
-        reactor.callInThread(myshell.cmdloop, "Welcome to pyterm!\nType '/exit' to exit.")
+        reactor.callInThread(myshell.cmdloop, "Welcome to pyterm!\n"
+                                              "Type '/exit' to exit.")
         signal.signal(signal.SIGINT, __stop_reactor)
         reactor.run()
     else:
-        myshell.cmdloop("Welcome to pyterm!\nType 'exit' to exit.")
+        myshell.cmdloop("Welcome to pyterm!\nType '/exit' to exit.")
-- 
GitLab