source: waflib/Task.py @ 904702d

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

waf, waflib: update to 1.8.7

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