0

My goal is to load dynamically my different subclasses and execute them. To call my script, I am using this:

python Plugin.py Nmap execute google.com

Or

python Plugin.py Dig execute google.com

Here it's the code

Parent Class: Plugin.py

class Plugin(object)
    def __init__(self):
        self.sName = ''
    def execPlugin(self):
        return 'something'
def main():
    # get the name of the plugin
    sPlugin = sys.argv[1]
    # create the object
    mMod = __import__(sPlugin, fromlist=[sPlugin])
    mInstance = getattr(mMod, sPlugin)
    oPlugin = mInstance()
    print oPlugin
    print type(oPlugin)
    if (sys.argv[2] == 'execute'):
        # then execute it
        return oPlugin.execPlugin(sys.argv[3])
if __name__ == '__main__':
    main()

Sub Class located in Nmap/Nmap.py

class Nmap(Plugin):
    def __init__(self):
        self.sName = 'Nmap'
    def execPlugin(self):
        return 'something else'

Sub Class located in Dig/Dig.py

class Dig(Plugin):
    def __init__(self):
        self.sName = 'Dig'
    def execPlugin(self):
        return 'yeahhh'

My problem is located in

oPlugin = mInstance()

With the following error

TypeError: 'module' object is not callable

I tried so many things but nothing worked. How can I solve my problem?

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
David
  • 131
  • 1
  • 7
  • Have you imported a module named `mInstance`? – Ethan Bierlein Nov 04 '15 at 16:00
  • Why are `Nmap.py` and `Dig.py` in subdirectories? Do they have `__init__.py` files, and what's in those? You probably want another level of `getattr` to get the classes rather than the modules, or to simplify your structure. – jonrsharpe Nov 04 '15 at 16:00
  • Possible duplicate of [TypeError: 'module' object is not callable](http://stackoverflow.com/questions/4534438/typeerror-module-object-is-not-callable) – Ethan Bierlein Nov 04 '15 at 16:03
  • Yes, I have an __init__.py (empty) in my subdirectories and I need them for another reasons. I – David Nov 04 '15 at 16:03
  • 1
    What happens if you e.g. `from Nmap import Nmap` in the `__init__.py` in `/Nmap`? I think that would fix it. – jonrsharpe Nov 04 '15 at 16:04
  • I have a (new) error but I think we're close: Plugin.__init__() TypeError: unbound method __init__() must be called with Plugin instance as first argument (got nothing instead). I am gonna investigate! – David Nov 04 '15 at 16:07
  • 1
    Then it's because you're importing the directory `Nmap`, not the file `Nmap.py`, as `mMod`, and therefore when you `getattr` from `mMod` you get `Nmap.py` not the class `Nmap`. Consider renaming to avoid this - modules should have `snake_case` names, only classes are `CamelCase`. – jonrsharpe Nov 04 '15 at 16:10

1 Answers1

1

You have a structure like:

Plugin.py
/Nmap
    __init__.py
    Nmap.py
        # class Nmap(Plugin): ...

In Plugin.py, when you do mMod = __import__(sPlugin, fromlist=[sPlugin]) where sPlugin == 'Nmap', this makes mMod refer to the directory /Nmap, not the file Nmap.py (note that both files and directories can be modules in Python). Hence mInstance = getattr(mMod, sPlugin) makes mInstance the file Nmap.py rather than the class Nmap.

There are two ways to fix this, either:

  1. Use the __init__.py in /Nmap to bring the class "up" one level, i.e. include from Nmap import Nmap; or
  2. Add an extra level of getattr into Plugin.py.

Additionally, you should follow the style guide's naming conventions, which might have helped you track the issue down faster.

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
  • You rock's ;). Thank you very much And yes, you're right, I will change my directory name :) – David Nov 04 '15 at 16:31