0
0
mirror of https://github.com/vim/vim.git synced 2025-09-29 04:34:16 -04:00

updated for version 7.3.1061

Problem:    Python: Dictionary is not standard.
Solution:   Python patch 20: Add standard methods and fields. (ZyX)
This commit is contained in:
Bram Moolenaar
2013-05-30 13:01:18 +02:00
parent a5b725c3f6
commit a9922d62e6
11 changed files with 821 additions and 180 deletions

View File

@@ -10156,6 +10156,62 @@ f_expand(argvars, rettv)
}
}
/*
* Go over all entries in "d2" and add them to "d1".
* When "action" is "error" then a duplicate key is an error.
* When "action" is "force" then a duplicate key is overwritten.
* Otherwise duplicate keys are ignored ("action" is "keep").
*/
void
dict_extend(d1, d2, action)
dict_T *d1;
dict_T *d2;
char_u *action;
{
dictitem_T *di1;
hashitem_T *hi2;
int todo;
todo = (int)d2->dv_hashtab.ht_used;
for (hi2 = d2->dv_hashtab.ht_array; todo > 0; ++hi2)
{
if (!HASHITEM_EMPTY(hi2))
{
--todo;
di1 = dict_find(d1, hi2->hi_key, -1);
if (d1->dv_scope != 0)
{
/* Disallow replacing a builtin function in l: and g:.
* Check the key to be valid when adding to any
* scope. */
if (d1->dv_scope == VAR_DEF_SCOPE
&& HI2DI(hi2)->di_tv.v_type == VAR_FUNC
&& var_check_func_name(hi2->hi_key,
di1 == NULL))
break;
if (!valid_varname(hi2->hi_key))
break;
}
if (di1 == NULL)
{
di1 = dictitem_copy(HI2DI(hi2));
if (di1 != NULL && dict_add(d1, di1) == FAIL)
dictitem_free(di1);
}
else if (*action == 'e')
{
EMSG2(_("E737: Key already exists: %s"), hi2->hi_key);
break;
}
else if (*action == 'f' && HI2DI(hi2) != di1)
{
clear_tv(&di1->di_tv);
copy_tv(&HI2DI(hi2)->di_tv, &di1->di_tv);
}
}
}
}
/*
* "extend(list, list [, idx])" function
* "extend(dict, dict [, action])" function
@@ -10206,12 +10262,9 @@ f_extend(argvars, rettv)
}
else if (argvars[0].v_type == VAR_DICT && argvars[1].v_type == VAR_DICT)
{
dict_T *d1, *d2;
dictitem_T *di1;
char_u *action;
int i;
hashitem_T *hi2;
int todo;
dict_T *d1, *d2;
char_u *action;
int i;
d1 = argvars[0].vval.v_dict;
d2 = argvars[1].vval.v_dict;
@@ -10238,46 +10291,7 @@ f_extend(argvars, rettv)
else
action = (char_u *)"force";
/* Go over all entries in the second dict and add them to the
* first dict. */
todo = (int)d2->dv_hashtab.ht_used;
for (hi2 = d2->dv_hashtab.ht_array; todo > 0; ++hi2)
{
if (!HASHITEM_EMPTY(hi2))
{
--todo;
di1 = dict_find(d1, hi2->hi_key, -1);
if (d1->dv_scope != 0)
{
/* Disallow replacing a builtin function in l: and g:.
* Check the key to be valid when adding to any
* scope. */
if (d1->dv_scope == VAR_DEF_SCOPE
&& HI2DI(hi2)->di_tv.v_type == VAR_FUNC
&& var_check_func_name(hi2->hi_key,
di1 == NULL))
break;
if (!valid_varname(hi2->hi_key))
break;
}
if (di1 == NULL)
{
di1 = dictitem_copy(HI2DI(hi2));
if (di1 != NULL && dict_add(d1, di1) == FAIL)
dictitem_free(di1);
}
else if (*action == 'e')
{
EMSG2(_("E737: Key already exists: %s"), hi2->hi_key);
break;
}
else if (*action == 'f' && HI2DI(hi2) != di1)
{
clear_tv(&di1->di_tv);
copy_tv(&HI2DI(hi2)->di_tv, &di1->di_tv);
}
}
}
dict_extend(d1, d2, action);
copy_tv(&argvars[0], rettv);
}

View File

