sutil API documentation

# Module `sutil`

Expand source code

    #!/usr/bin/python3

    from __future__ import absolute_import
    from __future__ import print_function

    import sys, traceback, os, time, warnings

    import gi
    gi.require_version("Gtk", "3.0")
    from gi.repository import Gtk
    from gi.repository import Gdk
    from gi.repository import GObject
    from gi.repository import GLib

    disp = Gdk.Display.get_default()
    scr = disp.get_default_screen()

    #print( "num_mon",  scr.get_n_monitors()    )
    #for aa in range(scr.get_n_monitors()):
    #    print( "mon", aa, scr.get_monitor_geometry(aa);)

    # ------------------------------------------------------------------------
    # Get current screen (monitor) width and height

    def get_screen_wh():

        ptr = disp.get_pointer()
        mon = scr.get_monitor_at_point(ptr[1], ptr[2])
        geo = scr.get_monitor_geometry(mon)
        www = geo.width; hhh = geo.height
        if www == 0 or hhh == 0:
            www = Gdk.get_screen_width();
            hhh = Gdk.get_screen_height();
        return www, hhh

    # ------------------------------------------------------------------------
    # Get current screen (monitor) upper left corner xx / yy

    def get_screen_xy():

        ptr = disp.get_pointer()
        mon = scr.get_monitor_at_point(ptr[1], ptr[2])
        geo = scr.get_monitor_geometry(mon)
        return geo.x, geo.y

    # ------------------------------------------------------------------------
    # Print( an exception as the system would print it)

    def print_exception(xstr):
        cumm = xstr + " "
        a,b,c = sys.exc_info()
        if a != None:
            cumm += str(a) + " " + str(b) + "\n"
            try:
                #cumm += str(traceback.format_tb(c, 10))
                ttt = traceback.extract_tb(c)
                for aa in ttt:
                    cumm += "File: " + os.path.basename(aa[0]) + \
                            " Line: " + str(aa[1]) + "\n" +  \
                        "   Context: " + aa[2] + " -> " + aa[3] + "\n"
            except:
                print("Could not print trace stack. ", sys.exc_info())
        print( cumm)

    # ------------------------------------------------------------------------
    # Show a regular message:

    def message(strx, parent = None, title = None, icon = Gtk.MessageType.INFO):

        dialog = Gtk.MessageDialog(parent, Gtk.DialogFlags.DESTROY_WITH_PARENT,
            icon, Gtk.ButtonsType.CLOSE, strx)

        dialog.set_modal(True)

        if title:
            dialog.set_title(title)
        else:
            dialog.set_title("DBGui Message")

        # Close dialog on user response
        dialog.connect("response", lambda d, r: d.destroy())
        dialog.show()

    # -----------------------------------------------------------------------
    # Sleep just a little, but allow the system to breed

    def  usleep(msec):

        if sys.version_info[0] < 3 or \
            (sys.version_info[0] == 3 and sys.version_info[1] < 3):
            timefunc = time.clock
        else:
            timefunc = time.process_time

        got_clock = timefunc() + float(msec) / 1000
        #print( got_clock)
        while True:
            if timefunc() > got_clock:
                break
            #print ("Sleeping")
            Gtk.main_iteration_do(False)

    # ------------------------------------------------------------------------
    # Create temporary file, return name. Empty string ("") if error.

    def tmpname(indir, template):

        fname = ""
        if not os.access(indir, os.W_OK):
            print( "Cannot access ", indir)
            return fname

        cnt = 1;
        while True:
            tmp = indir + "/" + template + "_" + str(cnt)
            if not os.access(tmp, os.R_OK):
                fname = tmp
                break
            # Safety valve
            if cnt > 10000:
                break
        return fname

    # ------------------------------------------------------------------------
    # Execute man loop

    def mainloop():
        while True:
            ev = Gdk.event_peek()
            #print( ev)
            if ev:
                if ev.type == Gdk.EventType.DELETE:
                    break
                if ev.type == Gdk.EventType.UNMAP:
                    break
            if Gtk.main_iteration_do(True):
                break

    class Unbuffered(object):
       def __init__(self, stream):
           self.stream = stream

       def write(self, data):
           self.stream.write(data)
           self.stream.flush()

       def writelines(self, datas):
           self.stream.writelines(datas)
           self.stream.flush()

       def __getattr__(self, attr):
           return getattr(self.stream, attr)

    # Time to str and str to time

    def time_n2s(ttt):
        sss = time.ctime(ttt)
        return sss

    def time_s2n(sss):
        rrr = time.strptime(sss)
        ttt = time.mktime(rrr)
        return ttt

    def yes_no_cancel(title, message, cancel = True, parent = None):

        #warnings.simplefilter("ignore")
        dialog = Gtk.Dialog(title,
                       None,
                       Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT)

        dialog.set_default_response(Gtk.ResponseType.YES)
        dialog.set_position(Gtk.WindowPosition.CENTER)
        dialog.set_transient_for(parent)

        sp = "     "
        label = Gtk.Label(message);
        label2 = Gtk.Label(sp);      label3 = Gtk.Label(sp)
        label2a = Gtk.Label(sp);     label3a = Gtk.Label(sp)

        hbox = Gtk.HBox() ;

        hbox.pack_start(label2, 0, 0, 0);
        hbox.pack_start(label, 1, 1, 0);
        hbox.pack_start(label3, 0, 0, 0)

        dialog.vbox.pack_start(label2a, 0, 0, 0);
        dialog.vbox.pack_start(hbox, 0, 0, 0)
        dialog.vbox.pack_start(label3a, 0, 0, 0);

        dialog.add_button("_Yes", Gtk.ResponseType.YES)
        dialog.add_button("_No", Gtk.ResponseType.NO)

        if cancel:
            dialog.add_button("_Cancel", Gtk.ResponseType.CANCEL)

        dialog.connect("key-press-event", yn_key, cancel)
        #dialog.connect("key-release-event", yn_key, cancel)
        #warnings.simplefilter("default")

        dialog.show_all()
        response = dialog.run()
        # Convert all responses to cancel
        if  response == Gtk.ResponseType.CANCEL or \
            response == Gtk.ResponseType.REJECT or \
            response == Gtk.ResponseType.CLOSE  or \
            response == Gtk.ResponseType.DELETE_EVENT:
            response = Gtk.ResponseType.CANCEL
        dialog.destroy()

        return  response

    def yn_key(win, event, cancel):
        #print( event)
        if event.keyval == Gdk.KEY_y or \
            event.keyval == Gdk.KEY_Y:
            win.response(Gtk.ResponseType.YES)

        if event.keyval == Gdk.KEY_n or \
            event.keyval == Gdk.KEY_N:
            win.response(Gtk.ResponseType.NO)

        if cancel:
            if event.keyval == Gdk.KEY_c or \
                event.keyval == Gdk.KEY_C:
                win.response(Gtk.ResponseType.CANCEL)

    def opendialog(parent=None):

        # We create an array, so it is passed around by reference
        fname = [""]

        def makefilter(mask, name):
            filter =  Gtk.FileFilter.new()
            filter.add_pattern(mask)
            filter.set_name(name)
            return filter

        def done_open_fc(win, resp, fname):
            #print "done_open_fc", win, resp
            if resp == Gtk.ButtonsType.OK:
                fname[0] = win.get_filename()
                if not fname[0]:
                    #print "Must have filename"
                    pass
                elif os.path.isdir(fname[0]):
                    os.chdir(fname[0])
                    win.set_current_folder(fname[0])
                    return
                else:
                    #print("OFD", fname[0])
                    pass
            win.destroy()

        but =   "Cancel", Gtk.ButtonsType.CANCEL,\
                "Open File", Gtk.ButtonsType.OK

        fc = Gtk.FileChooserDialog("Open file", parent, \
             Gtk.FileChooserAction.OPEN  \
            , but)

        filters = []
        filters.append(makefilter("*.mup", "MarkUp files (*.py)"))
        filters.append(makefilter("*.*", "All files (*.*)"))

        if filters:
            for aa in filters:
                fc.add_filter(aa)

        fc.set_default_response(Gtk.ButtonsType.OK)
        fc.set_current_folder(os.getcwd())
        fc.connect("response", done_open_fc, fname)
        #fc.connect("current-folder-changed", self.folder_ch )
        #fc.set_current_name(self.fname)
        fc.run()
        #print("OFD2", fname[0])
        return fname[0]

    def savedialog(resp):

        #print "File dialog"
        fname = [""]   # So it is passed around as a reference

        def makefilter(mask, name):
            filter =  Gtk.FileFilter.new()
            filter.add_pattern(mask)
            filter.set_name(name)
            return filter

        def done_fc(win, resp, fname):
            #print( "done_fc", win, resp)
            if resp == Gtk.ResponseType.OK:
                fname[0] = win.get_filename()
                if not fname[0]:
                    print("Must have filename")
                else:
                    pass
            win.destroy()

        but =   "Cancel", Gtk.ResponseType.CANCEL,   \
                        "Save File", Gtk.ResponseType.OK
        fc = Gtk.FileChooserDialog("Save file as ... ", None,
                Gtk.FileChooserAction.SAVE, but)

        #fc.set_do_overwrite_confirmation(True)

        filters = []
        filters.append(makefilter("*.mup", "MarkUp files (*.py)"))
        filters.append(makefilter("*.*", "All files (*.*)"))

        if filters:
            for aa in filters:
                fc.add_filter(aa)

        fc.set_current_name(os.path.basename(fname[0]))
        fc.set_current_folder(os.path.dirname(fname[0]))
        fc.set_default_response(Gtk.ResponseType.OK)
        fc.connect("response", done_fc, fname)
        fc.run()
        return fname[0]

    # ------------------------------------------------------------------------
    # Count lead spaces

    def leadspace(strx):
        cnt = 0;
        for aa in range(len(strx)):
            bb = strx[aa]
            if bb == " ":
                cnt += 1
            elif bb == "\t":
                cnt += 1
            elif bb == "\r":
                cnt += 1
            elif bb == "\n":
                cnt += 1
            else:
                break
        return cnt

    # EOF

