Automatic reload()?

Alex cut_me_out at hotmail.com
Sat Jun 3 19:26:06 EDT 2000


import sys, string
from types import ModuleType

class Reloader:

    ''' 
    This is so complex that I've probably added more problems than I've
    solved.  But anyway, here is my attempt at something that figures
    out an appropriate reloading order for you.  You create an instance
    of the class, call it 'rr', before you have imported any of the
    modules you'll be wanting to reload (the .pythonrc file would be a
    good place.)  Then when you wish to reload the modules in a given
    namespace, you run the command

    exec (rr (globals ())) 

    In my case, the namespace would usually be __main__, so this would
    just go at the top of the script I'm currently working on in
    emacs.

    Alex.
    '''

    def __init__ (self):
        self.keepem = sys.modules.copy ()

    def get_new_modules (self):
        modules = {}
        for i, m in sys.modules.items():
            if (not self.keepem.has_key (i)) and \
               (type(m) == ModuleType):
                modules[i] = m
        return modules

    def clear_sys_modules (self):
        for i in self.modules.keys ():
            if sys.modules.has_key (i):
                del sys.modules[i]

    def get_dependancies (self, module_name):
        self.clear_sys_modules ()
        exec 'import ' + module_name
        new_modules = self.get_new_modules ()
        del new_modules[module_name]
        return new_modules

    def determine_reloads (self):
        self.return_commands = []
        while self.dependancies:
            for i, deps in self.dependancies.items ():
                if not deps:
                    break
            else:
                raise 'Cyclic dependancy(?)'
            exec 'import ' + i
            reload (eval (i))
            if self.namespace.has_key (i) and \
               (self.namespace[i] == self.modules[i]):
                self.return_commands.append (
                    'import %s; reload (%s)' % (i, i))
            del self.dependancies[i]
            for deps in self.dependancies.values ():
                while deps.count (i):
                    deps.remove (i)

    def __call__ (self, namespace):
        self.namespace = namespace
        self.modules = self.get_new_modules ()
        self.dependancies = {}
        for module_name in self.modules.keys ():
            deps = self.get_dependancies (module_name).keys ()
            self.dependancies[module_name] = deps
        self.determine_reloads ()
        return string.join (self.return_commands, ';')

rr = Reloader ()

if __name__ == '__main__':
    '''This is a test script, intended to be run with two modules, B.py
    and C.py somewhere in the directories in sys.path.  Their contents
    should be

    B.py:
    ######################################################################
    import C

    class B (C.C):
    
        def __init__ (self):
            C.C.__init__ (self)
        
    C.py:
    ######################################################################
    class C:

        def __init__ (self):
            pass
    '''
    import B, C

    bid = id (B.B)
    cid = id (C.C)
    exec (rr (globals ()))
    assert (bid != id (B.B)) and (cid != id (C.C))

    t = B.B ()



More information about the Python-list mailing list