Skip to content

Commit

Permalink
Merge pull request #2260 from challurip/Develop_1
Browse files Browse the repository at this point in the history
Cat-log - open job logs in editor
  • Loading branch information
oliver-sanders committed May 12, 2017
2 parents ccc4b89 + 43ad6b5 commit e18c463
Show file tree
Hide file tree
Showing 4 changed files with 136 additions and 3 deletions.
60 changes: 60 additions & 0 deletions bin/cylc-cat-log
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ if remrun().execute():
sys.exit(0)

import os
import re
from tempfile import NamedTemporaryFile
from pipes import quote
import shlex
from subprocess import Popen, PIPE
Expand All @@ -41,6 +43,7 @@ from cylc.suite_host import is_remote_host
from cylc.suite_logging import get_logs
from cylc.cfgspec.globalcfg import GLOBAL_CFG
from cylc.task_id import TaskID
from parsec.fileparse import read_and_proc


NAME_DEFAULT = "log"
Expand Down Expand Up @@ -123,6 +126,16 @@ def get_option_parser():
help="Task job log only: List log directory on the job host",
action="store_const", const=LIST_MODE_REMOTE, dest="list_mode")

parser.add_option(
"-g", "--geditor",
help="force use of the configured GUI editor.",
action="store_true", default=False, dest="geditor")

parser.add_option(
"-b", "--teditor",
help="force use of the configured Non-GUI editor.",
action="store_true", default=False, dest="editor")

return parser


Expand Down Expand Up @@ -271,6 +284,32 @@ def main():
else:
owner, host = (None, user_at_host)

cylc_tmpdir = GLOBAL_CFG.get_tmpdir()
if options.geditor:
editor = GLOBAL_CFG.get(['editors', 'gui'])
elif options.editor:
editor = GLOBAL_CFG.get(['editors', 'terminal'])

if options.editor or options.geditor:
if os.path.exists(filename):
lines = read_and_proc(filename)
else:
print >> sys.stderr, 'No such file or directory: %s' % filename
sys.exit(1)

viewfile = NamedTemporaryFile(
suffix='.' + os.path.basename(filename),
prefix=suite.replace('/', '_') + '.', dir=cylc_tmpdir
)

for line in lines:
viewfile.write(line + '\n')
viewfile.seek(0, 0)

os.chmod(viewfile.name, 0400)

modtime1 = os.stat(viewfile.name).st_mtime

# Construct the shell command
commands = []
if options.location_mode:
Expand All @@ -296,6 +335,10 @@ def main():
cmd_tmpl = str(GLOBAL_CFG.get_host_item(
"local tail command template"))
commands.append(shlex.split(cmd_tmpl % {"filename": filename}))
elif options.geditor or options.editor:
command_list = shlex.split(editor)
command_list.append(viewfile.name)
commands.append(command_list)
else:
commands.append(["cat", filename])

Expand All @@ -308,15 +351,32 @@ def main():
err = None
for command in commands:
stderr = PIPE

if options.debug:
sys.stderr.write(
" ".join([quote(item) for item in command]) + "\n")
stderr = None
proc = Popen(command, stderr=stderr)
err = proc.communicate()[1]
ret_code = proc.wait()

if options.editor or options.geditor:
if ret_code != 0:
print >>sys.stderr, command, 'failed:', ret_code
sys.exit(1)

modtime2 = os.stat(viewfile.name).st_mtime

if modtime2 > modtime1:
print >> sys.stderr, (
'WARNING: YOU HAVE EDITED A TEMPORARY READ_ONLY COPY : ')
print >> sys.stderr, viewfile.name

viewfile.close()

if ret_code == 0:
break

if ret_code and err:
sys.stderr.write(err)
sys.exit(ret_code)
Expand Down
4 changes: 3 additions & 1 deletion bin/cylc-view
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,9 @@ def main():