## Functions

`def get_screen_wh()`
  Expand source code

      def get_screen_wh():

          ptr = disp.get_pointer()
          mon = scr.get_monitor_at_point(ptr[1], ptr[2])
          geo = scr.get_monitor_geometry(mon)
          www = geo.width; hhh = geo.height
          if www == 0 or hhh == 0:
              www = Gdk.get_screen_width();
              hhh = Gdk.get_screen_height();
          return www, hhh

`def get_screen_xy()`
  Expand source code

      def get_screen_xy():

          ptr = disp.get_pointer()
          mon = scr.get_monitor_at_point(ptr[1], ptr[2])
          geo = scr.get_monitor_geometry(mon)
          return geo.x, geo.y

`def leadspace(strx)`
  Expand source code

      def leadspace(strx):
          cnt = 0;
          for aa in range(len(strx)):
              bb = strx[aa]
              if bb == " ":
                  cnt += 1
              elif bb == "\t":
                  cnt += 1
              elif bb == "\r":
                  cnt += 1
              elif bb == "\n":
                  cnt += 1
              else:
                  break
          return cnt

`def mainloop()`
  Expand source code

      def mainloop():
          while True:
              ev = Gdk.event_peek()
              #print( ev)
              if ev:
                  if ev.type == Gdk.EventType.DELETE:
                      break
                  if ev.type == Gdk.EventType.UNMAP:
                      break
              if Gtk.main_iteration_do(True):
                  break

