def initial_adjust_up(self, T): """Adjust T up to the next valid cycle time if not already valid.""" try: # is T a legal cycle time ct(T) except CycleTimeError, x: raise CyclerError, str(x)
def graph_suite( reg, is_warm, ofile, start, stop, graph_opts, gcapture_windows, tmpdir, window=None ): """Launch the cylc graph command with some options.""" options = graph_opts if ofile != '': options += ' -o ' + ofile if True: if start != '': try: ct(start) except CycleTimeError,x: warning_dialog( str(x), window ).warn() return False if stop != '': if start == '': warning_dialog( "You cannot override Final Cycle without " + "overriding Initial Cycle.").warn() return False try: ct(stop) except CycleTimeError,x: warning_dialog( str(x), window ).warn() return False
def initial_adjust_up( self, T ): """Adjust T up to the next valid cycle time if not already valid.""" foo = ct( T ) # first get HH right if foo.hour == self.HH: # initial time is already valid pass else: # adjust up: must be suite start-up if int(foo.hour) < int(self.HH): # round up foo.parse( foo.strvalue[0:8] + self.HH ) else: # round down and increment by a day foo.parse( foo.strvalue[0:8] + self.HH ) foo.increment( days=1 ) # now adjust up relative to the anchor cycle and step diff = foo.subtract( ct(self.anchorYYYYMMDD) ) rem = diff.days % self.step if rem > 0: n = self.step - rem foo.increment( days=n ) return foo.get()
def focused_timezoom_popup( self, w, id ): window = gtk.Window() window.modify_bg( gtk.STATE_NORMAL, gtk.gdk.color_parse( self.log_colors.get_color())) window.set_border_width(5) window.set_title( "Cycle-Time Zoom") parent_window = self.xdot.widget.get_toplevel() if isinstance(parent_window, gtk.Window): window.set_transient_for( parent_window ) window.set_type_hint( gtk.gdk.WINDOW_TYPE_HINT_DIALOG ) vbox = gtk.VBox() name, ctime = id.split('%') # TO DO: do we need to check that oldeset_ctime is defined yet? cti = ct(ctime) octi = ct( self.x.oldest_ctime ) ncti = ct( self.x.newest_ctime ) diff_pre = cti.subtract_hrs( octi ) diff_post = ncti.subtract_hrs( cti ) # TO DO: 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 ) box = gtk.HBox() 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 ) cancel_button = gtk.Button( "_Close" ) cancel_button.connect("clicked", lambda x: window.destroy() ) reset_button = gtk.Button( "_Reset (No Zoom)" ) reset_button.connect("clicked", self.focused_timezoom_direct, None ) apply_button = gtk.Button( "_Apply" ) apply_button.connect("clicked", self.focused_timezoom, ctime, start_entry, stop_entry ) #help_button = gtk.Button( "_Help" ) #help_button.connect("clicked", helpwindow.stop_guide ) hbox = gtk.HBox() hbox.pack_start( apply_button, False ) hbox.pack_start( reset_button, False ) hbox.pack_end( cancel_button, False ) #hbox.pack_end( help_button, False ) vbox.pack_start( hbox ) window.add( vbox ) window.show_all()
def focused_timezoom_popup( self, w, id ): window = gtk.Window() window.modify_bg( gtk.STATE_NORMAL, gtk.gdk.color_parse( self.log_colors.get_color())) window.set_border_width(5) window.set_title( "Cycle-Time Zoom") parent_window = self.xdot.widget.get_toplevel() if isinstance(parent_window, gtk.Window): window.set_transient_for( parent_window ) window.set_type_hint( gtk.gdk.WINDOW_TYPE_HINT_DIALOG ) vbox = gtk.VBox() name, ctime = id.split(TaskID.DELIM) # TODO - do we need to check that oldeset_ctime is defined yet? cti = ct(ctime) octi = ct( self.t.oldest_ctime ) ncti = ct( self.t.newest_ctime ) diff_pre = cti.subtract_hrs( octi ) diff_post = ncti.subtract_hrs( cti ) # 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 ) box = gtk.HBox() 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 ) cancel_button = gtk.Button( "_Close" ) cancel_button.connect("clicked", lambda x: window.destroy() ) reset_button = gtk.Button( "_Reset (No Zoom)" ) reset_button.connect("clicked", self.focused_timezoom_direct, None ) apply_button = gtk.Button( "_Apply" ) apply_button.connect("clicked", self.focused_timezoom, ctime, start_entry, stop_entry ) hbox = gtk.HBox() hbox.pack_start( apply_button, False ) hbox.pack_start( reset_button, False ) hbox.pack_end( cancel_button, False ) #hbox.pack_end( help_button, False ) vbox.pack_start( hbox ) window.add( vbox ) window.show_all()
def focused_timezoom(self, w, focus_ctime, start_e, stop_e): pre_hours = start_e.get_text() post_hours = stop_e.get_text() foo = ct(focus_ctime) foo.decrement( hours=pre_hours ) self.x.start_ctime = foo.get() bar = ct(focus_ctime) bar.increment( hours=post_hours ) self.x.stop_ctime = bar.get() self.x.best_fit = True self.x.action_required = True
def focused_timezoom(self, w, focus_ctime, start_e, stop_e): pre_hours = start_e.get_text() post_hours = stop_e.get_text() foo = ct(focus_ctime) foo.decrement( hours=pre_hours ) self.t.focus_start_ctime = foo.get() bar = ct(focus_ctime) bar.increment( hours=post_hours ) self.t.focus_stop_ctime = bar.get() self.t.best_fit = True self.t.action_required = True
def sub_months(current_date, N): """Subtract N months from current_date; works for positive or negative N.""" start_date = current_date.get_datetime() s_year = start_date.year s_month = start_date.month s_day = start_date.day dyear = N / 12 year = s_year - dyear dmonth = N % 12 if dmonth >= s_month: year = year - 1 month = 12 - (dmonth - s_month) else: month = s_month - dmonth day = s_day days_next = calendar.monthrange(year, month)[1] if day > days_next: day = days_next return ct(start_date.replace(year, month, day))
def __init__( self, T=None, step=1 ): """Store HH, step, and anchor.""" # check input validity try: T = ct( T ).get() except CycleTimeError, x: raise CyclerError, str(x)
def __init__( self, T=None, step=1 ): """Store anniversary date, step, and anchor.""" # check input validity try: T = ct( T ).get() # allows input of just YYYY except CycleTimeError, x: raise CyclerError, str(x)
def prev( self, T ): """Jump to the previous valid hour in the list.""" foo = ct(T) # cheat: decrement one hour and then call adjust_dn() foo.decrement(hours=1) bar = self.adjust_dn(foo.get()) return bar
def next( self, T ): """Jump to the next valid hour in the list.""" foo = ct(T) # cheat: add one hour and then call initial_adjust_up() foo.increment(hours=1) bar = self.initial_adjust_up(foo.get()) return bar
def next(self, T): """Jump to the next valid hour in the list.""" foo = ct(T) # cheat: add one hour and then call initial_adjust_up() foo.increment(hours=1) bar = self.initial_adjust_up(foo.get()) return bar
def sub_months(current_date, N): """Subtract N months from current_date; works for positive or negative N.""" start_date = current_date.get_datetime() s_year = start_date.year s_month = start_date.month s_day = start_date.day dyear = N / 12 year = s_year - dyear dmonth = N % 12 if dmonth >= s_month: year = year - 1 month = 12 - (dmonth - s_month) else: month = s_month - dmonth day = s_day days_next = calendar.monthrange(year, month)[1] if day > days_next: day = days_next return ct( start_date.replace(year, month, day) )
def _coerce_cycletime( value, keys, args ): """Coerce value to a cycle time.""" value = _strip_and_unquote( keys, value ) try: return ct( value ).get() except: #raise raise IllegalValueError( 'cycle time', keys, value )
def start_time_reached( self ): reached = False # check current time against expected start time rt = ct( self.c_time ).get_datetime() delayed_start = rt + datetime.timedelta( 0,0,0,0,0,self.real_time_delay,0 ) if now() >= delayed_start: reached = True return reached
def start_time_reached( self ): reached = False # check current time against expected start time rt = ct( self.c_time ).get_datetime() delayed_start = rt + datetime.timedelta( 0,0,0,0,0,self.real_time_delay,0 ) current_time = clocktriggered.clock.get_datetime() if current_time >= delayed_start: reached = True return reached
def __init__(self, T=None, step=1): """Store anniversary date, step, and anchor.""" self.c_offset = 0 # check input validity try: T = ct(T).get() # allows input of just YYYY except CycleTimeError, x: raise CyclerError, str(x)
def __init__( self, T=None, step=1 ): """Store HH, step, and anchor.""" self.c_offset = 0 # check input validity try: T = ct( T ).get() except CycleTimeError, x: raise CyclerError, str(x)
def __init__( self, T=None, step=1 ): """Store date, step, and anchor.""" self.c_offset = 0 # check input validity try: T = ct( T ).get() # allows input of just YYYYMM except CycleTimeError, x: raise CyclerError, str(x)
def start_time_reached( self ): if self.trigger_now: return True reached = False # check current time against expected start time rt = ct( self.c_time ).get_datetime() delayed_start = rt + datetime.timedelta( 0,0,0,0,0,self.real_time_delay,0 ) current_time = clocktriggered.clock.get_datetime() if current_time >= delayed_start: reached = True return reached
def initial_adjust_up( self, T ): """Adjust T up to the next valid cycle time if not already valid.""" adjusted = ct( T ) rh = int(adjusted.hour) incr = None for vh in self.valid_hours: if rh <= vh: incr = vh - rh break if incr == None: incr = 24 - rh + self.valid_hours[0] adjusted.increment( hours=incr ) return adjusted.get()
def initial_adjust_up(self, T): """Adjust T up to the next valid cycle time if not already valid.""" adjusted = ct(T) rh = int(adjusted.hour) incr = None for vh in self.valid_hours: if rh <= vh: incr = vh - rh break if incr == None: incr = 24 - rh + self.valid_hours[0] adjusted.increment(hours=incr) return adjusted.get()
def valid( self, CT ): """Is CT a member of my cycle time sequence?""" foo = CT.get() res = True if foo[8:10] != self.HH: # wrong HH res = False else: # right HH, check the day is valid diff = CT.subtract( ct(self.anchorYYYYMMDD) ) rem = diff.days % self.step if rem != 0: res = False return res
def adjust_dn( self, T ): """Adjust T down to the next valid cycle time if not already valid.""" adjusted = ct( T ) rh = int(adjusted.hour) decr = None for vh in reversed(self.valid_hours): if rh >= vh: decr = rh - vh break if decr == None: # vh is < first valid hour decr = 24 + rh - self.valid_hours[-1] adjusted.decrement( hours=decr ) return adjusted.get()
def graph_suite( reg, start, stop, graph_opts, gcapture_windows, tmpdir, template_opts, window=None ): """Launch the cylc graph command with some options.""" options = graph_opts if True: if start != '': try: ct(start) except CycleTimeError,x: warning_dialog( str(x), window ).warn() return False if stop != '': if start == '': warning_dialog( "You cannot override Final Cycle without " + "overriding Initial Cycle.").warn() return False try: ct(stop) except CycleTimeError,x: warning_dialog( str(x), window ).warn() return False
def initial_adjust_up( self, T ): """Adjust T up to the next valid cycle time if not already valid.""" foo = ct( T ) # first get HH right if foo.hour == self.HH: # initial time is already valid pass else: # adjust up: must be suite start-up if int(foo.hour) < int(self.HH): # round up foo.parse( foo.strvalue[0:8] + self.HH ) else: # round down and increment by a day foo.parse( foo.strvalue[0:8] + self.HH ) foo.increment( days=1 ) # now adjust up to the next on-sequence cycle diff = ct(self.anchorYYYYMMDD).subtract( foo ) rem = diff.days % self.step foo.increment( days=rem ) return foo.get()
def next(self, T): """Add step years to get to the anniversary after T.""" return add_years(ct(T), self.step).get()
def prev(self, T): """Subtract step years to get to the anniversary before T.""" return sub_years(ct(T), self.step).get()
def initial_adjust_up(self, T): """Adjust T up to the next valid cycle time if not already valid.""" try: # is T a legal cycle time ct(T) except CycleTimeError, x: raise CyclerError, str(x) # first get the anniversary date MMDDHHmmss right if T[4:] < self.MMDDHHmmss: # just round up T = T[0:4] + self.MMDDHHmmss elif T[4:] > self.MMDDHHmmss: # increment the year and round up T = add_years(ct(T), 1).get()[0:4] + self.MMDDHHmmss else: # equal: no need to adjust pass # now adjust year up if necessary, according to anchor step diff = int(self.anchorDate[0:4]) - int(T[0:4]) rem = diff % self.step T = add_years(ct(T), rem).get()[0:4] + self.MMDDHHmmss return T def prev(self, T): """Subtract step years to get to the anniversary before T.""" return sub_years(ct(T), self.step).get()
def initial_adjust_up(self, T): """Adjust T up to the next valid cycle time if not already valid.""" try: # is T a legal cycle time ct(T) except CycleTimeError, x: raise CyclerError, str(x) # first get the monthiversary date DDHHmmss right if T[6:] < self.DDHHmmss: # just round up T = T[0:6] + self.DDHHmmss elif T[6:] > self.DDHHmmss: # increment the moth and round up T = add_months(ct(T), 1).get()[0:6] + self.DDHHmmss else: # equal: no need to adjust pass # now adjust up if necessary, according to step ta = 12 * int(self.anchorDate[0:4]) + int(self.anchorDate[4:6]) tc = 12 * int(T[0:4]) + int(T[4:6]) diff = ta - tc # difference in months from anchor date rem = diff % self.step return add_months(ct(T), rem).get()[0:6] + self.DDHHmmss def next(self, T): """Add step months to get to the next anniversary after T."""
def next( self, T ): """Add step days to T.""" foo = ct(T) foo.increment( days=self.step ) return foo.get()
def next(self, T): """Add step months to get to the next anniversary after T.""" return add_months(ct(T), self.step).get()
def offset(cls, T, n): """Decrement T by n years to the same MMDDHHmmss.""" return sub_years(ct(T), int(n)).get()
def update_graph(self): # To do: check edges against resolved ones # (adding new ones, and nodes, if necessary) self.oldest_ctime = self.global_summary['oldest cycle time'] self.newest_ctime = self.global_summary['newest cycle time'] if self.focus_start_ctime: oldest = self.focus_start_ctime newest = self.focus_stop_ctime else: oldest = self.oldest_ctime newest = self.newest_ctime start_time = self.global_summary['start time'] rawx = None if start_time == None or oldest > start_time: rawx = True else: # (show cold start tasks) - TO DO: actual raw start rawx = False extra_node_ids = {} # TO DO: mv ct().get() out of this call (for error checking): # TO DO: remote connection exception handling? try: gr_edges = self.sinfo.get( 'graph raw', ct(oldest).get(), ct(newest).get(), rawx, self.group, self.ungroup, self.ungroup_recursive, self.group_all, self.ungroup_all) except Exception: # PyroError return False extra_ids = [] for id in self.state_summary: try: node = self.graphw.get_node( id ) except AttributeError: # No graphw yet. break except KeyError: name, tag = id.split(TaskID.DELIM) if any( [name in self.families[fam] for fam in self.graphed_family_nodes] ): # if task name is a member of a family omit it #print 'Not graphing family-collapsed node', id continue state = self.state_summary[id]['state'] if state == 'submitted' or state == 'running' or state == 'failed' or state == 'held': if id not in extra_ids: extra_ids.append( id ) current_id = self.get_graph_id( gr_edges, extra_ids ) needs_redraw = current_id != self.prev_graph_id if needs_redraw: #Get a graph object self.graphw = graphing.CGraphPlain( self.cfg.suite ) # sort and then add edges in the hope that edges added in the # same order each time will result in the graph layout not # jumping around (does this help? -if not discard) gr_edges.sort() for e in gr_edges: l, r, dashed, suicide, conditional = e style=None arrowhead='normal' if dashed: style='dashed' if suicide: style='dashed' arrowhead='dot' if conditional: arrowhead='onormal' self.graphw.cylc_add_edge( l, r, True, style=style, arrowhead=arrowhead ) for n in self.graphw.nodes(): # base node defaults n.attr['style'] = 'filled' n.attr['color'] = '#888888' n.attr['fillcolor'] = 'white' n.attr['fontcolor'] = '#888888' self.group = [] self.ungroup = [] self.group_all = False self.ungroup_all = False self.ungroup_recursive = False self.rem_nodes = [] # FAMILIES if needs_redraw: for node in self.graphw.nodes(): name, tag = node.get_name().split(TaskID.DELIM) if name in self.family_nodes: if name in self.graphed_family_nodes: node.attr['shape'] = 'doubleoctagon' else: node.attr['shape'] = 'doublecircle' # CROPPING if self.crop: for node in self.graphw.nodes(): #if node in self.rem_nodes: # continue #if node.get_name() not in self.state_summary and \ # len( self.graphw.successors( node )) == 0: # self.remove_empty_nodes( node ) if node.get_name() not in self.state_summary: self.rem_nodes.append(node) continue # FILTERING: for node in self.graphw.nodes(): id = node.get_name() name, ctime = id.split(TaskID.DELIM) if self.filter_exclude: if re.match( self.filter_exclude, name ): if node not in self.rem_nodes: self.rem_nodes.append(node) if self.filter_include: if not re.match( self.filter_include, name ): if node not in self.rem_nodes: self.rem_nodes.append(node) if self.state_filter: if id in self.state_summary: state = self.state_summary[id]['state'] if state in self.state_filter: if node not in self.rem_nodes: self.rem_nodes.append(node) # remove_nodes_from( nbunch ) - nbunch is any iterable container. self.graphw.remove_nodes_from( self.rem_nodes ) #print '____' #print self.families #print #print self.family_nodes #print #print self.graphed_family_nodes #print '____' for id in self.state_summary: try: node = self.graphw.get_node( id ) except KeyError: # This live task proxy is not represented in the graph. # But it is live so if its state is deemed interesting # plot it off to the right of the main graph. # Tasks in this category include: members of collapsed # families; tasks outside of the current focus range (if # one is set), inserted tasks that are defined under # [runtime] but not used in the suite graph. # Now that we have family state coloring with family # member states listed in tool-tips, don't draw # off-graph family members: name, tag = id.split(TaskID.DELIM) if any( [name in self.families[fam] for fam in self.graphed_family_nodes] ): # if task name is a member of a family omit it #print 'Not graphing family-collapsed node', id continue if id not in self.graph_warned or not self.graph_warned[id]: print >> sys.stderr, 'WARNING: ' + id + ' is outside of the main graph.' self.graph_warned[id] = True state = self.state_summary[id]['state'] if state == 'submitted' or state == 'running' or state == 'failed' or state == 'held': if state not in extra_node_ids: extra_node_ids[state] = [id] else: extra_node_ids[state].append(id) continue else: continue self.set_live_node_attr( node, id ) for id in self.fam_state_summary: try: node = self.graphw.get_node( id ) except: continue self.set_live_node_attr( node, id ) # TO DO: ?optional transitive reduction: # self.graphw.tred() self.graphw.graph_attr['rankdir'] = self.orientation # process extra nodes (important nodes outside of focus range, # and family members that aren't plotted in the main graph). if needs_redraw: for state in extra_node_ids: for id in extra_node_ids[state]: self.graphw.cylc_add_node( id, True ) node = self.graphw.get_node(id) self.set_live_node_attr( node, id, shape='box') # add invisible edges to force vertical alignment for i in range( 0, len(extra_node_ids[state])): if i == len(extra_node_ids[state]) -1: break self.graphw.cylc_add_edge( extra_node_ids[state][i], extra_node_ids[state][i+1], True, style='invis') self.action_required = False if self.live_graph_movie: self.graph_frame_count += 1 arg = os.path.join( self.live_graph_dir, 'live' + '-' + \ str( self.graph_frame_count ) + '.dot' ) self.graphw.write( arg ) self.prev_graph_id = current_id return not needs_redraw
def initial_adjust_up(self, T): """Adjust T up to the next valid cycle time if not already valid.""" try: # is T a legal cycle time ct(T) except CycleTimeError, x: raise CyclerError, str(x) # first get the anniversary date MMDDHHmmss right if T[4:] < self.MMDDHHmmss: # just round up T = T[0:4] + self.MMDDHHmmss elif T[4:] > self.MMDDHHmmss: # increment the year and round up T = add_years(ct(T), 1).get()[0:4] + self.MMDDHHmmss else: # equal: no need to adjust pass # now adjust year up if necessary, according to anchor step diff = int(self.anchorDate[0:4]) - int(T[0:4]) rem = diff % self.step T = add_years(ct(T), rem).get()[0:4] + self.MMDDHHmmss return T def next(self, T): """Add step years to get to the next anniversary after T.""" return add_years(ct(T), self.step).get()
def offset(cls, T, n): # decrement n hours foo = ct(T) foo.decrement(hours=int(n)) return foo.get()
def offset( cls, T, n ): # decrement n hours foo = ct(T) foo.decrement(hours=int(n)) return foo.get()
bar = self.initial_adjust_up(foo.get()) return bar def valid( self, CT ): """Return True if CT.hour is in my list of valid hours.""" if int(CT.hour) in self.valid_hours: return True else: return False if __name__ == "__main__": # UNIT TEST inputs = [ \ ('0','12'), \ ('0','6','12','18'), \ ('3', '6','9','12', '15', '18'), \ ('0', 'x')] for i in inputs: print i try: foo = HoursOfTheDay( *i ) print ' + next(2010080800):', foo.next('2010080800' ) print ' + initial_adjust_up(2010080823):', foo.initial_adjust_up( '2010080823' ) print ' + valid(2012080900):', foo.valid( ct('2012080900') ) print ' + valid(201108019):', foo.valid( ct('2011080819') ) except Exception, x: print ' !', x
def _coerce_cycletime(value, keys, args): """Coerce value to a cycle time.""" try: return ct(value).get() except: raise IllegalValueError('cycle time', keys, value)
def adjust_state(self, offset): self.c_offset = int(offset) self.anchorDate = sub_years(ct(self.anchorDate), self.c_offset).get()
def sub_years(current_date, N): """Subtract N years from current_date; works for positive or negative N.""" start_date = current_date.get_datetime() year = start_date.year - N return ct(start_date.replace(year))
def adjust_state( self, offset ): foo = ct( self.anchorYYYYMMDD ) foo.decrement( days=int(offset) ) self.c_offset = int(offset) self.anchorYYYYMMDD = foo.get()[0:8]
def adjust_state(self, offset): self.c_offset = int(offset) self.anchorDate = sub_months(ct(self.anchorDate), self.c_offset).get()
def offset( cls, T, n ): # decrement n days foo = ct(T) foo.decrement(days=int(n)) return foo.get()
def update_graph(self): # TODO - check edges against resolved ones # (adding new ones, and nodes, if necessary) self.oldest_ctime = self.global_summary['oldest cycle time'] if self.croprunahead: try: self.newest_ctime = self.global_summary['newest non-runahead cycle time'] except KeyError: # pre-5.4.0 suite daemon backward compatibility (crop runahead nodes) self.newest_ctime = self.global_summary['newest cycle time'] else: self.newest_ctime = self.global_summary['newest cycle time'] if self.focus_start_ctime: oldest = self.focus_start_ctime newest = self.focus_stop_ctime else: oldest = self.oldest_ctime newest = self.newest_ctime start_time = self.global_summary['start time'] rawx = None if start_time == None or oldest > start_time: rawx = True else: # (show cold start tasks) - TODO - actual raw start rawx = False extra_node_ids = {} # TODO - mv ct().get() out of this call (for error checking): # TODO - remote connection exception handling? try: res = self.updater.sinfo.get( 'graph raw', ct(oldest).get(), ct(newest).get(), rawx, self.group, self.ungroup, self.ungroup_recursive, self.group_all, self.ungroup_all) except Exception: # PyroError return False # backward compatibility for old suite daemons still running self.have_leaves_and_feet = False if isinstance( res, list ): # prior to suite-polling tasks in 5.4.0 gr_edges = res suite_polling_tasks = [] self.leaves = [] self.feet = [] else: if len( res ) == 2: # prior to graph view grouping fix in 5.4.2 gr_edges, suite_polling_tasks = res self.leaves = [] self.feet = [] elif len( res ) == 4: # 5.4.2 and later self.have_leaves_and_feet = True gr_edges, suite_polling_tasks, self.leaves, self.feet = res # find nodes not present in the main graph extra_ids = [] omit = [] for id in self.state_summary: if not any( id in edge for edge in gr_edges ): # this node is not present in the main graph name, tag = id.split(TaskID.DELIM) if any( [ name in self.descendants[fam] for fam in self.all_families ] ): # must be a member of a collapsed family, don't graph it omit.append(name) continue state = self.state_summary[id]['state'] if state in ['submitted','submit-failed','running','failed']: if id not in extra_ids: extra_ids.append( id ) current_id = self.get_graph_id( gr_edges, extra_ids ) needs_redraw = current_id != self.prev_graph_id if needs_redraw: self.graphw = graphing.CGraphPlain( self.cfg.suite, suite_polling_tasks ) self.graphw.add_edges( gr_edges, ignore_suicide=self.ignore_suicide ) for n in self.graphw.nodes(): # base node defaults n.attr['style'] = 'filled' n.attr['color'] = '#888888' n.attr['fillcolor'] = 'white' n.attr['fontcolor'] = '#888888' self.rem_nodes = [] # FAMILIES if needs_redraw: for node in self.graphw.nodes(): name, tag = node.get_name().split(TaskID.DELIM) if name in self.all_families: if name in self.triggering_families: node.attr['shape'] = 'doubleoctagon' else: node.attr['shape'] = 'tripleoctagon' # CROPPING if self.crop: for node in self.graphw.nodes(): #if node in self.rem_nodes: # continue #if node.get_name() not in self.state_summary and \ # len( self.graphw.successors( node )) == 0: # self.remove_empty_nodes( node ) if node.get_name() not in self.state_summary: self.rem_nodes.append(node) continue # FILTERING: for node in self.graphw.nodes(): id = node.get_name() name, ctime = id.split(TaskID.DELIM) if self.filter_exclude: if re.match( self.filter_exclude, name ): if node not in self.rem_nodes: self.rem_nodes.append(node) if self.filter_include: if not re.match( self.filter_include, name ): if node not in self.rem_nodes: self.rem_nodes.append(node) if self.state_filter: if id in self.state_summary: state = self.state_summary[id]['state'] if state in self.state_filter: if node not in self.rem_nodes: self.rem_nodes.append(node) # remove_nodes_from( nbunch ) - nbunch is any iterable container. self.graphw.remove_nodes_from( self.rem_nodes ) for id in self.state_summary: try: node = self.graphw.get_node( id ) except KeyError: # This live task proxy is not represented in the graph. # But it is live so if its state is deemed interesting # plot it off to the right of the main graph. # Tasks in this category include: members of collapsed # families; tasks outside of the current focus range (if # one is set), inserted tasks that are defined under # [runtime] but not used in the suite graph. # Now that we have family state coloring with family # member states listed in tool-tips, don't draw # off-graph family members: name, tag = id.split(TaskID.DELIM) if name in omit: # (see above) continue if id not in self.graph_warned or not self.graph_warned[id]: print >> sys.stderr, 'WARNING: ' + id + ' is outside of the main graph.' self.graph_warned[id] = True state = self.state_summary[id]['state'] if state == 'submitted' or state == 'running' or state == 'failed' or state == 'held': if state not in extra_node_ids: extra_node_ids[state] = [id] else: extra_node_ids[state].append(id) continue else: continue self.set_live_node_attr( node, id ) for id in self.fam_state_summary: try: node = self.graphw.get_node( id ) except: continue self.set_live_node_attr( node, id ) # TODO - ?optional transitive reduction: # self.graphw.tred() self.graphw.graph_attr['rankdir'] = self.orientation # process extra nodes (important nodes outside of focus range, # and family members that aren't plotted in the main graph). if needs_redraw: for state in extra_node_ids: for id in extra_node_ids[state]: self.graphw.cylc_add_node( id, True ) node = self.graphw.get_node(id) self.set_live_node_attr( node, id, shape='box') # add invisible edges to force vertical alignment for i in range( len(extra_node_ids[state])): if i == len(extra_node_ids[state]) -1: break self.graphw.cylc_add_edge( extra_node_ids[state][i], extra_node_ids[state][i+1], True, style='invis') self.action_required = False if self.live_graph_movie: self.graph_frame_count += 1 arg = os.path.join( self.live_graph_dir, 'live' + '-' + \ str( self.graph_frame_count ) + '.dot' ) self.graphw.write( arg ) self.prev_graph_id = current_id return not needs_redraw
return bar def valid(self, CT): """Return True if CT.hour is in my list of valid hours.""" if int(CT.hour) in self.valid_hours: return True else: return False if __name__ == "__main__": # UNIT TEST inputs = [ \ ('0','12'), \ ('0','6','12','18'), \ ('3', '6','9','12', '15', '18'), \ ('0', 'x')] for i in inputs: print i try: foo = HoursOfTheDay(*i) print ' + next(2010080800):', foo.next('2010080800') print ' + initial_adjust_up(2010080823):', foo.initial_adjust_up( '2010080823') print ' + valid(2012080900):', foo.valid(ct('2012080900')) print ' + valid(201108019):', foo.valid(ct('2011080819')) except Exception, x: print ' !', x
def offset(cls, T, n): """Decrement T by n months to the same DDHHmmss.""" return sub_months(ct(T), int(n)).get()