예제 #1
0
class SuiteLogViewer(logviewer):
    """A popup window to view suite logs.

    Implemented using "cylc cat-log".

    """

    LABEL_ALL_LINES = "(all lines)"
    LABEL_ALL_TASKS = "(all tasks)"

    def __init__(self, suite_name, suite_log, remote_run_opts, task_list=None):
        """Initialise the suite log viewer."""
        if task_list is None:
            self.task_list = []
        else:
            self.task_list = task_list
        self.suite_name = suite_name
        self.suite_log = suite_log
        self.rotation = 0
        self.cmd_tmpl = "cylc cat-log %s" % remote_run_opts + (
            " -m t -r %(rotation)s -f %(suite_log)s %(suite_name)s")
        self.task_filter = None
        self.custom_filter = None
        logviewer.__init__(self)

    def create_gui_panel(self):
        """Create the GUI panel."""
        logviewer.create_gui_panel(self)

        self.window = gtk.Window()
        # self.window.set_border_width(5)
        self.window.set_title("log viewer")
        self.window.set_size_request(800, 400)
        self.window.set_icon(get_icon())

        combobox = gtk.combo_box_new_text()
        combobox.append_text(self.LABEL_ALL_LINES)
        combobox.append_text(self.LABEL_ALL_TASKS)
        for task in self.task_list:
            combobox.append_text(task)

        combobox.connect("changed", self.filter_log)
        combobox.set_active(0)

        newer = gtk.Button("_newer")
        newer.connect("clicked", self.rotate_log, False)
        self.hbox.pack_end(newer, False)

        older = gtk.Button("_older")
        older.connect("clicked", self.rotate_log, True)
        self.hbox.pack_end(older, False)

        self.hbox.pack_end(combobox, False)

        filterbox = gtk.HBox()
        entry = gtk.Entry()
        entry.connect("activate", self.custom_filter_log)
        label = gtk.Label('Filter')
        filterbox.pack_start(label, True)
        filterbox.pack_start(entry, True)
        self.hbox.pack_end(filterbox, False)

        close = gtk.Button("_Close")
        close.connect("clicked", self.shutdown, None, self.window)
        self.hbox.pack_start(close, False)

        self.window.add(self.vbox)
        self.window.connect("delete_event", self.shutdown, self.window)

        self.window.show_all()

    def shutdown(self, w, e, wind):
        """Quite the suite log viewer."""
        self.quit()
        wind.destroy()

    def filter_log(self, cb):
        """Filter for task names."""
        model = cb.get_model()
        index = cb.get_active()
        task = model[index][0]
        # Good enough to match "[task.CYCLE]"?
        if task == self.LABEL_ALL_LINES:
            filter_ = None
        elif task == self.LABEL_ALL_TASKS:
            filter_ = r'\[' + TaskID.ID_RE + r'\]'
        else:
            filter_ = r'\[' + task + TaskID.DELIM_RE + TaskID.POINT_RE + r'\]'
        self.task_filter = filter_
        self.update_view()
        return False

    def custom_filter_log(self, e):
        """Filter for arbitrary text."""
        txt = e.get_text()
        if txt == '':
            filter_ = None
        else:
            filter_ = txt
        self.custom_filter = filter_
        self.update_view()
        return False

    def rotate_log(self, bt, go_older):
        """Switch to other log rotations."""
        if go_older:
            self.rotation += 1
        elif self.rotation > 0:
            self.rotation -= 1
        self.update_view()

    def connect(self):
        """Run the tailer command."""
        cmd = self.cmd_tmpl % {
            'rotation': self.rotation,
            'suite_name': self.suite_name,
            'suite_log': self.suite_log
        }
        self.t = Tailer(
            self.logview,
            cmd,
            filters=[f for f in [self.task_filter, self.custom_filter] if f])
        self.t.start()

    def update_view(self):
        """Restart the log view on another log."""
        if self.t is None:
            return False
        self.t.stop()
        logbuffer = self.logview.get_buffer()
        s, e = logbuffer.get_bounds()
        self.reset_logbuffer()
        logbuffer.delete(s, e)
        label = "log (rot %d)" % self.rotation
        self.log_label.set_text(label)
        self.connect()