`def message(strx, parent=None, title=None, icon=<enum GTK_MESSAGE_INFO of type Gtk.MessageType>)`
  Expand source code

      def message(strx, parent = None, title = None, icon = Gtk.MessageType.INFO):

          dialog = Gtk.MessageDialog(parent, Gtk.DialogFlags.DESTROY_WITH_PARENT,
              icon, Gtk.ButtonsType.CLOSE, strx)

          dialog.set_modal(True)

          if title:
              dialog.set_title(title)
          else:
              dialog.set_title("DBGui Message")

          # Close dialog on user response
          dialog.connect("response", lambda d, r: d.destroy())
          dialog.show()

`def opendialog(parent=None)`
  Expand source code

      def opendialog(parent=None):

          # We create an array, so it is passed around by reference
          fname = [""]

          def makefilter(mask, name):
              filter =  Gtk.FileFilter.new()
              filter.add_pattern(mask)
              filter.set_name(name)
              return filter

          def done_open_fc(win, resp, fname):
              #print "done_open_fc", win, resp
              if resp == Gtk.ButtonsType.OK:
                  fname[0] = win.get_filename()
                  if not fname[0]:
                      #print "Must have filename"
                      pass
                  elif os.path.isdir(fname[0]):
                      os.chdir(fname[0])
                      win.set_current_folder(fname[0])
                      return
                  else:
                      #print("OFD", fname[0])
                      pass
              win.destroy()

          but =   "Cancel", Gtk.ButtonsType.CANCEL,\
                  "Open File", Gtk.ButtonsType.OK

          fc = Gtk.FileChooserDialog("Open file", parent, \
               Gtk.FileChooserAction.OPEN  \
              , but)

          filters = []
          filters.append(makefilter("*.mup", "MarkUp files (*.py)"))
          filters.append(makefilter("*.*", "All files (*.*)"))

          if filters:
              for aa in filters:
                  fc.add_filter(aa)

          fc.set_default_response(Gtk.ButtonsType.OK)
          fc.set_current_folder(os.getcwd())
          fc.connect("response", done_open_fc, fname)
          #fc.connect("current-folder-changed", self.folder_ch )
          #fc.set_current_name(self.fname)
          fc.run()
          #print("OFD2", fname[0])
          return fname[0]

