mirror of https://github.com/python/cpython
Issue #16840: Tkinter now supports 64-bit integers added in Tcl 8.4 and
arbitrary precision integers added in Tcl 8.5.
This commit is contained in:
parent
8e44aa5ae4
commit
ea134da929
|
@ -133,9 +133,22 @@ class TclTest(unittest.TestCase):
|
||||||
tcl = self.interp
|
tcl = self.interp
|
||||||
self.assertRaises(TclError,tcl.unsetvar,'a')
|
self.assertRaises(TclError,tcl.unsetvar,'a')
|
||||||
|
|
||||||
|
def get_integers(self):
|
||||||
|
integers = (0, 1, -1, 2**31-1, -2**31)
|
||||||
|
if tcl_version >= (8, 4): # wideInt was added in Tcl 8.4
|
||||||
|
integers += (2**31, -2**31-1, 2**63-1, -2**63)
|
||||||
|
if tcl_version >= (8, 5): # bignum was added in Tcl 8.5
|
||||||
|
integers += (2**63, -2**63-1, 2**1000, -2**1000)
|
||||||
|
return integers
|
||||||
|
|
||||||
def test_getint(self):
|
def test_getint(self):
|
||||||
tcl = self.interp.tk
|
tcl = self.interp.tk
|
||||||
self.assertEqual(tcl.getint(' 42 '), 42)
|
for i in self.get_integers():
|
||||||
|
self.assertEqual(tcl.getint(' %d ' % i), i)
|
||||||
|
self.assertEqual(tcl.getint(' %#o ' % i), i)
|
||||||
|
self.assertEqual(tcl.getint(' %#x ' % i), i)
|
||||||
|
if tcl_version < (8, 5): # bignum was added in Tcl 8.5
|
||||||
|
self.assertRaises(TclError, tcl.getint, str(2**1000))
|
||||||
self.assertEqual(tcl.getint(42), 42)
|
self.assertEqual(tcl.getint(42), 42)
|
||||||
self.assertRaises(TypeError, tcl.getint)
|
self.assertRaises(TypeError, tcl.getint)
|
||||||
self.assertRaises(TypeError, tcl.getint, '42', '10')
|
self.assertRaises(TypeError, tcl.getint, '42', '10')
|
||||||
|
@ -270,7 +283,7 @@ class TclTest(unittest.TestCase):
|
||||||
check('"a\xbd\u20ac"', 'a\xbd\u20ac')
|
check('"a\xbd\u20ac"', 'a\xbd\u20ac')
|
||||||
check(r'"a\xbd\u20ac"', 'a\xbd\u20ac')
|
check(r'"a\xbd\u20ac"', 'a\xbd\u20ac')
|
||||||
check(r'"a\0b"', 'a\x00b')
|
check(r'"a\0b"', 'a\x00b')
|
||||||
if tcl_version >= (8, 5):
|
if tcl_version >= (8, 5): # bignum was added in Tcl 8.5
|
||||||
check('2**64', str(2**64))
|
check('2**64', str(2**64))
|
||||||
|
|
||||||
def test_exprdouble(self):
|
def test_exprdouble(self):
|
||||||
|
@ -302,7 +315,7 @@ class TclTest(unittest.TestCase):
|
||||||
check('[string length "a\xbd\u20ac"]', 3.0)
|
check('[string length "a\xbd\u20ac"]', 3.0)
|
||||||
check(r'[string length "a\xbd\u20ac"]', 3.0)
|
check(r'[string length "a\xbd\u20ac"]', 3.0)
|
||||||
self.assertRaises(TclError, tcl.exprdouble, '"abc"')
|
self.assertRaises(TclError, tcl.exprdouble, '"abc"')
|
||||||
if tcl_version >= (8, 5):
|
if tcl_version >= (8, 5): # bignum was added in Tcl 8.5
|
||||||
check('2**64', float(2**64))
|
check('2**64', float(2**64))
|
||||||
|
|
||||||
def test_exprlong(self):
|
def test_exprlong(self):
|
||||||
|
@ -334,7 +347,7 @@ class TclTest(unittest.TestCase):
|
||||||
check('[string length "a\xbd\u20ac"]', 3)
|
check('[string length "a\xbd\u20ac"]', 3)
|
||||||
check(r'[string length "a\xbd\u20ac"]', 3)
|
check(r'[string length "a\xbd\u20ac"]', 3)
|
||||||
self.assertRaises(TclError, tcl.exprlong, '"abc"')
|
self.assertRaises(TclError, tcl.exprlong, '"abc"')
|
||||||
if tcl_version >= (8, 5):
|
if tcl_version >= (8, 5): # bignum was added in Tcl 8.5
|
||||||
self.assertRaises(TclError, tcl.exprlong, '2**64')
|
self.assertRaises(TclError, tcl.exprlong, '2**64')
|
||||||
|
|
||||||
def test_exprboolean(self):
|
def test_exprboolean(self):
|
||||||
|
@ -375,7 +388,7 @@ class TclTest(unittest.TestCase):
|
||||||
check('[string length "a\xbd\u20ac"]', True)
|
check('[string length "a\xbd\u20ac"]', True)
|
||||||
check(r'[string length "a\xbd\u20ac"]', True)
|
check(r'[string length "a\xbd\u20ac"]', True)
|
||||||
self.assertRaises(TclError, tcl.exprboolean, '"abc"')
|
self.assertRaises(TclError, tcl.exprboolean, '"abc"')
|
||||||
if tcl_version >= (8, 5):
|
if tcl_version >= (8, 5): # bignum was added in Tcl 8.5
|
||||||
check('2**64', True)
|
check('2**64', True)
|
||||||
|
|
||||||
def test_booleans(self):
|
def test_booleans(self):
|
||||||
|
@ -397,6 +410,21 @@ class TclTest(unittest.TestCase):
|
||||||
check('1 < 2', True)
|
check('1 < 2', True)
|
||||||
check('1 > 2', False)
|
check('1 > 2', False)
|
||||||
|
|
||||||
|
def test_expr_bignum(self):
|
||||||
|
tcl = self.interp
|
||||||
|
for i in self.get_integers():
|
||||||
|
result = tcl.call('expr', str(i))
|
||||||
|
if self.wantobjects:
|
||||||
|
self.assertEqual(result, i)
|
||||||
|
self.assertIsInstance(result, int)
|
||||||
|
else:
|
||||||
|
self.assertEqual(result, str(i))
|
||||||
|
self.assertIsInstance(result, str)
|
||||||
|
if tcl_version < (8, 5): # bignum was added in Tcl 8.5
|
||||||
|
result = tcl.call('expr', str(2**1000))
|
||||||
|
self.assertEqual(result, str(2**1000))
|
||||||
|
self.assertIsInstance(result, str)
|
||||||
|
|
||||||
def test_passing_values(self):
|
def test_passing_values(self):
|
||||||
def passValue(value):
|
def passValue(value):
|
||||||
return self.interp.call('set', '_', value)
|
return self.interp.call('set', '_', value)
|
||||||
|
@ -414,8 +442,10 @@ class TclTest(unittest.TestCase):
|
||||||
b'str\xc0\x80ing' if self.wantobjects else 'str\xc0\x80ing')
|
b'str\xc0\x80ing' if self.wantobjects else 'str\xc0\x80ing')
|
||||||
self.assertEqual(passValue(b'str\xbding'),
|
self.assertEqual(passValue(b'str\xbding'),
|
||||||
b'str\xbding' if self.wantobjects else 'str\xbding')
|
b'str\xbding' if self.wantobjects else 'str\xbding')
|
||||||
for i in (0, 1, -1, 2**31-1, -2**31):
|
for i in self.get_integers():
|
||||||
self.assertEqual(passValue(i), i if self.wantobjects else str(i))
|
self.assertEqual(passValue(i), i if self.wantobjects else str(i))
|
||||||
|
if tcl_version < (8, 5): # bignum was added in Tcl 8.5
|
||||||
|
self.assertEqual(passValue(2**1000), str(2**1000))
|
||||||
for f in (0.0, 1.0, -1.0, 1/3,
|
for f in (0.0, 1.0, -1.0, 1/3,
|
||||||
sys.float_info.min, sys.float_info.max,
|
sys.float_info.min, sys.float_info.max,
|
||||||
-sys.float_info.min, -sys.float_info.max):
|
-sys.float_info.min, -sys.float_info.max):
|
||||||
|
@ -473,8 +503,10 @@ class TclTest(unittest.TestCase):
|
||||||
check(b'str\x00ing', 'str\x00ing')
|
check(b'str\x00ing', 'str\x00ing')
|
||||||
check(b'str\xc0\x80ing', 'str\xc0\x80ing')
|
check(b'str\xc0\x80ing', 'str\xc0\x80ing')
|
||||||
check(b'str\xc0\x80ing\xe2\x82\xac', 'str\xc0\x80ing\xe2\x82\xac')
|
check(b'str\xc0\x80ing\xe2\x82\xac', 'str\xc0\x80ing\xe2\x82\xac')
|
||||||
for i in (0, 1, -1, 2**31-1, -2**31):
|
for i in self.get_integers():
|
||||||
check(i, str(i))
|
check(i, str(i))
|
||||||
|
if tcl_version < (8, 5): # bignum was added in Tcl 8.5
|
||||||
|
check(2**1000, str(2**1000))
|
||||||
for f in (0.0, 1.0, -1.0):
|
for f in (0.0, 1.0, -1.0):
|
||||||
check(f, repr(f))
|
check(f, repr(f))
|
||||||
for f in (1/3.0, sys.float_info.min, sys.float_info.max,
|
for f in (1/3.0, sys.float_info.min, sys.float_info.max,
|
||||||
|
|
|
@ -24,6 +24,9 @@ Core and Builtins
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Issue #16840: Tkinter now supports 64-bit integers added in Tcl 8.4 and
|
||||||
|
arbitrary precision integers added in Tcl 8.5.
|
||||||
|
|
||||||
- Issue #23834: Fix socket.sendto(), use the C Py_ssize_t type to store the
|
- Issue #23834: Fix socket.sendto(), use the C Py_ssize_t type to store the
|
||||||
result of sendto() instead of the C int type.
|
result of sendto() instead of the C int type.
|
||||||
|
|
||||||
|
|
|
@ -69,6 +69,11 @@ Copyright (C) 1994 Steen Lumholt.
|
||||||
#error "Tk older than 8.3.1 not supported"
|
#error "Tk older than 8.3.1 not supported"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if TK_VERSION_HEX >= 0x08050000
|
||||||
|
#define HAVE_LIBTOMMAMTH
|
||||||
|
#include <tclTomMath.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#if !(defined(MS_WINDOWS) || defined(__CYGWIN__))
|
#if !(defined(MS_WINDOWS) || defined(__CYGWIN__))
|
||||||
#define HAVE_CREATEFILEHANDLER
|
#define HAVE_CREATEFILEHANDLER
|
||||||
#endif
|
#endif
|
||||||
|
@ -247,6 +252,8 @@ typedef struct {
|
||||||
const Tcl_ObjType *ByteArrayType;
|
const Tcl_ObjType *ByteArrayType;
|
||||||
const Tcl_ObjType *DoubleType;
|
const Tcl_ObjType *DoubleType;
|
||||||
const Tcl_ObjType *IntType;
|
const Tcl_ObjType *IntType;
|
||||||
|
const Tcl_ObjType *WideIntType;
|
||||||
|
const Tcl_ObjType *BignumType;
|
||||||
const Tcl_ObjType *ListType;
|
const Tcl_ObjType *ListType;
|
||||||
const Tcl_ObjType *ProcBodyType;
|
const Tcl_ObjType *ProcBodyType;
|
||||||
const Tcl_ObjType *StringType;
|
const Tcl_ObjType *StringType;
|
||||||
|
@ -583,6 +590,8 @@ Tkapp_New(char *screenName, char *className,
|
||||||
v->ByteArrayType = Tcl_GetObjType("bytearray");
|
v->ByteArrayType = Tcl_GetObjType("bytearray");
|
||||||
v->DoubleType = Tcl_GetObjType("double");
|
v->DoubleType = Tcl_GetObjType("double");
|
||||||
v->IntType = Tcl_GetObjType("int");
|
v->IntType = Tcl_GetObjType("int");
|
||||||
|
v->WideIntType = Tcl_GetObjType("wideInt");
|
||||||
|
v->BignumType = Tcl_GetObjType("bignum");
|
||||||
v->ListType = Tcl_GetObjType("list");
|
v->ListType = Tcl_GetObjType("list");
|
||||||
v->ProcBodyType = Tcl_GetObjType("procbody");
|
v->ProcBodyType = Tcl_GetObjType("procbody");
|
||||||
v->StringType = Tcl_GetObjType("string");
|
v->StringType = Tcl_GetObjType("string");
|
||||||
|
@ -875,28 +884,92 @@ static PyType_Spec PyTclObject_Type_spec = {
|
||||||
#define CHECK_STRING_LENGTH(s)
|
#define CHECK_STRING_LENGTH(s)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBTOMMAMTH
|
||||||
|
static Tcl_Obj*
|
||||||
|
asBignumObj(PyObject *value)
|
||||||
|
{
|
||||||
|
Tcl_Obj *result;
|
||||||
|
int neg;
|
||||||
|
PyObject *hexstr;
|
||||||
|
char *hexchars;
|
||||||
|
mp_int bigValue;
|
||||||
|
|
||||||
|
neg = Py_SIZE(value) < 0;
|
||||||
|
hexstr = _PyLong_Format(value, 16);
|
||||||
|
if (hexstr == NULL)
|
||||||
|
return NULL;
|
||||||
|
hexchars = PyUnicode_AsUTF8(hexstr);
|
||||||
|
if (hexchars == NULL) {
|
||||||
|
Py_DECREF(hexstr);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
hexchars += neg + 2; /* skip sign and "0x" */
|
||||||
|
mp_init(&bigValue);
|
||||||
|
if (mp_read_radix(&bigValue, hexchars, 16) != MP_OKAY) {
|
||||||
|
mp_clear(&bigValue);
|
||||||
|
Py_DECREF(hexstr);
|
||||||
|
PyErr_NoMemory();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
Py_DECREF(hexstr);
|
||||||
|
bigValue.sign = neg ? MP_NEG : MP_ZPOS;
|
||||||
|
result = Tcl_NewBignumObj(&bigValue);
|
||||||
|
mp_clear(&bigValue);
|
||||||
|
if (result == NULL) {
|
||||||
|
PyErr_NoMemory();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static Tcl_Obj*
|
static Tcl_Obj*
|
||||||
AsObj(PyObject *value)
|
AsObj(PyObject *value)
|
||||||
{
|
{
|
||||||
Tcl_Obj *result;
|
Tcl_Obj *result;
|
||||||
long longVal;
|
|
||||||
int overflow;
|
|
||||||
|
|
||||||
if (PyBytes_Check(value))
|
if (PyBytes_Check(value))
|
||||||
return Tcl_NewByteArrayObj((unsigned char *)PyBytes_AS_STRING(value),
|
return Tcl_NewByteArrayObj((unsigned char *)PyBytes_AS_STRING(value),
|
||||||
PyBytes_GET_SIZE(value));
|
PyBytes_GET_SIZE(value));
|
||||||
else if (PyBool_Check(value))
|
|
||||||
|
if (PyBool_Check(value))
|
||||||
return Tcl_NewBooleanObj(PyObject_IsTrue(value));
|
return Tcl_NewBooleanObj(PyObject_IsTrue(value));
|
||||||
else if (PyLong_CheckExact(value) &&
|
|
||||||
((longVal = PyLong_AsLongAndOverflow(value, &overflow)),
|
if (PyLong_CheckExact(value)) {
|
||||||
!overflow)) {
|
int overflow;
|
||||||
/* If there is an overflow in the long conversion,
|
long longValue;
|
||||||
fall through to default object handling. */
|
#ifdef TCL_WIDE_INT_TYPE
|
||||||
return Tcl_NewLongObj(longVal);
|
Tcl_WideInt wideValue;
|
||||||
|
#endif
|
||||||
|
longValue = PyLong_AsLongAndOverflow(value, &overflow);
|
||||||
|
if (!overflow) {
|
||||||
|
return Tcl_NewLongObj(longValue);
|
||||||
}
|
}
|
||||||
else if (PyFloat_Check(value))
|
/* If there is an overflow in the long conversion,
|
||||||
|
fall through to wideInt handling. */
|
||||||
|
#ifdef TCL_WIDE_INT_TYPE
|
||||||
|
if (_PyLong_AsByteArray((PyLongObject *)value,
|
||||||
|
(unsigned char *)(void *)&wideValue,
|
||||||
|
sizeof(wideValue),
|
||||||
|
PY_LITTLE_ENDIAN,
|
||||||
|
/* signed */ 1) == 0) {
|
||||||
|
return Tcl_NewWideIntObj(wideValue);
|
||||||
|
}
|
||||||
|
PyErr_Clear();
|
||||||
|
#endif
|
||||||
|
/* If there is an overflow in the wideInt conversion,
|
||||||
|
fall through to bignum handling. */
|
||||||
|
#ifdef HAVE_LIBTOMMAMTH
|
||||||
|
return asBignumObj(value);
|
||||||
|
#endif
|
||||||
|
/* If there is no wideInt or bignum support,
|
||||||
|
fall through to default object handling. */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PyFloat_Check(value))
|
||||||
return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
|
return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
|
||||||
else if (PyTuple_Check(value)) {
|
|
||||||
|
if (PyTuple_Check(value)) {
|
||||||
Tcl_Obj **argv;
|
Tcl_Obj **argv;
|
||||||
Py_ssize_t size, i;
|
Py_ssize_t size, i;
|
||||||
|
|
||||||
|
@ -916,7 +989,8 @@ AsObj(PyObject *value)
|
||||||
ckfree(FREECAST argv);
|
ckfree(FREECAST argv);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
else if (PyUnicode_Check(value)) {
|
|
||||||
|
if (PyUnicode_Check(value)) {
|
||||||
void *inbuf;
|
void *inbuf;
|
||||||
Py_ssize_t size;
|
Py_ssize_t size;
|
||||||
int kind;
|
int kind;
|
||||||
|
@ -966,12 +1040,14 @@ AsObj(PyObject *value)
|
||||||
ckfree(FREECAST outbuf);
|
ckfree(FREECAST outbuf);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
else if(PyTclObject_Check(value)) {
|
|
||||||
|
if (PyTclObject_Check(value)) {
|
||||||
Tcl_Obj *v = ((PyTclObject*)value)->value;
|
Tcl_Obj *v = ((PyTclObject*)value)->value;
|
||||||
Tcl_IncrRefCount(v);
|
Tcl_IncrRefCount(v);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
|
{
|
||||||
PyObject *v = PyObject_Str(value);
|
PyObject *v = PyObject_Str(value);
|
||||||
if (!v)
|
if (!v)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -990,6 +1066,62 @@ fromBoolean(PyObject* tkapp, Tcl_Obj *value)
|
||||||
return PyBool_FromLong(boolValue);
|
return PyBool_FromLong(boolValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef TCL_WIDE_INT_TYPE
|
||||||
|
static PyObject*
|
||||||
|
fromWideIntObj(PyObject* tkapp, Tcl_Obj *value)
|
||||||
|
{
|
||||||
|
Tcl_WideInt wideValue;
|
||||||
|
if (Tcl_GetWideIntFromObj(Tkapp_Interp(tkapp), value, &wideValue) == TCL_OK) {
|
||||||
|
#ifdef HAVE_LONG_LONG
|
||||||
|
if (sizeof(wideValue) <= SIZEOF_LONG_LONG)
|
||||||
|
return PyLong_FromLongLong(wideValue);
|
||||||
|
#endif
|
||||||
|
return _PyLong_FromByteArray((unsigned char *)(void *)&wideValue,
|
||||||
|
sizeof(wideValue),
|
||||||
|
PY_LITTLE_ENDIAN,
|
||||||
|
/* signed */ 1);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBTOMMAMTH
|
||||||
|
static PyObject*
|
||||||
|
fromBignumObj(PyObject* tkapp, Tcl_Obj *value)
|
||||||
|
{
|
||||||
|
mp_int bigValue;
|
||||||
|
unsigned long numBytes;
|
||||||
|
unsigned char *bytes;
|
||||||
|
PyObject *res;
|
||||||
|
|
||||||
|
if (Tcl_GetBignumFromObj(Tkapp_Interp(tkapp), value, &bigValue) != TCL_OK)
|
||||||
|
return Tkinter_Error(tkapp);
|
||||||
|
numBytes = mp_unsigned_bin_size(&bigValue);
|
||||||
|
bytes = PyMem_Malloc(numBytes);
|
||||||
|
if (bytes == NULL) {
|
||||||
|
mp_clear(&bigValue);
|
||||||
|
return PyErr_NoMemory();
|
||||||
|
}
|
||||||
|
if (mp_to_unsigned_bin_n(&bigValue, bytes,
|
||||||
|
&numBytes) != MP_OKAY) {
|
||||||
|
mp_clear(&bigValue);
|
||||||
|
PyMem_Free(bytes);
|
||||||
|
return PyErr_NoMemory();
|
||||||
|
}
|
||||||
|
res = _PyLong_FromByteArray(bytes, numBytes,
|
||||||
|
/* big-endian */ 0,
|
||||||
|
/* unsigned */ 0);
|
||||||
|
PyMem_Free(bytes);
|
||||||
|
if (res != NULL && bigValue.sign == MP_NEG) {
|
||||||
|
PyObject *res2 = PyNumber_Negative(res);
|
||||||
|
Py_DECREF(res);
|
||||||
|
res = res2;
|
||||||
|
}
|
||||||
|
mp_clear(&bigValue);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
FromObj(PyObject* tkapp, Tcl_Obj *value)
|
FromObj(PyObject* tkapp, Tcl_Obj *value)
|
||||||
{
|
{
|
||||||
|
@ -1017,9 +1149,33 @@ FromObj(PyObject* tkapp, Tcl_Obj *value)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (value->typePtr == app->IntType) {
|
if (value->typePtr == app->IntType) {
|
||||||
return PyLong_FromLong(value->internalRep.longValue);
|
long longValue;
|
||||||
|
if (Tcl_GetLongFromObj(interp, value, &longValue) == TCL_OK)
|
||||||
|
return PyLong_FromLong(longValue);
|
||||||
|
/* If there is an error in the long conversion,
|
||||||
|
fall through to wideInt handling. */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef TCL_WIDE_INT_TYPE
|
||||||
|
if (value->typePtr == app->IntType ||
|
||||||
|
value->typePtr == app->WideIntType) {
|
||||||
|
result = fromWideIntObj(tkapp, value);
|
||||||
|
if (result != NULL || PyErr_Occurred())
|
||||||
|
return result;
|
||||||
|
Tcl_ResetResult(interp);
|
||||||
|
/* If there is an error in the wideInt conversion,
|
||||||
|
fall through to bignum handling. */
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBTOMMAMTH
|
||||||
|
if (value->typePtr == app->IntType ||
|
||||||
|
value->typePtr == app->WideIntType ||
|
||||||
|
value->typePtr == app->BignumType) {
|
||||||
|
return fromBignumObj(tkapp, value);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (value->typePtr == app->ListType) {
|
if (value->typePtr == app->ListType) {
|
||||||
int size;
|
int size;
|
||||||
int i, status;
|
int i, status;
|
||||||
|
@ -1067,6 +1223,15 @@ FromObj(PyObject* tkapp, Tcl_Obj *value)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBTOMMAMTH
|
||||||
|
if (app->BignumType == NULL &&
|
||||||
|
strcmp(value->typePtr->name, "bignum") == 0) {
|
||||||
|
/* bignum type is not registered in Tcl */
|
||||||
|
app->BignumType = value->typePtr;
|
||||||
|
return fromBignumObj(tkapp, value);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return newPyTclObject(value);
|
return newPyTclObject(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1700,7 +1865,12 @@ static PyObject *
|
||||||
Tkapp_GetInt(PyObject *self, PyObject *args)
|
Tkapp_GetInt(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
char *s;
|
char *s;
|
||||||
int v;
|
#if defined(TCL_WIDE_INT_TYPE) || defined(HAVE_LIBTOMMAMTH)
|
||||||
|
Tcl_Obj *value;
|
||||||
|
PyObject *result;
|
||||||
|
#else
|
||||||
|
int intValue;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (PyTuple_Size(args) == 1) {
|
if (PyTuple_Size(args) == 1) {
|
||||||
PyObject* o = PyTuple_GetItem(args, 0);
|
PyObject* o = PyTuple_GetItem(args, 0);
|
||||||
|
@ -1712,9 +1882,29 @@ Tkapp_GetInt(PyObject *self, PyObject *args)
|
||||||
if (!PyArg_ParseTuple(args, "s:getint", &s))
|
if (!PyArg_ParseTuple(args, "s:getint", &s))
|
||||||
return NULL;
|
return NULL;
|
||||||
CHECK_STRING_LENGTH(s);
|
CHECK_STRING_LENGTH(s);
|
||||||
if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
|
#if defined(TCL_WIDE_INT_TYPE) || defined(HAVE_LIBTOMMAMTH)
|
||||||
|
value = Tcl_NewStringObj(s, -1);
|
||||||
|
if (value == NULL)
|
||||||
|
return Tkinter_Error(self);
|
||||||
|
/* Don't use Tcl_GetInt() because it returns ambiguous result for value
|
||||||
|
in ranges -2**32..-2**31-1 and 2**31..2**32-1 (on 32-bit platform).
|
||||||
|
|
||||||
|
Prefer bignum because Tcl_GetWideIntFromObj returns ambiguous result for
|
||||||
|
value in ranges -2**64..-2**63-1 and 2**63..2**64-1 (on 32-bit platform).
|
||||||
|
*/
|
||||||
|
#ifdef HAVE_LIBTOMMAMTH
|
||||||
|
result = fromBignumObj(self, value);
|
||||||
|
#else
|
||||||
|
result = fromWideIntObj(self, value);
|
||||||
|
#endif
|
||||||
|
Tcl_DecrRefCount(value);
|
||||||
|
if (result != NULL || PyErr_Occurred())
|
||||||
|
return result;
|
||||||
|
#else
|
||||||
|
if (Tcl_GetInt(Tkapp_Interp(self), s, &intValue) == TCL_OK)
|
||||||
|
return PyLong_FromLong(intValue);
|
||||||
|
#endif
|
||||||
return Tkinter_Error(self);
|
return Tkinter_Error(self);
|
||||||
return Py_BuildValue("i", v);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
|
|
Loading…
Reference in New Issue