예제 #2
0
class logviewer(object):
    def __init__(self, name, dirname, filename):
        self.name = name
        self.dirname = dirname
        self.filename = filename
        self.t = None

        self.find_current = None
        self.find_current_iter = None
        self.search_warning_done = False

        self.freeze_button = None
        self.log_label = None
        self.logview = None
        self.hbox = None
        self.vbox = None
        self.create_gui_panel()
        self.logview.get_buffer()

        self.connect()

    def clear_and_reconnect(self):
        self.t.stop()
        self.clear()
        self.connect()

    def clear(self):
        logbuffer = self.logview.get_buffer()
        s, e = logbuffer.get_bounds()
        logbuffer.delete(s, e)

    def path(self):
        if self.dirname and not os.path.isabs(self.filename):
            return os.path.join(self.dirname, self.filename)
        else:
            return self.filename

    def connect(self):
        self.t = Tailer(self.logview, self.path())
        self.t.start()

    def quit_w_e(self, w, e):
        self.t.stop()

    def quit(self):
        self.t.stop()

    def get_widget(self):
        return self.vbox

    def reset_logbuffer(self):
        # clear log buffer iters and tags
        logbuffer = self.logview.get_buffer()
        s, e = logbuffer.get_bounds()
        logbuffer.remove_all_tags(s, e)
        self.find_current_iter = None
        self.find_current = None

    def enter_clicked(self, e, tv):
        self.on_find_clicked(tv, e)

    def on_find_clicked(self, tv, e):
        needle = e.get_text()
        if not needle:
            return

        self.t.freeze = True
        self.freeze_button.set_active(True)
        self.freeze_button.set_label('Reconnect')
        if not self.search_warning_done:
            warning_dialog("Find Next disconnects the live feed;" +
                           " click Reconnect when you're done").warn()
            self.search_warning_done = True

        tb = tv.get_buffer()

        if needle == self.find_current:
            s = self.find_current_iter
        else:
            s, e = tb.get_bounds()
            tb.remove_all_tags(s, e)
            s = tb.get_end_iter()
            tv.scroll_to_iter(s, 0)
        try:
            start, end = s.backward_search(needle, gtk.TEXT_SEARCH_TEXT_ONLY)
        except TypeError:
            # No search results.
            warning_dialog('"' + needle + '"' + " not found").warn()
        else:
            tag = tb.create_tag(None, background="#70FFA9")
            tb.apply_tag(tag, start, end)
            self.find_current_iter = start
            self.find_current = needle
            tv.scroll_to_iter(start, 0)

    def freeze_log(self, b):
        # TODO - HANDLE MORE STUFF IN THREADS LIKE THIS, RATHER THAN
        # PASSING IN ARGUMENTS?
        if b.get_active():
            self.t.freeze = True
            b.set_label('Re_connect')
            self.reset_logbuffer()
        else:
            self.t.freeze = False
            b.set_label('Dis_connect')

        return False

    def create_gui_panel(self):
        self.logview = gtk.TextView()
        self.logview.set_editable(False)
        # Use a monospace font. This is safe - by testing - setting an
        # illegal font description has no effect.
        self.logview.modify_font(pango.FontDescription("monospace"))

        searchbox = gtk.HBox()
        entry = gtk.Entry()
        entry.connect("activate", self.enter_clicked, self.logview)
        searchbox.pack_start(entry, True)
        b = gtk.Button("Find Next")
        b.connect_object('clicked', self.on_find_clicked, self.logview, entry)
        searchbox.pack_start(b, False)

        self.hbox = gtk.HBox()

        self.freeze_button = gtk.ToggleButton("Dis_connect")
        self.freeze_button.set_active(False)
        self.freeze_button.connect("toggled", self.freeze_log)

        searchbox.pack_end(self.freeze_button, False)

        sw = gtk.ScrolledWindow()
        sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        sw.add(self.logview)
        self.logview.set_border_width(5)
        self.logview.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("#fff"))

        self.vbox = gtk.VBox()

        self.log_label = gtk.Label(self.path())
        self.log_label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse("#00a"))
        self.vbox.pack_start(self.log_label, False)

        self.vbox.pack_start(sw, True)
        self.vbox.pack_start(searchbox, False)
        self.vbox.pack_start(self.hbox, False)