`def print_exception(xstr)`
  Expand source code

      def print_exception(xstr):
          cumm = xstr + " "
          a,b,c = sys.exc_info()
          if a != None:
              cumm += str(a) + " " + str(b) + "\n"
              try:
                  #cumm += str(traceback.format_tb(c, 10))
                  ttt = traceback.extract_tb(c)
                  for aa in ttt:
                      cumm += "File: " + os.path.basename(aa[0]) + \
                              " Line: " + str(aa[1]) + "\n" +  \
                          "   Context: " + aa[2] + " -> " + aa[3] + "\n"
              except:
                  print("Could not print trace stack. ", sys.exc_info())
          print( cumm)

`def savedialog(resp)`
  Expand source code

      def savedialog(resp):

          #print "File dialog"
          fname = [""]   # So it is passed around as a reference

          def makefilter(mask, name):
              filter =  Gtk.FileFilter.new()
              filter.add_pattern(mask)
              filter.set_name(name)
              return filter

          def done_fc(win, resp, fname):
              #print( "done_fc", win, resp)
              if resp == Gtk.ResponseType.OK:
                  fname[0] = win.get_filename()
                  if not fname[0]:
                      print("Must have filename")
                  else:
                      pass
              win.destroy()

          but =   "Cancel", Gtk.ResponseType.CANCEL,   \
                          "Save File", Gtk.ResponseType.OK
          fc = Gtk.FileChooserDialog("Save file as ... ", None,
                  Gtk.FileChooserAction.SAVE, but)

          #fc.set_do_overwrite_confirmation(True)

          filters = []
          filters.append(makefilter("*.mup", "MarkUp files (*.py)"))
          filters.append(makefilter("*.*", "All files (*.*)"))

          if filters:
              for aa in filters:
                  fc.add_filter(aa)

          fc.set_current_name(os.path.basename(fname[0]))
          fc.set_current_folder(os.path.dirname(fname[0]))
          fc.set_default_response(Gtk.ResponseType.OK)
          fc.connect("response", done_fc, fname)
          fc.run()
          return fname[0]

`def time_n2s(ttt)`
  Expand source code

      def time_n2s(ttt):
          sss = time.ctime(ttt)
          return sss

`def time_s2n(sss)`
  Expand source code

      def time_s2n(sss):
          rrr = time.strptime(sss)
          ttt = time.mktime(rrr)
          return ttt

