deycrypt / idapython

Automatically exported from code.google.com/p/idapython
0 stars 0 forks source link

Modules imported from scripts will not reload when script is rerun #42

Closed GoogleCodeExporter closed 8 years ago

GoogleCodeExporter commented 8 years ago
What steps will reproduce the problem?
1. Run script.py from Alt-9, which has 'import mymodule'
2. Observe output
3. Modify mymodule.py
4. Run script.py from Alt-9, which has 'import mymodule'

What is the expected output? What do you see instead?

Expected: import mymodule rereads mymodule.py
Actual: because mymodule is in sys.modules, it skips reading it from the disk

What version of the product are you using? On what operating system?

IDAPython 1.2.0

Please provide any additional information below.

To fix, edit init.py as follows:

At the bottom of the file, add:

class ModuleCleaner(object):
    def __init__(self):
        self.path = sys.path
        self.std = [sys.stdin, sys.stdout, sys.stderr]
        self.baseModules = sys.modules.copy()

    def revert(self):
        for moduleName in sys.modules.keys():
            if not self.baseModules.has_key(moduleName):
                del(sys.modules[moduleName]) #forcibly unload the module
        sys.stdin, sys.stdout, sys.stderr = self.std
        sys.path = self.path

_mc = ModuleCleaner()

as the first thing inside of def runscript(), add:

    global _mc
    _mc.revert()

Original issue reported on code.google.com by cbwhiz@gmail.com on 20 Dec 2009 at 7:21

GoogleCodeExporter commented 8 years ago
I'm sorry, there was a mistake in my above code. Corrected, the function should 
look
like:

def runscript(script):
    """
    Run the specified script after adding its directory path to
    system path.

    This function is used by the low-level plugin code.
    """
    _mc = ModuleCleaner()
    try:
        addscriptpath(script)
        watchdog.reset()
        argv = sys.argv
        sys.argv = [ script ]
        execfile(script, globals())
        sys.argv = argv
    except:
        raise
    finally:
        _mc.revert()

and this should be at the bottom (or wherever, really):

class ModuleCleaner(object):
    def __init__(self):
        self.path = sys.path
        self.std = [sys.stdin, sys.stdout, sys.stderr]
        self.baseModules = sys.modules.copy()

    def revert(self):
        for moduleName in sys.modules.keys():
            if not self.baseModules.has_key(moduleName):
                del(sys.modules[moduleName]) #forcibly unload the module
        sys.stdin, sys.stdout, sys.stderr = self.std
        sys.path = self.path

Original comment by cbwhiz@gmail.com on 20 Dec 2009 at 7:39

GoogleCodeExporter commented 8 years ago
This code will still fail if the recent file box (Alt-7) is used due to issue 
43.

Original comment by cbwhiz@gmail.com on 20 Dec 2009 at 7:57

GoogleCodeExporter commented 8 years ago
PS: http://pyunit.sourceforge.net/notes/reloading.html is where I got the idea 
for
the ModuleCleaner object.

Original comment by cbwhiz@gmail.com on 20 Dec 2009 at 8:00

GoogleCodeExporter commented 8 years ago
Functionality implemented, slightly differently, in 
http://code.google.com/p/idapython/source/detail?r=273

Thanks for the idea!

Original comment by gergely.erdelyi on 4 Feb 2010 at 9:01