Exemple #1
0
class MyNode(Node):
    p1 = Param()
    p2 = Param()

    def param_touched(self, param_name):
        if param_name == 'p1':
            self.p2.touch()
Exemple #2
0
class ComplexNode(Node):
    p1 = Param()
    p2 = Param()

    def param_touched(self, param_name):
        if param_name == 'p1':
            self.p2.touch()

    child1 = Child(MyNode)
    child2 = Child(MyNode)
Exemple #3
0
class NamingNode(Node):
    in_naming = Param()
    config = Param({})
    out_naming = ComputedParam()

    def _configure(self):
        super(NamingNode, self)._configure()
        parent = self.parent()
        if not parent:
            raise Exception('NamingNode cannot be a root')
        
        # default config is class_name:node_id
        self.config.set({parent.__class__.__name__:parent.node_id})
        
        # output is for parent _naming:
        parent._naming.add_source(self.out_naming)
        
        # input is from grand parent naming, or empty
        gparent = parent.parent()
        if not gparent:
            self.in_naming.set({})
        elif not gparent.has_param('_naming'):
            self.in_naming.set({'Project':gparent.node_id})
        else:
            self.in_naming.add_source(gparent._naming)
    
    def param_touched(self, param_name):
        if param_name in ('in_naming', 'config'):
            self.out_naming.touch()
            
    def compute(self, param_name):
        if param_name == 'out_naming':
            cfg = dict(self.in_naming.get() or {})
            config = self.config.get()
            if config:
                # Update cfg and remove the key with None value:
                for k, v in config.items():
                    if v is None:
                        try:
                            del cfg[k]
                        except KeyError:
                            pass
                    else:
                        cfg[k] = v
            self.out_naming.set(cfg)
Exemple #4
0
class MyNode(Node):
    p1 = Param()
    p2 = Param()
    mult = ComputedParam()

    def param_touched(self, param_name):
        if param_name in ('p1', 'p2'):
            self.mult.touch()

    def compute(self, param_name):
        if param_name == 'mult':
            p1 = self.p1.get()
            if not isinstance(p1, int):
                raise Exception('Invalid value for param p1: must be int')
            p2 = self.p2.get()
            if not isinstance(p2, int):
                raise Exception('Invalid value for param p2: must be int')

            self.mult.set(p1 * p2)
Exemple #5
0
class TaskGroup(NamedNode):
    ICON_NAME = 'action'

    with param_group('Tasks'):
        tasks_statuses = Param({}, sources_as_dict=True).ui(editor='status_sumary')
        tasks_progresses = Param({}, sources_as_dict=True)
        status = ComputedParam()
        progress = ComputedParam().ui(editor='percent')

    _status_manager = Child(TaskGroupStatus) # NB: this is a status summary, it does not affect a param 
    notes = Child(NoteThread)

    def _configure(self):
        super(TaskGroup, self)._configure()
        for _, child in self.iterchildren():
            if child.has_param('status'):
                self.tasks_statuses.add_source(child.status)
            if child.has_param('progress'):
                self.tasks_progresses.add_source(child.progress)

    def param_touched(self, param_name):
        if param_name == 'tasks_progresses':
            self.progress.touch()
            
        elif param_name == 'progress':
            self.status.touch()
            
    def compute(self, param_name):
        if param_name == 'progress':
            self.progress.set(
                self._status_manager.get_average_progress(
                    (self.tasks_progresses.get() or {}).values()
                )
            )
                
        if param_name == 'status':
            self.status.set(
                self._status_manager.get_status(
                    self.progress.get()
                )
            )
Exemple #6
0
class NamedNode(Node):
    with param_group('_Naming', group_index=1000):
        _naming = Param()

    _namer = Child(NamingNode)

    def set_namer_config(self, **config):
        self._namer.config.set(config)
    
    def add_namer_config(self, **config):
        cfg = self._namer.config.get() or {}
        cfg.update(config)
        self._namer.config.set(cfg)
        
    def set_namer_from_id(self, key=None):
        key = key or self.__class__.__name__
        self._namer.config.set({key:self.node_id})
Exemple #7
0
class NodeWithRelations(Node):
    nwr_param = Param()
    
    contained = Many(CasedNode)
Exemple #8
0
class CasedNode(Node):
    node_param = Param()
    node_case_param = CaseParam(default='Case Param Default')
    
    c1 = Child(ChildNode).configure('Param in c1')
    c2 = Child(ChildNode).configure('Param in c2')