예제 #3
0
파일: logviewer.py 프로젝트: m214089/cylc
class logviewer(object):
    def __init__(self, name, dirname, filename):
        self.name = name
        self.dirname = dirname
        self.filename = filename
        self.t = None

        self.find_current = None
        self.find_current_iter = None
        self.search_warning_done = False

        self.create_gui_panel()
        self.logview.get_buffer()

        self.connect()

    def clear_and_reconnect(self):
        self.t.stop()
        self.clear()
        self.connect()

    def clear(self):
        logbuffer = self.logview.get_buffer()
        s, e = logbuffer.get_bounds()
        logbuffer.delete(s, e)

    def path(self):
        if self.dirname and not os.path.isabs(self.filename):
            return os.path.join(self.dirname, self.filename)
        else:
            return self.filename

    def connect(self):
        self.t = Tailer(self.logview, self.path())
        self.t.start()

    def quit_w_e(self, w, e):
        self.t.stop()

    def quit(self):
        self.t.stop()

    def get_widget(self):
        return self.vbox

    def reset_logbuffer(self):
        # clear log buffer iters and tags
        logbuffer = self.logview.get_buffer()
        s, e = logbuffer.get_bounds()
        logbuffer.remove_all_tags(s, e)
        self.find_current_iter = None
        self.find_current = None

    def enter_clicked(self, e, tv):
        self.on_find_clicked(tv, e)

    def on_find_clicked(self, tv, e):
        needle = e.get_text()
        if not needle:
            return

        self.t.freeze = True
        self.freeze_button.set_active(True)
        self.freeze_button.set_label('Reconnect')
        if not self.search_warning_done:
            warning_dialog(
                "Find Next disconnects the live feed;" +
                " click Reconnect when you're done").warn()
            self.search_warning_done = True

        tb = tv.get_buffer()

        if needle == self.find_current:
            s = self.find_current_iter
        else:
            s, e = tb.get_bounds()
            tb.remove_all_tags(s, e)
            s = tb.get_end_iter()
            tv.scroll_to_iter(s, 0)
        try:
            f, l = s.backward_search(needle, gtk.TEXT_SEARCH_TEXT_ONLY)
        except:
            warning_dialog('"' + needle + '"' + " not found").warn()
        else:
            tag = tb.create_tag(None, background="#70FFA9")
            tb.apply_tag(tag, f, l)
            self.find_current_iter = f
            self.find_current = needle
            tv.scroll_to_iter(f, 0)

    def freeze_log(self, b):
        # TODO - HANDLE MORE STUFF IN THREADS LIKE THIS, RATHER THAN
        # PASSING IN ARGUMENTS?
        if b.get_active():
            self.t.freeze = True
            b.set_label('Re_connect')
            self.reset_logbuffer()
        else:
            self.t.freeze = False
            b.set_label('Dis_connect')

        return False

    def create_gui_panel(self):
        self.logview = gtk.TextView()
        self.logview.set_editable(False)
        # Use a monospace font. This is safe - by testing - setting an
        # illegal font description has no effect.
        self.logview.modify_font(pango.FontDescription("monospace"))

        searchbox = gtk.HBox()
        entry = gtk.Entry()
        entry.connect("activate", self.enter_clicked, self.logview)
        searchbox.pack_start(entry, True)
        b = gtk.Button("Find Next")
        b.connect_object('clicked', self.on_find_clicked, self.logview, entry)
        searchbox.pack_start(b, False)

        self.hbox = gtk.HBox()

        self.freeze_button = gtk.ToggleButton("Dis_connect")
        self.freeze_button.set_active(False)
        self.freeze_button.connect("toggled", self.freeze_log)

        searchbox.pack_end(self.freeze_button, False)

        sw = gtk.ScrolledWindow()
        sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        sw.add(self.logview)
        self.logview.set_border_width(5)
        self.logview.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("#fff"))

        self.vbox = gtk.VBox()

        self.log_label = gtk.Label(self.path())
        self.log_label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse("#00a"))
        self.vbox.pack_start(self.log_label, False)

        self.vbox.pack_start(sw, True)
        self.vbox.pack_start(searchbox, False)
        self.vbox.pack_start(self.hbox, False)
