From 6ff4e86588eb5c251b8e025508c2e785e62455b1 Mon Sep 17 00:00:00 2001 From: Ben Fitzpatrick Date: Tue, 15 Jul 2014 11:28:24 +0100 Subject: [PATCH 1/2] #119: implement some feedback from #996. --- bin/cylc-cycletime | 12 ++--- bin/cylc-monitor | 1 + bin/cylc-restart | 57 +++++++++++++++------- bin/cylc-stop | 42 ++++------------ lib/cylc/config.py | 7 ++- lib/cylc/cycling/__init__.py | 12 ++++- lib/cylc/cycling/integer.py | 14 ++++-- lib/cylc/cycling/iso8601.py | 7 ++- lib/cylc/cylc_xdot.py | 6 ++- lib/cylc/graphing.py | 80 ++++++++++++++++--------------- lib/cylc/gui/SuiteControl.py | 7 +-- lib/cylc/gui/SuiteControlGraph.py | 5 +- lib/cylc/gui/TreeUpdater.py | 2 +- lib/cylc/scheduler.py | 13 +++-- lib/cylc/task_pool.py | 3 +- lib/cylc/task_state.py | 34 ++++++++----- lib/cylc/time_parser.py | 23 +++++---- 17 files changed, 187 insertions(+), 138 deletions(-) diff --git a/bin/cylc-cycletime b/bin/cylc-cycletime index f316b5f87ca..5c6f093ee09 100755 --- a/bin/cylc-cycletime +++ b/bin/cylc-cycletime @@ -134,22 +134,22 @@ else: n_chosen = 0 if options.print_year: - n_chosen +=1 + n_chosen += 1 if options.num_expanded_year_digits: template = u"±XCCYY" else: template = "CCYY" if options.print_month: - n_chosen +=1 + n_chosen += 1 template = "MM" if options.print_day: - n_chosen +=1 + n_chosen += 1 template = "DD" if options.print_hour: - n_chosen +=1 + n_chosen += 1 template = "%H" if n_chosen != 0 and n_chosen != 1: @@ -177,7 +177,7 @@ except ValueError: try: cycle_point = cylc.cycling.iso8601.point_parse(cycle_point_string) except ValueError as exc: - parser.error( 'ERROR: invalid cycle: ' + str(exc) ) + parser.error( 'ERROR: invalid cycle: %s' % exc ) offset_props = {} @@ -217,7 +217,7 @@ if options.offset: offset += isodatetime.parsers.TimeIntervalParser().parse( opt_offset) * sign_factor except ValueError as exc: - parser.error( 'ERROR: offset not valid: ' + str(exc) ) + parser.error( 'ERROR: offset not valid: %s' % exc ) cycle_point += offset if template is None: print cycle_point diff --git a/bin/cylc-monitor b/bin/cylc-monitor index 6304e73bde3..f672a4f541a 100755 --- a/bin/cylc-monitor +++ b/bin/cylc-monitor @@ -146,6 +146,7 @@ try: task_ids = states.keys() n_tasks_all = len( task_ids ) + task_ids.sort() seen_time = {} seen_name = {} diff --git a/bin/cylc-restart b/bin/cylc-restart index 15e82548f87..a144733daf4 100755 --- a/bin/cylc-restart +++ b/bin/cylc-restart @@ -143,14 +143,14 @@ where they got to while the suite was down.""" nlines = len(lines) if nlines == 0: - raise Exception( "ERROR, empty suite state dump: " + file_name ) + raise Exception( "ERROR, empty suite state dump: %s" % file_name ) elif nlines < 3: - print >> sys.stderr, ("ERROR, The suite state dump contains only", - nlines, "lines:") + print >> sys.stderr, ( + "ERROR, The suite state dump contains only %d lines" % nlines) for l in lines: print ' ', l.rstrip() raise Exception( - "ERROR, incomplete suite state dump: " + file_name) + "ERROR, incomplete suite state dump: %s" % file_name) index = 0 # run mode : @@ -169,8 +169,8 @@ where they got to while the suite was down.""" if self.run_mode == 'live' and old_run_mode != 'live': raise Exception( - "ERROR: cannot RESTART in " + self.run_mode + " from a " + - old_run_mode + " state dump" + "ERROR: cannot RESTART in %s from a %s state dump" % ( + self.run_mode, old_run_mode) ) state_start_string = None @@ -218,7 +218,7 @@ where they got to while the suite was down.""" if line != 'Begin task states': raise Exception( "ERROR, illegal state dump line " + - "(expected 'Begin task states'): " + line + "(expected 'Begin task states'): %s" % line ) index += 1 @@ -262,9 +262,17 @@ where they got to while the suite was down.""" if self.start_point != state_start_point: # the state dump doesn't lie about start cycles if self.options.ignore_startcycle: - print >> sys.stderr, "WARNING: ignoring old initial cycle", state_start_point, "; using suite.rc", self.start_point + print >> sys.stderr, ( + "WARNING: ignoring old initial cycle " + + "%s; using suite.rc %s" % ( + state_start_point, self.start_point) + ) else: - print >> sys.stderr, "WARNING: old initial cycle", state_start_point, "overriding suite.rc", self.start_point + print >> sys.stderr, ( + "WARNING: old initial cycle " + + "%s, overriding suite.rc %s" % ( + state_start_point, self.start_point) + ) self.start_point = state_start_point else: # reinstate the former start cycle @@ -282,7 +290,10 @@ where they got to while the suite was down.""" elif self.stop_point is not None: # a stop cycle was given on the restart command line or suite.rc file if self.stop_point != state_stop_point: - print >> sys.stderr, "WARNING: overriding the old stop cycle", state_stop_point, "with", self.stop_point + print >> sys.stderr, ( + "WARNING: overriding the old stop cycle " + "%s with %s" % (state_stop_point, self.stop_point) + ) else: # reinstate the old stop cycle self.stop_point = state_stop_point @@ -380,12 +391,17 @@ where they got to while the suite was down.""" ) except TaskNotDefinedError, x: print >> sys.stderr, str(x) - print >> sys.stderr, "WARNING: ignoring task", name, "from the suite state dump file" + print >> sys.stderr, ( + "WARNING: ignoring task %s " % name + + "from the suite state dump file") print >> sys.stderr, "(the task definition has probably been deleted from the suite)." continue except Exception, x: print >> sys.stderr, str(x) - print >> sys.stderr, "ERROR: could not load task", name, "from the suite state dump file" + print >> sys.stderr, ( + "ERROR: could not load task %s " % name + + "from the suite state dump file" + ) # TODO: Is it safe to have "raise x" here? continue @@ -415,7 +431,10 @@ where they got to while the suite was down.""" user_at_host = row[0] self.old_user_at_host_set.add(str(user_at_host)) else: - print >> sys.stderr, "WARNING:", id, "failed to read user@host from run-db!" + print >> sys.stderr, ( + "WARNING: %s " % id + + "failed to read user@host from run-db!" + ) # get submit_method_id and try_num from run-db submit_method_id = try_num = None @@ -423,10 +442,15 @@ where they got to while the suite was down.""" if row and row[0]: submit_method_id, try_num = row else: - print >> sys.stderr, "WARNING:", id, "failed to read submit_method_id and try_num from run-db!" + print >> sys.stderr, ( + "WARNING: %s " % id + + "failed to read submit_method_id and try_num from " + + "run-db!" + ) if None in [ user_at_host, submit_method_id, try_num ]: - print >> sys.stderr, "WARNING: cannot determine what happened to " + id + print >> sys.stderr, ( + "WARNING: cannot determine what happened to %s" % id) else: # update the task proxy with submit ID etc. itask.submit_method_id = submit_method_id @@ -453,7 +477,8 @@ where they got to while the suite was down.""" itask.outputs.set_all_completed() else: - raise Exception( 'ERROR: unknown task state for ' + itask.id ) + raise Exception( + 'ERROR: unknown task state for %s' % itask.id) self.pool.add_to_runahead_pool( itask ) diff --git a/bin/cylc-stop b/bin/cylc-stop index 7e8b77101b9..d38ae86a3c4 100755 --- a/bin/cylc-stop +++ b/bin/cylc-stop @@ -167,40 +167,18 @@ except Exception, x: method = None if options.wall_clock: method = 'stop after clock time' - prompt_text = 'Set shutdown at wall clock ' + options.wall_clock + prompt_text = 'Set shutdown at wall clock %s' % options.wall_clock shutdown_arg = options.wall_clock elif shutdown_at: # STOP argument detected - if not cylc.TaskID.is_valid_id( shutdown_arg ): - # not a task ID - # not a task ID or a date time; - # TODO ISO - MOVE THIS LOGIC INTO SCHEDULER AND TEST - try: - # is it a cycle point? - ##ct(shutdown_arg) - pass - except CycleTimeError,x: - # nope: is it an async integer tag? - try: - int( shutdown_arg ) - except ValueError: - # nope: not task ID, date time, or CYCLE_POINT - raise SystemExit( "ERROR:, invalid STOP argument: " + shutdown_arg ) - else: - # is probably an async CYCLE_POINT - method = 'stop after tag' - prompt_text = 'Set shutdown at cycle point ' + shutdown_arg - #print 'async' - else: - # is a cycle point - method = 'stop after tag' - prompt_text = 'Set shutdown at cycle point ' + shutdown_arg - #print 'cycling' - else: + if cylc.TaskID.is_valid_id( shutdown_arg ): # is a task ID method = 'stop after task' - prompt_text = 'Set shutdown after task ' + shutdown_arg - #print 'task id' + prompt_text = 'Set shutdown after task %s' % shutdown_arg + else: + # not a task ID, may be a cycle point + method = 'stop after tag' + prompt_text = 'Set shutdown at cycle point %s' % shutdown_arg if method: prompt( prompt_text + ' for ' + suite, options.force ) @@ -212,7 +190,7 @@ if method: sys.exit(x) elif options.now: - prompt( 'Shut down ' + suite + ' now', options.force ) + prompt( 'Shut down %s now' % suite, options.force ) try: result = proxy.put( 'stop now' ) except Exception,x: @@ -221,7 +199,7 @@ elif options.now: sys.exit(x) elif options.quick: - prompt( 'Shut down ' + suite + ' quickly', options.force ) + prompt( 'Shut down %s quickly' % suite, options.force ) try: result = proxy.put( 'stop quickly' ) except Exception,x: @@ -230,7 +208,7 @@ elif options.quick: sys.exit(x) else: - prompt( 'Shut down ' + suite, options.force ) + prompt( 'Shut down %s' % suite, options.force ) print "Telling the suite to shut down ..." try: result = proxy.put( 'stop cleanly', options.kill ) diff --git a/lib/cylc/config.py b/lib/cylc/config.py index b30bc57eeb6..e8e160e8b14 100644 --- a/lib/cylc/config.py +++ b/lib/cylc/config.py @@ -856,16 +856,15 @@ def check_tasks( self ): # instantiate a task itask = self.taskdefs[name].get_task_class()( tag, 'waiting', None, True, validate=True ) except TypeError, x: - raise # This should not happen as we now explicitly catch use # of synchronous special tasks in an asynchronous graph. # But in principle a clash of multiply inherited base # classes due to choice of "special task" modifiers # could cause a TypeError. - raise SuiteConfigError, '(inconsistent use of special tasks?)' + raise SuiteConfigError('(inconsistent use of special tasks?)') except Exception, x: - raise - raise SuiteConfigError, 'ERROR, failed to instantiate task ' + str(name) + raise SuiteConfigError( + 'ERROR, failed to instantiate task %s: %s' % (name, x)) if not itask.tag: if flags.verbose: print " + Task out of bounds for " + str(tag) + ": " + itask.name diff --git a/lib/cylc/cycling/__init__.py b/lib/cylc/cycling/__init__.py index a16766290f6..f2b57823283 100644 --- a/lib/cylc/cycling/__init__.py +++ b/lib/cylc/cycling/__init__.py @@ -26,6 +26,16 @@ def __str__(self): return self.ERROR_MESSAGE.format(*self.args) +class PointParsingError(ValueError): + + """An error raised when a point has an incorrect value.""" + + ERROR_MESSAGE = "Incompatible value for {0}: {1}" + + def __str__(self): + return self.ERROR_MESSAGE.format(*self.args) + + class PointBase(object): """The base class for single points in a cycler sequence. @@ -51,7 +61,7 @@ def __init__(self, value): self.value = value def standardise(self): - """Format self.value into a standard representation.""" + """Format self.value into a standard representation and check it.""" return self def __str__(self): diff --git a/lib/cylc/cycling/integer.py b/lib/cylc/cycling/integer.py index b61d5dd5ea4..2b4ff9c6027 100755 --- a/lib/cylc/cycling/integer.py +++ b/lib/cylc/cycling/integer.py @@ -18,7 +18,7 @@ import re -from cylc.cycling import PointBase, IntervalBase +from cylc.cycling import PointBase, IntervalBase, PointParsingError """ Integer cycling by point, interval, and sequence classes. @@ -85,6 +85,14 @@ def sub(self, other): def add(self, other): return IntegerPoint(int(self) + int(other)) + def standardise(self): + """Format self.value into a standard representation and check it.""" + try: + self.value = str(int(self)) + except (TypeError, ValueError): + raise PointParsingError(type(self), self.value) + return self + def __int__(self): return int(self.value) @@ -391,10 +399,6 @@ def init_from_cfg(cfg): if __name__ == '__main__': r = IntegerSequence( 'R/1/P3', 1, 10 ) - #r = IntegerSequence( 'R/c2/P2', 1, 10 ) - #r = IntegerSequence( 'R2/c2/P2', 1, 10 ) - #r = IntegerSequence( 'R2/c4/c6', 1, 10 ) - #r = IntegerSequence( 'R2/P2/c6', 1, 10 ) r.set_offset( IntegerInterval('4') ) diff --git a/lib/cylc/cycling/iso8601.py b/lib/cylc/cycling/iso8601.py index 6df626aec2d..64f54d4addf 100755 --- a/lib/cylc/cycling/iso8601.py +++ b/lib/cylc/cycling/iso8601.py @@ -23,7 +23,7 @@ from isodatetime.timezone import ( get_local_time_zone, get_local_time_zone_format) from cylc.time_parser import CylcTimeParser -from cylc.cycling import PointBase, IntervalBase +from cylc.cycling import PointBase, IntervalBase, PointParsingError from parsec.validate import IllegalValueError # TODO - Consider copy vs reference of points, intervals, sequences @@ -103,7 +103,10 @@ def __cmp__(self, other): return self._iso_point_cmp(self.value, other.value) def standardise(self): - self.value = str(point_parse(self.value)) + try: + self.value = str(point_parse(self.value)) + except ValueError: + raise PointParsingError(type(self), self.value) return self def sub(self, other): diff --git a/lib/cylc/cylc_xdot.py b/lib/cylc/cylc_xdot.py index 034a33cb5ff..cd9d3f7a1bc 100644 --- a/lib/cylc/cylc_xdot.py +++ b/lib/cylc/cylc_xdot.py @@ -424,8 +424,10 @@ def get_graph( self, group_nodes=[], ungroup_nodes=[], one = self.ctime two = self.stop_after else: - one = str( self.suiterc.cfg['visualization']['initial cycle point']) - two = str(self.suiterc.cfg['visualization']['final cycle point']) + one = str( + self.suiterc.cfg['visualization']['initial cycle point']) + two = str( + self.suiterc.cfg['visualization']['final cycle point']) graph = self.suiterc.get_graph( one, two, raw=self.raw, group_nodes=group_nodes, diff --git a/lib/cylc/graphing.py b/lib/cylc/graphing.py index fe524b0fc06..b4387fc62fa 100644 --- a/lib/cylc/graphing.py +++ b/lib/cylc/graphing.py @@ -38,19 +38,19 @@ def __init__( self, title, suite_polling_tasks={} ): self.graph_attr['label'] = title self.suite_polling_tasks = suite_polling_tasks - def node_attr_by_taskname( self, n ): - name, tag = TaskID.split( n ) + def node_attr_by_taskname( self, node_string ): + name, tag = TaskID.split( node_string ) if name in self.task_attr: return self.task_attr[name] else: return [] - def style_edge( self, l, r ): + def style_edge( self, left, right ): pass - def style_node( self, n, autoURL, base=False ): - node = self.get_node( n ) - name, tag = TaskID.split( n ) + def style_node( self, node_string, autoURL, base=False ): + node = self.get_node( node_string ) + name, tag = TaskID.split( node_string ) label = name if name in self.suite_polling_tasks: label += "\\n" + self.suite_polling_tasks[name][3] @@ -64,31 +64,31 @@ def style_node( self, n, autoURL, base=False ): else: node.attr['URL'] = n - def cylc_add_node( self, n, autoURL, **attr ): - pygraphviz.AGraph.add_node( self, n, **attr ) - self.style_node( n, autoURL ) + def cylc_add_node( self, node_string, autoURL, **attr ): + pygraphviz.AGraph.add_node( self, node_string, **attr ) + self.style_node( node_string, autoURL ) - def cylc_add_edge( self, l, r, autoURL, **attr ): - if l == None and r == None: + def cylc_add_edge( self, left, right, autoURL, **attr ): + if left == None and right == None: pass - elif l == None: - self.cylc_add_node( r, autoURL ) - elif r == None: - self.cylc_add_node( l, autoURL ) - elif l == r: + elif left == None: + self.cylc_add_node( right, autoURL ) + elif right == None: + self.cylc_add_node( left, autoURL ) + elif left == right: # pygraphviz 1.1 adds a node instead of a self-edge # which results in a KeyError in get_edge() below. - self.cylc_add_node( l, autoURL ) + self.cylc_add_node( left, autoURL ) else: - pygraphviz.AGraph.add_edge( self, l, r, **attr ) - self.style_node( l, autoURL, base=True ) - self.style_node( r, autoURL, base=True ) - self.style_edge( l, r ) + pygraphviz.AGraph.add_edge( self, left, right, **attr ) + self.style_node( left, autoURL, base=True ) + self.style_node( right, autoURL, base=True ) + self.style_edge( left, right ) def add_edges( self, edges, ignore_suicide=False ): edges.sort() # TODO: does sorting help layout stability? - for e in edges: - l, r, dashed, suicide, conditional = e + for edge in edges: + left, right, dashed, suicide, conditional = edge if suicide and ignore_suicide: continue if conditional: @@ -109,7 +109,8 @@ def add_edges( self, edges, ignore_suicide=False ): # override style='dashed' - self.cylc_add_edge( l, r, True, style=style, arrowhead=arrowhead ) + self.cylc_add_edge( + left, right, True, style=style, arrowhead=arrowhead) class CGraph( CGraphPlain ): @@ -153,32 +154,33 @@ def __init__( self, title, suite_polling_tasks={}, vizconfig={} ): self.task_attr[item] = [] self.task_attr[item].append( attr ) - def style_node( self, n, autoURL, base=False ): - super( self.__class__, self ).style_node( n, autoURL, False ) - node = self.get_node(n) - for item in self.node_attr_by_taskname( n ): + def style_node( self, node_string, autoURL, base=False ): + super( self.__class__, self ).style_node( + node_string, autoURL, False) + node = self.get_node(node_string) + for item in self.node_attr_by_taskname( node_string ): attr, value = re.split( '\s*=\s*', item ) node.attr[ attr ] = value if self.vizconfig['use node color for labels']: node.attr['fontcolor'] = node.attr['color'] - def style_edge( self, l, r ): - super( self.__class__, self ).style_edge( l, r ) - nl = self.get_node(l) - nr = self.get_node(r) - edge = self.get_edge(l,r) + def style_edge( self, left, right ): + super( self.__class__, self ).style_edge( left, right ) + left_node = self.get_node(left) + edge = self.get_edge(left, right) if self.vizconfig['use node color for edges']: - if nl.attr['style'] == 'filled': - edge.attr['color'] = nl.attr['fillcolor'] + if left_node.attr['style'] == 'filled': + edge.attr['color'] = left_node.attr['fillcolor'] else: - edge.attr['color'] = nl.attr['color'] + edge.attr['color'] = left_node.attr['color'] class edge( object): - def __init__( self, l, r, sequence, sasl=False, suicide=False, conditional=False ): + def __init__( self, left, right, sequence, sasl=False, suicide=False, + conditional=False ): """contains qualified node names, e.g. 'foo[T-6]:out1'""" - self.left = l - self.right = r + self.left = left + self.right = right self.sequence = sequence self.sasl = sasl self.suicide = suicide diff --git a/lib/cylc/gui/SuiteControl.py b/lib/cylc/gui/SuiteControl.py index 10ff369f400..2d61803db8d 100644 --- a/lib/cylc/gui/SuiteControl.py +++ b/lib/cylc/gui/SuiteControl.py @@ -869,9 +869,10 @@ def stopsuite( self, bt, window, kill_cb, return if not cylc.TaskID.is_valid_id( stoptask_id ): warning_dialog( - "ERROR: Bad task ID (" + - cylc.TaskID.get( "TASK", "CYCLE_POINT") + "): " + - stoptask_id, + "ERROR: Bad task ID (%s): %s" % ( + cylc.TaskID.get( "TASK", "CYCLE_POINT"), + stoptask_id + ), self.window ).warn() return diff --git a/lib/cylc/gui/SuiteControlGraph.py b/lib/cylc/gui/SuiteControlGraph.py index 155b287e172..3ba4db94daf 100644 --- a/lib/cylc/gui/SuiteControlGraph.py +++ b/lib/cylc/gui/SuiteControlGraph.py @@ -486,13 +486,15 @@ def focused_timezoom_popup( self, w, id ): # TODO ISO - RESTORE OR REMOVE THIS FUNCTIONALITY #diff_pre = ctime - self.t.oldest_ctime.hours #diff_post = self.t.newest_ctime - ctime.hours + # ... + #start_entry.set_text(str(diff_pre)) + #stop_entry.set_text(str(diff_post)) # TODO - error checking on date range given box = gtk.HBox() label = gtk.Label( 'Pre (hours)' ) box.pack_start( label, True ) start_entry = gtk.Entry() - #start_entry.set_text(str(diff_pre)) box.pack_start (start_entry, True) vbox.pack_start( box ) @@ -500,7 +502,6 @@ def focused_timezoom_popup( self, w, id ): label = gtk.Label( 'Post (hours)' ) box.pack_start( label, True ) stop_entry = gtk.Entry() - #stop_entry.set_text(str(diff_post)) box.pack_start (stop_entry, True) vbox.pack_start( box ) diff --git a/lib/cylc/gui/TreeUpdater.py b/lib/cylc/gui/TreeUpdater.py index 232df172dd1..331d831f88d 100644 --- a/lib/cylc/gui/TreeUpdater.py +++ b/lib/cylc/gui/TreeUpdater.py @@ -237,7 +237,7 @@ def update_gui( self ): ) ) if isinstance(meant, float): - if not meant: + if meant == 0: # This is a very fast (sub-cylc-resolution) task. meant = 1 meant = int(meant) diff --git a/lib/cylc/scheduler.py b/lib/cylc/scheduler.py index 77d9559befe..868f8680d5a 100644 --- a/lib/cylc/scheduler.py +++ b/lib/cylc/scheduler.py @@ -54,6 +54,7 @@ import subprocess from wallclock import ( now, get_current_time_string, get_seconds_as_interval_string) +from cycling import PointParsingError from cycling.loader import get_point import isodatetime.data import isodatetime.parsers @@ -1153,14 +1154,20 @@ def shutdown( self, reason='' ): def set_stop_ctime( self, stop_string ): - self.log.info( "Setting stop cycle point: " + stop_string ) self.stop_point = get_point(stop_string) + try: + self.stop_point.standardise() + except PointParsingError as exc: + self.log.critical( + "Cannot set stop cycle point: %s: %s" % (stop_string, exc)) + return + self.log.info( "Setting stop cycle point: %s" % stop_string ) self.pool.set_stop_point(self.stop_point) def set_stop_clock( self, unix_time, date_time_string ): - self.log.info( "Setting stop clock time: " + date_time_string + - " (unix time: " + str(unix_time) + ")") + self.log.info( "Setting stop clock time: %s (unix time: %s)" % ( + date_time_string, unix_time)) self.stop_clock_time = unix_time self.stop_clock_time_string = date_time_string diff --git a/lib/cylc/task_pool.py b/lib/cylc/task_pool.py index 701ca2002ce..a250ca119b0 100644 --- a/lib/cylc/task_pool.py +++ b/lib/cylc/task_pool.py @@ -21,6 +21,7 @@ import TaskID from batch_submit import task_batcher from task_types import task +from task_state import task_state from broker import broker import flags from Pyro.errors import NamingError, ProtocolError @@ -717,7 +718,7 @@ def remove_spent_cycling_tasks( self ): def reset_task_states( self, ids, state ): # we only allow resetting to a subset of available task states - if state not in [ 'ready', 'waiting', 'succeeded', 'failed', 'held', 'spawn' ]: + if state not in task_state.legal_for_reset: raise SchedulerError, 'Illegal reset state: ' + state tasks = [] diff --git a/lib/cylc/task_state.py b/lib/cylc/task_state.py index 30bdf349e57..ade8dda1409 100644 --- a/lib/cylc/task_state.py +++ b/lib/cylc/task_state.py @@ -31,17 +31,28 @@ def __str__( self ): class task_state(object): - legal = [ 'waiting', - 'held', - 'queued', - 'ready', - 'submitted', - 'submit-failed', - 'submit-retrying', - 'running', - 'succeeded', - 'failed', - 'retrying' ] + legal = [ + 'waiting', + 'held', + 'queued', + 'ready', + 'submitted', + 'submit-failed', + 'submit-retrying', + 'running', + 'succeeded', + 'failed', + 'retrying' + ] + + legal_for_reset = [ + 'waiting', + 'held', + 'ready', + 'succeeded', + 'failed', + 'spawn' + ] @classmethod def is_legal( cls, state ): @@ -75,7 +86,6 @@ def is_legal( cls, state ): 'retrying' : "\033[1;35m", 'held' : "\033[1;37;43m", } - # spare: "\033[1;37;44m" ctrl_end = "\033[0m" diff --git a/lib/cylc/time_parser.py b/lib/cylc/time_parser.py index 1b7b3cd4fb9..abc09000d63 100644 --- a/lib/cylc/time_parser.py +++ b/lib/cylc/time_parser.py @@ -39,6 +39,9 @@ import isodatetime.parsers +UTC_UTC_OFFSET_HOURS_MINUTES = (0, 0) + + class CylcTimeSyntaxError(cylc.CylcError.CylcError): """An error denoting invalid ISO/Cylc input syntax.""" @@ -212,8 +215,6 @@ def parse_recurrence(self, expression, start_point=start_point, interval=interval, end_point=end_point - # min_point=context_start_point, - # max_point=context_end_point ) raise CylcTimeSyntaxError("Could not parse %s" % expression) @@ -298,13 +299,17 @@ def setUp(self): # Note: the following timezone will be Z-ified *after* truncation # or offsets are applied. self._end_point = "20010506T1200+0200" - self._parsers = {0: CylcTimeParser(self._start_point, - self._end_point, - assumed_time_zone=(0, 0)), - 2: CylcTimeParser(self._start_point, - self._end_point, - num_expanded_year_digits=2, - assumed_time_zone=(0, 0))} + self._parsers = { + 0: CylcTimeParser( + self._start_point, self._end_point, + assumed_time_zone=UTC_UTC_OFFSET_HOURS_MINUTES + ), + 2: CylcTimeParser( + self._start_point, self._end_point, + num_expanded_year_digits=2, + assumed_time_zone=UTC_UTC_OFFSET_HOURS_MINUTES + ) + } def test_first_recurrence_format(self): """Test the first ISO 8601 recurrence format.""" From 72f627157156a4bee99eaa331785ebf3029d2519 Mon Sep 17 00:00:00 2001 From: Ben Fitzpatrick Date: Thu, 17 Jul 2014 16:58:25 +0100 Subject: [PATCH 2/2] #996: fix bugs picked up in review --- lib/cylc/graphing.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/cylc/graphing.py b/lib/cylc/graphing.py index b4387fc62fa..0dc8e83d368 100644 --- a/lib/cylc/graphing.py +++ b/lib/cylc/graphing.py @@ -60,9 +60,9 @@ def style_node( self, node_string, autoURL, base=False ): if base: # TODO - This is only called from cylc_add_edge in this # base class ... should it also be called from add_node? - node.attr[ 'URL' ] = 'base:' + n + node.attr[ 'URL' ] = 'base:' + node_string else: - node.attr['URL'] = n + node.attr['URL'] = node_string def cylc_add_node( self, node_string, autoURL, **attr ): pygraphviz.AGraph.add_node( self, node_string, **attr )