`def tmpname(indir, template)`
  Expand source code

      def tmpname(indir, template):

          fname = ""
          if not os.access(indir, os.W_OK):
              print( "Cannot access ", indir)
              return fname

          cnt = 1;
          while True:
              tmp = indir + "/" + template + "_" + str(cnt)
              if not os.access(tmp, os.R_OK):
                  fname = tmp
                  break
              # Safety valve
              if cnt > 10000:
                  break
          return fname

`def usleep(msec)`
  Expand source code

      def  usleep(msec):

          if sys.version_info[0] < 3 or \
              (sys.version_info[0] == 3 and sys.version_info[1] < 3):
              timefunc = time.clock
          else:
              timefunc = time.process_time

          got_clock = timefunc() + float(msec) / 1000
          #print( got_clock)
          while True:
              if timefunc() > got_clock:
                  break
              #print ("Sleeping")
              Gtk.main_iteration_do(False)

`def yes_no_cancel(title, message, cancel=True, parent=None)`
  Expand source code

      def yes_no_cancel(title, message, cancel = True, parent = None):

          #warnings.simplefilter("ignore")
          dialog = Gtk.Dialog(title,
                         None,
                         Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT)

          dialog.set_default_response(Gtk.ResponseType.YES)
          dialog.set_position(Gtk.WindowPosition.CENTER)
          dialog.set_transient_for(parent)

          sp = "     "
          label = Gtk.Label(message);
          label2 = Gtk.Label(sp);      label3 = Gtk.Label(sp)
          label2a = Gtk.Label(sp);     label3a = Gtk.Label(sp)

          hbox = Gtk.HBox() ;

          hbox.pack_start(label2, 0, 0, 0);
          hbox.pack_start(label, 1, 1, 0);
          hbox.pack_start(label3, 0, 0, 0)

          dialog.vbox.pack_start(label2a, 0, 0, 0);
          dialog.vbox.pack_start(hbox, 0, 0, 0)
          dialog.vbox.pack_start(label3a, 0, 0, 0);

          dialog.add_button("_Yes", Gtk.ResponseType.YES)
          dialog.add_button("_No", Gtk.ResponseType.NO)

          if cancel:
              dialog.add_button("_Cancel", Gtk.ResponseType.CANCEL)

          dialog.connect("key-press-event", yn_key, cancel)
          #dialog.connect("key-release-event", yn_key, cancel)
          #warnings.simplefilter("default")

          dialog.show_all()
          response = dialog.run()
          # Convert all responses to cancel
          if  response == Gtk.ResponseType.CANCEL or \
              response == Gtk.ResponseType.REJECT or \
              response == Gtk.ResponseType.CLOSE  or \
              response == Gtk.ResponseType.DELETE_EVENT:
              response = Gtk.ResponseType.CANCEL
          dialog.destroy()

          return  response

`def yn_key(win, event, cancel)`
  Expand source code

      def yn_key(win, event, cancel):
          #print( event)
          if event.keyval == Gdk.KEY_y or \
              event.keyval == Gdk.KEY_Y:
              win.response(Gtk.ResponseType.YES)

          if event.keyval == Gdk.KEY_n or \
              event.keyval == Gdk.KEY_N:
              win.response(Gtk.ResponseType.NO)

          if cancel:
              if event.keyval == Gdk.KEY_c or \
                  event.keyval == Gdk.KEY_C:
                  win.response(Gtk.ResponseType.CANCEL)

## Classes

`class Unbuffered (stream)`
  Expand source code

      class Unbuffered(object):
         def __init__(self, stream):
             self.stream = stream

         def write(self, data):
             self.stream.write(data)
             self.stream.flush()

         def writelines(self, datas):
             self.stream.writelines(datas)
             self.stream.flush()

         def __getattr__(self, attr):
             return getattr(self.stream, attr)

  ### Methods

  `def write(self, data)`
    Expand source code

        def write(self, data):
            self.stream.write(data)
            self.stream.flush()

  `def writelines(self, datas)`
    Expand source code

        def writelines(self, datas):
            self.stream.writelines(datas)
            self.stream.flush()