# -*- coding: utf-8 -*-
#
# module.py - commander
#
# Copyright (C) 2010 - Jesse van den Kieboom
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor,
# Boston, MA 02110-1301, USA.
import sys, os, types, bisect, importlib
import utils
import commands.exceptions as exceptions
import commands.method as method
import commands.rollbackimporter as rollbackimporter
class Module(method.Method):
def __init__(self, base, mod, parent=None):
method.Method.__init__(self, None, base, parent)
self._commands = None
self._dirname = None
self._roots = None
if type(mod) == types.ModuleType:
self.mod = mod
if '__default__' in mod.__dict__:
self.method = mod.__dict__['__default__']
else:
self.method = None
else:
self.mod = None
self._dirname = mod
self._rollback = rollbackimporter.RollbackImporter()
def commands(self):
if self._commands == None:
self.scan_commands()
return self._commands
def clear(self):
self._commands = None
def roots(self):
if self._roots == None:
if not self.mod:
return []
dic = self.mod.__dict__
if '__root__' in dic:
root = dic['__root__']
else:
root = []
root = list(filter(lambda x: x in dic and type(dic[x]) == types.FunctionType, root))
self._roots = list(map(lambda x: method.Method(dic[x], x, self.mod), root))
return self._roots
def scan_commands(self):
self._commands = []
if self.mod == None:
return
dic = self.mod.__dict__
if '__root__' in dic:
root = dic['__root__']
else:
root = []
for k in dic:
if k.startswith('_') or k in root:
continue
item = dic[k]
if type(item) == types.FunctionType:
bisect.insort(self._commands, method.Method(item, k, self))
elif type(item) == types.ModuleType and utils.is_commander_module(item):
mod = Module(k, item, self)
bisect.insort(self._commands, mod)
# Insert root functions into this module
for r in mod.roots():
bisect.insert(self._commands, r)
def unload(self):
self._commands = None
if not self._dirname:
return False
self._rollback.uninstall()
self.mod = None
return True
def reload(self):
if not self.unload():
return
if self.real_name in sys.modules:
raise Exception('Module already exists...')
oldpath = list(sys.path)
try:
sys.path.insert(0, self._dirname)
self._rollback.monitor()
self.mod = importlib.import_module(self.real_name)
self._rollback.cancel()
if not utils.is_commander_module(self.mod):
raise Exception('Module is not a commander module...')
self._rollback.insert_main(self.real_name)
if '__default__' in self.mod.__dict__:
self.method = self.mod.__dict__['__default__']
else:
self.method = None
self._func_props = None
except:
sys.path = oldpath
self._rollback.uninstall()
if self.real_name in sys.modules:
del sys.modules[self.real_name]
raise
sys.path = oldpath
# ex:ts=4:et