Exemple #9
0
class ChildNode(Node):
    child_param = Param()
    
    def configure(self, value):
        self.child_param.set(value)
Exemple #10
0
class Scheduled(TaskGroup):
    ICON_NAME = 'scheduled'

    AFTER_PREV_END = 'After Previous End'
    AFTER_PREV_START = 'After Previous Start'
    FIXED_START = 'Fixed Start Date'
    SCHEDULE_MODES = (
        AFTER_PREV_END,
        AFTER_PREV_START,
        FIXED_START,
    )

    with param_group('Planning'):
        schedule_mode = CaseParam().ui(
            editor='choice', editor_options={'choices': SCHEDULE_MODES})
        fixed_start_date = CaseParam().ui(editor='date')
        start_offset = CaseParam().ui(editor='int')
        start_date = ComputedParam().ui(editor='date')
        work_days = CaseParam().ui(editor='int')
        end_date = ComputedParam().ui(editor='date')

    with param_group('Planning Dependencies'):
        dep_start_dates = Param().ui(editor='date')
        dep_end_dates = Param().ui(editor='date')

    with param_group('Assigned'):
        manager = CaseParam().ui(editor='node_ref',
                                 editor_options={'root_name': 'resources'})
        lead = CaseParam().ui(editor='node_ref',
                              editor_options={'root_name': 'resources'})
        user_groups = CaseParam().ui(editor='node_refs',
                                     editor_options={'root_name': 'resources'})

    def add_dependency(self, scheduled):
        self.dep_start_dates.add_source(scheduled.start_date)
        self.dep_end_dates.add_source(scheduled.end_date)

    def param_touched(self, param_name):
        if param_name in ('schedule_mode', 'fixed_start_date', 'start_offset',
                          'dep_start_dates', 'dep_end_dates'):
            self.start_date.touch()
        elif param_name in ('start_date', 'work_days'):
            self.end_date.touch()
        else:
            return super(Scheduled, self).param_touched(param_name)

    def compute(self, param_name):
        if param_name == 'start_date':
            mode = self.schedule_mode.get()

            if mode == self.FIXED_START:
                self.start_date.set(
                    self.fixed_start_date.get() +
                    datetime.timedelta(self.start_offset.get() or 0))

            elif not mode or mode == self.AFTER_PREV_END:
                prev_end = self.dep_end_dates.get()
                if prev_end is None:
                    raise Exception(
                        'Cannot use schedule mode %r without a dependency.' %
                        (mode, ))
                self.start_date.set(
                    prev_end +
                    datetime.timedelta(self.start_offset.get() or 0))

            elif mode == self.AFTER_PREV_START:
                prev_start = self.dep_start_dates.get()
                if prev_start is None:
                    raise Exception(
                        'Cannot use schedule mode %r without a dependency.' %
                        (mode, ))
                self.start_date.set(
                    prev_start +
                    datetime.timedelta(self.start_offset.get() or 0))

            else:
                raise Exception('Unknown Schedule Mode %r' % (mode, ))

        elif param_name == 'end_date':
            start = self.start_date.get()
            if start is None:
                raise Exception('Cannot find end date without start date')
            self.end_date.set(start +
                              datetime.timedelta(self.work_days.get() or 0))

        else:
            return super(Scheduled, self).compute(param_name)