# write to a temporary file
viewfile = NamedTemporaryFile(
suffix=".suite.rc", prefix=suite + '.', dir=cylc_tmpdir)
suffix=".suite.rc", prefix=suite.replace('/', '_') + '.',
dir=cylc_tmpdir
)
for line in lines:
viewfile.write(line + '\n')
viewfile.seek(0, 0)
Expand Down
2 changes: 1 addition & 1 deletion lib/cylc/cycling/iso8601.py
Original file line number Diff line number Diff line change
Expand Up @@ -783,7 +783,7 @@ def test_multiple_exclusions_complex2(self):
'20000101T0500Z'])

def test_multiple_exclusions_simple(self):
"""Tests the generation of points for sequences with multiple exclusions
"""Tests generation of points for sequences with multiple exclusions
"""
init(time_zone='Z')
sequence = ISO8601Sequence('PT1H!(20000101T02Z,20000101T03Z)',
Expand Down
73 changes: 72 additions & 1 deletion lib/cylc/gui/app_gcylc.py
Original file line number Diff line number Diff line change
Expand Up @@ -1233,6 +1233,36 @@ def view_task_descr(self, w, e, task_id, *args):
self.gcapture_windows.append(foo)
foo.run()

def view_in_editor(self, w, e, task_id, choice):
try:
task_state_summary = self.updater.full_state_summary[task_id]
except KeyError:
warning_dialog('%s is not live' % task_id, self.window).warn()
return False
if (not task_state_summary['logfiles'] and
not task_state_summary.get('job_hosts')):
warning_dialog('%s has no log files' % task_id, self.window).warn()
else:
if choice == 'job-activity.log':
command_opt = "--activity"
elif choice == 'job.status':
command_opt = "--status"
elif choice == 'job.out':
command_opt = "--stdout"
elif choice == 'job.err':
command_opt = "--stderr"
elif choice == 'job':
command_opt = ""

command = (
"cylc cat-log %s --geditor %s %s" % (
command_opt, self.cfg.suite, task_id)
)

foo = gcapture_tmpfile(command, self.cfg.cylc_tmpdir, 400, 400)
self.gcapture_windows.append(foo)
foo.run()

def view_task_info(self, w, e, task_id, choice):
try:
task_state_summary = self.updater.full_state_summary[task_id]
Expand Down Expand Up @@ -1368,7 +1398,48 @@ def get_right_click_menu(self, task_ids, t_states, task_is_family=False,
# help_menu.append(cug_pdf_item)
# cug_pdf_item.connect('activate', self.browse, '--pdf')

# Separator.
# View In Editor.
view_editor_menu = gtk.Menu()
view_editor_item = gtk.ImageMenuItem("View In Editor")
img = gtk.image_new_from_stock(gtk.STOCK_DIALOG_INFO,
gtk.ICON_SIZE_MENU)
view_editor_item.set_image(img)
view_editor_item.set_submenu(view_editor_menu)
menu.append(view_editor_item)

# NOTE: we have to respond to 'button-release-event' rather
# than 'activate' in order for sub-menus to work in the
# graph-view so use connect_right_click_sub_menu instead of
# item.connect

for key, filename in [
('job script', 'job'),
('job activity log', 'job-activity.log'),
('job status file', 'job.status')]:
item = gtk.ImageMenuItem(key)
item.set_image(gtk.image_new_from_stock(
gtk.STOCK_DND, gtk.ICON_SIZE_MENU))
view_editor_menu.append(item)
self.connect_right_click_sub_menu(is_graph_view, item,
self.view_in_editor,
task_ids[0], filename)
item.set_sensitive(
t_states[0] in TASK_STATUSES_WITH_JOB_SCRIPT)

for key, filename in [
('job stdout', 'job.out'),
('job stderr', 'job.err')]:
item = gtk.ImageMenuItem(key)
item.set_image(gtk.image_new_from_stock(
gtk.STOCK_DND, gtk.ICON_SIZE_MENU))
view_editor_menu.append(item)
self.connect_right_click_sub_menu(is_graph_view, item,
self.view_in_editor,
task_ids[0], filename)
item.set_sensitive(
t_states[0] in TASK_STATUSES_WITH_JOB_LOGS)

# Separator
menu.append(gtk.SeparatorMenuItem())

# Trigger (run now).
Expand Down

0 comments on commit e18c463

Please sign in to comment.