importer.py revision 13670
15522Snate@binkert.org# Copyright (c) 2008 The Hewlett-Packard Development Company
25522Snate@binkert.org# All rights reserved.
35522Snate@binkert.org#
45522Snate@binkert.org# Redistribution and use in source and binary forms, with or without
55522Snate@binkert.org# modification, are permitted provided that the following conditions are
65522Snate@binkert.org# met: redistributions of source code must retain the above copyright
75522Snate@binkert.org# notice, this list of conditions and the following disclaimer;
85522Snate@binkert.org# redistributions in binary form must reproduce the above copyright
95522Snate@binkert.org# notice, this list of conditions and the following disclaimer in the
105522Snate@binkert.org# documentation and/or other materials provided with the distribution;
115522Snate@binkert.org# neither the name of the copyright holders nor the names of its
125522Snate@binkert.org# contributors may be used to endorse or promote products derived from
135522Snate@binkert.org# this software without specific prior written permission.
145522Snate@binkert.org#
155522Snate@binkert.org# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
165522Snate@binkert.org# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
175522Snate@binkert.org# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
185522Snate@binkert.org# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
195522Snate@binkert.org# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
205522Snate@binkert.org# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
215522Snate@binkert.org# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
225522Snate@binkert.org# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
235522Snate@binkert.org# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
245522Snate@binkert.org# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
255522Snate@binkert.org# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
265522Snate@binkert.org#
275522Snate@binkert.org# Authors: Nathan Binkert
285522Snate@binkert.org
295522Snate@binkert.org# Simple importer that allows python to import data from a dict of
305522Snate@binkert.org# code objects.  The keys are the module path, and the items are the
315522Snate@binkert.org# filename and bytecode of the file.
325522Snate@binkert.orgclass CodeImporter(object):
335522Snate@binkert.org    def __init__(self):
345522Snate@binkert.org        self.modules = {}
355522Snate@binkert.org
367502Snate@binkert.org    def add_module(self, filename, abspath, modpath, code):
375522Snate@binkert.org        if modpath in self.modules:
3813663Sandreas.sandberg@arm.com            raise AttributeError("%s already found in importer" % modpath)
395522Snate@binkert.org
407502Snate@binkert.org        self.modules[modpath] = (filename, abspath, code)
415522Snate@binkert.org
425522Snate@binkert.org    def find_module(self, fullname, path):
435522Snate@binkert.org        if fullname in self.modules:
445522Snate@binkert.org            return self
455522Snate@binkert.org
465522Snate@binkert.org        return None
475522Snate@binkert.org
485522Snate@binkert.org    def load_module(self, fullname):
495522Snate@binkert.org        # Because the importer is created and initialized in its own
505522Snate@binkert.org        # little sandbox (in init.cc), the globals that were available
515522Snate@binkert.org        # when the importer module was loaded and CodeImporter was
525522Snate@binkert.org        # defined are not available when load_module is actually
535522Snate@binkert.org        # called. Soooo, the imports must live here.
545522Snate@binkert.org        import imp
555522Snate@binkert.org        import os
565522Snate@binkert.org        import sys
579737Sandreas@sandberg.pp.se
589737Sandreas@sandberg.pp.se        try:
599737Sandreas@sandberg.pp.se            mod = sys.modules[fullname]
609737Sandreas@sandberg.pp.se        except KeyError:
619737Sandreas@sandberg.pp.se            mod = imp.new_module(fullname)
629737Sandreas@sandberg.pp.se            sys.modules[fullname] = mod
635522Snate@binkert.org
645522Snate@binkert.org        try:
655522Snate@binkert.org            mod.__loader__ = self
667502Snate@binkert.org            srcfile,abspath,code = self.modules[fullname]
677502Snate@binkert.org
687502Snate@binkert.org            override = os.environ.get('M5_OVERRIDE_PY_SOURCE', 'false').lower()
697502Snate@binkert.org            if override in ('true', 'yes') and  os.path.exists(abspath):
7013670Sandreas.sandberg@arm.com                src = open(abspath, 'r').read()
717502Snate@binkert.org                code = compile(src, abspath, 'exec')
727502Snate@binkert.org
735522Snate@binkert.org            if os.path.basename(srcfile) == '__init__.py':
745522Snate@binkert.org                mod.__path__ = fullname.split('.')
759737Sandreas@sandberg.pp.se                mod.__package__ = fullname
769737Sandreas@sandberg.pp.se            else:
779737Sandreas@sandberg.pp.se                mod.__package__ = fullname.rpartition('.')[0]
785522Snate@binkert.org            mod.__file__ = srcfile
795522Snate@binkert.org
805522Snate@binkert.org            exec code in mod.__dict__
815522Snate@binkert.org        except Exception:
825522Snate@binkert.org            del sys.modules[fullname]
835522Snate@binkert.org            raise
845522Snate@binkert.org
855522Snate@binkert.org        return mod
865522Snate@binkert.org
875522Snate@binkert.org# Create an importer and add it to the meta_path so future imports can
885522Snate@binkert.org# use it.  There's currently nothing in the importer, but calls to
895522Snate@binkert.org# add_module can be used to add code.
905522Snate@binkert.orgimport sys
915522Snate@binkert.orgimporter = CodeImporter()
925522Snate@binkert.orgadd_module = importer.add_module
935522Snate@binkert.orgsys.meta_path.append(importer)
94