mirror of
https://github.com/znc/znc.git
synced 2026-03-28 17:42:41 +01:00
modules: modpython: Implement Module.AddCommand()
Currently, there is no usable wrapper for CModCommand for use within
bindings, so this commit adds a proxy class that adds itself as a
callback and allows implementing Python classes to implement commands
via __call__().
A completely synthetic example:
import znc
class foo(znc.Module):
module_types = [znc.CModInfo.UserModule]
def OnLoad(self, args, message):
self.AddHelpCommand()
self.AddCommand(FooCmd)
return True
class FooCmd(znc.Command):
cmd = 'foo'
args = foo.t_d('bar')
desc = foo.t_d('baz')
def __call__(self, line):
self.GetModule().PutModule('I have been foo’d!')
Fixes https://github.com/znc/znc/issues/198
This commit is contained in:
@@ -334,3 +334,35 @@ class CModulesIter {
|
||||
CModules* m_pModules;
|
||||
CModules::const_iterator m_it;
|
||||
};
|
||||
|
||||
class ZNC_EXPORT_LIB_EXPORT CPyModCommand : public CModCommand {
|
||||
CPyModule* m_pModule;
|
||||
CModPython* m_pModPython;
|
||||
PyObject* m_pyObj;
|
||||
|
||||
void operator()(const CString& sLine);
|
||||
|
||||
public:
|
||||
CPyModCommand(CPyModule* pModule,
|
||||
const CString& sCmd, const COptionalTranslation& sArgs,
|
||||
const COptionalTranslation& sDesc, PyObject *pyObj)
|
||||
: CModCommand(sCmd, [=](const CString& sLine) { (*this)(sLine); }, sArgs,
|
||||
sDesc),
|
||||
m_pModule(pModule),
|
||||
m_pModPython(pModule->GetModPython()),
|
||||
m_pyObj(pyObj) {
|
||||
Py_INCREF(pyObj);
|
||||
pModule->AddCommand(*this);
|
||||
}
|
||||
virtual ~CPyModCommand();
|
||||
|
||||
CPyModule* GetModule();
|
||||
};
|
||||
|
||||
inline CPyModCommand* CreatePyModCommand(CPyModule* pModule,
|
||||
const CString& sCmd,
|
||||
const COptionalTranslation& sArgs,
|
||||
const COptionalTranslation& sDesc,
|
||||
PyObject* pyObj) {
|
||||
return new CPyModCommand(pModule, sCmd, sArgs, sDesc, pyObj);
|
||||
}
|
||||
|
||||
@@ -197,7 +197,9 @@ class Module:
|
||||
num)
|
||||
return fmt.format
|
||||
|
||||
# TODO is "t_d" needed for python? Maybe after AddCommand is implemented
|
||||
@classmethod
|
||||
def t_d(cls, english, context=''):
|
||||
return CDelayedTranslation('znc-' + cls.__name__, context, english)
|
||||
|
||||
def OnLoad(self, sArgs, sMessage):
|
||||
return True
|
||||
@@ -295,7 +297,7 @@ class Module:
|
||||
pass
|
||||
|
||||
def OnModCommand(self, sCommand):
|
||||
pass
|
||||
self.HandleCommand(sCommand)
|
||||
|
||||
def OnModNotice(self, sMessage):
|
||||
pass
|
||||
@@ -429,6 +431,16 @@ class Module:
|
||||
def OnSendToIRC(self, sLine):
|
||||
pass
|
||||
|
||||
# Command stuff
|
||||
def AddCommand(self, cls, *args, **kwargs):
|
||||
cmd = cls(*args, **kwargs)
|
||||
cmd._cmodcommand = CreatePyModCommand(self._cmod, cls.cmd,
|
||||
COptionalTranslation(cls.args),
|
||||
COptionalTranslation(cls.desc),
|
||||
cmd)
|
||||
|
||||
return cmd
|
||||
|
||||
# Global modules
|
||||
def OnAddUser(self, User, sErrorRet):
|
||||
pass
|
||||
@@ -672,6 +684,18 @@ class Module:
|
||||
pass
|
||||
|
||||
|
||||
class Command:
|
||||
cmd = ''
|
||||
args = ''
|
||||
desc = ''
|
||||
|
||||
def __call__(self, sLine):
|
||||
pass
|
||||
|
||||
def GetModule(self):
|
||||
return self._cmodcommand.GetModule().GetNewPyObj()
|
||||
|
||||
|
||||
def make_inherit(cl, parent, attr):
|
||||
def make_caller(parent, name, attr):
|
||||
return lambda self, *a: parent.__dict__[name](self.__dict__[attr], *a)
|
||||
@@ -688,6 +712,7 @@ def make_inherit(cl, parent, attr):
|
||||
make_inherit(Socket, CPySocket, '_csock')
|
||||
make_inherit(Module, CPyModule, '_cmod')
|
||||
make_inherit(Timer, CPyTimer, '_ctimer')
|
||||
make_inherit(Command, CPyModCommand, '_cmodcommand')
|
||||
|
||||
|
||||
class ZNCModuleLoader(importlib.abc.SourceLoader):
|
||||
|
||||
Reference in New Issue
Block a user