@@ -31,7 +31,7 @@ typedef int Py_ssize_t; /* Python 2.4 and earlier don't have this type. */
#define INVALID_TABPAGE_VALUE ((tabpage_T *)(-1))
#define DICTKEY_DECL \
PyObject *dictkey_todecref;
PyObject *dictkey_todecref = NULL;
#define DICTKEY_CHECK_EMPTY(err) \
if (*key == NUL) \
{ \
@@ -63,6 +63,7 @@ typedef void (*runner)(const char *, void *
static int ConvertFromPyObject(PyObject *, typval_T *);
static int _ConvertFromPyObject(PyObject *, typval_T *, PyObject *);
static int ConvertFromPyMapping(PyObject *, typval_T *);
static PyObject *WindowNew(win_T *, tabpage_T *);
static PyObject *BufferNew (buf_T *);
static PyObject *LineToString(const char *);
@@ -877,12 +878,16 @@ typedef struct
pylinkedlist_T ref;
} DictionaryObject;
static PyObject *DictionaryUpdate(DictionaryObject *, PyObject *, PyObject *);
#define NEW_DICTIONARY(dict) DictionaryNew(&DictionaryType, dict)
static PyObject *
DictionaryNew(dict_T *dict)
DictionaryNew(PyTypeObject *subtype, dict_T *dict)
{
DictionaryObject *self;
self = PyObject_NEW(DictionaryObject, &DictionaryType);
self = (DictionaryObject *) subtype->tp_alloc(subtype, 0);
if (self == NULL)
return NULL;
self->dict = dict;
@@ -890,6 +895,49 @@ DictionaryNew(dict_T *dict)
pyll_add((PyObject *)(self), &self->ref, &lastdict);
return (PyObject *)(self);
}
static dict_T *
py_dict_alloc()
{
dict_T *r;
if (!(r = dict_alloc()))
{
PyErr_NoMemory();
return NULL;
}
++r->dv_refcount;
return r;
}
static PyObject *
DictionaryConstructor(PyTypeObject *subtype, PyObject *args, PyObject *kwargs)
{
DictionaryObject *self;
dict_T *dict;
if (!(dict = py_dict_alloc()))
return NULL;
self = (DictionaryObject *) DictionaryNew(subtype, dict);
--dict->dv_refcount;
if (kwargs || PyTuple_Size(args))
{
PyObject *tmp;
if (!(tmp = DictionaryUpdate(self, args, kwargs)))
{
Py_DECREF(self);
return NULL;
}
Py_DECREF(tmp);
}
return (PyObject *)(self);
}
@@ -918,7 +966,8 @@ DictionarySetattr(DictionaryObject *self, char *name, PyObject *val)
{
if (val == NULL)
{
PyErr_SetString(PyExc_AttributeError, _("Cannot delete DictionaryObject attributes"));
PyErr_SetString(PyExc_AttributeError,
_("cannot delete vim.Dictionary attributes"));
return -1;
}
@@ -926,7 +975,7 @@ DictionarySetattr(DictionaryObject *self, char *name, PyObject *val)
{
if (self->dict->dv_lock == VAR_FIXED)
{
PyErr_SetString(PyExc_TypeError, _("Cannot modify fixed dictionary"));
PyErr_SetString(PyExc_TypeError, _("cannot modify fixed dictionary"));
return -1;
}
else
@@ -943,7 +992,7 @@ DictionarySetattr(DictionaryObject *self, char *name, PyObject *val)
}
else
{
PyErr_SetString(PyExc_AttributeError, _("Cannot set this attribute"));
PyErr_SetString(PyExc_AttributeError, _("cannot set this attribute"));
return -1;
}
}
@@ -954,26 +1003,170 @@ DictionaryLength(DictionaryObject *self)
return ((PyInt) (self->dict->dv_hashtab.ht_used));
}
#define DICT_FLAG_HAS_DEFAULT 0x01
#define DICT_FLAG_POP 0x02
#define DICT_FLAG_NONE_DEFAULT 0x04
#define DICT_FLAG_RETURN_BOOL 0x08 /* Incompatible with DICT_FLAG_POP */
#define DICT_FLAG_RETURN_PAIR 0x10
static PyObject *
DictionaryItem(DictionaryObject *self, PyObject *keyObject)
_DictionaryItem(DictionaryObject *self, PyObject *args, int flags)
{
PyObject *keyObject;
PyObject *defObject = ((flags & DICT_FLAG_NONE_DEFAULT)? Py_None : NULL);
PyObject *r;
char_u *key;
dictitem_T *di;
dict_T *dict = self->dict;
hashitem_T *hi;
DICTKEY_DECL
if (flags & DICT_FLAG_HAS_DEFAULT)
{
if (!PyArg_ParseTuple(args, "O|O", &keyObject, &defObject))
return NULL;
}
else
keyObject = args;
if (flags & DICT_FLAG_RETURN_BOOL)
defObject = Py_False;
DICTKEY_GET(NULL, 0)
di = dict_find(self->dict, key, -1);
hi = hash_find(&dict->dv_hashtab, key);
DICTKEY_UNREF
if (di == NULL)
if (HASHITEM_EMPTY(hi))
{
PyErr_SetObject(PyExc_KeyError, keyObject);
if (defObject)
{
Py_INCREF(defObject);
return defObject;
}
else
{
PyErr_SetObject(PyExc_KeyError, keyObject);
return NULL;
}
}
else if (flags & DICT_FLAG_RETURN_BOOL)
{
Py_INCREF(Py_True);
return Py_True;
}
di = dict_lookup(hi);
if (!(r = ConvertToPyObject(&di->di_tv)))
return NULL;
if (flags & DICT_FLAG_POP)
{
if (dict->dv_lock)
{
PyErr_SetVim(_("dict is locked"));
Py_DECREF(r);
return NULL;
}
hash_remove(&dict->dv_hashtab, hi);
dictitem_free(di);
}
if (flags & DICT_FLAG_RETURN_PAIR)
{
PyObject *tmp = r;
if (!(r = Py_BuildValue("(" Py_bytes_fmt "O)", hi->hi_key, tmp)))
{
Py_DECREF(tmp);
return NULL;
}
}
return r;
}
static PyObject *
DictionaryItem(DictionaryObject *self, PyObject *keyObject)
{
return _DictionaryItem(self, keyObject, 0);
}
static int
DictionaryContains(DictionaryObject *self, PyObject *keyObject)
{
PyObject *rObj = _DictionaryItem(self, keyObject, DICT_FLAG_RETURN_BOOL);
int r;
r = (rObj == Py_True);
Py_DECREF(Py_True);
return r;
}
typedef struct
{
hashitem_T *ht_array;
long_u ht_used;
hashtab_T *ht;
hashitem_T *hi;
int todo;
} dictiterinfo_T;
static PyObject *
DictionaryIterNext(dictiterinfo_T **dii)
{
PyObject *r;
if (!(*dii)->todo)
return NULL;
if ((*dii)->ht->ht_array != (*dii)->ht_array ||
(*dii)->ht->ht_used != (*dii)->ht_used)
{
PyErr_SetString(PyExc_RuntimeError,
_("hashtab changed during iteration"));
return NULL;
}
return ConvertToPyObject(&di->di_tv);
while (((*dii)->todo) && HASHITEM_EMPTY((*dii)->hi))
++((*dii)->hi);
--((*dii)->todo);
if (!(r = PyBytes_FromString((char *) (*dii)->hi->hi_key)))
return NULL;
return r;
}
static PyObject *
DictionaryIter(DictionaryObject *self)
{
dictiterinfo_T *dii;
hashtab_T *ht;
if (!(dii = PyMem_New(dictiterinfo_T, 1)))
{
PyErr_NoMemory();
return NULL;
}
ht = &self->dict->dv_hashtab;
dii->ht_array = ht->ht_array;
dii->ht_used = ht->ht_used;
dii->ht = ht;
dii->hi = dii->ht_array;
dii->todo = dii->ht_used;
return IterNew(dii,
(destructorfun) PyMem_Free, (nextfun) DictionaryIterNext,
NULL, NULL);
}
static PyInt
@@ -1016,18 +1209,19 @@ DictionaryAssItem(DictionaryObject *self, PyObject *keyObject, PyObject *valObje
if (di == NULL)
{
di = dictitem_alloc(key);
if (di == NULL)
if (!(di = dictitem_alloc(key)))
{
PyErr_NoMemory();
return -1;
}
di->di_tv.v_lock = 0;
di->di_tv.v_type = VAR_UNKNOWN;
if (dict_add(dict, di) == FAIL)
{
DICTKEY_UNREF
vim_free(di);
dictitem_free(di);
PyErr_SetVim(_("failed to add key to dictionary"));
return -1;
}
@@ -1042,21 +1236,34 @@ DictionaryAssItem(DictionaryObject *self, PyObject *keyObject, PyObject *valObje
return 0;
}
typedef PyObject *(*hi_to_py)(hashitem_T *);
static PyObject *
DictionaryListKeys(DictionaryObject *self)
DictionaryListObjects(DictionaryObject *self, hi_to_py hiconvert)
{
dict_T *dict = self->dict;
long_u todo = dict->dv_hashtab.ht_used;
Py_ssize_t i = 0;
PyObject *r;
hashitem_T *hi;
PyObject *newObj;
r = PyList_New(todo);
for (hi = dict->dv_hashtab.ht_array; todo > 0; ++hi)
{
if (!HASHITEM_EMPTY(hi))
{
PyList_SetItem(r, i, PyBytes_FromString((char *)(hi->hi_key)));
if (!(newObj = hiconvert(hi)))
{
Py_DECREF(r);
return NULL;
}
if (PyList_SetItem(r, i, newObj))
{
Py_DECREF(r);
Py_DECREF(newObj);
return NULL;
}
--todo;
++i;
}
@@ -1064,6 +1271,235 @@ DictionaryListKeys(DictionaryObject *self)
return r;
}
static PyObject *
dict_key(hashitem_T *hi)
{
return PyBytes_FromString((char *)(hi->hi_key));
}
static PyObject *
DictionaryListKeys(DictionaryObject *self)
{
return DictionaryListObjects(self, dict_key);
}
static PyObject *
dict_val(hashitem_T *hi)
{
dictitem_T *di;
di = dict_lookup(hi);
return ConvertToPyObject(&di->di_tv);
}
static PyObject *
DictionaryListValues(DictionaryObject *self)
{
return DictionaryListObjects(self, dict_val);
}
static PyObject *
dict_item(hashitem_T *hi)
{
PyObject *keyObject;
PyObject *valObject;
PyObject *r;
if (!(keyObject = dict_key(hi)))
return NULL;
if (!(valObject = dict_val(hi)))
{
Py_DECREF(keyObject);
return NULL;
}
r = Py_BuildValue("(OO)", keyObject, valObject);
Py_DECREF(keyObject);
Py_DECREF(valObject);
return r;
}
static PyObject *
DictionaryListItems(DictionaryObject *self)
{
return DictionaryListObjects(self, dict_item);
}
static PyObject *
DictionaryUpdate(DictionaryObject *self, PyObject *args, PyObject *kwargs)
{
dict_T *dict = self->dict;
if (dict->dv_lock)
{
PyErr_SetVim(_("dict is locked"));
return NULL;
}
if (kwargs)
{
typval_T tv;
if (ConvertFromPyMapping(kwargs, &tv) == -1)
return NULL;
VimTryStart();
dict_extend(self->dict, tv.vval.v_dict, (char_u *) "force");
clear_tv(&tv);
if (VimTryEnd())
return NULL;
}
else
{
PyObject *object;
if (!PyArg_Parse(args, "(O)", &object))
return NULL;
if (PyObject_HasAttrString(object, "keys"))
return DictionaryUpdate(self, NULL, object);
else
{
PyObject *iterator;
PyObject *item;
if (!(iterator = PyObject_GetIter(object)))
return NULL;
while ((item = PyIter_Next(iterator)))
{
PyObject *fast;
PyObject *keyObject;
PyObject *valObject;
PyObject *todecref;
char_u *key;
dictitem_T *di;
if (!(fast = PySequence_Fast(item, "")))
{
Py_DECREF(iterator);
Py_DECREF(item);
return NULL;
}
Py_DECREF(item);
if (PySequence_Fast_GET_SIZE(fast) != 2)
{
Py_DECREF(iterator);
Py_DECREF(fast);
PyErr_SetString(PyExc_ValueError,
_("expected sequence element of size 2"));
return NULL;
}
keyObject = PySequence_Fast_GET_ITEM(fast, 0);
if (!(key = StringToChars(keyObject, &todecref)))
{
Py_DECREF(iterator);
Py_DECREF(fast);
return NULL;
}
di = dictitem_alloc(key);
Py_XDECREF(todecref);
if (di == NULL)
{
Py_DECREF(fast);
Py_DECREF(iterator);
PyErr_NoMemory();
return NULL;
}
di->di_tv.v_lock = 0;
di->di_tv.v_type = VAR_UNKNOWN;
valObject = PySequence_Fast_GET_ITEM(fast, 1);
if (ConvertFromPyObject(valObject, &di->di_tv) == -1)
{
Py_DECREF(iterator);
Py_DECREF(fast);
dictitem_free(di);
return NULL;
}
Py_DECREF(fast);
if (dict_add(dict, di) == FAIL)
{
Py_DECREF(iterator);
dictitem_free(di);
PyErr_SetVim(_("failed to add key to dictionary"));
return NULL;
}
}
Py_DECREF(iterator);
/* Iterator may have finished due to an exception */
if (PyErr_Occurred())
return NULL;
}
}
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *
DictionaryGet(DictionaryObject *self, PyObject *args)
{
return _DictionaryItem(self, args,
DICT_FLAG_HAS_DEFAULT|DICT_FLAG_NONE_DEFAULT);
}
static PyObject *
DictionaryPop(DictionaryObject *self, PyObject *args)
{
return _DictionaryItem(self, args, DICT_FLAG_HAS_DEFAULT|DICT_FLAG_POP);
}
static PyObject *
DictionaryPopItem(DictionaryObject *self, PyObject *args)
{
PyObject *keyObject;
if (!PyArg_ParseTuple(args, "O", &keyObject))
return NULL;
return _DictionaryItem(self, keyObject,
DICT_FLAG_POP|DICT_FLAG_RETURN_PAIR);
}
static PyObject *
DictionaryHasKey(DictionaryObject *self, PyObject *args)
{
PyObject *keyObject;
if (!PyArg_ParseTuple(args, "O", &keyObject))
return NULL;
return _DictionaryItem(self, keyObject, DICT_FLAG_RETURN_BOOL);
}
static PySequenceMethods DictionaryAsSeq = {
0, /* sq_length */
0, /* sq_concat */
0, /* sq_repeat */
0, /* sq_item */
0, /* sq_slice */
0, /* sq_ass_item */
0, /* sq_ass_slice */
(objobjproc) DictionaryContains, /* sq_contains */
0, /* sq_inplace_concat */
0, /* sq_inplace_repeat */
};
static PyMappingMethods DictionaryAsMapping = {
(lenfunc) DictionaryLength,
(binaryfunc) DictionaryItem,
@@ -1072,6 +1508,13 @@ static PyMappingMethods DictionaryAsMapping = {
static struct PyMethodDef DictionaryMethods[] = {
{"keys", (PyCFunction)DictionaryListKeys, METH_NOARGS, ""},
{"values", (PyCFunction)DictionaryListValues, METH_NOARGS, ""},
{"items", (PyCFunction)DictionaryListItems, METH_NOARGS, ""},
{"update", (PyCFunction)DictionaryUpdate, METH_VARARGS|METH_KEYWORDS, ""},
{"get", (PyCFunction)DictionaryGet, METH_VARARGS, ""},
{"pop", (PyCFunction)DictionaryPop, METH_VARARGS, ""},
{"popitem", (PyCFunction)DictionaryPopItem, METH_VARARGS, ""},
{"has_key", (PyCFunction)DictionaryHasKey, METH_VARARGS, ""},
{"__dir__", (PyCFunction)DictionaryDir, METH_NOARGS, ""},
{ NULL, NULL, 0, NULL}
};
@@ -1541,14 +1984,7 @@ FunctionCall(FunctionObject *self, PyObject *argsObject, PyObject *kwargs)
selfdictObject = PyDict_GetItemString(kwargs, "self");
if (selfdictObject != NULL)
{
if (!PyMapping_Check(selfdictObject))
{
PyErr_SetString(PyExc_TypeError,
_("'self' argument must be a dictionary"));
clear_tv(&args);
return NULL;
}
if (ConvertFromPyObject(selfdictObject, &selfdicttv) == -1)
if (ConvertFromPyMapping(selfdictObject, &selfdicttv) == -1)
{
clear_tv(&args);
return NULL;
@@ -1994,7 +2430,7 @@ TabPageAttr(TabPageObject *self, char *name)
else if (strcmp(name, "number") == 0)
return PyLong_FromLong((long) get_tab_number(self->tab));
else if (strcmp(name, "vars") == 0)
return DictionaryNew(self->tab->tp_vars);
return NEW_DICTIONARY(self->tab->tp_vars);
else if (strcmp(name, "window") == 0)
{
/* For current tab window.c does not bother to set or update tp_curwin
@@ -2225,7 +2661,7 @@ WindowAttr(WindowObject *self, char *name)
return PyLong_FromLong((long)(W_WINCOL(self->win)));
#endif
else if (strcmp(name, "vars") == 0)
return DictionaryNew(self->win->w_vars);
return NEW_DICTIONARY(self->win->w_vars);
else if (strcmp(name, "options") == 0)
return OptionsNew(SREQ_WIN, self->win, (checkfun) CheckWindow,
(PyObject *) self);
@@ -3402,7 +3838,7 @@ BufferAttr(BufferObject *self, char *name)
else if (strcmp(name, "number") == 0)
return Py_BuildValue(Py_ssize_t_fmt, self->buf->b_fnum);
else if (strcmp(name, "vars") == 0)
return DictionaryNew(self->buf->b_vars);
return NEW_DICTIONARY(self->buf->b_vars);
else if (strcmp(name, "options") == 0)
return OptionsNew(SREQ_BUF, self->buf, (checkfun) CheckBuffer,
(PyObject *) self);
@@ -4306,6 +4742,36 @@ convert_dl(PyObject *obj, typval_T *tv,
return 0;
}
static int
ConvertFromPyMapping(PyObject *obj, typval_T *tv)
{
PyObject *lookup_dict;
int r;
if (!(lookup_dict = PyDict_New()))
return -1;
if (PyType_IsSubtype(obj->ob_type, &DictionaryType))
{
tv->v_type = VAR_DICT;
tv->vval.v_dict = (((DictionaryObject *)(obj))->dict);
++tv->vval.v_dict->dv_refcount;
r = 0;
}
else if (PyDict_Check(obj))
r = convert_dl(obj, tv, pydict_to_tv, lookup_dict);
else if (PyMapping_Check(obj))
r = convert_dl(obj, tv, pymap_to_tv, lookup_dict);
else
{
PyErr_SetString(PyExc_TypeError,
_("unable to convert object to vim dictionary"));
r = -1;
}
Py_DECREF(lookup_dict);
return r;
}
static int
ConvertFromPyObject(PyObject *obj, typval_T *tv)
{
@@ -4322,7 +4788,7 @@ ConvertFromPyObject(PyObject *obj, typval_T *tv)
static int
_ConvertFromPyObject(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
{
if (obj->ob_type == &DictionaryType)
if (PyType_IsSubtype(obj->ob_type, &DictionaryType))
{
tv->v_type = VAR_DICT;
tv->vval.v_dict = (((DictionaryObject *)(obj))->dict);
@@ -4437,7 +4903,7 @@ ConvertToPyObject(typval_T *tv)
case VAR_LIST:
return ListNew(tv->vval.v_list);
case VAR_DICT:
return DictionaryNew(tv->vval.v_dict);
return NEW_DICTIONARY(tv->vval.v_dict);
case VAR_FUNC:
return FunctionNew(tv->vval.v_string == NULL
? (char_u *)"" : tv->vval.v_string);
@@ -4608,10 +5074,14 @@ init_structs(void)
DictionaryType.tp_name = "vim.dictionary";
DictionaryType.tp_basicsize = sizeof(DictionaryObject);
DictionaryType.tp_dealloc = (destructor)DictionaryDestructor;
DictionaryType.tp_as_sequence = &DictionaryAsSeq;
DictionaryType.tp_as_mapping = &DictionaryAsMapping;
DictionaryType.tp_flags = Py_TPFLAGS_DEFAULT;
DictionaryType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE;
DictionaryType.tp_doc = "dictionary pushing modifications to vim structure";
DictionaryType.tp_methods = DictionaryMethods;
DictionaryType.tp_iter = (getiterfunc)DictionaryIter;
DictionaryType.tp_new = (newfunc)DictionaryConstructor;
DictionaryType.tp_alloc = (allocfunc)PyType_GenericAlloc;
#if PY_MAJOR_VERSION >= 3
DictionaryType.tp_getattro = (getattrofunc)DictionaryGetattro;
DictionaryType.tp_setattro = (setattrofunc)DictionarySetattro;
@@ -4786,8 +5256,8 @@ populate_module(PyObject *m, object_adder add_object)
return -1;
ADD_OBJECT(m, "error", VimError);
ADD_CHECKED_OBJECT(m, "vars", DictionaryNew(&globvardict));
ADD_CHECKED_OBJECT(m, "vvars", DictionaryNew(&vimvardict));
ADD_CHECKED_OBJECT(m, "vars", NEW_DICTIONARY(&globvardict));
ADD_CHECKED_OBJECT(m, "vvars", NEW_DICTIONARY(&vimvardict));
ADD_CHECKED_OBJECT(m, "options",
OptionsNew(SREQ_GLOBAL, NULL, dummy_check, NULL));
return 0;

View File

@@ -103,6 +103,7 @@ struct PyMethodDef { Py_ssize_t a; };
# define PyIntIntObjArgProc intintobjargproc
# define Py_ssize_t_fmt "i"
#endif
#define Py_bytes_fmt "s"
/* Parser flags */
#define single_input 256
@@ -187,6 +188,7 @@ struct PyMethodDef { Py_ssize_t a; };
# define PySequence_Check dll_PySequence_Check
# define PySequence_Size dll_PySequence_Size
# define PySequence_GetItem dll_PySequence_GetItem
# define PySequence_Fast dll_PySequence_Fast
# define PyTuple_Size dll_PyTuple_Size
# define PyTuple_GetItem dll_PyTuple_GetItem
# define PyTuple_Type (*dll_PyTuple_Type)
@@ -207,6 +209,7 @@ struct PyMethodDef { Py_ssize_t a; };
# define PyRun_SimpleString dll_PyRun_SimpleString
# define PyRun_String dll_PyRun_String
# define PyObject_GetAttrString dll_PyObject_GetAttrString
# define PyObject_HasAttrString dll_PyObject_HasAttrString
# define PyObject_SetAttrString dll_PyObject_SetAttrString
# define PyObject_CallFunctionObjArgs dll_PyObject_CallFunctionObjArgs
# define PyString_AsString dll_PyString_AsString
@@ -227,6 +230,7 @@ struct PyMethodDef { Py_ssize_t a; };
# define PySys_SetArgv dll_PySys_SetArgv
# define PyType_Type (*dll_PyType_Type)
# define PyType_Ready (*dll_PyType_Ready)
# define PyType_GenericAlloc dll_PyType_GenericAlloc
# define Py_BuildValue dll_Py_BuildValue
# define Py_FindMethod dll_Py_FindMethod
# define Py_InitModule4 dll_Py_InitModule4
@@ -318,6 +322,7 @@ static PyTypeObject* dll_PyList_Type;
static int (*dll_PySequence_Check)(PyObject *);
static PyInt(*dll_PySequence_Size)(PyObject *);
static PyObject*(*dll_PySequence_GetItem)(PyObject *, PyInt);
static PyObject*(*dll_PySequence_Fast)(PyObject *, const char *);
static PyInt(*dll_PyTuple_Size)(PyObject *);
static PyObject*(*dll_PyTuple_GetItem)(PyObject *, PyInt);
static PyTypeObject* dll_PyTuple_Type;
@@ -336,6 +341,7 @@ static PyObject*(*dll_PyModule_GetDict)(PyObject *);
static int(*dll_PyRun_SimpleString)(char *);
static PyObject *(*dll_PyRun_String)(char *, int, PyObject *, PyObject *);
static PyObject* (*dll_PyObject_GetAttrString)(PyObject *, const char *);
static int (*dll_PyObject_HasAttrString)(PyObject *, const char *);
static PyObject* (*dll_PyObject_SetAttrString)(PyObject *, const char *, PyObject *);
static PyObject* (*dll_PyObject_CallFunctionObjArgs)(PyObject *, ...);
static char*(*dll_PyString_AsString)(PyObject *);
@@ -354,6 +360,7 @@ static int(*dll_PySys_SetObject)(char *, PyObject *);
static int(*dll_PySys_SetArgv)(int, char **);
static PyTypeObject* dll_PyType_Type;
static int (*dll_PyType_Ready)(PyTypeObject *type);
static PyObject* (*dll_PyType_GenericAlloc)(PyTypeObject *type, PyInt nitems);
static PyObject*(*dll_Py_BuildValue)(char *, ...);
static PyObject*(*dll_Py_FindMethod)(struct PyMethodDef[], PyObject *, char *);
static PyObject*(*dll_Py_InitModule4)(char *, struct PyMethodDef *, char *, PyObject *, int);
@@ -475,9 +482,10 @@ static struct
{"PyList_SetItem", (PYTHON_PROC*)&dll_PyList_SetItem},
{"PyList_Size", (PYTHON_PROC*)&dll_PyList_Size},
{"PyList_Type", (PYTHON_PROC*)&dll_PyList_Type},
{"PySequence_GetItem", (PYTHON_PROC*)&dll_PySequence_GetItem},
{"PySequence_Size", (PYTHON_PROC*)&dll_PySequence_Size},
{"PySequence_Check", (PYTHON_PROC*)&dll_PySequence_Check},
{"PySequence_GetItem", (PYTHON_PROC*)&dll_PySequence_GetItem},
{"PySequence_Fast", (PYTHON_PROC*)&dll_PySequence_Fast},
{"PyTuple_GetItem", (PYTHON_PROC*)&dll_PyTuple_GetItem},
{"PyTuple_Size", (PYTHON_PROC*)&dll_PyTuple_Size},
{"PyTuple_Type", (PYTHON_PROC*)&dll_PyTuple_Type},
@@ -496,6 +504,7 @@ static struct
{"PyRun_SimpleString", (PYTHON_PROC*)&dll_PyRun_SimpleString},
{"PyRun_String", (PYTHON_PROC*)&dll_PyRun_String},
{"PyObject_GetAttrString", (PYTHON_PROC*)&dll_PyObject_GetAttrString},
{"PyObject_HasAttrString", (PYTHON_PROC*)&dll_PyObject_HasAttrString},
{"PyObject_SetAttrString", (PYTHON_PROC*)&dll_PyObject_SetAttrString},
{"PyObject_CallFunctionObjArgs", (PYTHON_PROC*)&dll_PyObject_CallFunctionObjArgs},
{"PyString_AsString", (PYTHON_PROC*)&dll_PyString_AsString},
@@ -514,6 +523,7 @@ static struct
{"PySys_SetArgv", (PYTHON_PROC*)&dll_PySys_SetArgv},
{"PyType_Type", (PYTHON_PROC*)&dll_PyType_Type},
{"PyType_Ready", (PYTHON_PROC*)&dll_PyType_Ready},
{"PyType_GenericAlloc", (PYTHON_PROC*)&dll_PyType_GenericAlloc},
{"Py_FindMethod", (PYTHON_PROC*)&dll_Py_FindMethod},
{"Py_SetPythonHome", (PYTHON_PROC*)&dll_Py_SetPythonHome},
{"Py_Initialize", (PYTHON_PROC*)&dll_Py_Initialize},
@@ -1116,10 +1126,8 @@ static PySequenceMethods BufferAsSeq = {
(PyIntObjArgProc) BufferAssItem, /* sq_ass_item, x[i]=v */
(PyIntIntObjArgProc) BufferAssSlice, /* sq_ass_slice, x[i:j]=v */
(objobjproc) 0,
#if PY_MAJOR_VERSION >= 2
(binaryfunc) 0,
0,
#endif
};
/* Buffer object - Implementation

View File

@@ -96,6 +96,7 @@
#define PyInt_FromLong(i) PyLong_FromLong(i)
#define PyInt_AsLong(obj) PyLong_AsLong(obj)
#define Py_ssize_t_fmt "n"
#define Py_bytes_fmt "y"
#if defined(DYNAMIC_PYTHON3) || defined(PROTO)
@@ -149,6 +150,7 @@
# define PySequence_Check py3_PySequence_Check
# define PySequence_Size py3_PySequence_Size
# define PySequence_GetItem py3_PySequence_GetItem
# define PySequence_Fast py3_PySequence_Fast
# define PyTuple_Size py3_PyTuple_Size
# define PyTuple_GetItem py3_PyTuple_GetItem
# define PySlice_GetIndicesEx py3_PySlice_GetIndicesEx
@@ -168,6 +170,7 @@
#undef PyRun_String
# define PyRun_String py3_PyRun_String
# define PyObject_GetAttrString py3_PyObject_GetAttrString
# define PyObject_HasAttrString py3_PyObject_HasAttrString
# define PyObject_SetAttrString py3_PyObject_SetAttrString
# define PyObject_CallFunctionObjArgs py3_PyObject_CallFunctionObjArgs
# define PyEval_GetLocals py3_PyEval_GetLocals
@@ -269,6 +272,7 @@ static Py_ssize_t (*py3_PyList_Size)(PyObject *);
static int (*py3_PySequence_Check)(PyObject *);
static Py_ssize_t (*py3_PySequence_Size)(PyObject *);
static PyObject* (*py3_PySequence_GetItem)(PyObject *, Py_ssize_t);
static PyObject* (*py3_PySequence_Fast)(PyObject *, const char *);
static Py_ssize_t (*py3_PyTuple_Size)(PyObject *);
static PyObject* (*py3_PyTuple_GetItem)(PyObject *, Py_ssize_t);
static int (*py3_PyMapping_Check)(PyObject *);
@@ -282,6 +286,7 @@ static void (*py3_PyErr_SetObject)(PyObject *, PyObject *);
static int (*py3_PyRun_SimpleString)(char *);
static PyObject* (*py3_PyRun_String)(char *, int, PyObject *, PyObject *);
static PyObject* (*py3_PyObject_GetAttrString)(PyObject *, const char *);
static int (*py3_PyObject_HasAttrString)(PyObject *, const char *);
static PyObject* (*py3_PyObject_SetAttrString)(PyObject *, const char *, PyObject *);
static PyObject* (*py3_PyObject_CallFunctionObjArgs)(PyObject *, ...);
static PyObject* (*py3_PyEval_GetGlobals)();
@@ -425,6 +430,7 @@ static struct
{"PySequence_Check", (PYTHON_PROC*)&py3_PySequence_Check},
{"PySequence_Size", (PYTHON_PROC*)&py3_PySequence_Size},
{"PySequence_GetItem", (PYTHON_PROC*)&py3_PySequence_GetItem},
{"PySequence_Fast", (PYTHON_PROC*)&py3_PySequence_Fast},
{"PyTuple_Size", (PYTHON_PROC*)&py3_PyTuple_Size},
{"PyTuple_GetItem", (PYTHON_PROC*)&py3_PyTuple_GetItem},
{"PySlice_GetIndicesEx", (PYTHON_PROC*)&py3_PySlice_GetIndicesEx},
@@ -435,6 +441,7 @@ static struct
{"PyRun_SimpleString", (PYTHON_PROC*)&py3_PyRun_SimpleString},
{"PyRun_String", (PYTHON_PROC*)&py3_PyRun_String},
{"PyObject_GetAttrString", (PYTHON_PROC*)&py3_PyObject_GetAttrString},
{"PyObject_HasAttrString", (PYTHON_PROC*)&py3_PyObject_HasAttrString},
{"PyObject_SetAttrString", (PYTHON_PROC*)&py3_PyObject_SetAttrString},
{"PyObject_CallFunctionObjArgs", (PYTHON_PROC*)&py3_PyObject_CallFunctionObjArgs},
{"PyEval_GetGlobals", (PYTHON_PROC*)&py3_PyEval_GetGlobals},

View File

@@ -75,6 +75,7 @@ int dict_add_list __ARGS((dict_T *d, char *key, list_T *list));
dictitem_T *dict_find __ARGS((dict_T *d, char_u *key, int len));
char_u *get_dict_string __ARGS((dict_T *d, char_u *key, int save));
long get_dict_number __ARGS((dict_T *d, char_u *key));
void dict_extend __ARGS((dict_T *d1, dict_T *d2, char_u *action));
char_u *get_function_name __ARGS((expand_T *xp, int idx));
char_u *get_expr_name __ARGS((expand_T *xp, int idx));
char_u *get_expanded_name __ARGS((char_u *name, int check));

View File

@@ -31,16 +31,22 @@ STARTTEST
:"
:" Extending Dictionary directly with different types
:let d = {}
:py d=vim.bindeval('d')
:py d['1']='asd'
:py d['b']=[1, 2, f]
:py d['-1']={'a': 1}
:let dkeys = []
:py dk=vim.bindeval('dkeys')
:py dkeys=d.keys()
:py dkeys.sort()
:py dk.extend(dkeys)
:$put =string(dkeys)
py << EOF
d=vim.bindeval('d')
d['1']='asd'
d.update(b=[1, 2, f])
d.update((('-1', {'a': 1}),))
d.update({'0': -1})
dk = d.keys()
dv = d.values()
di = d.items()
dk.sort(key=repr)
dv.sort(key=repr)
di.sort(key=repr)
EOF
:$put =pyeval('repr(dk)')
:$put =substitute(pyeval('repr(dv)'),'0x\x\+','','g')
:$put =substitute(pyeval('repr(di)'),'0x\x\+','','g')
:for [key, val] in sort(items(d))
: $put =string(key) . ' : ' . string(val)
: unlet key val
@@ -60,7 +66,20 @@ STARTTEST
:$put =string(l)
:"
:py del d['-1']
:$put =string(pyeval('d.get(''b'', 1)'))
:$put =string(pyeval('d.pop(''b'')'))
:$put =string(pyeval('d.get(''b'', 1)'))
:$put =string(pyeval('d.pop(''1'', 2)'))
:$put =string(pyeval('d.pop(''1'', 2)'))
:$put =pyeval('repr(d.has_key(''0''))')
:$put =pyeval('repr(d.has_key(''1''))')
:$put =pyeval('repr(''0'' in d)')
:$put =pyeval('repr(''1'' in d)')
:$put =pyeval('repr(list(iter(d)))')
:$put =string(d)
:$put =pyeval('repr(d.popitem(''0''))')
:$put =pyeval('repr(d.get(''0''))')
:$put =pyeval('repr(list(iter(d)))')
:"
:" removing items out of range: silently skip items that don't exist
:let l = [0, 1, 2, 3]
@@ -198,6 +217,9 @@ em('d["abc"]=vim')
em('d[""]=1')
em('d["a\\0b"]=1')
em('d[u"a\\0b"]=1')
em('d.pop("abc")')
em('d.popitem("abc")')
EOF
:$put =messages
:unlet messages
@@ -709,6 +731,10 @@ del name
del o
EOF
:"
:" Test vim.*.__new__
:$put =string(pyeval('vim.Dictionary({})'))
:$put =string(pyeval('vim.Dictionary(a=1)'))
:$put =string(pyeval('vim.Dictionary(((''a'', 1),))'))
:"
:" Test stdout/stderr
:redir => messages
@@ -718,6 +744,16 @@ EOF
:py sys.stderr.writelines(iter('abc'))
:redir END
:$put =string(substitute(messages, '\d\+', '', 'g'))
:" Test subclassing
py << EOF
class DupDict(vim.Dictionary):
def __setitem__(self, key, value):
super(DupDict, self).__setitem__(key, value)
super(DupDict, self).__setitem__('dup_' + key, value)
dd = DupDict()
dd['a'] = 'b'
EOF
:$put =string(sort(keys(pyeval('dd'))))
:"
:" Test exceptions
:fun Exe(e)

View File

@@ -4,13 +4,29 @@ start:
Vim(put):E684:
[0, 'as''d', [1, 2, function('strlen'), {'a': 1}]]
[0, function('strlen'), [1, 2, function('strlen'), {'a': 1}]]
['-1', '1', 'b']
['-1', '0', '1', 'b']
['asd', -1L, <vim.dictionary object at >, <vim.list object at >]
[('-1', <vim.dictionary object at >), ('0', -1L), ('1', 'asd'), ('b', <vim.list object at >)]
'-1' : {'a': 1}
'0' : -1
'1' : 'asd'
'b' : [1, 2, function('strlen')]
[0, function('strlen')]
[3]
{'1': 'asd', 'b': [1, 2, function('strlen')]}
[1, 2, function('strlen')]
[1, 2, function('strlen')]
1
'asd'
2
True
False
True
False
['0']
{'0': -1}
('', -1L)
None
[]
[0, 1, 2, 3]
[0, 1, 2, 3]
[0, 1, 3]
@@ -44,6 +60,8 @@ TypeError
ValueError
TypeError
TypeError
KeyError
KeyError
d : locked:0;scope:0
dl : locked:1;scope:0
v: : locked:2;scope:1
@@ -387,10 +405,13 @@ buffer:__dir__,__members__,append,mark,name,number,options,range,valid,vars
window:__dir__,__members__,buffer,col,cursor,height,number,options,row,tabpage,valid,vars
tabpage:__dir__,__members__,number,valid,vars,window,windows
range:__dir__,__members__,append,end,start
dictionary:__dir__,__members__,keys,locked,scope
dictionary:__dir__,__members__,get,has_key,items,keys,locked,pop,popitem,scope,update,values
list:__dir__,__members__,extend,locked
function:__call__,__dir__,__members__,softspace
output:__dir__,__members__,flush,softspace,write,writelines
{}
{'a': 1}
{'a': 1}
'
abcdef
line :
@@ -398,6 +419,7 @@ abcdef
abc
line :
abc'
['a', 'dup_a']
(<class 'vim.error'>, error('abc',))
(<class 'vim.error'>, error('def',))
(<class 'vim.error'>, error('ghi',))

View File

@@ -26,16 +26,22 @@ STARTTEST
:"
:" Extending Dictionary directly with different types
:let d = {}
:py3 d=vim.bindeval('d')
:py3 d['1']='asd'
:py3 d['b']=[1, 2, f]
:py3 d['-1']={'a': 1}
:let dkeys = []
:py3 dk=vim.bindeval('dkeys')
:py3 dkeys=d.keys()
:py3 dkeys.sort()
:py3 dk+=dkeys
:$put =string(dkeys)
py3 << EOF
d=vim.bindeval('d')
d['1']='asd'
d.update(b=[1, 2, f])
d.update((('-1', {'a': 1}),))
d.update({'0': -1})
dk = d.keys()
dv = d.values()
di = d.items()
dk.sort(key=repr)
dv.sort(key=repr)
di.sort(key=repr)
EOF
:$put =py3eval('repr(dk)')
:$put =substitute(py3eval('repr(dv)'),'0x\x\+','','g')
:$put =substitute(py3eval('repr(di)'),'0x\x\+','','g')
:for [key, val] in sort(items(d))
: $put =string(key) . ' : ' . string(val)
: unlet key val
@@ -55,7 +61,20 @@ STARTTEST
:$put =string(l)
:"
:py3 del d['-1']
:$put =string(py3eval('d.get(''b'', 1)'))
:$put =string(py3eval('d.pop(''b'')'))
:$put =string(py3eval('d.get(''b'', 1)'))
:$put =string(py3eval('d.pop(''1'', 2)'))
:$put =string(py3eval('d.pop(''1'', 2)'))
:$put =py3eval('repr(d.has_key(''0''))')
:$put =py3eval('repr(d.has_key(''1''))')
:$put =py3eval('repr(''0'' in d)')
:$put =py3eval('repr(''1'' in d)')
:$put =py3eval('repr(list(iter(d)))')
:$put =string(d)
:$put =py3eval('repr(d.popitem(''0''))')
:$put =py3eval('repr(d.get(''0''))')
:$put =py3eval('repr(list(iter(d)))')
:"
:" removing items out of range: silently skip items that don't exist
:let l = [0, 1, 2, 3]
@@ -181,35 +200,21 @@ STARTTEST
:py3 <<EOF
d=vim.bindeval('{}')
m=vim.bindeval('messages')
try:
d['abc']
except Exception as e:
m.extend([e.__class__.__name__])
def em(expr, g=globals(), l=locals()):
try:
exec(expr, g, l)
except Exception as e:
m.extend([e.__class__.__name__])
try:
d['abc']="\0"
except Exception as e:
m.extend([e.__class__.__name__])
em('d["abc"]')
em('d["abc"]="\\0"')
em('d["abc"]=vim')
em('d[""]=1')
em('d["a\\0b"]=1')
em('d[b"a\\0b"]=1')
try:
d['abc']=vim
except Exception as e:
m.extend([e.__class__.__name__])
try:
d['']=1
except Exception as e:
m.extend([e.__class__.__name__])
try:
d['a\0b']=1
except Exception as e:
m.extend([e.__class__.__name__])
try:
d[b'a\0b']=1
except Exception as e:
m.extend([e.__class__.__name__])
em('d.pop("abc")')
em('d.popitem("abc")')
EOF
:$put =messages
:unlet messages
@@ -687,6 +692,10 @@ del name
del o
EOF
:"
:" Test vim.Dictionary.__new__
:$put =string(py3eval('vim.Dictionary({})'))
:$put =string(py3eval('vim.Dictionary(a=1)'))
:$put =string(py3eval('vim.Dictionary(((''a'', 1),))'))
:"
:" Test stdout/stderr
:redir => messages
@@ -696,6 +705,16 @@ EOF
:py sys.stderr.writelines(iter('abc'))
:redir END
:$put =string(substitute(messages, '\d\+', '', 'g'))
:" Test subclassing
py3 << EOF
class DupDict(vim.Dictionary):
def __setitem__(self, key, value):
super(DupDict, self).__setitem__(key, value)
super(DupDict, self).__setitem__('dup_' + key, value)
dd = DupDict()
dd['a'] = 'b'
EOF
:$put =string(sort(keys(py3eval('dd'))))
:"
:" Test exceptions
:fun Exe(e)

View File

@@ -4,13 +4,29 @@ start:
Vim(put):E684:
[0, 'as''d', [1, 2, function('strlen'), {'a': 1}]]
[0, function('strlen'), [1, 2, function('strlen'), {'a': 1}]]
['-1', '1', 'b']
[b'-1', b'0', b'1', b'b']
[-1, <vim.dictionary object at >, <vim.list object at >, b'asd']
[(b'-1', <vim.dictionary object at >), (b'0', -1), (b'1', b'asd'), (b'b', <vim.list object at >)]
'-1' : {'a': 1}
'0' : -1
'1' : 'asd'
'b' : [1, 2, function('strlen')]
[0, function('strlen')]
[3]
{'1': 'asd', 'b': [1, 2, function('strlen')]}
[1, 2, function('strlen')]
[1, 2, function('strlen')]
1
'asd'
2
True
False
True
False
[b'0']
{'0': -1}
(b'', -1)
None
[]
[0, 1, 2, 3]
[0, 1, 2, 3]
[0, 1, 3]
@@ -44,6 +60,8 @@ TypeError
ValueError
TypeError
TypeError
KeyError
KeyError
d : locked:0;scope:0
dl : locked:1;scope:0
v: : locked:2;scope:1
@@ -376,10 +394,13 @@ buffer:__dir__,append,mark,name,number,options,range,valid,vars
window:__dir__,buffer,col,cursor,height,number,options,row,tabpage,valid,vars
tabpage:__dir__,number,valid,vars,window,windows
range:__dir__,append,end,start
dictionary:__dir__,keys,locked,scope
dictionary:__dir__,get,has_key,items,keys,locked,pop,popitem,scope,update,values
list:__dir__,extend,locked
function:__call__,__dir__,softspace
output:__dir__,flush,softspace,write,writelines
{}
{'a': 1}
{'a': 1}
'
abcdef
line :
@@ -387,6 +408,7 @@ abcdef
abc
line :
abc'
['a', 'dup_a']
(<class 'vim.error'>, error('abc',))
(<class 'vim.error'>, error('def',))
(<class 'vim.error'>, error('ghi',))

View File

@@ -728,6 +728,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
1061,
/**/
1060,
/**/