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:
Ernestas Kulik
2022-07-04 00:03:30 +03:00
parent fab1bb1bd5
commit 94f1c32729
4 changed files with 110 additions and 2 deletions

View File

@@ -505,6 +505,25 @@ CPySocket::~CPySocket() {
Py_CLEAR(m_pyObj);
}
CPyModule* CPyModCommand::GetModule() {
return this->m_pModule;
}
void CPyModCommand::operator()(const CString& sLine) {
PyObject* pyRes = PyObject_CallMethod(
m_pyObj, const_cast<char*>("__call__"), const_cast<char*>("s"),
sLine.c_str());
if (!pyRes) {
CString sRetMsg = m_pModPython->GetPyExceptionStr();
DEBUG("oops, something went wrong when calling command: " << sRetMsg);
}
Py_CLEAR(pyRes);
}
CPyModCommand::~CPyModCommand() {
Py_CLEAR(m_pyObj);
}
template <>
void TModInfo<CModPython>(CModInfo& Info) {
Info.SetWikiPage("modpython");