Skip to content
This repository
tree: fde20bbf6b
Fetching contributors…

Cannot retrieve contributors at this time

file 104 lines (89 sloc) 3.274 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
"""
This module handles dictionary generation of classes for use
in the Python environment. Dictionaries are kept in
$ROOTPY_DATA for later use so they are not repeatedly regenerated
"""
import ROOT
import os
import sys
import re
import atexit
import uuid
from rootpy.userdata import DATA_ROOT


__NEW_DICTS = False
if sys.maxsize > 2 ** 32:
    __NBITS = '64'
else:
    __NBITS = '32'
__ROOT_VERSION = str(ROOT.gROOT.GetVersionCode())
__LOADED_DICTS = {}
__DICTS_PATH = os.path.join(DATA_ROOT, 'dicts', __NBITS, __ROOT_VERSION)
ROOT.gSystem.SetDynamicPath(":".join([__DICTS_PATH, ROOT.gSystem.GetDynamicPath()]))
__LOOKUP_TABLE_NAME = 'lookup'

if not os.path.exists(__DICTS_PATH):
    os.makedirs(__DICTS_PATH)

if os.path.exists(os.path.join(__DICTS_PATH, __LOOKUP_TABLE_NAME)):
    __LOOKUP_FILE = open(os.path.join(__DICTS_PATH, __LOOKUP_TABLE_NAME), 'r')
    __LOOKUP_TABLE = dict([reversed(line.strip().split('\t')) for line in __LOOKUP_FILE.readlines()])
    __LOOKUP_FILE.close()
else:
    __LOOKUP_TABLE = {}


def generate(declaration, headers=None):

    global __NEW_DICTS

    if headers is not None:
        headers = sorted(headers.split(';'))
        unique_name = ';'.join([declaration] + headers)
    else:
        unique_name = declaration

    # The library is already loaded, do nothing
    if unique_name in __LOADED_DICTS:
        return True

    # If as .so already exists for this class, use it.
    if unique_name in __LOOKUP_TABLE:
        if ROOT.gSystem.Load('%s.so' % __LOOKUP_TABLE[unique_name]) in (0, 1):
            __LOADED_DICTS[unique_name] = None
            return True
        return False

    # This dict was not previously generated so we must create it now
    print "generating dictionary for %s..." % declaration
    source = ""
    if headers is not None:
        for header in headers:
            if re.match('^<.+>$', header):
                source += '#include %s\n' % header
            else:
                source += '#include "%s"\n' % header
    source += '#ifdef __CINT__\n'
    source += '#pragma link C++ class %s+;\n' % declaration
    source += '#else\n'
    source += 'using namespace std;\n'
    source += 'template class %s;\n' % declaration
    source += '#endif\n'

    dict_id = uuid.uuid4().hex
    sourcefilename = os.path.join(__DICTS_PATH, '%s.C' % dict_id)
    sourcefile = open(sourcefilename, 'w')
    sourcefile.write(source)
    sourcefile.close()
    msg_level = ROOT.gErrorIgnoreLevel
    ROOT.gErrorIgnoreLevel = ROOT.kFatal
    success = ROOT.gSystem.CompileMacro(sourcefilename, 'k-', dict_id, __DICTS_PATH) == 1
    ROOT.gErrorIgnoreLevel = msg_level
    if success:
        __LOOKUP_TABLE[unique_name] = dict_id
        __LOADED_DICTS[unique_name] = None
        __NEW_DICTS = True
    else:
        os.unlink(sourcefilename)
        try:
            os.unlink(os.path.join(__DICTS_PATH, '%s_C.d' % dict_id))
            os.unlink(os.path.join(__DICTS_PATH, '%s.so' % dict_id))
        except:
            pass
    return success


@atexit.register
def __cleanup():

    if __NEW_DICTS:
        file = open(os.path.join(__DICTS_PATH, __LOOKUP_TABLE_NAME), 'w')
        for name, dict_id in __LOOKUP_TABLE.items():
            file.write('%s\t%s\n' % (dict_id, name))
        file.close()
Something went wrong with that request. Please try again.