Exemple #11
0
class BrowseCmdNode(ProcNode):
    NEEDED_FEATURES = ['kabaret']
    ICON_NAME = 'editor_proc' 

    filename = Param().tag('filename')
    folder = ComputedParam()
    existing_folder = ComputedParam()
    
    def _needs_to_run(self, ups_needs_to_run):
        # This proc is not intended to be dependent on 
        # upstream procs. It should run whenever requested:
        return True, 'By User Request'
    
    def param_touched(self, param_name):
        if param_name == 'filename':
            self.folder.touch()
            return

        if param_name == 'folder':
            self.existing_folder.touch()
            return

        super(BrowseCmdNode, self).param_touched(param_name)
        
    def compute(self, param_name):
        if param_name == 'folder':
            self.folder.set(
                os.path.dirname(self.filename.get() or '')
            )
            return
        
        if param_name == 'existing_folder':
            p = self.folder.get()
            deepest_folder = ''
            while p:
                if os.path.exists(p):
                    deepest_folder = p
                    break
                p, _ = os.path.split(p)
            self.existing_folder.set(p)
            return 
        
        super(BrowseCmdNode, self).compute(param_name)

    def validate_execution_context(self, context):
        folder = self.folder.get()
        existing_folder = self.existing_folder.get()
        if folder == existing_folder:
            context.allow_exec = True
            context.why = None
            return
        
        if not context.get_value('Open this instead', ''):
            context.set_param(
                'Open this instead',
                existing_folder,
                doc='''
The path %r does not exists, the deepest existing folder is %r.
(Clear the value to update the deepest existing folder)
                '''%(folder, existing_folder))
            
        if not context.has_param('Confirm'):
            context.set_param(
                'Confirm',
                False,
                editor='bool',
                doc='Check this to allow execution'
            )
            context.allow_exec = False
            context.why = 'Please confirm'
        else:
            if context.get_value('Confirm'):
                context.allow_exec = True
                context.why = 'Confirmed'
            else:
                context.allow_exec = False
                context.why = 'Please confirm'
            
    def process(self, context, worker):
        if context.has_param('Open this instead'):
            path = context.get_value('Open this instead')
        else:
            path = self.existing_folder.get()
        
        # Get the system command and its env:
        station_class = worker.get_station_class()
        cmd = self.flow().get_client_system_cmd(station_class, 'BROWSE')
        if 'window' in station_class.lower():
            path = path.replace('/', '\\')
        
        additional_env = cmd['additional_env']
        additional_env['KABARET_FOCUS_ID'] = repr(self.uid())
        
        # define a launcher function:
        def run_sys_cmd(executable, args, env, additional_env):
            import kabaret.core.syscmd
            cmd = kabaret.core.syscmd.SysCmd(
                executable, args, env, additional_env
            )
            cmd.execute()
            
        # trigger the launcher function on the worker
        with worker.busy():
            worker.send_func(run_sys_cmd)
            worker.call(
                'run_sys_cmd', 
                cmd['executable'], 
                [path], 
                cmd['env'], additional_env
            ) 
Exemple #12
0
class FileNode(NamedNode):
    
    thumbnail = ComputedParam().tag('preview').ui(editor='thumbnail', group_index=-1, index=-1)
    
    with param_group('Previous File'):
        prev_filename = Param().tag('filename')
        prev_mtime = Param().ui(editor='timestamp')
        
    with param_group('File'):
        filename = ComputedParam().tag('filename')
        exists = ComputedParam()
        mtime = ComputedParam().ui(editor='timestamp')
        
    def set_prev_file(self, file_node):
        self.prev_filename.disconnect()
        self.prev_filename.add_source(file_node.filename)
        
        self.prev_mtime.disconnect()
        self.prev_mtime.add_source(file_node.mtime)

    browse = Proc(BrowseCmdNode)
    
    def _configure(self):
        super(FileNode, self)._configure()
        self.browse.filename.add_source(self.filename)
        self.set_ticked()

    def tick(self):
        '''
        Checks for mtime modifications and update it
        if needed.
        '''
        # Skip tick when it might come from a touch of the params used here:
        # (it could lead to a loop)
        if self.exists.is_dirty() or self.mtime.is_dirty() or self.filename.is_dirty():
            return
        
        # Check file existence first
        filename = self.filename.get()
        if not os.path.exists(filename):
            if self.exists.get():
                self.exists.touch()
            return
        elif not self.exists.get():
            self.exists.touch()
            return
        
        curr_mtime = self.mtime.get()
        real_mtime = os.stat(filename)[stat.ST_MTIME]   
        if real_mtime != curr_mtime:
            self.mtime.touch()
            
    def param_touched(self, param_name):
        if param_name == '_naming':
            self.filename.touch()
        elif param_name == 'filename':
            self.exists.touch()
            self.thumbnail.touch()
        elif param_name == 'exists':
            self.mtime.touch()
        else:
            super(FileNode, self).param_touched(param_name)
            
    def compute(self, param_name):
        if param_name == 'filename':
            config = self._naming.get()
            named = self.flow().get_named(config)
            self.filename.set(named.path())
            
        elif param_name == 'exists':
            filename = self.filename.get()
            if not filename:
                self.exists.set(False)
            else:
                self.exists.set(os.path.exists(filename))
        
        elif param_name == 'mtime':
            if not self.exists.get():
                self.mtime.set(0)
            else:
                filename = self.filename.get()
                self.mtime.set(
                    os.stat(filename)[stat.ST_MTIME]
                )

        elif param_name == 'thumbnail':
            dir, name = os.path.split(self.filename.get())
            thumbnail = os.path.join(dir, '.thumbnails', name+'.png')
            self.thumbnail.set(thumbnail)