Skip to content

Commit 8d4edd3

Browse files
committed
Editor callback function does not get cleared if used as bound method in a class bruderstein#153
- replaced the implementation of ScintillaWrapper with the one from NotepadPlusWrapper - fixed issue by usage of boost::python::object instead of PyObject* - fixed NotepadPlusWrapper::clearCallbackFunction() - added parameter annotation in ScintillaPython.cpp
1 parent 4cad63b commit 8d4edd3

File tree

4 files changed

+21
-21
lines changed

4 files changed

+21
-21
lines changed

PythonScript/src/NotepadPlusWrapper.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -751,7 +751,7 @@ void NotepadPlusWrapper::clearCallbackFunction(boost::python::object callback)
751751
{
752752
for(callbackT::iterator it = m_callbacks.begin(); it != m_callbacks.end();)
753753
{
754-
if (callback.ptr() == it->second.ptr())
754+
if (callback == it->second)
755755
{
756756
it = m_callbacks.erase(it);
757757
}

PythonScript/src/ScintillaPython.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ BOOST_PYTHON_MODULE(Npp)
2929

3030
boost::python::class_<ScintillaWrapper, boost::shared_ptr<ScintillaWrapper>, boost::noncopyable >("Editor", boost::python::no_init)
3131
.def("write", &ScintillaWrapper::AddText, "Add text to the document at current position (alias for addText).")
32-
.def("callbackSync", &ScintillaWrapper::addSyncCallback, "Registers a callback to a Python function when a Scintilla event occurs. See also callback() to register an asynchronous callback. Callbacks are called synchronously with the event, so try not to perform too much work in the event handler.\nCertain operations cannot be performed in a synchronous callback. setDocPointer, searchInTarget or findText calls are examples. Scintilla doesn't allow recursively modifying the text, so you can't modify the text in a SCINTILLANOTIFICATION.MODIFIED callback - use a standard Asynchronous callback to do this.\ne.g. editor.callbackSync(my_function, [SCINTILLANOTIFICATION.CHARADDED])")
33-
.def("callback", &ScintillaWrapper::addAsyncCallback, "Registers a callback to call a Python function synchronously when a Scintilla event occurs. Events are queued up, and run in the order they arrive, one after the other, but asynchronously with the main GUI. See editor.callbackSync() to register a synchronous callback. e.g. editor.callback(my_function, [SCINTILLANOTIFICATION.CHARADDED])")
32+
.def("callbackSync", &ScintillaWrapper::addSyncCallback, boost::python::args("callable", "listOfNotifications"), "Registers a callback to a Python function when a Scintilla event occurs. See also callback() to register an asynchronous callback. Callbacks are called synchronously with the event, so try not to perform too much work in the event handler.\nCertain operations cannot be performed in a synchronous callback. setDocPointer, searchInTarget or findText calls are examples. Scintilla doesn't allow recursively modifying the text, so you can't modify the text in a SCINTILLANOTIFICATION.MODIFIED callback - use a standard Asynchronous callback to do this.\ne.g. editor.callbackSync(my_function, [SCINTILLANOTIFICATION.CHARADDED])")
33+
.def("callback", &ScintillaWrapper::addAsyncCallback, boost::python::args("callable", "listOfNotifications"), "Registers a callback to call a Python function synchronously when a Scintilla event occurs. Events are queued up, and run in the order they arrive, one after the other, but asynchronously with the main GUI. See editor.callbackSync() to register a synchronous callback. e.g. editor.callback(my_function, [SCINTILLANOTIFICATION.CHARADDED])")
3434
.def("__getitem__", &ScintillaWrapper::GetLine, "Gets a line from the given (zero based) index")
3535
.def("__len__", &ScintillaWrapper::GetLength, "Gets the length (number of bytes) in the document")
3636
.def("forEachLine", &ScintillaWrapper::forEachLine, "Runs the function passed for each line in the current document. The function gets passed 3 arguments, the contents of the line, the line number (starting from zero), and the total number of lines. If the function returns a number, that number is added to the current line number for the next iteration.\nThat way, if you delete the current line, you should return 0, so as to stay on the current physical line.\n\nUnder normal circumstances, you do not need to return anything from the function (i.e. None)\n(Helper function)")
@@ -41,9 +41,9 @@ BOOST_PYTHON_MODULE(Npp)
4141
.def("getUserLineSelection", &ScintillaWrapper::getUserLineSelection, "Gets the start and end (zero indexed) line numbers of the user selection, or the whole document if nothing is selected. (Helper function)")
4242
.def("getUserCharSelection", &ScintillaWrapper::getUserCharSelection, "Gets the start and end (zero indexed) byte numbers of the user selection, or the whole document if nothing is selected. (Helper function)")
4343
.def("clearCallbacks", &ScintillaWrapper::clearAllCallbacks, "Clears all callbacks")
44-
.def("clearCallbacks", &ScintillaWrapper::clearCallbackFunction, "Clears all callbacks for a given function")
45-
.def("clearCallbacks", &ScintillaWrapper::clearCallbackEvents, "Clears all callbacks for the given list of events")
46-
.def("clearCallbacks", &ScintillaWrapper::clearCallback, "Clears the callback for the given callback function for the list of events")
44+
.def("clearCallbacks", &ScintillaWrapper::clearCallbackFunction, boost::python::args("callable"), "Clears all callbacks for a given function")
45+
.def("clearCallbacks", &ScintillaWrapper::clearCallbackEvents, boost::python::args("notificationList"), "Clears all callbacks for the given list of events")
46+
.def("clearCallbacks", &ScintillaWrapper::clearCallback, boost::python::args("callable", "notificationList"), "Clears the callback for the given callback function for the list of events")
4747
.def("flash", &ScintillaWrapper::flash, "Flash the editor by reversing the foreground and background colours briefly")
4848
.def("flash", &ScintillaWrapper::flashMilliseconds, boost::python::args("milliseconds"), "Flash the editor by reversing the foreground and background colours briefly")
4949
.add_static_property("WHOLEDOC", &ScintillaWrapper::getWholeDocFlag)

PythonScript/src/ScintillaWrapper.cpp

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -344,20 +344,20 @@ void ScintillaWrapper::runCallbacks(std::shared_ptr<CallbackExecArgs> args)
344344
DEBUG_TRACE(L"Finished consuming scintilla callbacks\n");
345345
}
346346

347-
bool ScintillaWrapper::addSyncCallback(PyObject* callback, boost::python::list events)
347+
bool ScintillaWrapper::addSyncCallback(boost::python::object callback, boost::python::list events)
348348
{
349349
return addCallbackImpl(callback, events, false);
350350
}
351351

352-
bool ScintillaWrapper::addAsyncCallback(PyObject* callback, boost::python::list events)
352+
bool ScintillaWrapper::addAsyncCallback(boost::python::object callback, boost::python::list events)
353353
{
354354
return addCallbackImpl(callback, events, true);
355355
}
356356

357357

358-
bool ScintillaWrapper::addCallbackImpl(PyObject* callback, boost::python::list events, bool isAsync)
358+
bool ScintillaWrapper::addCallbackImpl(boost::python::object callback, boost::python::list events, bool isAsync)
359359
{
360-
if (PyCallable_Check(callback))
360+
if (PyCallable_Check(callback.ptr()))
361361
{
362362

363363
{
@@ -366,9 +366,9 @@ bool ScintillaWrapper::addCallbackImpl(PyObject* callback, boost::python::list e
366366
size_t eventCount = _len(events);
367367
for(idx_t i = 0; i < eventCount; ++i)
368368
{
369-
Py_INCREF(callback);
369+
Py_INCREF(callback.ptr());
370370
m_callbacks.insert(std::pair<int, boost::shared_ptr<ScintillaCallback> >(boost::python::extract<int>(events[i]),
371-
boost::shared_ptr<ScintillaCallback>(new ScintillaCallback(boost::python::object(boost::python::handle<>(callback)), isAsync))));
371+
boost::shared_ptr<ScintillaCallback>(new ScintillaCallback(callback, isAsync))));
372372
}
373373
m_notificationsEnabled = true;
374374
}
@@ -381,12 +381,12 @@ bool ScintillaWrapper::addCallbackImpl(PyObject* callback, boost::python::list e
381381
}
382382
}
383383

384-
void ScintillaWrapper::clearCallbackFunction(PyObject* callback)
384+
void ScintillaWrapper::clearCallbackFunction(boost::python::object callback)
385385
{
386386
NppPythonScript::MutexHolder hold(m_callbackMutex);
387387
for(callbackT::iterator it = m_callbacks.begin(); it != m_callbacks.end();)
388388
{
389-
if (callback == it->second->getCallback().ptr())
389+
if (callback == it->second->getCallback())
390390
{
391391
it = m_callbacks.erase(it);
392392
}
@@ -425,13 +425,13 @@ void ScintillaWrapper::clearCallbackEvents(boost::python::list events)
425425
}
426426

427427

428-
void ScintillaWrapper::clearCallback(PyObject* callback, boost::python::list events)
428+
void ScintillaWrapper::clearCallback(boost::python::object callback, boost::python::list events)
429429
{
430430
NppPythonScript::MutexHolder hold(m_callbackMutex);
431431

432432
for(callbackT::iterator it = m_callbacks.begin(); it != m_callbacks.end(); )
433433
{
434-
if(it->second->getCallback().ptr() == callback && boost::python::extract<bool>(events.contains(it->first)))
434+
if(it->second->getCallback() == callback && boost::python::extract<bool>(events.contains(it->first)))
435435
{
436436
it = m_callbacks.erase(it);
437437
}

PythonScript/src/ScintillaWrapper.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,14 +59,14 @@ class ScintillaWrapper : public PyProducerConsumer<CallbackExecArgs>
5959
void invalidateHandle() { m_handle = NULL; };
6060

6161
void notify(SCNotification *notifyCode);
62-
bool addSyncCallback(PyObject* callback, boost::python::list events);
63-
bool addAsyncCallback(PyObject *callback, boost::python::list events);
64-
bool addCallbackImpl(PyObject *callback, boost::python::list events, bool isAsync);
62+
bool addSyncCallback(boost::python::object callback, boost::python::list events);
63+
bool addAsyncCallback(boost::python::object callback, boost::python::list events);
64+
bool addCallbackImpl(boost::python::object callback, boost::python::list events, bool isAsync);
6565

6666
void clearAllCallbacks();
67-
void clearCallbackFunction(PyObject* callback);
67+
void clearCallbackFunction(boost::python::object callback);
6868
void clearCallbackEvents(boost::python::list events);
69-
void clearCallback(PyObject* callback, boost::python::list events);
69+
void clearCallback(boost::python::object callback, boost::python::list events);
7070

7171
/* Helper functions
7272
* These functions are designed to make life easier for scripting,

0 commit comments

Comments
 (0)