Skip to content

Commit ce9a6dc

Browse files
committed
updated for version 7.3.1231
Problem: Python: use of numbers not consistent. Solution: Add support for Number protocol. (ZyX)
1 parent 8d5c9be commit ce9a6dc

File tree

6 files changed

+154
-44
lines changed

6 files changed

+154
-44
lines changed

src/if_py_both.h

Lines changed: 118 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,95 @@ StringToChars(PyObject *object, PyObject **todecref)
151151
return (char_u *) p;
152152
}
153153

154+
#define NUMBER_LONG 1
155+
#define NUMBER_INT 2
156+
#define NUMBER_NATURAL 4
157+
#define NUMBER_UNSIGNED 8
158+
159+
static int
160+
NumberToLong(PyObject *obj, long *result, int flags)
161+
{
162+
#if PY_MAJOR_VERSION < 3
163+
if (PyInt_Check(obj))
164+
{
165+
*result = PyInt_AsLong(obj);
166+
if (PyErr_Occurred())
167+
return -1;
168+
}
169+
else
170+
#endif
171+
if (PyLong_Check(obj))
172+
{
173+
*result = PyLong_AsLong(obj);
174+
if (PyErr_Occurred())
175+
return -1;
176+
}
177+
else if (PyNumber_Check(obj))
178+
{
179+
PyObject *num;
180+
181+
if (!(num = PyNumber_Long(obj)))
182+
return -1;
183+
184+
*result = PyLong_AsLong(num);
185+
186+
Py_DECREF(num);
187+
188+
if (PyErr_Occurred())
189+
return -1;
190+
}
191+
else
192+
{
193+
PyErr_FORMAT(PyExc_TypeError,
194+
#if PY_MAJOR_VERSION < 3
195+
"expected int(), long() or something supporting "
196+
"coercing to long(), but got %s"
197+
#else
198+
"expected int() or something supporting coercing to int(), "
199+
"but got %s"
200+
#endif
201+
, Py_TYPE_NAME(obj));
202+
return -1;
203+
}
204+
205+
if (flags & NUMBER_INT)
206+
{
207+
if (*result > INT_MAX)
208+
{
209+
PyErr_SET_STRING(PyExc_OverflowError,
210+
"value is too large to fit into C int type");
211+
return -1;
212+
}
213+
else if (*result < INT_MIN)
214+
{
215+
PyErr_SET_STRING(PyExc_OverflowError,
216+
"value is too small to fit into C int type");
217+
return -1;
218+
}
219+
}
220+
221+
if (flags & NUMBER_NATURAL)
222+
{
223+
if (*result <= 0)
224+
{
225+
PyErr_SET_STRING(PyExc_ValueError,
226+
"number must be greater then zero");
227+
return -1;
228+
}
229+
}
230+
else if (flags & NUMBER_UNSIGNED)
231+
{
232+
if (*result < 0)
233+
{
234+
PyErr_SET_STRING(PyExc_ValueError,
235+
"number must be greater or equal to zero");
236+
return -1;
237+
}
238+
}
239+
240+
return 0;
241+
}
242+
154243
static int
155244
add_string(PyObject *list, char *s)
156245
{
@@ -243,13 +332,8 @@ OutputSetattr(OutputObject *self, char *name, PyObject *val)
243332

244333
if (strcmp(name, "softspace") == 0)
245334
{
246-
if (!PyInt_Check(val))
247-
{
248-
PyErr_SET_STRING(PyExc_TypeError, "softspace must be an integer");
335+
if (NumberToLong(val, &(self->softspace), NUMBER_UNSIGNED))
249336
return -1;
250-
}
251-
252-
self->softspace = PyInt_AsLong(val);
253337
return 0;
254338
}
255339

@@ -2839,23 +2923,15 @@ OptionsAssItem(OptionsObject *self, PyObject *keyObject, PyObject *valObject)
28392923
}
28402924
else if (flags & SOPT_NUM)
28412925
{
2842-
int val;
2926+
long val;
28432927

2844-
#if PY_MAJOR_VERSION < 3
2845-
if (PyInt_Check(valObject))
2846-
val = PyInt_AsLong(valObject);
2847-
else
2848-
#endif
2849-
if (PyLong_Check(valObject))
2850-
val = PyLong_AsLong(valObject);
2851-
else
2928+
if (NumberToLong(valObject, &val, NUMBER_INT))
28522929
{
2853-
PyErr_SET_STRING(PyExc_TypeError, "object must be integer");
28542930
Py_XDECREF(todecref);
28552931
return -1;
28562932
}
28572933

2858-
r = set_option_value_for(key, val, NULL, opt_flags,
2934+
r = set_option_value_for(key, (int) val, NULL, opt_flags,
28592935
self->opt_type, self->from);
28602936
}
28612937
else
@@ -3265,10 +3341,10 @@ WindowSetattr(WindowObject *self, char *name, PyObject *val)
32653341
}
32663342
else if (strcmp(name, "height") == 0)
32673343
{
3268-
int height;
3344+
long height;
32693345
win_T *savewin;
32703346

3271-
if (!PyArg_Parse(val, "i", &height))
3347+
if (NumberToLong(val, &height, NUMBER_INT))
32723348
return -1;
32733349

32743350
#ifdef FEAT_GUI
@@ -3278,7 +3354,7 @@ WindowSetattr(WindowObject *self, char *name, PyObject *val)
32783354
curwin = self->win;
32793355

32803356
VimTryStart();
3281-
win_setheight(height);
3357+
win_setheight((int) height);
32823358
curwin = savewin;
32833359
if (VimTryEnd())
32843360
return -1;
@@ -3288,10 +3364,10 @@ WindowSetattr(WindowObject *self, char *name, PyObject *val)
32883364
#ifdef FEAT_VERTSPLIT
32893365
else if (strcmp(name, "width") == 0)
32903366
{
3291-
int width;
3367+
long width;
32923368
win_T *savewin;
32933369

3294-
if (!PyArg_Parse(val, "i", &width))
3370+
if (NumberToLong(val, &width, NUMBER_INT))
32953371
return -1;
32963372

32973373
#ifdef FEAT_GUI
@@ -3301,7 +3377,7 @@ WindowSetattr(WindowObject *self, char *name, PyObject *val)
33013377
curwin = self->win;
33023378

33033379
VimTryStart();
3304-
win_setwidth(width);
3380+
win_setwidth((int) width);
33053381
curwin = savewin;
33063382
if (VimTryEnd())
33073383
return -1;
@@ -4555,22 +4631,12 @@ BufMapLength(PyObject *self UNUSED)
45554631
BufMapItem(PyObject *self UNUSED, PyObject *keyObject)
45564632
{
45574633
buf_T *b;
4558-
int bnr;
4634+
long bnr;
45594635

4560-
#if PY_MAJOR_VERSION < 3
4561-
if (PyInt_Check(keyObject))
4562-
bnr = PyInt_AsLong(keyObject);
4563-
else
4564-
#endif
4565-
if (PyLong_Check(keyObject))
4566-
bnr = PyLong_AsLong(keyObject);
4567-
else
4568-
{
4569-
PyErr_SET_STRING(PyExc_TypeError, "key must be integer");
4636+
if (NumberToLong(keyObject, &bnr, NUMBER_INT|NUMBER_NATURAL))
45704637
return NULL;
4571-
}
45724638

4573-
b = buflist_findnr(bnr);
4639+
b = buflist_findnr((int) bnr);
45744640

45754641
if (b)
45764642
return BufferNew(b);
@@ -5345,12 +5411,16 @@ _ConvertFromPyObject(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
53455411
{
53465412
tv->v_type = VAR_NUMBER;
53475413
tv->vval.v_number = (varnumber_T) PyInt_AsLong(obj);
5414+
if (PyErr_Occurred())
5415+
return -1;
53485416
}
53495417
#endif
53505418
else if (PyLong_Check(obj))
53515419
{
53525420
tv->v_type = VAR_NUMBER;
53535421
tv->vval.v_number = (varnumber_T) PyLong_AsLong(obj);
5422+
if (PyErr_Occurred())
5423+
return -1;
53545424
}
53555425
else if (PyDict_Check(obj))
53565426
return convert_dl(obj, tv, pydict_to_tv, lookup_dict);
@@ -5367,6 +5437,18 @@ _ConvertFromPyObject(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
53675437
return convert_dl(obj, tv, pyseq_to_tv, lookup_dict);
53685438
else if (PyMapping_Check(obj))
53695439
return convert_dl(obj, tv, pymap_to_tv, lookup_dict);
5440+
else if (PyNumber_Check(obj))
5441+
{
5442+
PyObject *num;
5443+
5444+
if (!(num = PyNumber_Long(obj)))
5445+
return -1;
5446+
5447+
tv->v_type = VAR_NUMBER;
5448+
tv->vval.v_number = (varnumber_T) PyLong_AsLong(num);
5449+
5450+
Py_DECREF(num);
5451+
}
53705452
else
53715453
{
53725454
PyErr_FORMAT(PyExc_TypeError,

src/if_python.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,7 @@ struct PyMethodDef { Py_ssize_t a; };
220220
# define PyObject_CallFunctionObjArgs dll_PyObject_CallFunctionObjArgs
221221
# define PyObject_CallFunction dll_PyObject_CallFunction
222222
# define PyObject_Call dll_PyObject_Call
223+
# define PyObject_Repr dll_PyObject_Repr
223224
# define PyString_AsString dll_PyString_AsString
224225
# define PyString_AsStringAndSize dll_PyString_AsStringAndSize
225226
# define PyString_FromString dll_PyString_FromString
@@ -233,6 +234,8 @@ struct PyMethodDef { Py_ssize_t a; };
233234
# define PyFloat_AsDouble dll_PyFloat_AsDouble
234235
# define PyFloat_FromDouble dll_PyFloat_FromDouble
235236
# define PyFloat_Type (*dll_PyFloat_Type)
237+
# define PyNumber_Check dll_PyNumber_Check
238+
# define PyNumber_Long dll_PyNumber_Long
236239
# define PyImport_AddModule (*dll_PyImport_AddModule)
237240
# define PySys_SetObject dll_PySys_SetObject
238241
# define PySys_GetObject dll_PySys_GetObject
@@ -360,6 +363,7 @@ static PyObject* (*dll_PyObject_SetAttrString)(PyObject *, const char *, PyObjec
360363
static PyObject* (*dll_PyObject_CallFunctionObjArgs)(PyObject *, ...);
361364
static PyObject* (*dll_PyObject_CallFunction)(PyObject *, char *, ...);
362365
static PyObject* (*dll_PyObject_Call)(PyObject *, PyObject *, PyObject *);
366+
static PyObject* (*dll_PyObject_Repr)(PyObject *);
363367
static char*(*dll_PyString_AsString)(PyObject *);
364368
static int(*dll_PyString_AsStringAndSize)(PyObject *, char **, int *);
365369
static PyObject*(*dll_PyString_FromString)(const char *);
@@ -372,6 +376,8 @@ static PyObject *(*py_PyUnicode_AsEncodedString)(PyObject *, char *, char *);
372376
static double(*dll_PyFloat_AsDouble)(PyObject *);
373377
static PyObject*(*dll_PyFloat_FromDouble)(double);
374378
static PyTypeObject* dll_PyFloat_Type;
379+
static int(*dll_PyNumber_Check)(PyObject *);
380+
static PyObject*(*dll_PyNumber_Long)(PyObject *);
375381
static int(*dll_PySys_SetObject)(char *, PyObject *);
376382
static PyObject *(*dll_PySys_GetObject)(char *);
377383
static int(*dll_PySys_SetArgv)(int, char **);
@@ -440,6 +446,7 @@ static PyObject *imp_PyExc_TypeError;
440446
static PyObject *imp_PyExc_ValueError;
441447
static PyObject *imp_PyExc_RuntimeError;
442448
static PyObject *imp_PyExc_ImportError;
449+
static PyObject *imp_PyExc_OverflowError;
443450

444451
# define PyExc_AttributeError imp_PyExc_AttributeError
445452
# define PyExc_IndexError imp_PyExc_IndexError
@@ -449,6 +456,7 @@ static PyObject *imp_PyExc_ImportError;
449456
# define PyExc_ValueError imp_PyExc_ValueError
450457
# define PyExc_RuntimeError imp_PyExc_RuntimeError
451458
# define PyExc_ImportError imp_PyExc_ImportError
459+
# define PyExc_OverflowError imp_PyExc_OverflowError
452460

453461
/*
454462
* Table of name to function pointer of python.
@@ -533,6 +541,7 @@ static struct
533541
{"PyObject_CallFunctionObjArgs", (PYTHON_PROC*)&dll_PyObject_CallFunctionObjArgs},
534542
{"PyObject_CallFunction", (PYTHON_PROC*)&dll_PyObject_CallFunction},
535543
{"PyObject_Call", (PYTHON_PROC*)&dll_PyObject_Call},
544+
{"PyObject_Repr", (PYTHON_PROC*)&dll_PyObject_Repr},
536545
{"PyString_AsString", (PYTHON_PROC*)&dll_PyString_AsString},
537546
{"PyString_AsStringAndSize", (PYTHON_PROC*)&dll_PyString_AsStringAndSize},
538547
{"PyString_FromString", (PYTHON_PROC*)&dll_PyString_FromString},
@@ -545,6 +554,8 @@ static struct
545554
{"PyFloat_AsDouble", (PYTHON_PROC*)&dll_PyFloat_AsDouble},
546555
{"PyFloat_FromDouble", (PYTHON_PROC*)&dll_PyFloat_FromDouble},
547556
{"PyImport_AddModule", (PYTHON_PROC*)&dll_PyImport_AddModule},
557+
{"PyNumber_Check", (PYTHON_PROC*)&dll_PyNumber_Check},
558+
{"PyNumber_Long", (PYTHON_PROC*)&dll_PyNumber_Long},
548559
{"PySys_SetObject", (PYTHON_PROC*)&dll_PySys_SetObject},
549560
{"PySys_GetObject", (PYTHON_PROC*)&dll_PySys_GetObject},
550561
{"PySys_SetArgv", (PYTHON_PROC*)&dll_PySys_SetArgv},
@@ -722,6 +733,7 @@ get_exceptions(void)
722733
imp_PyExc_ValueError = PyDict_GetItemString(exdict, "ValueError");
723734
imp_PyExc_RuntimeError = PyDict_GetItemString(exdict, "RuntimeError");
724735
imp_PyExc_ImportError = PyDict_GetItemString(exdict, "ImportError");
736+
imp_PyExc_OverflowError = PyDict_GetItemString(exdict, "OverflowError");
725737
Py_XINCREF(imp_PyExc_AttributeError);
726738
Py_XINCREF(imp_PyExc_IndexError);
727739
Py_XINCREF(imp_PyExc_KeyError);
@@ -730,6 +742,7 @@ get_exceptions(void)
730742
Py_XINCREF(imp_PyExc_ValueError);
731743
Py_XINCREF(imp_PyExc_RuntimeError);
732744
Py_XINCREF(imp_PyExc_ImportError);
745+
Py_XINCREF(imp_PyExc_OverflowError);
733746
Py_XDECREF(exmod);
734747
}
735748
#endif /* DYNAMIC_PYTHON */

0 commit comments

Comments
 (0)