0
0
mirror of https://github.com/vim/vim.git synced 2025-08-31 20:53:42 -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

@ -12,9 +12,10 @@ The Python Interface to Vim *python* *Python*
4. Range objects |python-range| 4. Range objects |python-range|
5. Window objects |python-window| 5. Window objects |python-window|
6. Tab page objects |python-tabpage| 6. Tab page objects |python-tabpage|
7. pyeval(), py3eval() Vim functions |python-pyeval| 7. vim.bindeval objects |python-bindeval-objects|
8. Dynamic loading |python-dynamic| 8. pyeval(), py3eval() Vim functions |python-pyeval|
9. Python 3 |python3| 9. Dynamic loading |python-dynamic|
10. Python 3 |python3|
{Vi does not have any of these commands} {Vi does not have any of these commands}
@ -171,47 +172,9 @@ vim.eval(str) *python-eval*
'eval_expr', 'kind': 'f', 'filename': './src/eval.c'}] 'eval_expr', 'kind': 'f', 'filename': './src/eval.c'}]
vim.bindeval(str) *python-bindeval* vim.bindeval(str) *python-bindeval*
Like |python-eval|, but Like |python-eval|, but returns special objects described in
1. if expression evaluates to |List| or |Dictionary| it is returned as |python-bindeval-objects|. These python objects let you modify (|List|
vimlist or vimdictionary python type that are connected to original or |Dictionary|) or call (|Funcref|) vim objecs.
list or dictionary. Thus modifications to these objects imply
modifications of the original.
Additionally, vim.List and vim.Dictionary type have read-write
`.locked` attribute that returns
Value Meaning ~
zero Variable is not locked
vim.VAR_LOCKED Variable is locked, but can be unlocked
vim.VAR_FIXED Variable is locked and can't be unlocked
integer constants. If variable is not fixed, you can do
`var.locked=True` to lock it and `var.locked=False` to unlock.
There is no recursive locking like |:lockvar|! does. There is also
no way to lock a specific key or check whether it is locked (in any
case these locks are ignored by anything except |:let|: |extend()|
does not care, neither does python interface).
vim.Dictionary type also supports `.scope` attribute which is one
of
Value Meaning ~
zero Dictionary is not a scope one
vim.VAR_DEF_SCOPE Function-local or global scope dictionary
vim.VAR_SCOPE Other scope dictionary
2. if expression evaluates to a function reference, then it returns
callable vim.Function object. Use self keyword argument to assign
|self| object for dictionary functions.
Note: this function has the same behavior as |lua-eval| (except that
lua does not support running vim functions), |python-eval| is
kept for backwards compatibility in order not to make scripts
relying on outputs of vim.eval() being a copy of original or
vim.eval("1") returning a string.
You can use "List", "Dictionary" and "Function" vim module attributes
to test whether object has given type. These types are currently not
subclassable, neither they contain constructors, so you can use them
only for checks like `isinstance(obj, vim.List)`.
Error object of the "vim" module Error object of the "vim" module
@ -497,13 +460,90 @@ Tab page attributes are:
TabPage object type is available using "TabPage" attribute of vim module. TabPage object type is available using "TabPage" attribute of vim module.
============================================================================== ==============================================================================
7. pyeval() and py3eval() Vim functions *python-pyeval* 7. vim.bindeval objects *python-bindeval-objects*
vim.Dictionary object *python-Dictionary*
Dictionary-like object providing access to vim |Dictionary| type.
Attributes:
Attribute Description ~
locked One of *python-.locked*
Value Description ~
zero Variable is not locked
vim.VAR_LOCKED Variable is locked, but can be unlocked
vim.VAR_FIXED Variable is locked and can't be unlocked
Read-write. You can unlock locked variable by assigning
`True` or `False` to this attribute. No recursive locking
is supported.
scope One of
Value Description ~
zero Dictionary is not a scope one
vim.VAR_DEF_SCOPE |g:| or |l:| dictionary
vim.VAR_SCOPE Other scope dictionary,
see |internal-variables|
Methods:
Method Description ~
keys() Returns a list with dictionary keys.
values() Returns a list with dictionary values.
items() Returns a list of 2-tuples with dictionary contents.
update(iterable)
update(dictionary)
update(**kwargs)
Adds keys to dictionary.
Examples: >
py d = vim.bindeval('{}')
d['a'] = 'b' # Item assignment
print d['a'] # getting item
d.update({'c': 'd'}) # .update(dictionary)
d.update(e='f') # .update(**kwargs)
d.update((('g', 'h'), ('i', 'j'))) # .update(iterable)
for key in d.keys(): # .keys()
for val in d.values(): # .values()
for key, val in d.items(): # .items()
print isinstance(d, vim.Dictionary) # True
for key in d: # Iteration over keys
<
Note: when iterating over keys you should not modify dictionary.
vim.List object *python-List*
Sequence-like object providing access to vim |List| type.
Supports `.locked` attribute, see |python-.locked|. Also supports the
following methods:
Method Description ~
extend(item) Add items to the list.
Examples: >
l = vim.bindeval('[]')
l.extend(['abc', 'def']) # .extend() method
print l[1:] # slicing
l[:0] = ['ghi', 'jkl'] # slice assignment
print l[0] # getting item
l[0] = 'mno' # assignment
for i in l: # iteration
print isinstance(l, vim.List) # True
vim.Function object *python-Function*
Function-like object, acting like vim |Funcref| object. Supports `.name`
attribute and is callable. Accepts special keyword argument `self`, see
|Dictionary-function|.
Examples: >
f = vim.bindeval('function("tr")')
print f('abc', 'a', 'b') # Calls tr('abc', 'a', 'b')
vim.command('''
function DictFun() dict
return self
endfunction
''')
f = vim.bindeval('function("DictFun")')
print f(self={}) # Like call('DictFun', [], {})
print isinstance(f, vim.Function) # True
==============================================================================
8. pyeval() and py3eval() Vim functions *python-pyeval*
To facilitate bi-directional interface, you can use |pyeval()| and |py3eval()| To facilitate bi-directional interface, you can use |pyeval()| and |py3eval()|
functions to evaluate Python expressions and pass their values to VimL. functions to evaluate Python expressions and pass their values to VimL.
============================================================================== ==============================================================================
8. Dynamic loading *python-dynamic* 9. Dynamic loading *python-dynamic*
On MS-Windows the Python library can be loaded dynamically. The |:version| On MS-Windows the Python library can be loaded dynamically. The |:version|
output then includes |+python/dyn|. output then includes |+python/dyn|.
@ -520,7 +560,7 @@ Currently the name is "python24.dll". That is for Python 2.4. To know for
sure edit "gvim.exe" and search for "python\d*.dll\c". sure edit "gvim.exe" and search for "python\d*.dll\c".
============================================================================== ==============================================================================
9. Python 3 *python3* 10. Python 3 *python3*
*:py3* *:python3* *:py3* *:python3*
The `:py3` and `:python3` commands work similar to `:python`. A simple check The `:py3` and `:python3` commands work similar to `:python`. A simple check

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(list, list [, idx])" function
* "extend(dict, dict [, action])" 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) else if (argvars[0].v_type == VAR_DICT && argvars[1].v_type == VAR_DICT)
{ {
dict_T *d1, *d2; dict_T *d1, *d2;
dictitem_T *di1; char_u *action;
char_u *action; int i;
int i;
hashitem_T *hi2;
int todo;
d1 = argvars[0].vval.v_dict; d1 = argvars[0].vval.v_dict;
d2 = argvars[1].vval.v_dict; d2 = argvars[1].vval.v_dict;
@ -10238,46 +10291,7 @@ f_extend(argvars, rettv)
else else
action = (char_u *)"force"; action = (char_u *)"force";
/* Go over all entries in the second dict and add them to the dict_extend(d1, d2, action);
* 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);
}
}
}
copy_tv(&argvars[0], rettv); 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 INVALID_TABPAGE_VALUE ((tabpage_T *)(-1))
#define DICTKEY_DECL \ #define DICTKEY_DECL \
PyObject *dictkey_todecref; PyObject *dictkey_todecref = NULL;
#define DICTKEY_CHECK_EMPTY(err) \ #define DICTKEY_CHECK_EMPTY(err) \
if (*key == NUL) \ 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 *);
static int _ConvertFromPyObject(PyObject *, typval_T *, PyObject *); static int _ConvertFromPyObject(PyObject *, typval_T *, PyObject *);
static int ConvertFromPyMapping(PyObject *, typval_T *);
static PyObject *WindowNew(win_T *, tabpage_T *); static PyObject *WindowNew(win_T *, tabpage_T *);
static PyObject *BufferNew (buf_T *); static PyObject *BufferNew (buf_T *);
static PyObject *LineToString(const char *); static PyObject *LineToString(const char *);
@ -877,12 +878,16 @@ typedef struct
pylinkedlist_T ref; pylinkedlist_T ref;
} DictionaryObject; } DictionaryObject;
static PyObject *DictionaryUpdate(DictionaryObject *, PyObject *, PyObject *);
#define NEW_DICTIONARY(dict) DictionaryNew(&DictionaryType, dict)
static PyObject * static PyObject *
DictionaryNew(dict_T *dict) DictionaryNew(PyTypeObject *subtype, dict_T *dict)
{ {
DictionaryObject *self; DictionaryObject *self;
self = PyObject_NEW(DictionaryObject, &DictionaryType); self = (DictionaryObject *) subtype->tp_alloc(subtype, 0);
if (self == NULL) if (self == NULL)
return NULL; return NULL;
self->dict = dict; self->dict = dict;
@ -890,6 +895,49 @@ DictionaryNew(dict_T *dict)
pyll_add((PyObject *)(self), &self->ref, &lastdict); 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); return (PyObject *)(self);
} }
@ -918,7 +966,8 @@ DictionarySetattr(DictionaryObject *self, char *name, PyObject *val)
{ {
if (val == NULL) if (val == NULL)
{ {
PyErr_SetString(PyExc_AttributeError, _("Cannot delete DictionaryObject attributes")); PyErr_SetString(PyExc_AttributeError,
_("cannot delete vim.Dictionary attributes"));
return -1; return -1;
} }
@ -926,7 +975,7 @@ DictionarySetattr(DictionaryObject *self, char *name, PyObject *val)
{ {
if (self->dict->dv_lock == VAR_FIXED) 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; return -1;
} }
else else
@ -943,7 +992,7 @@ DictionarySetattr(DictionaryObject *self, char *name, PyObject *val)
} }
else else
{ {
PyErr_SetString(PyExc_AttributeError, _("Cannot set this attribute")); PyErr_SetString(PyExc_AttributeError, _("cannot set this attribute"));
return -1; return -1;
} }
} }
@ -954,26 +1003,170 @@ DictionaryLength(DictionaryObject *self)
return ((PyInt) (self->dict->dv_hashtab.ht_used)); 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 * 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; char_u *key;
dictitem_T *di; dictitem_T *di;
dict_T *dict = self->dict;
hashitem_T *hi;
DICTKEY_DECL 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) DICTKEY_GET(NULL, 0)
di = dict_find(self->dict, key, -1); hi = hash_find(&dict->dv_hashtab, key);
DICTKEY_UNREF 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 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 static PyInt
@ -1016,18 +1209,19 @@ DictionaryAssItem(DictionaryObject *self, PyObject *keyObject, PyObject *valObje
if (di == NULL) if (di == NULL)
{ {
di = dictitem_alloc(key); if (!(di = dictitem_alloc(key)))
if (di == NULL)
{ {
PyErr_NoMemory(); PyErr_NoMemory();
return -1; return -1;
} }
di->di_tv.v_lock = 0; di->di_tv.v_lock = 0;
di->di_tv.v_type = VAR_UNKNOWN;
if (dict_add(dict, di) == FAIL) if (dict_add(dict, di) == FAIL)
{ {
DICTKEY_UNREF DICTKEY_UNREF
vim_free(di); vim_free(di);
dictitem_free(di);
PyErr_SetVim(_("failed to add key to dictionary")); PyErr_SetVim(_("failed to add key to dictionary"));
return -1; return -1;
} }
@ -1042,21 +1236,34 @@ DictionaryAssItem(DictionaryObject *self, PyObject *keyObject, PyObject *valObje
return 0; return 0;
} }
typedef PyObject *(*hi_to_py)(hashitem_T *);
static PyObject * static PyObject *
DictionaryListKeys(DictionaryObject *self) DictionaryListObjects(DictionaryObject *self, hi_to_py hiconvert)
{ {
dict_T *dict = self->dict; dict_T *dict = self->dict;
long_u todo = dict->dv_hashtab.ht_used; long_u todo = dict->dv_hashtab.ht_used;
Py_ssize_t i = 0; Py_ssize_t i = 0;
PyObject *r; PyObject *r;
hashitem_T *hi; hashitem_T *hi;
PyObject *newObj;
r = PyList_New(todo); r = PyList_New(todo);
for (hi = dict->dv_hashtab.ht_array; todo > 0; ++hi) for (hi = dict->dv_hashtab.ht_array; todo > 0; ++hi)
{ {
if (!HASHITEM_EMPTY(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; --todo;
++i; ++i;
} }
@ -1064,6 +1271,235 @@ DictionaryListKeys(DictionaryObject *self)
return r; 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 = { static PyMappingMethods DictionaryAsMapping = {
(lenfunc) DictionaryLength, (lenfunc) DictionaryLength,
(binaryfunc) DictionaryItem, (binaryfunc) DictionaryItem,
@ -1072,6 +1508,13 @@ static PyMappingMethods DictionaryAsMapping = {
static struct PyMethodDef DictionaryMethods[] = { static struct PyMethodDef DictionaryMethods[] = {
{"keys", (PyCFunction)DictionaryListKeys, METH_NOARGS, ""}, {"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, ""}, {"__dir__", (PyCFunction)DictionaryDir, METH_NOARGS, ""},
{ NULL, NULL, 0, NULL} { NULL, NULL, 0, NULL}
}; };
@ -1541,14 +1984,7 @@ FunctionCall(FunctionObject *self, PyObject *argsObject, PyObject *kwargs)
selfdictObject = PyDict_GetItemString(kwargs, "self"); selfdictObject = PyDict_GetItemString(kwargs, "self");
if (selfdictObject != NULL) if (selfdictObject != NULL)
{ {
if (!PyMapping_Check(selfdictObject)) if (ConvertFromPyMapping(selfdictObject, &selfdicttv) == -1)
{
PyErr_SetString(PyExc_TypeError,
_("'self' argument must be a dictionary"));
clear_tv(&args);
return NULL;
}
if (ConvertFromPyObject(selfdictObject, &selfdicttv) == -1)
{ {
clear_tv(&args); clear_tv(&args);
return NULL; return NULL;
@ -1994,7 +2430,7 @@ TabPageAttr(TabPageObject *self, char *name)
else if (strcmp(name, "number") == 0) else if (strcmp(name, "number") == 0)
return PyLong_FromLong((long) get_tab_number(self->tab)); return PyLong_FromLong((long) get_tab_number(self->tab));
else if (strcmp(name, "vars") == 0) 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) else if (strcmp(name, "window") == 0)
{ {
/* For current tab window.c does not bother to set or update tp_curwin /* 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))); return PyLong_FromLong((long)(W_WINCOL(self->win)));
#endif #endif
else if (strcmp(name, "vars") == 0) 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) else if (strcmp(name, "options") == 0)
return OptionsNew(SREQ_WIN, self->win, (checkfun) CheckWindow, return OptionsNew(SREQ_WIN, self->win, (checkfun) CheckWindow,
(PyObject *) self); (PyObject *) self);
@ -3402,7 +3838,7 @@ BufferAttr(BufferObject *self, char *name)
else if (strcmp(name, "number") == 0) else if (strcmp(name, "number") == 0)
return Py_BuildValue(Py_ssize_t_fmt, self->buf->b_fnum); return Py_BuildValue(Py_ssize_t_fmt, self->buf->b_fnum);
else if (strcmp(name, "vars") == 0) 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) else if (strcmp(name, "options") == 0)
return OptionsNew(SREQ_BUF, self->buf, (checkfun) CheckBuffer, return OptionsNew(SREQ_BUF, self->buf, (checkfun) CheckBuffer,
(PyObject *) self); (PyObject *) self);
@ -4306,6 +4742,36 @@ convert_dl(PyObject *obj, typval_T *tv,
return 0; 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 static int
ConvertFromPyObject(PyObject *obj, typval_T *tv) ConvertFromPyObject(PyObject *obj, typval_T *tv)
{ {
@ -4322,7 +4788,7 @@ ConvertFromPyObject(PyObject *obj, typval_T *tv)
static int static int
_ConvertFromPyObject(PyObject *obj, typval_T *tv, PyObject *lookup_dict) _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->v_type = VAR_DICT;
tv->vval.v_dict = (((DictionaryObject *)(obj))->dict); tv->vval.v_dict = (((DictionaryObject *)(obj))->dict);
@ -4437,7 +4903,7 @@ ConvertToPyObject(typval_T *tv)
case VAR_LIST: case VAR_LIST:
return ListNew(tv->vval.v_list); return ListNew(tv->vval.v_list);
case VAR_DICT: case VAR_DICT:
return DictionaryNew(tv->vval.v_dict); return NEW_DICTIONARY(tv->vval.v_dict);
case VAR_FUNC: case VAR_FUNC:
return FunctionNew(tv->vval.v_string == NULL return FunctionNew(tv->vval.v_string == NULL
? (char_u *)"" : tv->vval.v_string); ? (char_u *)"" : tv->vval.v_string);
@ -4608,10 +5074,14 @@ init_structs(void)
DictionaryType.tp_name = "vim.dictionary"; DictionaryType.tp_name = "vim.dictionary";
DictionaryType.tp_basicsize = sizeof(DictionaryObject); DictionaryType.tp_basicsize = sizeof(DictionaryObject);
DictionaryType.tp_dealloc = (destructor)DictionaryDestructor; DictionaryType.tp_dealloc = (destructor)DictionaryDestructor;
DictionaryType.tp_as_sequence = &DictionaryAsSeq;
DictionaryType.tp_as_mapping = &DictionaryAsMapping; 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_doc = "dictionary pushing modifications to vim structure";
DictionaryType.tp_methods = DictionaryMethods; 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 #if PY_MAJOR_VERSION >= 3
DictionaryType.tp_getattro = (getattrofunc)DictionaryGetattro; DictionaryType.tp_getattro = (getattrofunc)DictionaryGetattro;
DictionaryType.tp_setattro = (setattrofunc)DictionarySetattro; DictionaryType.tp_setattro = (setattrofunc)DictionarySetattro;
@ -4786,8 +5256,8 @@ populate_module(PyObject *m, object_adder add_object)
return -1; return -1;
ADD_OBJECT(m, "error", VimError); ADD_OBJECT(m, "error", VimError);
ADD_CHECKED_OBJECT(m, "vars", DictionaryNew(&globvardict)); ADD_CHECKED_OBJECT(m, "vars", NEW_DICTIONARY(&globvardict));
ADD_CHECKED_OBJECT(m, "vvars", DictionaryNew(&vimvardict)); ADD_CHECKED_OBJECT(m, "vvars", NEW_DICTIONARY(&vimvardict));
ADD_CHECKED_OBJECT(m, "options", ADD_CHECKED_OBJECT(m, "options",
OptionsNew(SREQ_GLOBAL, NULL, dummy_check, NULL)); OptionsNew(SREQ_GLOBAL, NULL, dummy_check, NULL));
return 0; return 0;

View File

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

View File

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

View File

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

View File

@ -4,13 +4,29 @@ start:
Vim(put):E684: Vim(put):E684:
[0, 'as''d', [1, 2, function('strlen'), {'a': 1}]] [0, 'as''d', [1, 2, function('strlen'), {'a': 1}]]
[0, function('strlen'), [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} '-1' : {'a': 1}
'0' : -1
'1' : 'asd' '1' : 'asd'
'b' : [1, 2, function('strlen')] 'b' : [1, 2, function('strlen')]
[0, function('strlen')] [0, function('strlen')]
[3] [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, 2, 3] [0, 1, 2, 3]
[0, 1, 3] [0, 1, 3]
@ -44,6 +60,8 @@ TypeError
ValueError ValueError
TypeError TypeError
TypeError TypeError
KeyError
KeyError
d : locked:0;scope:0 d : locked:0;scope:0
dl : locked:1;scope:0 dl : locked:1;scope:0
v: : locked:2;scope:1 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 window:__dir__,__members__,buffer,col,cursor,height,number,options,row,tabpage,valid,vars
tabpage:__dir__,__members__,number,valid,vars,window,windows tabpage:__dir__,__members__,number,valid,vars,window,windows
range:__dir__,__members__,append,end,start 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 list:__dir__,__members__,extend,locked
function:__call__,__dir__,__members__,softspace function:__call__,__dir__,__members__,softspace
output:__dir__,__members__,flush,softspace,write,writelines output:__dir__,__members__,flush,softspace,write,writelines
{}
{'a': 1}
{'a': 1}
' '
abcdef abcdef
line : line :
@ -398,6 +419,7 @@ abcdef
abc abc
line : line :
abc' abc'
['a', 'dup_a']
(<class 'vim.error'>, error('abc',)) (<class 'vim.error'>, error('abc',))
(<class 'vim.error'>, error('def',)) (<class 'vim.error'>, error('def',))
(<class 'vim.error'>, error('ghi',)) (<class 'vim.error'>, error('ghi',))

View File

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

View File

@ -4,13 +4,29 @@ start:
Vim(put):E684: Vim(put):E684:
[0, 'as''d', [1, 2, function('strlen'), {'a': 1}]] [0, 'as''d', [1, 2, function('strlen'), {'a': 1}]]
[0, function('strlen'), [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} '-1' : {'a': 1}
'0' : -1
'1' : 'asd' '1' : 'asd'
'b' : [1, 2, function('strlen')] 'b' : [1, 2, function('strlen')]
[0, function('strlen')] [0, function('strlen')]
[3] [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, 2, 3] [0, 1, 2, 3]
[0, 1, 3] [0, 1, 3]
@ -44,6 +60,8 @@ TypeError
ValueError ValueError
TypeError TypeError
TypeError TypeError
KeyError
KeyError
d : locked:0;scope:0 d : locked:0;scope:0
dl : locked:1;scope:0 dl : locked:1;scope:0
v: : locked:2;scope:1 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 window:__dir__,buffer,col,cursor,height,number,options,row,tabpage,valid,vars
tabpage:__dir__,number,valid,vars,window,windows tabpage:__dir__,number,valid,vars,window,windows
range:__dir__,append,end,start 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 list:__dir__,extend,locked
function:__call__,__dir__,softspace function:__call__,__dir__,softspace
output:__dir__,flush,softspace,write,writelines output:__dir__,flush,softspace,write,writelines
{}
{'a': 1}
{'a': 1}
' '
abcdef abcdef
line : line :
@ -387,6 +408,7 @@ abcdef
abc abc
line : line :
abc' abc'
['a', 'dup_a']
(<class 'vim.error'>, error('abc',)) (<class 'vim.error'>, error('abc',))
(<class 'vim.error'>, error('def',)) (<class 'vim.error'>, error('def',))
(<class 'vim.error'>, error('ghi',)) (<class 'vim.error'>, error('ghi',))

View File

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