예제 #4
0
class ComboLogViewer(logviewer):
    """Implement a viewer for task jobs in the "cylc gui".

    It has a a combo box for log file selection.

    task_id -- The NAME.POINT of a task proxy.
    filenames -- The names of the task job logs.
    cmd_tmpls -- A dict to map file names and alternate commands to tail follow
                 the file.
    init_active_index -- The index for selecting the initial log file.
    """

    LABEL_TEXT = "Choose Log File: "

    def __init__(self, task_id, filenames, cmd_tmpls, init_active_index):
        self.filenames = OrderedDict()
        name_str, point_str = TaskID.split(task_id)
        for filename in filenames:
            try:
                f_point_str, f_name_str, f_submit_num_str, f_base_name = (
                    filename.rsplit(os.sep, 4)[1:])
                if (f_point_str == point_str and f_name_str == name_str
                        and int(f_submit_num_str) and f_base_name):
                    name = f_submit_num_str + os.sep + f_base_name
                if ":" in filename:
                    name += " (%s)" % (filename.split(":", 1)[0])
            except ValueError:
                name = filename
            self.filenames[name] = filename
        self.init_active_index = init_active_index
        self.cmd_tmpls = cmd_tmpls
        logviewer.__init__(self, task_id, None,
                           filenames[self.init_active_index])

    def connect(self):
        """Connect to the selected log file tailer."""
        try:
            cmd_tmpl = self.cmd_tmpls[self.filename]
        except (KeyError, TypeError):
            cmd_tmpl = None
        self.t = Tailer(self.logview, self.filename, cmd_tmpl=cmd_tmpl)
        self.t.start()

    def create_gui_panel(self):
        """Create the panel."""
        logviewer.create_gui_panel(self)
        label = gtk.Label(self.LABEL_TEXT)
        combobox = gtk.combo_box_new_text()

        for name in self.filenames:
            combobox.append_text(name)

        combobox.connect("changed", self.switch_log)
        if self.init_active_index:
            combobox.set_active(self.init_active_index)
        else:
            combobox.set_active(0)

        self.hbox.pack_end(combobox, False)
        self.hbox.pack_end(label, False)

    def switch_log(self, callback):
        """Switch to another file, if necessary."""
        if self.t is None:
            return False
        model = callback.get_model()
        index = callback.get_active()

        name = model[index][0]
        filename = self.filenames[name]
        if filename != self.filename:
            self.filename = filename
            self.t.stop()
            self.t.join()
            logbuffer = self.logview.get_buffer()
            pos_start, pos_end = logbuffer.get_bounds()
            self.reset_logbuffer()
            logbuffer.delete(pos_start, pos_end)
            self.log_label.set_text(name)
            self.connect()

        return False
