mirror of
https://github.com/python/cpython.git
synced 2025-08-04 08:59:19 +00:00
gh-71592: Add ability to trace Tcl commands executed by Tkinter (GH-118291)
This is an experimental feature, for internal use. Setting tkinter._debug = True before creating the root window enables printing every executed Tcl command (or a Tcl command equivalent to the used Tcl C API). This will help to convert a Tkinter example into Tcl script to check whether the issue is caused by Tkinter or exists in the underlying Tcl/Tk library.
This commit is contained in:
parent
417dd3aca7
commit
1ff626ebda
3 changed files with 190 additions and 6 deletions
|
@ -41,6 +41,7 @@ from tkinter.constants import *
|
||||||
import re
|
import re
|
||||||
|
|
||||||
wantobjects = 1
|
wantobjects = 1
|
||||||
|
_debug = False # set to True to print executed Tcl/Tk commands
|
||||||
|
|
||||||
TkVersion = float(_tkinter.TK_VERSION)
|
TkVersion = float(_tkinter.TK_VERSION)
|
||||||
TclVersion = float(_tkinter.TCL_VERSION)
|
TclVersion = float(_tkinter.TCL_VERSION)
|
||||||
|
@ -69,7 +70,10 @@ def _stringify(value):
|
||||||
else:
|
else:
|
||||||
value = '{%s}' % _join(value)
|
value = '{%s}' % _join(value)
|
||||||
else:
|
else:
|
||||||
value = str(value)
|
if isinstance(value, bytes):
|
||||||
|
value = str(value, 'latin1')
|
||||||
|
else:
|
||||||
|
value = str(value)
|
||||||
if not value:
|
if not value:
|
||||||
value = '{}'
|
value = '{}'
|
||||||
elif _magic_re.search(value):
|
elif _magic_re.search(value):
|
||||||
|
@ -411,7 +415,6 @@ class Variable:
|
||||||
self._tk.globalunsetvar(self._name)
|
self._tk.globalunsetvar(self._name)
|
||||||
if self._tclCommands is not None:
|
if self._tclCommands is not None:
|
||||||
for name in self._tclCommands:
|
for name in self._tclCommands:
|
||||||
#print '- Tkinter: deleted command', name
|
|
||||||
self._tk.deletecommand(name)
|
self._tk.deletecommand(name)
|
||||||
self._tclCommands = None
|
self._tclCommands = None
|
||||||
|
|
||||||
|
@ -683,7 +686,6 @@ class Misc:
|
||||||
this widget in the Tcl interpreter."""
|
this widget in the Tcl interpreter."""
|
||||||
if self._tclCommands is not None:
|
if self._tclCommands is not None:
|
||||||
for name in self._tclCommands:
|
for name in self._tclCommands:
|
||||||
#print '- Tkinter: deleted command', name
|
|
||||||
self.tk.deletecommand(name)
|
self.tk.deletecommand(name)
|
||||||
self._tclCommands = None
|
self._tclCommands = None
|
||||||
|
|
||||||
|
@ -691,7 +693,6 @@ class Misc:
|
||||||
"""Internal function.
|
"""Internal function.
|
||||||
|
|
||||||
Delete the Tcl command provided in NAME."""
|
Delete the Tcl command provided in NAME."""
|
||||||
#print '- Tkinter: deleted command', name
|
|
||||||
self.tk.deletecommand(name)
|
self.tk.deletecommand(name)
|
||||||
try:
|
try:
|
||||||
self._tclCommands.remove(name)
|
self._tclCommands.remove(name)
|
||||||
|
@ -2450,6 +2451,8 @@ class Tk(Misc, Wm):
|
||||||
baseName = baseName + ext
|
baseName = baseName + ext
|
||||||
interactive = False
|
interactive = False
|
||||||
self.tk = _tkinter.create(screenName, baseName, className, interactive, wantobjects, useTk, sync, use)
|
self.tk = _tkinter.create(screenName, baseName, className, interactive, wantobjects, useTk, sync, use)
|
||||||
|
if _debug:
|
||||||
|
self.tk.settrace(_print_command)
|
||||||
if useTk:
|
if useTk:
|
||||||
self._loadtk()
|
self._loadtk()
|
||||||
if not sys.flags.ignore_environment:
|
if not sys.flags.ignore_environment:
|
||||||
|
@ -2536,6 +2539,14 @@ class Tk(Misc, Wm):
|
||||||
"Delegate attribute access to the interpreter object"
|
"Delegate attribute access to the interpreter object"
|
||||||
return getattr(self.tk, attr)
|
return getattr(self.tk, attr)
|
||||||
|
|
||||||
|
|
||||||
|
def _print_command(cmd, *, file=sys.stderr):
|
||||||
|
# Print executed Tcl/Tk commands.
|
||||||
|
assert isinstance(cmd, tuple)
|
||||||
|
cmd = _join(cmd)
|
||||||
|
print(cmd, file=file)
|
||||||
|
|
||||||
|
|
||||||
# Ideally, the classes Pack, Place and Grid disappear, the
|
# Ideally, the classes Pack, Place and Grid disappear, the
|
||||||
# pack/place/grid methods are defined on the Widget class, and
|
# pack/place/grid methods are defined on the Widget class, and
|
||||||
# everybody uses w.pack_whatever(...) instead of Pack.whatever(w,
|
# everybody uses w.pack_whatever(...) instead of Pack.whatever(w,
|
||||||
|
|
|
@ -306,6 +306,7 @@ typedef struct {
|
||||||
int threaded; /* True if tcl_platform[threaded] */
|
int threaded; /* True if tcl_platform[threaded] */
|
||||||
Tcl_ThreadId thread_id;
|
Tcl_ThreadId thread_id;
|
||||||
int dispatching;
|
int dispatching;
|
||||||
|
PyObject *trace;
|
||||||
/* We cannot include tclInt.h, as this is internal.
|
/* We cannot include tclInt.h, as this is internal.
|
||||||
So we cache interesting types here. */
|
So we cache interesting types here. */
|
||||||
const Tcl_ObjType *OldBooleanType;
|
const Tcl_ObjType *OldBooleanType;
|
||||||
|
@ -570,6 +571,7 @@ Tkapp_New(const char *screenName, const char *className,
|
||||||
TCL_GLOBAL_ONLY) != NULL;
|
TCL_GLOBAL_ONLY) != NULL;
|
||||||
v->thread_id = Tcl_GetCurrentThread();
|
v->thread_id = Tcl_GetCurrentThread();
|
||||||
v->dispatching = 0;
|
v->dispatching = 0;
|
||||||
|
v->trace = NULL;
|
||||||
|
|
||||||
#ifndef TCL_THREADS
|
#ifndef TCL_THREADS
|
||||||
if (v->threaded) {
|
if (v->threaded) {
|
||||||
|
@ -1306,6 +1308,29 @@ Tkapp_ObjectResult(TkappObject *self)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
Tkapp_Trace(TkappObject *self, PyObject *args)
|
||||||
|
{
|
||||||
|
if (args == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (self->trace) {
|
||||||
|
PyObject *res = PyObject_CallObject(self->trace, args);
|
||||||
|
if (res == NULL) {
|
||||||
|
Py_DECREF(args);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
Py_DECREF(res);
|
||||||
|
}
|
||||||
|
Py_DECREF(args);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define TRACE(_self, ARGS) do { \
|
||||||
|
if ((_self)->trace && !Tkapp_Trace((_self), Py_BuildValue ARGS)) { \
|
||||||
|
return NULL; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
/* Tkapp_CallProc is the event procedure that is executed in the context of
|
/* Tkapp_CallProc is the event procedure that is executed in the context of
|
||||||
the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
|
the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
|
||||||
|
@ -1320,7 +1345,12 @@ Tkapp_CallProc(Tcl_Event *evPtr, int flags)
|
||||||
int objc;
|
int objc;
|
||||||
int i;
|
int i;
|
||||||
ENTER_PYTHON
|
ENTER_PYTHON
|
||||||
objv = Tkapp_CallArgs(e->args, objStore, &objc);
|
if (e->self->trace && !Tkapp_Trace(e->self, PyTuple_Pack(1, e->args))) {
|
||||||
|
objv = NULL;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
objv = Tkapp_CallArgs(e->args, objStore, &objc);
|
||||||
|
}
|
||||||
if (!objv) {
|
if (!objv) {
|
||||||
*(e->exc) = PyErr_GetRaisedException();
|
*(e->exc) = PyErr_GetRaisedException();
|
||||||
*(e->res) = NULL;
|
*(e->res) = NULL;
|
||||||
|
@ -1413,6 +1443,7 @@ Tkapp_Call(PyObject *selfptr, PyObject *args)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
TRACE(self, ("(O)", args));
|
||||||
|
|
||||||
objv = Tkapp_CallArgs(args, objStore, &objc);
|
objv = Tkapp_CallArgs(args, objStore, &objc);
|
||||||
if (!objv)
|
if (!objv)
|
||||||
|
@ -1455,6 +1486,8 @@ _tkinter_tkapp_eval_impl(TkappObject *self, const char *script)
|
||||||
CHECK_STRING_LENGTH(script);
|
CHECK_STRING_LENGTH(script);
|
||||||
CHECK_TCL_APPARTMENT;
|
CHECK_TCL_APPARTMENT;
|
||||||
|
|
||||||
|
TRACE(self, ("((ss))", "eval", script));
|
||||||
|
|
||||||
ENTER_TCL
|
ENTER_TCL
|
||||||
err = Tcl_Eval(Tkapp_Interp(self), script);
|
err = Tcl_Eval(Tkapp_Interp(self), script);
|
||||||
ENTER_OVERLAP
|
ENTER_OVERLAP
|
||||||
|
@ -1484,6 +1517,8 @@ _tkinter_tkapp_evalfile_impl(TkappObject *self, const char *fileName)
|
||||||
CHECK_STRING_LENGTH(fileName);
|
CHECK_STRING_LENGTH(fileName);
|
||||||
CHECK_TCL_APPARTMENT;
|
CHECK_TCL_APPARTMENT;
|
||||||
|
|
||||||
|
TRACE(self, ("((ss))", "source", fileName));
|
||||||
|
|
||||||
ENTER_TCL
|
ENTER_TCL
|
||||||
err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
|
err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
|
||||||
ENTER_OVERLAP
|
ENTER_OVERLAP
|
||||||
|
@ -1513,6 +1548,8 @@ _tkinter_tkapp_record_impl(TkappObject *self, const char *script)
|
||||||
CHECK_STRING_LENGTH(script);
|
CHECK_STRING_LENGTH(script);
|
||||||
CHECK_TCL_APPARTMENT;
|
CHECK_TCL_APPARTMENT;
|
||||||
|
|
||||||
|
TRACE(self, ("((ssss))", "history", "add", script, "exec"));
|
||||||
|
|
||||||
ENTER_TCL
|
ENTER_TCL
|
||||||
err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
|
err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
|
||||||
ENTER_OVERLAP
|
ENTER_OVERLAP
|
||||||
|
@ -1702,6 +1739,15 @@ SetVar(TkappObject *self, PyObject *args, int flags)
|
||||||
newval = AsObj(newValue);
|
newval = AsObj(newValue);
|
||||||
if (newval == NULL)
|
if (newval == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
if (flags & TCL_GLOBAL_ONLY) {
|
||||||
|
TRACE((TkappObject *)self, ("((ssssO))", "uplevel", "#0", "set",
|
||||||
|
name1, newValue));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
TRACE((TkappObject *)self, ("((ssO))", "set", name1, newValue));
|
||||||
|
}
|
||||||
|
|
||||||
ENTER_TCL
|
ENTER_TCL
|
||||||
ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
|
ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
|
||||||
newval, flags);
|
newval, flags);
|
||||||
|
@ -1719,8 +1765,22 @@ SetVar(TkappObject *self, PyObject *args, int flags)
|
||||||
return NULL;
|
return NULL;
|
||||||
CHECK_STRING_LENGTH(name1);
|
CHECK_STRING_LENGTH(name1);
|
||||||
CHECK_STRING_LENGTH(name2);
|
CHECK_STRING_LENGTH(name2);
|
||||||
|
|
||||||
/* XXX must hold tcl lock already??? */
|
/* XXX must hold tcl lock already??? */
|
||||||
newval = AsObj(newValue);
|
newval = AsObj(newValue);
|
||||||
|
if (((TkappObject *)self)->trace) {
|
||||||
|
if (flags & TCL_GLOBAL_ONLY) {
|
||||||
|
TRACE((TkappObject *)self, ("((sssNO))", "uplevel", "#0", "set",
|
||||||
|
PyUnicode_FromFormat("%s(%s)", name1, name2),
|
||||||
|
newValue));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
TRACE((TkappObject *)self, ("((sNO))", "set",
|
||||||
|
PyUnicode_FromFormat("%s(%s)", name1, name2),
|
||||||
|
newValue));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ENTER_TCL
|
ENTER_TCL
|
||||||
ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
|
ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
|
||||||
ENTER_OVERLAP
|
ENTER_OVERLAP
|
||||||
|
@ -1807,6 +1867,28 @@ UnsetVar(TkappObject *self, PyObject *args, int flags)
|
||||||
|
|
||||||
CHECK_STRING_LENGTH(name1);
|
CHECK_STRING_LENGTH(name1);
|
||||||
CHECK_STRING_LENGTH(name2);
|
CHECK_STRING_LENGTH(name2);
|
||||||
|
|
||||||
|
if (((TkappObject *)self)->trace) {
|
||||||
|
if (flags & TCL_GLOBAL_ONLY) {
|
||||||
|
if (name2) {
|
||||||
|
TRACE((TkappObject *)self, ("((sssN))", "uplevel", "#0", "unset",
|
||||||
|
PyUnicode_FromFormat("%s(%s)", name1, name2)));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
TRACE((TkappObject *)self, ("((ssss))", "uplevel", "#0", "unset", name1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (name2) {
|
||||||
|
TRACE((TkappObject *)self, ("((sN))", "unset",
|
||||||
|
PyUnicode_FromFormat("%s(%s)", name1, name2)));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
TRACE((TkappObject *)self, ("((ss))", "unset", name1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ENTER_TCL
|
ENTER_TCL
|
||||||
code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
|
code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
|
||||||
ENTER_OVERLAP
|
ENTER_OVERLAP
|
||||||
|
@ -1973,6 +2055,8 @@ _tkinter_tkapp_exprstring_impl(TkappObject *self, const char *s)
|
||||||
CHECK_STRING_LENGTH(s);
|
CHECK_STRING_LENGTH(s);
|
||||||
CHECK_TCL_APPARTMENT;
|
CHECK_TCL_APPARTMENT;
|
||||||
|
|
||||||
|
TRACE(self, ("((ss))", "expr", s));
|
||||||
|
|
||||||
ENTER_TCL
|
ENTER_TCL
|
||||||
retval = Tcl_ExprString(Tkapp_Interp(self), s);
|
retval = Tcl_ExprString(Tkapp_Interp(self), s);
|
||||||
ENTER_OVERLAP
|
ENTER_OVERLAP
|
||||||
|
@ -2003,6 +2087,8 @@ _tkinter_tkapp_exprlong_impl(TkappObject *self, const char *s)
|
||||||
CHECK_STRING_LENGTH(s);
|
CHECK_STRING_LENGTH(s);
|
||||||
CHECK_TCL_APPARTMENT;
|
CHECK_TCL_APPARTMENT;
|
||||||
|
|
||||||
|
TRACE(self, ("((ss))", "expr", s));
|
||||||
|
|
||||||
ENTER_TCL
|
ENTER_TCL
|
||||||
retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
|
retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
|
||||||
ENTER_OVERLAP
|
ENTER_OVERLAP
|
||||||
|
@ -2032,6 +2118,9 @@ _tkinter_tkapp_exprdouble_impl(TkappObject *self, const char *s)
|
||||||
|
|
||||||
CHECK_STRING_LENGTH(s);
|
CHECK_STRING_LENGTH(s);
|
||||||
CHECK_TCL_APPARTMENT;
|
CHECK_TCL_APPARTMENT;
|
||||||
|
|
||||||
|
TRACE(self, ("((ss))", "expr", s));
|
||||||
|
|
||||||
ENTER_TCL
|
ENTER_TCL
|
||||||
retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
|
retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
|
||||||
ENTER_OVERLAP
|
ENTER_OVERLAP
|
||||||
|
@ -2061,6 +2150,9 @@ _tkinter_tkapp_exprboolean_impl(TkappObject *self, const char *s)
|
||||||
|
|
||||||
CHECK_STRING_LENGTH(s);
|
CHECK_STRING_LENGTH(s);
|
||||||
CHECK_TCL_APPARTMENT;
|
CHECK_TCL_APPARTMENT;
|
||||||
|
|
||||||
|
TRACE(self, ("((ss))", "expr", s));
|
||||||
|
|
||||||
ENTER_TCL
|
ENTER_TCL
|
||||||
retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
|
retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
|
||||||
ENTER_OVERLAP
|
ENTER_OVERLAP
|
||||||
|
@ -2286,6 +2378,8 @@ _tkinter_tkapp_createcommand_impl(TkappObject *self, const char *name,
|
||||||
!WaitForMainloop(self))
|
!WaitForMainloop(self))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
TRACE(self, ("((ss()O))", "proc", name, func));
|
||||||
|
|
||||||
data = PyMem_NEW(PythonCmd_ClientData, 1);
|
data = PyMem_NEW(PythonCmd_ClientData, 1);
|
||||||
if (!data)
|
if (!data)
|
||||||
return PyErr_NoMemory();
|
return PyErr_NoMemory();
|
||||||
|
@ -2344,6 +2438,8 @@ _tkinter_tkapp_deletecommand_impl(TkappObject *self, const char *name)
|
||||||
|
|
||||||
CHECK_STRING_LENGTH(name);
|
CHECK_STRING_LENGTH(name);
|
||||||
|
|
||||||
|
TRACE(self, ("((sss))", "rename", name, ""));
|
||||||
|
|
||||||
if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
|
if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
|
||||||
Tcl_Condition cond = NULL;
|
Tcl_Condition cond = NULL;
|
||||||
CommandEvent *ev;
|
CommandEvent *ev;
|
||||||
|
@ -2469,6 +2565,8 @@ _tkinter_tkapp_createfilehandler_impl(TkappObject *self, PyObject *file,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TRACE(self, ("((ssiiO))", "#", "createfilehandler", tfile, mask, func));
|
||||||
|
|
||||||
data = NewFHCD(func, file, tfile);
|
data = NewFHCD(func, file, tfile);
|
||||||
if (data == NULL)
|
if (data == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -2500,6 +2598,8 @@ _tkinter_tkapp_deletefilehandler(TkappObject *self, PyObject *file)
|
||||||
if (tfile < 0)
|
if (tfile < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
TRACE(self, ("((ssi))", "#", "deletefilehandler", tfile));
|
||||||
|
|
||||||
DeleteFHCD(tfile);
|
DeleteFHCD(tfile);
|
||||||
|
|
||||||
/* Ought to check for null Tcl_File object... */
|
/* Ought to check for null Tcl_File object... */
|
||||||
|
@ -2534,6 +2634,7 @@ _tkinter_tktimertoken_deletetimerhandler_impl(TkttObject *self)
|
||||||
PyObject *func = v->func;
|
PyObject *func = v->func;
|
||||||
|
|
||||||
if (v->token != NULL) {
|
if (v->token != NULL) {
|
||||||
|
/* TRACE(...) */
|
||||||
Tcl_DeleteTimerHandler(v->token);
|
Tcl_DeleteTimerHandler(v->token);
|
||||||
v->token = NULL;
|
v->token = NULL;
|
||||||
}
|
}
|
||||||
|
@ -2636,6 +2737,8 @@ _tkinter_tkapp_createtimerhandler_impl(TkappObject *self, int milliseconds,
|
||||||
|
|
||||||
CHECK_TCL_APPARTMENT;
|
CHECK_TCL_APPARTMENT;
|
||||||
|
|
||||||
|
TRACE(self, ("((siO))", "after", milliseconds, func));
|
||||||
|
|
||||||
v = Tktt_New(func);
|
v = Tktt_New(func);
|
||||||
if (v) {
|
if (v) {
|
||||||
v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
|
v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
|
||||||
|
@ -2803,6 +2906,47 @@ Tkapp_WantObjects(PyObject *self, PyObject *args)
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*[clinic input]
|
||||||
|
_tkinter.tkapp.settrace
|
||||||
|
|
||||||
|
func: object
|
||||||
|
/
|
||||||
|
|
||||||
|
Set the tracing function.
|
||||||
|
[clinic start generated code]*/
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
_tkinter_tkapp_settrace(TkappObject *self, PyObject *func)
|
||||||
|
/*[clinic end generated code: output=847f6ebdf46e84fa input=31b260d46d3d018a]*/
|
||||||
|
{
|
||||||
|
if (func == Py_None) {
|
||||||
|
func = NULL;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Py_INCREF(func);
|
||||||
|
}
|
||||||
|
Py_XSETREF(self->trace, func);
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*[clinic input]
|
||||||
|
_tkinter.tkapp.gettrace
|
||||||
|
|
||||||
|
Get the tracing function.
|
||||||
|
[clinic start generated code]*/
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
_tkinter_tkapp_gettrace_impl(TkappObject *self)
|
||||||
|
/*[clinic end generated code: output=d4e2ba7d63e77bb5 input=ac2aea5be74e8c4c]*/
|
||||||
|
{
|
||||||
|
PyObject *func = self->trace;
|
||||||
|
if (!func) {
|
||||||
|
func = Py_None;
|
||||||
|
}
|
||||||
|
Py_INCREF(func);
|
||||||
|
return func;
|
||||||
|
}
|
||||||
|
|
||||||
/*[clinic input]
|
/*[clinic input]
|
||||||
_tkinter.tkapp.willdispatch
|
_tkinter.tkapp.willdispatch
|
||||||
|
|
||||||
|
@ -3038,6 +3182,8 @@ static PyMethodDef Tkapp_methods[] =
|
||||||
{
|
{
|
||||||
_TKINTER_TKAPP_WILLDISPATCH_METHODDEF
|
_TKINTER_TKAPP_WILLDISPATCH_METHODDEF
|
||||||
{"wantobjects", Tkapp_WantObjects, METH_VARARGS},
|
{"wantobjects", Tkapp_WantObjects, METH_VARARGS},
|
||||||
|
_TKINTER_TKAPP_SETTRACE_METHODDEF
|
||||||
|
_TKINTER_TKAPP_GETTRACE_METHODDEF
|
||||||
{"call", Tkapp_Call, METH_VARARGS},
|
{"call", Tkapp_Call, METH_VARARGS},
|
||||||
_TKINTER_TKAPP_EVAL_METHODDEF
|
_TKINTER_TKAPP_EVAL_METHODDEF
|
||||||
_TKINTER_TKAPP_EVALFILE_METHODDEF
|
_TKINTER_TKAPP_EVALFILE_METHODDEF
|
||||||
|
|
29
Modules/clinic/_tkinter.c.h
generated
29
Modules/clinic/_tkinter.c.h
generated
|
@ -622,6 +622,33 @@ _tkinter_tkapp_loadtk(TkappObject *self, PyObject *Py_UNUSED(ignored))
|
||||||
return _tkinter_tkapp_loadtk_impl(self);
|
return _tkinter_tkapp_loadtk_impl(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PyDoc_STRVAR(_tkinter_tkapp_settrace__doc__,
|
||||||
|
"settrace($self, func, /)\n"
|
||||||
|
"--\n"
|
||||||
|
"\n"
|
||||||
|
"Set the tracing function.");
|
||||||
|
|
||||||
|
#define _TKINTER_TKAPP_SETTRACE_METHODDEF \
|
||||||
|
{"settrace", (PyCFunction)_tkinter_tkapp_settrace, METH_O, _tkinter_tkapp_settrace__doc__},
|
||||||
|
|
||||||
|
PyDoc_STRVAR(_tkinter_tkapp_gettrace__doc__,
|
||||||
|
"gettrace($self, /)\n"
|
||||||
|
"--\n"
|
||||||
|
"\n"
|
||||||
|
"Get the tracing function.");
|
||||||
|
|
||||||
|
#define _TKINTER_TKAPP_GETTRACE_METHODDEF \
|
||||||
|
{"gettrace", (PyCFunction)_tkinter_tkapp_gettrace, METH_NOARGS, _tkinter_tkapp_gettrace__doc__},
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
_tkinter_tkapp_gettrace_impl(TkappObject *self);
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
_tkinter_tkapp_gettrace(TkappObject *self, PyObject *Py_UNUSED(ignored))
|
||||||
|
{
|
||||||
|
return _tkinter_tkapp_gettrace_impl(self);
|
||||||
|
}
|
||||||
|
|
||||||
PyDoc_STRVAR(_tkinter_tkapp_willdispatch__doc__,
|
PyDoc_STRVAR(_tkinter_tkapp_willdispatch__doc__,
|
||||||
"willdispatch($self, /)\n"
|
"willdispatch($self, /)\n"
|
||||||
"--\n"
|
"--\n"
|
||||||
|
@ -861,4 +888,4 @@ exit:
|
||||||
#ifndef _TKINTER_TKAPP_DELETEFILEHANDLER_METHODDEF
|
#ifndef _TKINTER_TKAPP_DELETEFILEHANDLER_METHODDEF
|
||||||
#define _TKINTER_TKAPP_DELETEFILEHANDLER_METHODDEF
|
#define _TKINTER_TKAPP_DELETEFILEHANDLER_METHODDEF
|
||||||
#endif /* !defined(_TKINTER_TKAPP_DELETEFILEHANDLER_METHODDEF) */
|
#endif /* !defined(_TKINTER_TKAPP_DELETEFILEHANDLER_METHODDEF) */
|
||||||
/*[clinic end generated code: output=d447501ec5aa9447 input=a9049054013a1b77]*/
|
/*[clinic end generated code: output=86a515890d48a2ce input=a9049054013a1b77]*/
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue