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

@@ -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);
}