예제 #5
0
class ComboLogViewer(logviewer):

    """Implement a viewer for task jobs in the "cylc gui".

    It has a a combo box for log file selection.

    task_id -- The NAME.POINT of a task proxy.
    filenames -- The names of the task job logs.
    cmd_tmpls -- A dict to map file names and alternate commands to tail follow
                 the file.
    init_active_index -- The index for selecting the initial log file.
    """

    LABEL_TEXT = "Choose Log File: "

    def __init__(self, task_id, filenames, cmd_tmpls, init_active_index):
        self.filenames = OrderedDict()
        name_str, point_str = TaskID.split(task_id)
        for filename in filenames:
            try:
                f_point_str, f_name_str, f_submit_num_str, f_base_name = (
                    filename.rsplit(os.sep, 4)[1:])
                if (f_point_str == point_str and f_name_str == name_str and
                        int(f_submit_num_str) and f_base_name):
                    name = f_submit_num_str + os.sep + f_base_name
                if ":" in filename:
                    name += " (%s)" % (filename.split(":", 1)[0])
            except ValueError:
                name = filename
            self.filenames[name] = filename
        self.init_active_index = init_active_index
        self.cmd_tmpls = cmd_tmpls
        logviewer.__init__(
            self, task_id, None, filenames[self.init_active_index])

    def connect(self):
        """Connect to the selected log file tailer."""
        try:
            cmd_tmpl = self.cmd_tmpls[self.filename]
        except (KeyError, TypeError):
            cmd_tmpl = None
        self.t = Tailer(self.logview, self.filename, cmd_tmpl=cmd_tmpl)
        self.t.start()

    def create_gui_panel(self):
        """Create the panel."""
        logviewer.create_gui_panel(self)
        label = gtk.Label(self.LABEL_TEXT)
        combobox = gtk.combo_box_new_text()

        for name in self.filenames:
            combobox.append_text(name)

        combobox.connect("changed", self.switch_log)
        if self.init_active_index:
            combobox.set_active(self.init_active_index)
        else:
            combobox.set_active(0)

        self.hbox.pack_end(combobox, False)
        self.hbox.pack_end(label, False)

    def switch_log(self, callback):
        """Switch to another file, if necessary."""
        if self.t is None:
            return False
        model = callback.get_model()
        index = callback.get_active()

        name = model[index][0]
        filename = self.filenames[name]
        if filename != self.filename:
            self.filename = filename
            self.t.stop()
            self.t.join()
            logbuffer = self.logview.get_buffer()
            pos_start, pos_end = logbuffer.get_bounds()
            self.reset_logbuffer()
            logbuffer.delete(pos_start, pos_end)
            self.log_label.set_text(name)
            self.connect()

        return False
