source: waflib/Task.py @ 4ed4b1f

feature/autosinkfeature/cnnfeature/cnn_orgfeature/constantqfeature/crepefeature/crepe_orgfeature/pitchshiftfeature/pydocstringsfeature/timestretchfix/ffmpeg5pitchshiftsamplertimestretchyinfft+
Last change on this file since 4ed4b1f was 0fa325b, checked in by Paul Brossier <piem@piem.org>, 11 years ago

waf: unpack

  • Property mode set to 100644
File size: 17.9 KB
Line 
1#! /usr/bin/env python
2# encoding: utf-8
3# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file
4
5import os,shutil,re,tempfile
6from waflib import Utils,Logs,Errors
7NOT_RUN=0
8MISSING=1
9CRASHED=2
10EXCEPTION=3
11SKIPPED=8
12SUCCESS=9
13ASK_LATER=-1
14SKIP_ME=-2
15RUN_ME=-3
16COMPILE_TEMPLATE_SHELL='''
17def f(tsk):
18        env = tsk.env
19        gen = tsk.generator
20        bld = gen.bld
21        wd = getattr(tsk, 'cwd', None)
22        p = env.get_flat
23        tsk.last_cmd = cmd = \'\'\' %s \'\'\' % s
24        return tsk.exec_command(cmd, cwd=wd, env=env.env or None)
25'''
26COMPILE_TEMPLATE_NOSHELL='''
27def f(tsk):
28        env = tsk.env
29        gen = tsk.generator
30        bld = gen.bld
31        wd = getattr(tsk, 'cwd', None)
32        def to_list(xx):
33                if isinstance(xx, str): return [xx]
34                return xx
35        tsk.last_cmd = lst = []
36        %s
37        lst = [x for x in lst if x]
38        return tsk.exec_command(lst, cwd=wd, env=env.env or None)
39'''
40def cache_outputs(cls):
41        m1=cls.run
42        def run(self):
43                bld=self.generator.bld
44                if bld.cache_global and not bld.nocache:
45                        if self.can_retrieve_cache():
46                                return 0
47                return m1(self)
48        cls.run=run
49        m2=cls.post_run
50        def post_run(self):
51                bld=self.generator.bld
52                ret=m2(self)
53                if bld.cache_global and not bld.nocache:
54                        self.put_files_cache()
55                return ret
56        cls.post_run=post_run
57        return cls
58classes={}
59class store_task_type(type):
60        def __init__(cls,name,bases,dict):
61                super(store_task_type,cls).__init__(name,bases,dict)
62                name=cls.__name__
63                if name.endswith('_task'):
64                        name=name.replace('_task','')
65                if name!='evil'and name!='TaskBase':
66                        global classes
67                        if getattr(cls,'run_str',None):
68                                (f,dvars)=compile_fun(cls.run_str,cls.shell)
69                                cls.hcode=cls.run_str
70                                cls.run_str=None
71                                cls.run=f
72                                cls.vars=list(set(cls.vars+dvars))
73                                cls.vars.sort()
74                        elif getattr(cls,'run',None)and not'hcode'in cls.__dict__:
75                                cls.hcode=Utils.h_fun(cls.run)
76                        if not getattr(cls,'nocache',None):
77                                cls=cache_outputs(cls)
78                        getattr(cls,'register',classes)[name]=cls
79evil=store_task_type('evil',(object,),{})
80class TaskBase(evil):
81        color='GREEN'
82        ext_in=[]
83        ext_out=[]
84        before=[]
85        after=[]
86        hcode=''
87        def __init__(self,*k,**kw):
88                self.hasrun=NOT_RUN
89                try:
90                        self.generator=kw['generator']
91                except KeyError:
92                        self.generator=self
93        def __repr__(self):
94                return'\n\t{task %r: %s %s}'%(self.__class__.__name__,id(self),str(getattr(self,'fun','')))
95        def __str__(self):
96                if hasattr(self,'fun'):
97                        return'executing: %s\n'%self.fun.__name__
98                return self.__class__.__name__+'\n'
99        def __hash__(self):
100                return id(self)
101        def exec_command(self,cmd,**kw):
102                bld=self.generator.bld
103                try:
104                        if not kw.get('cwd',None):
105                                kw['cwd']=bld.cwd
106                except AttributeError:
107                        bld.cwd=kw['cwd']=bld.variant_dir
108                return bld.exec_command(cmd,**kw)
109        def runnable_status(self):
110                return RUN_ME
111        def process(self):
112                m=self.master
113                if m.stop:
114                        m.out.put(self)
115                        return
116                try:
117                        del self.generator.bld.task_sigs[self.uid()]
118                except KeyError:
119                        pass
120                try:
121                        self.generator.bld.returned_tasks.append(self)
122                        self.log_display(self.generator.bld)
123                        ret=self.run()
124                except Exception:
125                        self.err_msg=Utils.ex_stack()
126                        self.hasrun=EXCEPTION
127                        m.error_handler(self)
128                        m.out.put(self)
129                        return
130                if ret:
131                        self.err_code=ret
132                        self.hasrun=CRASHED
133                else:
134                        try:
135                                self.post_run()
136                        except Errors.WafError:
137                                pass
138                        except Exception:
139                                self.err_msg=Utils.ex_stack()
140                                self.hasrun=EXCEPTION
141                        else:
142                                self.hasrun=SUCCESS
143                if self.hasrun!=SUCCESS:
144                        m.error_handler(self)
145                m.out.put(self)
146        def run(self):
147                if hasattr(self,'fun'):
148                        return self.fun(self)
149                return 0
150        def post_run(self):
151                pass
152        def log_display(self,bld):
153                bld.to_log(self.display())
154        def display(self):
155                col1=Logs.colors(self.color)
156                col2=Logs.colors.NORMAL
157                master=self.master
158                def cur():
159                        tmp=-1
160                        if hasattr(master,'ready'):
161                                tmp-=master.ready.qsize()
162                        return master.processed+tmp
163                if self.generator.bld.progress_bar==1:
164                        return self.generator.bld.progress_line(cur(),master.total,col1,col2)
165                if self.generator.bld.progress_bar==2:
166                        ela=str(self.generator.bld.timer)
167                        try:
168                                ins=','.join([n.name for n in self.inputs])
169                        except AttributeError:
170                                ins=''
171                        try:
172                                outs=','.join([n.name for n in self.outputs])
173                        except AttributeError:
174                                outs=''
175                        return'|Total %s|Current %s|Inputs %s|Outputs %s|Time %s|\n'%(master.total,cur(),ins,outs,ela)
176                s=str(self)
177                if not s:
178                        return None
179                total=master.total
180                n=len(str(total))
181                fs='[%%%dd/%%%dd] %%s%%s%%s'%(n,n)
182                return fs%(cur(),total,col1,s,col2)
183        def attr(self,att,default=None):
184                ret=getattr(self,att,self)
185                if ret is self:return getattr(self.__class__,att,default)
186                return ret
187        def hash_constraints(self):
188                cls=self.__class__
189                tup=(str(cls.before),str(cls.after),str(cls.ext_in),str(cls.ext_out),cls.__name__,cls.hcode)
190                h=hash(tup)
191                return h
192        def format_error(self):
193                msg=getattr(self,'last_cmd','')
194                name=getattr(self.generator,'name','')
195                if getattr(self,"err_msg",None):
196                        return self.err_msg
197                elif not self.hasrun:
198                        return'task in %r was not executed for some reason: %r'%(name,self)
199                elif self.hasrun==CRASHED:
200                        try:
201                                return' -> task in %r failed (exit status %r): %r\n%r'%(name,self.err_code,self,msg)
202                        except AttributeError:
203                                return' -> task in %r failed: %r\n%r'%(name,self,msg)
204                elif self.hasrun==MISSING:
205                        return' -> missing files in %r: %r\n%r'%(name,self,msg)
206                else:
207                        return'invalid status for task in %r: %r'%(name,self.hasrun)
208        def colon(self,var1,var2):
209                tmp=self.env[var1]
210                if isinstance(var2,str):
211                        it=self.env[var2]
212                else:
213                        it=var2
214                if isinstance(tmp,str):
215                        return[tmp%x for x in it]
216                else:
217                        if Logs.verbose and not tmp and it:
218                                Logs.warn('Missing env variable %r for task %r (generator %r)'%(var1,self,self.generator))
219                        lst=[]
220                        for y in it:
221                                lst.extend(tmp)
222                                lst.append(y)
223                        return lst
224class Task(TaskBase):
225        vars=[]
226        shell=False
227        def __init__(self,*k,**kw):
228                TaskBase.__init__(self,*k,**kw)
229                self.env=kw['env']
230                self.inputs=[]
231                self.outputs=[]
232                self.dep_nodes=[]
233                self.run_after=set([])
234        def __str__(self):
235                env=self.env
236                src_str=' '.join([a.nice_path()for a in self.inputs])
237                tgt_str=' '.join([a.nice_path()for a in self.outputs])
238                if self.outputs:sep=' -> '
239                else:sep=''
240                return'%s: %s%s%s\n'%(self.__class__.__name__.replace('_task',''),src_str,sep,tgt_str)
241        def __repr__(self):
242                try:
243                        ins=",".join([x.name for x in self.inputs])
244                        outs=",".join([x.name for x in self.outputs])
245                except AttributeError:
246                        ins=",".join([str(x)for x in self.inputs])
247                        outs=",".join([str(x)for x in self.outputs])
248                return"".join(['\n\t{task %r: '%id(self),self.__class__.__name__," ",ins," -> ",outs,'}'])
249        def uid(self):
250                try:
251                        return self.uid_
252                except AttributeError:
253                        m=Utils.md5()
254                        up=m.update
255                        up(self.__class__.__name__)
256                        for x in self.inputs+self.outputs:
257                                up(x.abspath())
258                        self.uid_=m.digest()
259                        return self.uid_
260        def set_inputs(self,inp):
261                if isinstance(inp,list):self.inputs+=inp
262                else:self.inputs.append(inp)
263        def set_outputs(self,out):
264                if isinstance(out,list):self.outputs+=out
265                else:self.outputs.append(out)
266        def set_run_after(self,task):
267                assert isinstance(task,TaskBase)
268                self.run_after.add(task)
269        def signature(self):
270                try:return self.cache_sig
271                except AttributeError:pass
272                self.m=Utils.md5()
273                self.m.update(self.hcode)
274                self.sig_explicit_deps()
275                self.sig_vars()
276                if self.scan:
277                        try:
278                                self.sig_implicit_deps()
279                        except Errors.TaskRescan:
280                                return self.signature()
281                ret=self.cache_sig=self.m.digest()
282                return ret
283        def runnable_status(self):
284                for t in self.run_after:
285                        if not t.hasrun:
286                                return ASK_LATER
287                bld=self.generator.bld
288                try:
289                        new_sig=self.signature()
290                except Errors.TaskNotReady:
291                        return ASK_LATER
292                key=self.uid()
293                try:
294                        prev_sig=bld.task_sigs[key]
295                except KeyError:
296                        Logs.debug("task: task %r must run as it was never run before or the task code changed"%self)
297                        return RUN_ME
298                for node in self.outputs:
299                        try:
300                                if node.sig!=new_sig:
301                                        return RUN_ME
302                        except AttributeError:
303                                Logs.debug("task: task %r must run as the output nodes do not exist"%self)
304                                return RUN_ME
305                if new_sig!=prev_sig:
306                        return RUN_ME
307                return SKIP_ME
308        def post_run(self):
309                bld=self.generator.bld
310                sig=self.signature()
311                for node in self.outputs:
312                        try:
313                                os.stat(node.abspath())
314                        except OSError:
315                                self.hasrun=MISSING
316                                self.err_msg='-> missing file: %r'%node.abspath()
317                                raise Errors.WafError(self.err_msg)
318                        node.sig=sig
319                bld.task_sigs[self.uid()]=self.cache_sig
320        def sig_explicit_deps(self):
321                bld=self.generator.bld
322                upd=self.m.update
323                for x in self.inputs+self.dep_nodes:
324                        try:
325                                upd(x.get_bld_sig())
326                        except(AttributeError,TypeError):
327                                raise Errors.WafError('Missing node signature for %r (required by %r)'%(x,self))
328                if bld.deps_man:
329                        additional_deps=bld.deps_man
330                        for x in self.inputs+self.outputs:
331                                try:
332                                        d=additional_deps[id(x)]
333                                except KeyError:
334                                        continue
335                                for v in d:
336                                        if isinstance(v,bld.root.__class__):
337                                                try:
338                                                        v=v.get_bld_sig()
339                                                except AttributeError:
340                                                        raise Errors.WafError('Missing node signature for %r (required by %r)'%(v,self))
341                                        elif hasattr(v,'__call__'):
342                                                v=v()
343                                        upd(v)
344                return self.m.digest()
345        def sig_vars(self):
346                bld=self.generator.bld
347                env=self.env
348                upd=self.m.update
349                act_sig=bld.hash_env_vars(env,self.__class__.vars)
350                upd(act_sig)
351                dep_vars=getattr(self,'dep_vars',None)
352                if dep_vars:
353                        upd(bld.hash_env_vars(env,dep_vars))
354                return self.m.digest()
355        scan=None
356        def sig_implicit_deps(self):
357                bld=self.generator.bld
358                key=self.uid()
359                prev=bld.task_sigs.get((key,'imp'),[])
360                if prev:
361                        try:
362                                if prev==self.compute_sig_implicit_deps():
363                                        return prev
364                        except Exception:
365                                for x in bld.node_deps.get(self.uid(),[]):
366                                        if x.is_child_of(bld.srcnode):
367                                                try:
368                                                        os.stat(x.abspath())
369                                                except OSError:
370                                                        try:
371                                                                del x.parent.children[x.name]
372                                                        except KeyError:
373                                                                pass
374                        del bld.task_sigs[(key,'imp')]
375                        raise Errors.TaskRescan('rescan')
376                (nodes,names)=self.scan()
377                if Logs.verbose:
378                        Logs.debug('deps: scanner for %s returned %s %s'%(str(self),str(nodes),str(names)))
379                bld.node_deps[key]=nodes
380                bld.raw_deps[key]=names
381                self.are_implicit_nodes_ready()
382                try:
383                        bld.task_sigs[(key,'imp')]=sig=self.compute_sig_implicit_deps()
384                except Exception:
385                        if Logs.verbose:
386                                for k in bld.node_deps.get(self.uid(),[]):
387                                        try:
388                                                k.get_bld_sig()
389                                        except Exception:
390                                                Logs.warn('Missing signature for node %r (may cause rebuilds)'%k)
391                else:
392                        return sig
393        def compute_sig_implicit_deps(self):
394                upd=self.m.update
395                bld=self.generator.bld
396                self.are_implicit_nodes_ready()
397                for k in bld.node_deps.get(self.uid(),[]):
398                        upd(k.get_bld_sig())
399                return self.m.digest()
400        def are_implicit_nodes_ready(self):
401                bld=self.generator.bld
402                try:
403                        cache=bld.dct_implicit_nodes
404                except AttributeError:
405                        bld.dct_implicit_nodes=cache={}
406                try:
407                        dct=cache[bld.cur]
408                except KeyError:
409                        dct=cache[bld.cur]={}
410                        for tsk in bld.cur_tasks:
411                                for x in tsk.outputs:
412                                        dct[x]=tsk
413                modified=False
414                for x in bld.node_deps.get(self.uid(),[]):
415                        if x in dct:
416                                self.run_after.add(dct[x])
417                                modified=True
418                if modified:
419                        for tsk in self.run_after:
420                                if not tsk.hasrun:
421                                        raise Errors.TaskNotReady('not ready')
422        def can_retrieve_cache(self):
423                if not getattr(self,'outputs',None):
424                        return None
425                sig=self.signature()
426                ssig=Utils.to_hex(self.uid())+Utils.to_hex(sig)
427                dname=os.path.join(self.generator.bld.cache_global,ssig)
428                try:
429                        t1=os.stat(dname).st_mtime
430                except OSError:
431                        return None
432                for node in self.outputs:
433                        orig=os.path.join(dname,node.name)
434                        try:
435                                shutil.copy2(orig,node.abspath())
436                                os.utime(orig,None)
437                        except(OSError,IOError):
438                                Logs.debug('task: failed retrieving file')
439                                return None
440                try:
441                        t2=os.stat(dname).st_mtime
442                except OSError:
443                        return None
444                if t1!=t2:
445                        return None
446                for node in self.outputs:
447                        node.sig=sig
448                        if self.generator.bld.progress_bar<1:
449                                self.generator.bld.to_log('restoring from cache %r\n'%node.abspath())
450                self.cached=True
451                return True
452        def put_files_cache(self):
453                if getattr(self,'cached',None):
454                        return None
455                if not getattr(self,'outputs',None):
456                        return None
457                sig=self.signature()
458                ssig=Utils.to_hex(self.uid())+Utils.to_hex(sig)
459                dname=os.path.join(self.generator.bld.cache_global,ssig)
460                tmpdir=tempfile.mkdtemp(prefix=self.generator.bld.cache_global+os.sep+'waf')
461                try:
462                        shutil.rmtree(dname)
463                except Exception:
464                        pass
465                try:
466                        for node in self.outputs:
467                                dest=os.path.join(tmpdir,node.name)
468                                shutil.copy2(node.abspath(),dest)
469                except(OSError,IOError):
470                        try:
471                                shutil.rmtree(tmpdir)
472                        except Exception:
473                                pass
474                else:
475                        try:
476                                os.rename(tmpdir,dname)
477                        except OSError:
478                                try:
479                                        shutil.rmtree(tmpdir)
480                                except Exception:
481                                        pass
482                        else:
483                                try:
484                                        os.chmod(dname,Utils.O755)
485                                except Exception:
486                                        pass
487def is_before(t1,t2):
488        to_list=Utils.to_list
489        for k in to_list(t2.ext_in):
490                if k in to_list(t1.ext_out):
491                        return 1
492        if t1.__class__.__name__ in to_list(t2.after):
493                return 1
494        if t2.__class__.__name__ in to_list(t1.before):
495                return 1
496        return 0
497def set_file_constraints(tasks):
498        ins=Utils.defaultdict(set)
499        outs=Utils.defaultdict(set)
500        for x in tasks:
501                for a in getattr(x,'inputs',[])+getattr(x,'dep_nodes',[]):
502                        ins[id(a)].add(x)
503                for a in getattr(x,'outputs',[]):
504                        outs[id(a)].add(x)
505        links=set(ins.keys()).intersection(outs.keys())
506        for k in links:
507                for a in ins[k]:
508                        a.run_after.update(outs[k])
509def set_precedence_constraints(tasks):
510        cstr_groups=Utils.defaultdict(list)
511        for x in tasks:
512                h=x.hash_constraints()
513                cstr_groups[h].append(x)
514        keys=list(cstr_groups.keys())
515        maxi=len(keys)
516        for i in range(maxi):
517                t1=cstr_groups[keys[i]][0]
518                for j in range(i+1,maxi):
519                        t2=cstr_groups[keys[j]][0]
520                        if is_before(t1,t2):
521                                a=i
522                                b=j
523                        elif is_before(t2,t1):
524                                a=j
525                                b=i
526                        else:
527                                continue
528                        aval=set(cstr_groups[keys[a]])
529                        for x in cstr_groups[keys[b]]:
530                                x.run_after.update(aval)
531def funex(c):
532        dc={}
533        exec(c,dc)
534        return dc['f']
535reg_act=re.compile(r"(?P<backslash>\\)|(?P<dollar>\$\$)|(?P<subst>\$\{(?P<var>\w+)(?P<code>.*?)\})",re.M)
536def compile_fun_shell(line):
537        extr=[]
538        def repl(match):
539                g=match.group
540                if g('dollar'):return"$"
541                elif g('backslash'):return'\\\\'
542                elif g('subst'):extr.append((g('var'),g('code')));return"%s"
543                return None
544        line=reg_act.sub(repl,line)or line
545        parm=[]
546        dvars=[]
547        app=parm.append
548        for(var,meth)in extr:
549                if var=='SRC':
550                        if meth:app('tsk.inputs%s'%meth)
551                        else:app('" ".join([a.path_from(bld.bldnode) for a in tsk.inputs])')
552                elif var=='TGT':
553                        if meth:app('tsk.outputs%s'%meth)
554                        else:app('" ".join([a.path_from(bld.bldnode) for a in tsk.outputs])')
555                elif meth:
556                        if meth.startswith(':'):
557                                m=meth[1:]
558                                if m=='SRC':
559                                        m='[a.path_from(bld.bldnode) for a in tsk.inputs]'
560                                elif m=='TGT':
561                                        m='[a.path_from(bld.bldnode) for a in tsk.outputs]'
562                                elif m[:3]not in('tsk','gen','bld'):
563                                        dvars.extend([var,meth[1:]])
564                                        m='%r'%m
565                                app('" ".join(tsk.colon(%r, %s))'%(var,m))
566                        else:
567                                app('%s%s'%(var,meth))
568                else:
569                        if not var in dvars:dvars.append(var)
570                        app("p('%s')"%var)
571        if parm:parm="%% (%s) "%(',\n\t\t'.join(parm))
572        else:parm=''
573        c=COMPILE_TEMPLATE_SHELL%(line,parm)
574        Logs.debug('action: %s'%c.strip().splitlines())
575        return(funex(c),dvars)
576def compile_fun_noshell(line):
577        extr=[]
578        def repl(match):
579                g=match.group
580                if g('dollar'):return"$"
581                elif g('subst'):extr.append((g('var'),g('code')));return"<<|@|>>"
582                return None
583        line2=reg_act.sub(repl,line)
584        params=line2.split('<<|@|>>')
585        assert(extr)
586        buf=[]
587        dvars=[]
588        app=buf.append
589        for x in range(len(extr)):
590                params[x]=params[x].strip()
591                if params[x]:
592                        app("lst.extend(%r)"%params[x].split())
593                (var,meth)=extr[x]
594                if var=='SRC':
595                        if meth:app('lst.append(tsk.inputs%s)'%meth)
596                        else:app("lst.extend([a.path_from(bld.bldnode) for a in tsk.inputs])")
597                elif var=='TGT':
598                        if meth:app('lst.append(tsk.outputs%s)'%meth)
599                        else:app("lst.extend([a.path_from(bld.bldnode) for a in tsk.outputs])")
600                elif meth:
601                        if meth.startswith(':'):
602                                m=meth[1:]
603                                if m=='SRC':
604                                        m='[a.path_from(bld.bldnode) for a in tsk.inputs]'
605                                elif m=='TGT':
606                                        m='[a.path_from(bld.bldnode) for a in tsk.outputs]'
607                                elif m[:3]not in('tsk','gen','bld'):
608                                        dvars.extend([var,m])
609                                        m='%r'%m
610                                app('lst.extend(tsk.colon(%r, %s))'%(var,m))
611                        else:
612                                app('lst.extend(gen.to_list(%s%s))'%(var,meth))
613                else:
614                        app('lst.extend(to_list(env[%r]))'%var)
615                        if not var in dvars:dvars.append(var)
616        if extr:
617                if params[-1]:
618                        app("lst.extend(%r)"%params[-1].split())
619        fun=COMPILE_TEMPLATE_NOSHELL%"\n\t".join(buf)
620        Logs.debug('action: %s'%fun.strip().splitlines())
621        return(funex(fun),dvars)
622def compile_fun(line,shell=False):
623        if line.find('<')>0 or line.find('>')>0 or line.find('&&')>0:
624                shell=True
625        if shell:
626                return compile_fun_shell(line)
627        else:
628                return compile_fun_noshell(line)
629def task_factory(name,func=None,vars=None,color='GREEN',ext_in=[],ext_out=[],before=[],after=[],shell=False,scan=None):
630        params={'vars':vars or[],'color':color,'name':name,'ext_in':Utils.to_list(ext_in),'ext_out':Utils.to_list(ext_out),'before':Utils.to_list(before),'after':Utils.to_list(after),'shell':shell,'scan':scan,}
631        if isinstance(func,str):
632                params['run_str']=func
633        else:
634                params['run']=func
635        cls=type(Task)(name,(Task,),params)
636        global classes
637        classes[name]=cls
638        return cls
639def always_run(cls):
640        old=cls.runnable_status
641        def always(self):
642                ret=old(self)
643                if ret==SKIP_ME:
644                        ret=RUN_ME
645                return ret
646        cls.runnable_status=always
647        return cls
648def update_outputs(cls):
649        old_post_run=cls.post_run
650        def post_run(self):
651                old_post_run(self)
652                for node in self.outputs:
653                        node.sig=Utils.h_file(node.abspath())
654                        self.generator.bld.task_sigs[node.abspath()]=self.uid()
655        cls.post_run=post_run
656        old_runnable_status=cls.runnable_status
657        def runnable_status(self):
658                status=old_runnable_status(self)
659                if status!=RUN_ME:
660                        return status
661                try:
662                        bld=self.generator.bld
663                        prev_sig=bld.task_sigs[self.uid()]
664                        if prev_sig==self.signature():
665                                for x in self.outputs:
666                                        if not x.sig or bld.task_sigs[x.abspath()]!=self.uid():
667                                                return RUN_ME
668                                return SKIP_ME
669                except KeyError:
670                        pass
671                except IndexError:
672                        pass
673                except AttributeError:
674                        pass
675                return RUN_ME
676        cls.runnable_status=runnable_status
677        return cls
Note: See TracBrowser for help on using the repository browser.