custom.py revision 97e2c5ac0bba7298c9a32703fe3d19de1f7b815a
197e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca"""custom
297e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
397e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé FonsecaCustom builders and methods.
497e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
597e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca"""
697e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
797e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca#
897e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca# Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
997e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca# All Rights Reserved.
1097e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca#
1197e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca# Permission is hereby granted, free of charge, to any person obtaining a
1297e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca# copy of this software and associated documentation files (the
1397e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca# "Software"), to deal in the Software without restriction, including
1497e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca# without limitation the rights to use, copy, modify, merge, publish,
1597e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca# distribute, sub license, and/or sell copies of the Software, and to
1697e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca# permit persons to whom the Software is furnished to do so, subject to
1797e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca# the following conditions:
1897e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca#
1997e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca# The above copyright notice and this permission notice (including the
2097e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca# next paragraph) shall be included in all copies or substantial portions
2197e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca# of the Software.
2297e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca#
2397e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
2497e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
2597e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
2697e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca# IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
2797e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
2897e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
2997e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
3097e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca#
3197e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
3297e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
3397e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonsecaimport os
3497e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonsecaimport os.path
3597e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonsecaimport re
3697e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
3797e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonsecaimport SCons.Action
3897e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonsecaimport SCons.Builder
3997e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonsecaimport SCons.Scanner
4097e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
4197e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonsecaimport fixes
4297e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
4397e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
4497e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonsecadef quietCommandLines(env):
4597e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    # Quiet command lines
4697e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    # See also http://www.scons.org/wiki/HidingCommandLinesInOutput
4797e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    env['ASCOMSTR'] = "  Assembling $SOURCE ..."
4897e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    env['ASPPCOMSTR'] = "  Assembling $SOURCE ..."
4997e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    env['CCCOMSTR'] = "  Compiling $SOURCE ..."
5097e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    env['SHCCCOMSTR'] = "  Compiling $SOURCE ..."
5197e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    env['CXXCOMSTR'] = "  Compiling $SOURCE ..."
5297e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    env['SHCXXCOMSTR'] = "  Compiling $SOURCE ..."
5397e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    env['ARCOMSTR'] = "  Archiving $TARGET ..."
5497e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    env['RANLIBCOMSTR'] = "  Indexing $TARGET ..."
5597e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    env['LINKCOMSTR'] = "  Linking $TARGET ..."
5697e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    env['SHLINKCOMSTR'] = "  Linking $TARGET ..."
5797e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    env['LDMODULECOMSTR'] = "  Linking $TARGET ..."
5897e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    env['SWIGCOMSTR'] = "  Generating $TARGET ..."
5997e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
6097e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
6197e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonsecadef createConvenienceLibBuilder(env):
6297e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    """This is a utility function that creates the ConvenienceLibrary
6397e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    Builder in an Environment if it is not there already.
6497e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
6597e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    If it is already there, we return the existing one.
6697e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
6797e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    Based on the stock StaticLibrary and SharedLibrary builders.
6897e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    """
6997e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
7097e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    try:
7197e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca        convenience_lib = env['BUILDERS']['ConvenienceLibrary']
7297e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    except KeyError:
7397e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca        action_list = [ SCons.Action.Action("$ARCOM", "$ARCOMSTR") ]
7497e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca        if env.Detect('ranlib'):
7597e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca            ranlib_action = SCons.Action.Action("$RANLIBCOM", "$RANLIBCOMSTR")
7697e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca            action_list.append(ranlib_action)
7797e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
7897e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca        convenience_lib = SCons.Builder.Builder(action = action_list,
7997e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca                                  emitter = '$LIBEMITTER',
8097e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca                                  prefix = '$LIBPREFIX',
8197e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca                                  suffix = '$LIBSUFFIX',
8297e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca                                  src_suffix = '$SHOBJSUFFIX',
8397e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca                                  src_builder = 'SharedObject')
8497e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca        env['BUILDERS']['ConvenienceLibrary'] = convenience_lib
8597e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
8697e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    return convenience_lib
8797e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
8897e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
8997e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca# TODO: handle import statements with multiple modules
9097e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca# TODO: handle from import statements
9197e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonsecaimport_re = re.compile(r'^import\s+(\S+)$', re.M)
9297e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
9397e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonsecadef python_scan(node, env, path):
9497e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    # http://www.scons.org/doc/0.98.5/HTML/scons-user/c2781.html#AEN2789
9597e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    contents = node.get_contents()
9697e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    source_dir = node.get_dir()
9797e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    imports = import_re.findall(contents)
9897e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    results = []
9997e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    for imp in imports:
10097e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca        for dir in path:
10197e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca            file = os.path.join(str(dir), imp.replace('.', os.sep) + '.py')
10297e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca            if os.path.exists(file):
10397e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca                results.append(env.File(file))
10497e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca                break
10597e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca            file = os.path.join(str(dir), imp.replace('.', os.sep), '__init__.py')
10697e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca            if os.path.exists(file):
10797e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca                results.append(env.File(file))
10897e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca                break
10997e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    return results
11097e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
11197e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonsecapython_scanner = SCons.Scanner.Scanner(function = python_scan, skeys = ['.py'])
11297e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
11397e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
11497e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonsecadef code_generate(env, script, target, source, command):
11597e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    """Method to simplify code generation via python scripts.
11697e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
11797e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    http://www.scons.org/wiki/UsingCodeGenerators
11897e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    http://www.scons.org/doc/0.98.5/HTML/scons-user/c2768.html
11997e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    """
12097e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
12197e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    # We're generating code using Python scripts, so we have to be
12297e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    # careful with our scons elements.  This entry represents
12397e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    # the generator file *in the source directory*.
12497e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    script_src = env.File(script).srcnode()
12597e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
12697e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    # This command creates generated code *in the build directory*.
12797e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    command = command.replace('$SCRIPT', script_src.path)
12897e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    code = env.Command(target, source, command)
12997e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
13097e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    # Explicitly mark that the generated code depends on the generator,
13197e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    # and on implicitly imported python modules
13297e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    path = (script_src.get_dir(),)
13397e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    deps = [script_src]
13497e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    deps += script_src.get_implicit_deps(env, python_scanner, path)
13597e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    env.Depends(code, deps)
13697e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
13797e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    # Running the Python script causes .pyc files to be generated in the
13897e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    # source directory.  When we clean up, they should go too. So add side
13997e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    # effects for .pyc files
14097e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    for dep in deps:
14197e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca        pyc = env.File(str(dep) + 'c')
14297e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca        env.SideEffect(pyc, code)
14397e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
14497e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    return code
14597e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
14697e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
14797e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonsecadef createCodeGenerateMethod(env):
14897e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    env.Append(SCANNERS = python_scanner)
14997e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    env.AddMethod(code_generate, 'CodeGenerate')
15097e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
15197e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
15297e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonsecadef symlink(target, source, env):
15397e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    target = str(target[0])
15497e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    source = str(source[0])
15597e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    if os.path.islink(target) or os.path.exists(target):
15697e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca        os.remove(target)
15797e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    os.symlink(os.path.basename(source), target)
15897e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
15997e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonsecadef install_program(env, source):
16097e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    source = str(source[0])
16197e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    target_dir =  os.path.join(env.Dir('#.').srcnode().abspath, env['build'], 'bin')
16297e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    target_name = str(source)
16397e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    env.InstallAs(os.path.join(target_dir, target_name), source)
16497e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
16597e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonsecadef install_shared_library(env, source, version = ()):
16697e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    source = str(source[0])
16797e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    version = tuple(map(str, version))
16897e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    target_dir =  os.path.join(env.Dir('#.').srcnode().abspath, env['build'], 'lib')
16997e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    target_name = '.'.join((str(source),) + version)
17097e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    last = env.InstallAs(os.path.join(target_dir, target_name), source)
17197e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    while len(version):
17297e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca        version = version[:-1]
17397e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca        target_name = '.'.join((str(source),) + version)
17497e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca        action = SCons.Action.Action(symlink, "$TARGET -> $SOURCE")
17597e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca        last = env.Command(os.path.join(target_dir, target_name), last, action)
17697e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
17797e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonsecadef createInstallMethods(env):
17897e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    env.AddMethod(install_program, 'InstallProgram')
17997e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    env.AddMethod(install_shared_library, 'InstallSharedLibrary')
18097e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
18197e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
18297e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonsecadef generate(env):
18397e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    """Common environment generation code"""
18497e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
18597e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    if env.get('quiet', True):
18697e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca        quietCommandLines(env)
18797e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
18897e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    # Custom builders and methods
18997e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    createConvenienceLibBuilder(env)
19097e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    createCodeGenerateMethod(env)
19197e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    createInstallMethods(env)
19297e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
19397e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    # for debugging
19497e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    #print env.Dump()
19597e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
19697e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
19797e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonsecadef exists(env):
19897e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    return 1
199