예제 #6
0
class SuiteLogViewer(logviewer):
    """A popup window to view suite logs.

    Implemented using "cylc cat-log".

    """

    LABEL_ALL_LINES = "(all lines)"
    LABEL_ALL_TASKS = "(all tasks)"

    def __init__(self, suite_name, suite_log, remote_run_opts, task_list=None):
        """Initialise the suite log viewer."""
        if task_list is None:
            self.task_list = []
        else:
            self.task_list = task_list
        self.suite_name = suite_name
        self.suite_log = suite_log
        self.suite_log_name = SUITE_LOG_OPTS[suite_log]
        self.rotation = 0
        self.cmd_tmpl = "cylc cat-log %s" % remote_run_opts + (
            " -m t -r %(rotation)s -f %(suite_log)s %(suite_name)s")
        self.task_filter = None
        self.custom_filter = None
        logviewer.__init__(self)

    def create_gui_panel(self):
        """Create the GUI panel."""
        logviewer.create_gui_panel(self)

        self.window = gtk.Window()
        # self.window.set_border_width(5)
        self.window.set_title("log viewer")
        self.window.set_size_request(800, 400)
        self.window.set_icon(get_icon())

        combobox = gtk.combo_box_new_text()
        combobox.append_text(self.LABEL_ALL_LINES)
        combobox.append_text(self.LABEL_ALL_TASKS)
        for task in self.task_list:
            combobox.append_text(task)

        combobox.connect("changed", self.filter_log)
        combobox.set_active(0)

        newer = gtk.Button("_newer")
        newer.connect("clicked", self.rotate_log, False)
        self.hbox.pack_end(newer, False)

        older = gtk.Button("_older")
        older.connect("clicked", self.rotate_log, True)
        self.hbox.pack_end(older, False)

        self.hbox.pack_end(combobox, False)

        filterbox = gtk.HBox()
        entry = gtk.Entry()
        entry.connect("activate", self.custom_filter_log)
        label = gtk.Label('Filter')
        filterbox.pack_start(label, True)
        filterbox.pack_start(entry, True)
        self.hbox.pack_end(filterbox, False)

        close = gtk.Button("_Close")
        close.connect("clicked", self.shutdown, None, self.window)
        self.hbox.pack_start(close, False)

        self.window.add(self.vbox)
        self.window.connect("delete_event", self.shutdown, self.window)

        self.window.show_all()

    def shutdown(self, w, e, wind):
        """Quite the suite log viewer."""
        self.quit()
        wind.destroy()

    def filter_log(self, cb):
        """Filter for task names."""
        model = cb.get_model()
        index = cb.get_active()
        task = model[index][0]
        # Good enough to match "[task.CYCLE]"?
        if task == self.LABEL_ALL_LINES:
            filter_ = None
        elif task == self.LABEL_ALL_TASKS:
            filter_ = r'\[' + TaskID.ID_RE + r'\]'
        else:
            filter_ = r'\[' + task + TaskID.DELIM_RE + TaskID.POINT_RE + r'\]'
        self.task_filter = filter_
        self.update_view()
        return False

    def custom_filter_log(self, e):
        """Filter for arbitrary text."""
        txt = e.get_text()
        if txt == '':
            filter_ = None
        else:
            filter_ = txt
        self.custom_filter = filter_
        self.update_view()
        return False

    def rotate_log(self, bt, go_older):
        """Switch to other log rotations."""
        if go_older:
            self.rotation += 1
        elif self.rotation > 0:
            self.rotation -= 1
        self.update_view()

    def connect(self):
        """Run the tailer command."""
        cmd = self.cmd_tmpl % {'rotation': self.rotation,
                               'suite_name': self.suite_name,
                               'suite_log': self.suite_log}
        self.t = Tailer(
            self.logview, cmd,
            filters=[f for f in [self.task_filter, self.custom_filter] if f])
        self.t.start()

    def update_view(self):
        """Restart the log view on another log."""
        if self.t is None:
            return False
        self.t.stop()
        logbuffer = self.logview.get_buffer()
        s, e = logbuffer.get_bounds()
        self.reset_logbuffer()
        logbuffer.delete(s, e)
        label = "%s (rot %d)" % (self.suite_log_name, self.rotation)
        self.log_label.set_text(label)
        self.connect()
