Mercurial > vim
diff src/if_py_both.h @ 4972:537bbfff0c5c v7.3.1231
updated for version 7.3.1231
Problem: Python: use of numbers not consistent.
Solution: Add support for Number protocol. (ZyX)
author | Bram Moolenaar <bram@vim.org> |
---|---|
date | Sun, 23 Jun 2013 14:16:57 +0200 |
parents | f5c822e5a0eb |
children | a594ce86b5ea |
line wrap: on
line diff
--- a/src/if_py_both.h +++ b/src/if_py_both.h @@ -151,6 +151,95 @@ StringToChars(PyObject *object, PyObject return (char_u *) p; } +#define NUMBER_LONG 1 +#define NUMBER_INT 2 +#define NUMBER_NATURAL 4 +#define NUMBER_UNSIGNED 8 + + static int +NumberToLong(PyObject *obj, long *result, int flags) +{ +#if PY_MAJOR_VERSION < 3 + if (PyInt_Check(obj)) + { + *result = PyInt_AsLong(obj); + if (PyErr_Occurred()) + return -1; + } + else +#endif + if (PyLong_Check(obj)) + { + *result = PyLong_AsLong(obj); + if (PyErr_Occurred()) + return -1; + } + else if (PyNumber_Check(obj)) + { + PyObject *num; + + if (!(num = PyNumber_Long(obj))) + return -1; + + *result = PyLong_AsLong(num); + + Py_DECREF(num); + + if (PyErr_Occurred()) + return -1; + } + else + { + PyErr_FORMAT(PyExc_TypeError, +#if PY_MAJOR_VERSION < 3 + "expected int(), long() or something supporting " + "coercing to long(), but got %s" +#else + "expected int() or something supporting coercing to int(), " + "but got %s" +#endif + , Py_TYPE_NAME(obj)); + return -1; + } + + if (flags & NUMBER_INT) + { + if (*result > INT_MAX) + { + PyErr_SET_STRING(PyExc_OverflowError, + "value is too large to fit into C int type"); + return -1; + } + else if (*result < INT_MIN) + { + PyErr_SET_STRING(PyExc_OverflowError, + "value is too small to fit into C int type"); + return -1; + } + } + + if (flags & NUMBER_NATURAL) + { + if (*result <= 0) + { + PyErr_SET_STRING(PyExc_ValueError, + "number must be greater then zero"); + return -1; + } + } + else if (flags & NUMBER_UNSIGNED) + { + if (*result < 0) + { + PyErr_SET_STRING(PyExc_ValueError, + "number must be greater or equal to zero"); + return -1; + } + } + + return 0; +} + static int add_string(PyObject *list, char *s) { @@ -243,13 +332,8 @@ OutputSetattr(OutputObject *self, char * if (strcmp(name, "softspace") == 0) { - if (!PyInt_Check(val)) - { - PyErr_SET_STRING(PyExc_TypeError, "softspace must be an integer"); + if (NumberToLong(val, &(self->softspace), NUMBER_UNSIGNED)) return -1; - } - - self->softspace = PyInt_AsLong(val); return 0; } @@ -2839,23 +2923,15 @@ OptionsAssItem(OptionsObject *self, PyOb } else if (flags & SOPT_NUM) { - int val; - -#if PY_MAJOR_VERSION < 3 - if (PyInt_Check(valObject)) - val = PyInt_AsLong(valObject); - else -#endif - if (PyLong_Check(valObject)) - val = PyLong_AsLong(valObject); - else + long val; + + if (NumberToLong(valObject, &val, NUMBER_INT)) { - PyErr_SET_STRING(PyExc_TypeError, "object must be integer"); Py_XDECREF(todecref); return -1; } - r = set_option_value_for(key, val, NULL, opt_flags, + r = set_option_value_for(key, (int) val, NULL, opt_flags, self->opt_type, self->from); } else @@ -3265,10 +3341,10 @@ WindowSetattr(WindowObject *self, char * } else if (strcmp(name, "height") == 0) { - int height; + long height; win_T *savewin; - if (!PyArg_Parse(val, "i", &height)) + if (NumberToLong(val, &height, NUMBER_INT)) return -1; #ifdef FEAT_GUI @@ -3278,7 +3354,7 @@ WindowSetattr(WindowObject *self, char * curwin = self->win; VimTryStart(); - win_setheight(height); + win_setheight((int) height); curwin = savewin; if (VimTryEnd()) return -1; @@ -3288,10 +3364,10 @@ WindowSetattr(WindowObject *self, char * #ifdef FEAT_VERTSPLIT else if (strcmp(name, "width") == 0) { - int width; + long width; win_T *savewin; - if (!PyArg_Parse(val, "i", &width)) + if (NumberToLong(val, &width, NUMBER_INT)) return -1; #ifdef FEAT_GUI @@ -3301,7 +3377,7 @@ WindowSetattr(WindowObject *self, char * curwin = self->win; VimTryStart(); - win_setwidth(width); + win_setwidth((int) width); curwin = savewin; if (VimTryEnd()) return -1; @@ -4555,22 +4631,12 @@ BufMapLength(PyObject *self UNUSED) BufMapItem(PyObject *self UNUSED, PyObject *keyObject) { buf_T *b; - int bnr; - -#if PY_MAJOR_VERSION < 3 - if (PyInt_Check(keyObject)) - bnr = PyInt_AsLong(keyObject); - else -#endif - if (PyLong_Check(keyObject)) - bnr = PyLong_AsLong(keyObject); - else - { - PyErr_SET_STRING(PyExc_TypeError, "key must be integer"); + long bnr; + + if (NumberToLong(keyObject, &bnr, NUMBER_INT|NUMBER_NATURAL)) return NULL; - } - - b = buflist_findnr(bnr); + + b = buflist_findnr((int) bnr); if (b) return BufferNew(b); @@ -5345,12 +5411,16 @@ ConvertFromPyObject(PyObject *obj, typva { tv->v_type = VAR_NUMBER; tv->vval.v_number = (varnumber_T) PyInt_AsLong(obj); + if (PyErr_Occurred()) + return -1; } #endif else if (PyLong_Check(obj)) { tv->v_type = VAR_NUMBER; tv->vval.v_number = (varnumber_T) PyLong_AsLong(obj); + if (PyErr_Occurred()) + return -1; } else if (PyDict_Check(obj)) return convert_dl(obj, tv, pydict_to_tv, lookup_dict); @@ -5367,6 +5437,18 @@ ConvertFromPyObject(PyObject *obj, typva return convert_dl(obj, tv, pyseq_to_tv, lookup_dict); else if (PyMapping_Check(obj)) return convert_dl(obj, tv, pymap_to_tv, lookup_dict); + else if (PyNumber_Check(obj)) + { + PyObject *num; + + if (!(num = PyNumber_Long(obj))) + return -1; + + tv->v_type = VAR_NUMBER; + tv->vval.v_number = (varnumber_T) PyLong_AsLong(num); + + Py_DECREF(num); + } else { PyErr_FORMAT(PyExc_TypeError,