Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit e475e70

Browse files
committed
Patch from /F:
this patch adds a fast _flatten function to the _tkinter module, and imports it from Tkinter.py (if available). this speeds up canvas operations like create_line and create_polygon. for example, a create_line with 5000 vertices runs about 50 times faster with this patch in place.
1 parent 74042d6 commit e475e70

2 files changed

Lines changed: 106 additions & 0 deletions

File tree

Lib/lib-tk/Tkinter.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ def _flatten(tuple):
3939
res = res + (item,)
4040
return res
4141

42+
try: _flatten = _tkinter._flatten
43+
except AttributeError: pass
44+
4245
def _cnfmerge(cnfs):
4346
if type(cnfs) is DictionaryType:
4447
return cnfs
@@ -55,6 +58,9 @@ def _cnfmerge(cnfs):
5558
cnf[k] = v
5659
return cnf
5760

61+
try: _cnfmerge = _tkinter._cnfmerge
62+
except AttributeError: pass
63+
5864
class Event:
5965
pass
6066

Modules/_tkinter.c

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1978,6 +1978,105 @@ static PyTypeObject Tkapp_Type =
19781978

19791979
/**** Tkinter Module ****/
19801980

1981+
typedef struct {
1982+
PyObject* tuple;
1983+
int size; /* current size */
1984+
int maxsize; /* allocated size */
1985+
} FlattenContext;
1986+
1987+
static int
1988+
_bump(FlattenContext* context, int size)
1989+
{
1990+
/* expand tuple to hold (at least) size new items. return true if
1991+
successful, false if an exception was raised*/
1992+
1993+
int maxsize = context->maxsize * 2;
1994+
1995+
if (maxsize < context->size + size)
1996+
maxsize = context->size + size;
1997+
1998+
context->maxsize = maxsize;
1999+
2000+
return _PyTuple_Resize(&context->tuple, maxsize, 0) >= 0;
2001+
}
2002+
2003+
static int
2004+
_flatten1(FlattenContext* context, PyObject* item)
2005+
{
2006+
/* add tuple or list to argument tuple (recursively) */
2007+
2008+
int i, size;
2009+
2010+
if (PyList_Check(item)) {
2011+
size = PyList_GET_SIZE(item);
2012+
/* preallocate (assume no nesting) */
2013+
if (context->size + size > context->maxsize && !_bump(context, size))
2014+
return 0;
2015+
/* copy items to output tuple */
2016+
for (i = 0; i < size; i++) {
2017+
PyObject *o = PyList_GET_ITEM(item, i);
2018+
if (PyList_Check(o) || PyTuple_Check(o)) {
2019+
if (!_flatten1(context, o))
2020+
return 0;
2021+
} else if (o != Py_None) {
2022+
if (context->size + 1 > context->maxsize && !_bump(context, 1))
2023+
return 0;
2024+
Py_INCREF(o);
2025+
PyTuple_SET_ITEM(context->tuple, context->size++, o);
2026+
}
2027+
}
2028+
} else if (PyTuple_Check(item)) {
2029+
/* same, for tuples */
2030+
size = PyTuple_GET_SIZE(item);
2031+
if (context->size + size > context->maxsize && !_bump(context, size))
2032+
return 0;
2033+
for (i = 0; i < size; i++) {
2034+
PyObject *o = PyTuple_GET_ITEM(item, i);
2035+
if (PyList_Check(o) || PyTuple_Check(o)) {
2036+
if (!_flatten1(context, o))
2037+
return 0;
2038+
} else if (o != Py_None) {
2039+
if (context->size + 1 > context->maxsize && !_bump(context, 1))
2040+
return 0;
2041+
Py_INCREF(o);
2042+
PyTuple_SET_ITEM(context->tuple, context->size++, o);
2043+
}
2044+
}
2045+
} else {
2046+
PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2047+
return 0;
2048+
}
2049+
return 1;
2050+
}
2051+
2052+
static PyObject *
2053+
Tkinter_Flatten(PyObject* self, PyObject* args)
2054+
{
2055+
FlattenContext context;
2056+
PyObject* item;
2057+
2058+
if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2059+
return NULL;
2060+
2061+
context.maxsize = PySequence_Length(item);
2062+
if (context.maxsize <= 0)
2063+
return PyTuple_New(0);
2064+
2065+
context.tuple = PyTuple_New(context.maxsize);
2066+
if (!context.tuple)
2067+
return NULL;
2068+
2069+
context.size = 0;
2070+
2071+
if (!_flatten1(&context, item))
2072+
return NULL;
2073+
2074+
if (_PyTuple_Resize(&context.tuple, context.size, 0))
2075+
return NULL;
2076+
2077+
return context.tuple;
2078+
}
2079+
19812080
static PyObject *
19822081
Tkinter_Create(self, args)
19832082
PyObject *self;
@@ -2006,6 +2105,7 @@ Tkinter_Create(self, args)
20062105

20072106
static PyMethodDef moduleMethods[] =
20082107
{
2108+
{"_flatten", Tkinter_Flatten, 1},
20092109
{"create", Tkinter_Create, 1},
20102110
#ifdef HAVE_CREATEFILEHANDLER
20112111
{"createfilehandler", Tkapp_CreateFileHandler, 1},

0 commit comments

Comments
 (0)