예제 #7
0
class ComboLogViewer(logviewer):

    """Implement a viewer for task job logs in the GUI, via "cylc cat-log".

    It has a a combo box for log file selection.

    """
    LABEL_TEXT = "File: "
    LABEL_TEXT2 = "Submit: "

    def __init__(self, suite, task_id, choice, extra_logs, nsubmits,
                 remote_run_opts):
        self.suite_name = suite
        self.task_id = task_id
        self.nsubmits = nsubmits
        self.nsubmit = nsubmits
        self.extra_logs = extra_logs
        self.suite = suite
        self.choice = choice
        self.cmd_tmpl = "cylc cat-log %s" % remote_run_opts + (
            " -m t -s %(subnum)s -f %(job_log)s %(suite_name)s %(task_id)s")
        logviewer.__init__(self)

    def connect(self):
        """Connect to the selected log file tailer."""
        cmd = self.cmd_tmpl % {'subnum': self.nsubmit,
                               'suite_name': self.suite_name,
                               'task_id': self.task_id,
                               'job_log': self.choice}
        self.log_label.set_text(self.choice)
        self.t = Tailer(self.logview, cmd)
        self.t.start()

    def create_gui_panel(self):
        """Create the panel."""
        logviewer.create_gui_panel(self)

        label2 = gtk.Label(self.LABEL_TEXT2)
        combobox2 = gtk.combo_box_new_text()
        snums = range(1, self.nsubmits + 1)
        for snum in snums:
            combobox2.append_text(str(snum))
        combobox2.connect("changed", self.switch_snum)
        combobox2.set_active(snums.index(self.nsubmit))
        self.hbox.pack_end(combobox2, False)
        self.hbox.pack_end(label2, False)

        label = gtk.Label(self.LABEL_TEXT)
        combobox = gtk.combo_box_new_text()
        names = JOB_LOG_OPTS.values() + self.extra_logs
        for name in names:
            combobox.append_text(name)
        combobox.connect("changed", self.switch_log)
        combobox.set_active(names.index(self.choice))
        self.hbox.pack_end(combobox, False)
        self.hbox.pack_end(label, False)

    def switch_log(self, callback):
        """Switch to another file."""
        if self.t is None:
            return False
        model = callback.get_model()
        index = callback.get_active()

        filename = model[index][0]
        if filename != self.choice:
            self.choice = filename
            self.t.stop()
            self.t.join()
            logbuffer = self.logview.get_buffer()
            pos_start, pos_end = logbuffer.get_bounds()
            self.reset_logbuffer()
            logbuffer.delete(pos_start, pos_end)
            self.connect()
        return False

    def switch_snum(self, callback):
        """Switch to another file."""
        if self.t is None:
            return False
        model = callback.get_model()
        index = callback.get_active()
        snum = model[index][0]
        if snum != self.nsubmit:
            self.nsubmit = snum
            self.t.stop()
            self.t.join()
            logbuffer = self.logview.get_buffer()
            pos_start, pos_end = logbuffer.get_bounds()
            self.reset_logbuffer()
            logbuffer.delete(pos_start, pos_end)
            self.connect()
        return False
예제 #8
0
class ComboLogViewer(logviewer):
    """Implement a viewer for task job logs in the GUI, via "cylc cat-log".

    It has a a combo box for log file selection.

    """
    LABEL_TEXT = "File: "
    LABEL_TEXT2 = "Submit: "

    def __init__(self, suite, task_id, choice, extra_logs, nsubmits,
                 remote_run_opts):
        self.suite_name = suite
        self.task_id = task_id
        self.nsubmits = nsubmits
        self.nsubmit = nsubmits
        self.extra_logs = extra_logs
        self.suite = suite
        self.choice = choice
        self.cmd_tmpl = "cylc cat-log %s" % remote_run_opts + (
            " -m t -s %(subnum)s -f %(job_log)s %(suite_name)s %(task_id)s")
        logviewer.__init__(self)

    def connect(self):
        """Connect to the selected log file tailer."""
        cmd = self.cmd_tmpl % {
            'subnum': self.nsubmit,
            'suite_name': self.suite_name,
            'task_id': self.task_id,
            'job_log': self.choice
        }
        self.log_label.set_text(self.choice)
        self.t = Tailer(self.logview, cmd)
        self.t.start()

    def create_gui_panel(self):
        """Create the panel."""
        logviewer.create_gui_panel(self)

        label2 = gtk.Label(self.LABEL_TEXT2)
        combobox2 = gtk.combo_box_new_text()
        snums = range(1, self.nsubmits + 1)
        for snum in snums:
            combobox2.append_text(str(snum))
        combobox2.connect("changed", self.switch_snum)
        if self.nsubmit in snums:
            combobox2.set_active(snums.index(self.nsubmit))
        self.hbox.pack_end(combobox2, False)
        self.hbox.pack_end(label2, False)

        label = gtk.Label(self.LABEL_TEXT)
        combobox = gtk.combo_box_new_text()
        names = JOB_LOG_OPTS.values() + self.extra_logs
        for name in names:
            combobox.append_text(name)
        combobox.connect("changed", self.switch_log)
        combobox.set_active(names.index(self.choice))
        self.hbox.pack_end(combobox, False)
        self.hbox.pack_end(label, False)

    def switch_log(self, callback):
        """Switch to another file."""
        if self.t is None:
            return False
        model = callback.get_model()
        index = callback.get_active()

        filename = model[index][0]
        if filename != self.choice:
            self.choice = filename
            self.t.stop()
            self.t.join()
            logbuffer = self.logview.get_buffer()
            pos_start, pos_end = logbuffer.get_bounds()
            self.reset_logbuffer()
            logbuffer.delete(pos_start, pos_end)
            self.connect()
        return False

    def switch_snum(self, callback):
        """Switch to another file."""
        if self.t is None:
            return False
        model = callback.get_model()
        index = callback.get_active()
        snum = model[index][0]
        if snum != self.nsubmit:
            self.nsubmit = snum
            self.t.stop()
            self.t.join()
            logbuffer = self.logview.get_buffer()
            pos_start, pos_end = logbuffer.get_bounds()
            self.reset_logbuffer()
            logbuffer.delete(pos_start, pos_end)
            self.connect()
        return False
예제 #9
0
class ComboLogViewer(logviewer):

    """Implement a viewer for task jobs in the "cylc gui".

    It has a a combo box for log file selection.

    task_id -- The NAME.POINT of a task proxy.
    filenames -- The names of the task job logs.
    cmd_tmpls -- A dict to map file names and alternate commands to tail follow
                 the file.
    init_active_index -- The index for selecting the initial log file.
    """

    LABEL_TEXT = "Choose Log File: "

    def __init__(self, task_id, filenames, cmd_tmpls, init_active_index):
        self.filenames = filenames
        self.init_active_index = init_active_index
        self.cmd_tmpls = cmd_tmpls
        self.common_dir = os.path.dirname(os.path.commonprefix(self.filenames))
        logviewer.__init__(
            self, task_id, None, self.filenames[self.init_active_index])

    def connect(self):
        """Connect to the selected log file tailer."""
        try:
            cmd_tmpl = self.cmd_tmpls[self.filename]
        except (KeyError, TypeError):
            cmd_tmpl = None
        self.t = Tailer(self.logview, self.filename, cmd_tmpl=cmd_tmpl)
        self.t.start()

    def create_gui_panel(self):
        """Create the panel."""
        logviewer.create_gui_panel(self)
        label = gtk.Label(self.LABEL_TEXT)
        combobox = gtk.combo_box_new_text()

        for filename in self.filenames:
            relpath = os.path.relpath(filename, self.common_dir)
            if len(relpath) < len(filename):
                combobox.append_text(relpath)
            else:
                combobox.append_text(filename)

        combobox.connect("changed", self.switch_log)
        if self.init_active_index:
            combobox.set_active(self.init_active_index)
        else:
            combobox.set_active(0)

        self.hbox.pack_end(combobox, False)
        self.hbox.pack_end(label, False)

    def switch_log(self, callback):
        """Switch to another file, if necessary."""
        if self.t is None:
            return False
        model = callback.get_model()
        index = callback.get_active()

        name = model[index][0]
        if name in self.filenames:
            filename = name
        else:
            filename = os.path.join(self.common_dir, name)
        if filename != self.filename:
            self.filename = filename
            self.t.stop()
            self.t.join()
            logbuffer = self.logview.get_buffer()
            pos_start, pos_end = logbuffer.get_bounds()
            self.reset_logbuffer()
            logbuffer.delete(pos_start, pos_end)
            self.log_label.set_text(name)
            self.connect()

        return False