build: check that the user is not using an old /usr/bin/waf
[nivanova/samba-autobuild/.git] / buildtools / wafsamba / wafsamba.py
1 # a waf tool to add autoconf-like macros to the configure section
2 # and for SAMBA_ macros for building libraries, binaries etc
3
4 import Build, os, Options, Task, Utils, cc, TaskGen, fnmatch, re, shutil, Logs, Constants
5 from Configure import conf
6 from Logs import debug
7 from samba_utils import SUBST_VARS_RECURSIVE
8
9 # bring in the other samba modules
10 from samba_optimisation import *
11 from samba_utils import *
12 from samba_autoconf import *
13 from samba_patterns import *
14 from samba_pidl import *
15 from samba_errtable import *
16 from samba_asn1 import *
17 from samba_autoproto import *
18 from samba_python import *
19 from samba_deps import *
20 from samba_bundled import *
21 import samba_install
22 import samba_conftests
23 import tru64cc
24 import irixcc
25 import generic_cc
26 import samba_dist
27
28 O644 = 420
29
30 # some systems have broken threading in python
31 if os.environ.get('WAF_NOTHREADS') == '1':
32     import nothreads
33
34 LIB_PATH="shared"
35
36 os.putenv('PYTHONUNBUFFERED', '1')
37
38
39 if Constants.HEXVERSION < 0x105016:
40     Logs.error('''
41 Please use the version of waf that comes with Samba, not
42 a system installed version. See http://wiki.samba.org/index.php/Waf
43 for details
44 ''')
45     sys.exit(1)
46
47
48 @conf
49 def SAMBA_BUILD_ENV(conf):
50     '''create the samba build environment'''
51     conf.env.BUILD_DIRECTORY = conf.blddir
52     mkdir_p(os.path.join(conf.blddir, LIB_PATH))
53     mkdir_p(os.path.join(conf.blddir, 'python/samba/dcerpc'))
54     # this allows all of the bin/shared and bin/python targets
55     # to be expressed in terms of build directory paths
56     for p in ['python','shared']:
57         link_target = os.path.join(conf.blddir, 'default/' + p)
58         if not os.path.lexists(link_target):
59             os.symlink('../' + p, link_target)
60
61     # get perl to put the blib files in the build directory
62     blib_bld = os.path.join(conf.blddir, 'default/pidl/blib')
63     blib_src = os.path.join(conf.srcdir, 'pidl/blib')
64     mkdir_p(blib_bld + '/man1')
65     mkdir_p(blib_bld + '/man3')
66     if os.path.islink(blib_src):
67         os.unlink(blib_src)
68     elif os.path.exists(blib_src):
69         shutil.rmtree(blib_src)
70
71
72 def ADD_INIT_FUNCTION(bld, subsystem, target, init_function):
73     '''add an init_function to the list for a subsystem'''
74     if init_function is None:
75         return
76     bld.ASSERT(subsystem is not None, "You must specify a subsystem for init_function '%s'" % init_function)
77     cache = LOCAL_CACHE(bld, 'INIT_FUNCTIONS')
78     if not subsystem in cache:
79         cache[subsystem] = []
80     cache[subsystem].append( { 'TARGET':target, 'INIT_FUNCTION':init_function } )
81 Build.BuildContext.ADD_INIT_FUNCTION = ADD_INIT_FUNCTION
82
83
84
85 #################################################################
86 def SAMBA_LIBRARY(bld, libname, source,
87                   deps='',
88                   public_deps='',
89                   includes='',
90                   public_headers=None,
91                   header_path=None,
92                   pc_files=None,
93                   vnum=None,
94                   cflags='',
95                   external_library=False,
96                   realname=None,
97                   autoproto=None,
98                   group='main',
99                   depends_on='',
100                   local_include=True,
101                   vars=None,
102                   install_path=None,
103                   install=True,
104                   needs_python=False,
105                   target_type='LIBRARY',
106                   bundled_extension=True,
107                   link_name=None,
108                   enabled=True):
109     '''define a Samba library'''
110
111     if not enabled:
112         SET_TARGET_TYPE(bld, libname, 'DISABLED')
113         return
114
115     source = bld.EXPAND_VARIABLES(source, vars=vars)
116
117     # remember empty libraries, so we can strip the dependencies
118     if (source == '') or (source == []):
119         SET_TARGET_TYPE(bld, libname, 'EMPTY')
120         return
121
122     if target_type != 'PYTHON' and BUILTIN_LIBRARY(bld, libname):
123         obj_target = libname
124     else:
125         obj_target = libname + '.objlist'
126
127     # first create a target for building the object files for this library
128     # by separating in this way, we avoid recompiling the C files
129     # separately for the install library and the build library
130     bld.SAMBA_SUBSYSTEM(obj_target,
131                         source         = source,
132                         deps           = deps,
133                         public_deps    = public_deps,
134                         includes       = includes,
135                         public_headers = public_headers,
136                         header_path    = header_path,
137                         cflags         = cflags,
138                         group          = group,
139                         autoproto      = autoproto,
140                         depends_on     = depends_on,
141                         needs_python   = needs_python,
142                         local_include  = local_include)
143
144     if libname == obj_target:
145         return
146
147     if not SET_TARGET_TYPE(bld, libname, target_type):
148         return
149
150     # the library itself will depend on that object target
151     deps += ' ' + public_deps
152     deps = TO_LIST(deps)
153     deps.append(obj_target)
154
155     if target_type == 'PYTHON':
156         bundled_name = libname
157     else:
158         bundled_name = BUNDLED_NAME(bld, libname, bundled_extension)
159
160     features = 'cc cshlib symlink_lib install_lib'
161     if target_type == 'PYTHON':
162         features += ' pyext'
163     elif needs_python:
164         features += ' pyembed'
165
166     bld.SET_BUILD_GROUP(group)
167     t = bld(
168         features        = features,
169         source          = [],
170         target          = bundled_name,
171         samba_cflags    = CURRENT_CFLAGS(bld, libname, cflags),
172         depends_on      = depends_on,
173         samba_deps      = deps,
174         samba_includes  = includes,
175         local_include   = local_include,
176         vnum            = vnum,
177         install_path    = None,
178         samba_inst_path = install_path,
179         name            = libname,
180         samba_realname  = realname,
181         samba_install   = install
182         )
183
184     if link_name:
185         t.link_name = link_name
186
187     if autoproto is not None:
188         bld.SAMBA_AUTOPROTO(autoproto, source)
189
190     if public_headers is not None:
191         bld.PUBLIC_HEADERS(public_headers, header_path=header_path)
192
193     if pc_files is not None:
194         bld.PKG_CONFIG_FILES(pc_files, vnum=vnum)
195
196 Build.BuildContext.SAMBA_LIBRARY = SAMBA_LIBRARY
197
198
199 #################################################################
200 def SAMBA_BINARY(bld, binname, source,
201                  deps='',
202                  includes='',
203                  public_headers=None,
204                  header_path=None,
205                  modules=None,
206                  installdir=None,
207                  ldflags=None,
208                  cflags='',
209                  autoproto=None,
210                  use_hostcc=False,
211                  use_global_deps=True,
212                  compiler=None,
213                  group='binaries',
214                  manpages=None,
215                  local_include=True,
216                  subsystem_name=None,
217                  needs_python=False,
218                  vars=None,
219                  install=True,
220                  install_path=None):
221     '''define a Samba binary'''
222
223     if not SET_TARGET_TYPE(bld, binname, 'BINARY'):
224         return
225
226     features = 'cc cprogram symlink_bin install_bin'
227     if needs_python:
228         features += ' pyembed'
229
230     obj_target = binname + '.objlist'
231
232     source = bld.EXPAND_VARIABLES(source, vars=vars)
233
234     # first create a target for building the object files for this binary
235     # by separating in this way, we avoid recompiling the C files
236     # separately for the install binary and the build binary
237     bld.SAMBA_SUBSYSTEM(obj_target,
238                         source         = source,
239                         deps           = deps,
240                         includes       = includes,
241                         cflags         = cflags,
242                         group          = group,
243                         autoproto      = autoproto,
244                         subsystem_name = subsystem_name,
245                         needs_python   = needs_python,
246                         local_include  = local_include,
247                         use_hostcc     = use_hostcc,
248                         use_global_deps= use_global_deps)
249
250     bld.SET_BUILD_GROUP(group)
251
252     # the binary itself will depend on that object target
253     deps = TO_LIST(deps)
254     deps.append(obj_target)
255
256     t = bld(
257         features       = features,
258         source         = [],
259         target         = binname,
260         samba_cflags   = CURRENT_CFLAGS(bld, binname, cflags),
261         samba_deps     = deps,
262         samba_includes = includes,
263         local_include  = local_include,
264         samba_modules  = modules,
265         top            = True,
266         samba_subsystem= subsystem_name,
267         install_path   = None,
268         samba_inst_path= install_path,
269         samba_install  = install
270         )
271
272     # setup the subsystem_name as an alias for the real
273     # binary name, so it can be found when expanding
274     # subsystem dependencies
275     if subsystem_name is not None:
276         bld.TARGET_ALIAS(subsystem_name, binname)
277
278     if autoproto is not None:
279         bld.SAMBA_AUTOPROTO(autoproto, source)
280     if public_headers is not None:
281         bld.PUBLIC_HEADERS(public_headers, header_path=header_path)
282 Build.BuildContext.SAMBA_BINARY = SAMBA_BINARY
283
284
285 #################################################################
286 def SAMBA_MODULE(bld, modname, source,
287                  deps='',
288                  includes='',
289                  subsystem=None,
290                  init_function=None,
291                  autoproto=None,
292                  autoproto_extra_source='',
293                  aliases=None,
294                  cflags='',
295                  internal_module=True,
296                  local_include=True,
297                  vars=None,
298                  enabled=True):
299     '''define a Samba module.'''
300
301     # we add the init function regardless of whether the module
302     # is enabled or not, as we need to generate a null list if
303     # all disabled
304     bld.ADD_INIT_FUNCTION(subsystem, modname, init_function)
305
306     if internal_module or BUILTIN_LIBRARY(bld, modname):
307         # treat internal modules as subsystems for now
308         SAMBA_SUBSYSTEM(bld, modname, source,
309                         deps=deps,
310                         includes=includes,
311                         autoproto=autoproto,
312                         autoproto_extra_source=autoproto_extra_source,
313                         cflags=cflags,
314                         local_include=local_include,
315                         enabled=enabled)
316         return
317
318     if not enabled:
319         SET_TARGET_TYPE(bld, modname, 'DISABLED')
320         return
321
322     source = bld.EXPAND_VARIABLES(source, vars=vars)
323
324     # remember empty modules, so we can strip the dependencies
325     if (source == '') or (source == []):
326         SET_TARGET_TYPE(bld, modname, 'EMPTY')
327         return
328
329     if not SET_TARGET_TYPE(bld, modname, 'MODULE'):
330         return
331
332     if subsystem is not None:
333         deps += ' ' + subsystem
334
335     bld.SET_BUILD_GROUP('main')
336     bld(
337         features       = 'cc',
338         source         = source,
339         target         = modname,
340         samba_cflags   = CURRENT_CFLAGS(bld, modname, cflags),
341         samba_includes = includes,
342         local_include  = local_include,
343         samba_deps     = TO_LIST(deps)
344         )
345
346     if autoproto is not None:
347         bld.SAMBA_AUTOPROTO(autoproto, source + ' ' + autoproto_extra_source)
348
349 Build.BuildContext.SAMBA_MODULE = SAMBA_MODULE
350
351
352 #################################################################
353 def SAMBA_SUBSYSTEM(bld, modname, source,
354                     deps='',
355                     public_deps='',
356                     includes='',
357                     public_headers=None,
358                     header_path=None,
359                     cflags='',
360                     cflags_end=None,
361                     group='main',
362                     init_function_sentinal=None,
363                     heimdal_autoproto=None,
364                     heimdal_autoproto_options=None,
365                     heimdal_autoproto_private=None,
366                     autoproto=None,
367                     autoproto_extra_source='',
368                     depends_on='',
369                     local_include=True,
370                     local_include_first=True,
371                     subsystem_name=None,
372                     enabled=True,
373                     use_hostcc=False,
374                     use_global_deps=True,
375                     vars=None,
376                     needs_python=False):
377     '''define a Samba subsystem'''
378
379     if not enabled:
380         SET_TARGET_TYPE(bld, modname, 'DISABLED')
381         return
382
383     # remember empty subsystems, so we can strip the dependencies
384     if (source == '') or (source == []):
385         SET_TARGET_TYPE(bld, modname, 'EMPTY')
386         return
387
388     if not SET_TARGET_TYPE(bld, modname, 'SUBSYSTEM'):
389         return
390
391     source = bld.EXPAND_VARIABLES(source, vars=vars)
392
393     deps += ' ' + public_deps
394
395     bld.SET_BUILD_GROUP(group)
396
397     features = 'cc'
398     if needs_python:
399         features += ' pyext'
400
401     t = bld(
402         features       = features,
403         source         = source,
404         target         = modname,
405         samba_cflags   = CURRENT_CFLAGS(bld, modname, cflags),
406         depends_on     = depends_on,
407         samba_deps     = TO_LIST(deps),
408         samba_includes = includes,
409         local_include  = local_include,
410         local_include_first  = local_include_first,
411         samba_subsystem= subsystem_name,
412         samba_use_hostcc = use_hostcc,
413         samba_use_global_deps = use_global_deps
414         )
415
416     if cflags_end is not None:
417         t.samba_cflags.extend(TO_LIST(cflags_end))
418
419     if heimdal_autoproto is not None:
420         bld.HEIMDAL_AUTOPROTO(heimdal_autoproto, source, options=heimdal_autoproto_options)
421     if heimdal_autoproto_private is not None:
422         bld.HEIMDAL_AUTOPROTO_PRIVATE(heimdal_autoproto_private, source)
423     if autoproto is not None:
424         bld.SAMBA_AUTOPROTO(autoproto, source + ' ' + autoproto_extra_source)
425     if public_headers is not None:
426         bld.PUBLIC_HEADERS(public_headers, header_path=header_path)
427     return t
428
429
430 Build.BuildContext.SAMBA_SUBSYSTEM = SAMBA_SUBSYSTEM
431
432
433 def SAMBA_GENERATOR(bld, name, rule, source='', target='',
434                     group='generators', enabled=True,
435                     public_headers=None,
436                     header_path=None,
437                     vars=None):
438     '''A generic source generator target'''
439
440     if not SET_TARGET_TYPE(bld, name, 'GENERATOR'):
441         return
442
443     if not enabled:
444         return
445
446     bld.SET_BUILD_GROUP(group)
447     t = bld(
448         rule=rule,
449         source=bld.EXPAND_VARIABLES(source, vars=vars),
450         target=target,
451         shell=isinstance(rule, str),
452         on_results=True,
453         before='cc',
454         ext_out='.c',
455         name=name)
456
457     if public_headers is not None:
458         bld.PUBLIC_HEADERS(public_headers, header_path=header_path)
459     return t
460 Build.BuildContext.SAMBA_GENERATOR = SAMBA_GENERATOR
461
462
463
464 @runonce
465 def SETUP_BUILD_GROUPS(bld):
466     '''setup build groups used to ensure that the different build
467     phases happen consecutively'''
468     bld.p_ln = bld.srcnode # we do want to see all targets!
469     bld.env['USING_BUILD_GROUPS'] = True
470     bld.add_group('setup')
471     bld.add_group('build_compiler_source')
472     bld.add_group('base_libraries')
473     bld.add_group('generators')
474     bld.add_group('compiler_prototypes')
475     bld.add_group('compiler_libraries')
476     bld.add_group('build_compilers')
477     bld.add_group('build_source')
478     bld.add_group('prototypes')
479     bld.add_group('main')
480     bld.add_group('binaries')
481     bld.add_group('final')
482 Build.BuildContext.SETUP_BUILD_GROUPS = SETUP_BUILD_GROUPS
483
484
485 def SET_BUILD_GROUP(bld, group):
486     '''set the current build group'''
487     if not 'USING_BUILD_GROUPS' in bld.env:
488         return
489     bld.set_group(group)
490 Build.BuildContext.SET_BUILD_GROUP = SET_BUILD_GROUP
491
492
493
494 @conf
495 def ENABLE_TIMESTAMP_DEPENDENCIES(conf):
496     """use timestamps instead of file contents for deps
497     this currently doesn't work"""
498     def h_file(filename):
499         import stat
500         st = os.stat(filename)
501         if stat.S_ISDIR(st[stat.ST_MODE]): raise IOError('not a file')
502         m = Utils.md5()
503         m.update(str(st.st_mtime))
504         m.update(str(st.st_size))
505         m.update(filename)
506         return m.digest()
507     Utils.h_file = h_file
508
509
510
511 t = Task.simple_task_type('copy_script', 'rm -f ${LINK_TARGET} && ln -s ${SRC[0].abspath(env)} ${LINK_TARGET}',
512                           shell=True, color='PINK', ext_in='.bin')
513 t.quiet = True
514
515 @feature('copy_script')
516 @before('apply_link')
517 def copy_script(self):
518     tsk = self.create_task('copy_script', self.allnodes[0])
519     tsk.env.TARGET = self.target
520
521 def SAMBA_SCRIPT(bld, name, pattern, installdir, installname=None):
522     '''used to copy scripts from the source tree into the build directory
523        for use by selftest'''
524
525     source = bld.path.ant_glob(pattern)
526
527     bld.SET_BUILD_GROUP('build_source')
528     for s in TO_LIST(source):
529         iname = s
530         if installname != None:
531             iname = installname
532         target = os.path.join(installdir, iname)
533         tgtdir = os.path.dirname(os.path.join(bld.srcnode.abspath(bld.env), '..', target))
534         mkdir_p(tgtdir)
535         t = bld(features='copy_script',
536                 source       = s,
537                 target       = target,
538                 always       = True,
539                 install_path = None)
540         t.env.LINK_TARGET = target
541
542 Build.BuildContext.SAMBA_SCRIPT = SAMBA_SCRIPT
543
544
545 def install_file(bld, destdir, file, chmod=O644, flat=False,
546                  python_fixup=False, destname=None, base_name=None):
547     '''install a file'''
548     destdir = bld.EXPAND_VARIABLES(destdir)
549     if not destname:
550         destname = file
551         if flat:
552             destname = os.path.basename(destname)
553     dest = os.path.join(destdir, destname)
554     if python_fixup:
555         # fixup the python path it will use to find Samba modules
556         inst_file = file + '.inst'
557         bld.SAMBA_GENERATOR('python_%s' % destname,
558                             rule="sed 's|\(sys.path.insert.*\)bin/python\(.*\)$|\\1${PYTHONDIR}\\2|g' < ${SRC} > ${TGT}",
559                             source=file,
560                             target=inst_file)
561         file = inst_file
562     if base_name:
563         file = os.path.join(base_name, file)
564     bld.install_as(dest, file, chmod=chmod)
565
566
567 def INSTALL_FILES(bld, destdir, files, chmod=O644, flat=False,
568                   python_fixup=False, destname=None, base_name=None):
569     '''install a set of files'''
570     for f in TO_LIST(files):
571         install_file(bld, destdir, f, chmod=chmod, flat=flat,
572                      python_fixup=python_fixup, destname=destname,
573                      base_name=base_name)
574 Build.BuildContext.INSTALL_FILES = INSTALL_FILES
575
576
577 def INSTALL_WILDCARD(bld, destdir, pattern, chmod=O644, flat=False,
578                      python_fixup=False, exclude=None, trim_path=None):
579     '''install a set of files matching a wildcard pattern'''
580     files=TO_LIST(bld.path.ant_glob(pattern))
581     if trim_path:
582         files2 = []
583         for f in files:
584             files2.append(os_path_relpath(f, trim_path))
585         files = files2
586
587     if exclude:
588         for f in files[:]:
589             if fnmatch.fnmatch(f, exclude):
590                 files.remove(f)
591     INSTALL_FILES(bld, destdir, files, chmod=chmod, flat=flat,
592                   python_fixup=python_fixup, base_name=trim_path)
593 Build.BuildContext.INSTALL_WILDCARD = INSTALL_WILDCARD
594
595
596 def PUBLIC_HEADERS(bld, public_headers, header_path=None):
597     '''install some headers
598
599     header_path may either be a string that is added to the INCLUDEDIR,
600     or it can be a dictionary of wildcard patterns which map to destination
601     directories relative to INCLUDEDIR
602     '''
603     dest = '${INCLUDEDIR}'
604     if isinstance(header_path, str):
605         dest += '/' + header_path
606     for h in TO_LIST(public_headers):
607         hdest = dest
608         if isinstance(header_path, list):
609             for (p1, dir) in header_path:
610                 found_match=False
611                 lst = TO_LIST(p1)
612                 for p2 in lst:
613                     if fnmatch.fnmatch(h, p2):
614                         if dir:
615                             hdest = os.path.join(hdest, dir)
616                         found_match=True
617                         break
618                 if found_match: break
619         if h.find(':') != -1:
620             hs=h.split(':')
621             INSTALL_FILES(bld, hdest, hs[0], flat=True, destname=hs[1])
622         else:
623             INSTALL_FILES(bld, hdest, h, flat=True)
624 Build.BuildContext.PUBLIC_HEADERS = PUBLIC_HEADERS
625
626
627 def subst_at_vars(task):
628     '''substiture @VAR@ style variables in a file'''
629     src = task.inputs[0].srcpath(task.env)
630     tgt = task.outputs[0].bldpath(task.env)
631
632     f = open(src, 'r')
633     s = f.read()
634     f.close()
635     # split on the vars
636     a = re.split('(@\w+@)', s)
637     out = []
638     back_sub = [ ('PREFIX', '${prefix}'), ('EXEC_PREFIX', '${exec_prefix}')]
639     for v in a:
640         if re.match('@\w+@', v):
641             vname = v[1:-1]
642             if not vname in task.env and vname.upper() in task.env:
643                 vname = vname.upper()
644             if not vname in task.env:
645                 Logs.error("Unknown substitution %s in %s" % (v, task.name))
646                 sys.exit(1)
647             v = SUBST_VARS_RECURSIVE(task.env[vname], task.env)
648             # now we back substitute the allowed pc vars
649             for (b, m) in back_sub:
650                 s = task.env[b]
651                 if s == v[0:len(s)]:
652                     v = m + v[len(s):]
653         out.append(v)
654     contents = ''.join(out)
655     f = open(tgt, 'w')
656     s = f.write(contents)
657     f.close()
658     return 0
659
660
661
662 def PKG_CONFIG_FILES(bld, pc_files, vnum=None):
663     '''install some pkg_config pc files'''
664     dest = '${PKGCONFIGDIR}'
665     dest = bld.EXPAND_VARIABLES(dest)
666     for f in TO_LIST(pc_files):
667         base=os.path.basename(f)
668         t = bld.SAMBA_GENERATOR('PKGCONFIG_%s' % base,
669                                 rule=subst_at_vars,
670                                 source=f+'.in',
671                                 target=f)
672         if vnum:
673             t.env.PACKAGE_VERSION = vnum
674         INSTALL_FILES(bld, dest, f, flat=True, destname=base)
675 Build.BuildContext.PKG_CONFIG_FILES = PKG_CONFIG_FILES
676
677
678
679 #############################################################
680 # give a nicer display when building different types of files
681 def progress_display(self, msg, fname):
682     col1 = Logs.colors(self.color)
683     col2 = Logs.colors.NORMAL
684     total = self.position[1]
685     n = len(str(total))
686     fs = '[%%%dd/%%%dd] %s %%s%%s%%s\n' % (n, n, msg)
687     return fs % (self.position[0], self.position[1], col1, fname, col2)
688
689 def link_display(self):
690     if Options.options.progress_bar != 0:
691         return Task.Task.old_display(self)
692     fname = self.outputs[0].bldpath(self.env)
693     return progress_display(self, 'Linking', fname)
694 Task.TaskBase.classes['cc_link'].display = link_display
695
696 def samba_display(self):
697     if Options.options.progress_bar != 0:
698         return Task.Task.old_display(self)
699
700     targets    = LOCAL_CACHE(self, 'TARGET_TYPE')
701     if self.name in targets:
702         target_type = targets[self.name]
703         type_map = { 'GENERATOR' : 'Generating',
704                      'PROTOTYPE' : 'Generating'
705                      }
706         if target_type in type_map:
707             return progress_display(self, type_map[target_type], self.name)
708
709     fname = self.inputs[0].bldpath(self.env)
710     if fname[0:3] == '../':
711         fname = fname[3:]
712     ext_loc = fname.rfind('.')
713     if ext_loc == -1:
714         return Task.Task.old_display(self)
715     ext = fname[ext_loc:]
716
717     ext_map = { '.idl' : 'Compiling IDL',
718                 '.et'  : 'Compiling ERRTABLE',
719                 '.asn1': 'Compiling ASN1',
720                 '.c'   : 'Compiling' }
721     if ext in ext_map:
722         return progress_display(self, ext_map[ext], fname)
723     return Task.Task.old_display(self)
724
725 Task.TaskBase.classes['Task'].old_display = Task.TaskBase.classes['Task'].display
726 Task.TaskBase.classes['Task'].display = samba_display