summaryrefslogtreecommitdiff
path: root/src/if_py_both.h
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2013-06-23 14:16:57 +0200
committerBram Moolenaar <Bram@vim.org>2013-06-23 14:16:57 +0200
commit141be8a585145d2217fb425739ccc121aed4a8d4 (patch)
tree1fbdd6ad7db5cc23313f05d9ef8f4f1aaa0772f1 /src/if_py_both.h
parentc476e52fcaf9e1ad779add6368e4f46b2c0d881c (diff)
downloadvim-git-141be8a585145d2217fb425739ccc121aed4a8d4.tar.gz
updated for version 7.3.1231v7.3.1231
Problem: Python: use of numbers not consistent. Solution: Add support for Number protocol. (ZyX)
Diffstat (limited to 'src/if_py_both.h')
-rw-r--r--src/if_py_both.h154
1 files changed, 118 insertions, 36 deletions
diff --git a/src/if_py_both.h b/src/if_py_both.h
index e11c62e86..93470fac0 100644
--- a/src/if_py_both.h
+++ b/src/if_py_both.h
@@ -151,6 +151,95 @@ StringToChars(PyObject *object, PyObject **todecref)
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 *name, PyObject *val)
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, PyObject *keyObject, PyObject *valObject)
}
else if (flags & SOPT_NUM)
{
- int val;
+ long 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
+ 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 *name, PyObject *val)
}
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 *name, PyObject *val)
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 *name, PyObject *val)
#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 *name, PyObject *val)
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;
+ long 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");
+ 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, typval_T *tv, PyObject *lookup_dict)
{
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, typval_T *tv, PyObject *lookup_dict)
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,