diff --git a/7.3.1061 b/7.3.1061 new file mode 100644 index 0000000..a263d65 --- /dev/null +++ b/7.3.1061 @@ -0,0 +1,1964 @@ +To: vim_dev@googlegroups.com +Subject: Patch 7.3.1061 +Fcc: outbox +From: Bram Moolenaar +Mime-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +------------ + +Patch 7.3.1061 +Problem: Python: Dictionary is not standard. +Solution: Python patch 20: Add standard methods and fields. (ZyX) +Files: runtime/doc/if_pyth.txt, src/eval.c, src/if_py_both.h, + src/if_python3.c, src/if_python.c, src/proto/eval.pro, + src/testdir/test86.in, src/testdir/test86.ok, + src/testdir/test87.in, src/testdir/test87.ok + + +*** ../vim-7.3.1060/runtime/doc/if_pyth.txt 2013-05-29 22:02:18.000000000 +0200 +--- runtime/doc/if_pyth.txt 2013-05-30 12:47:48.000000000 +0200 +*************** +*** 12,20 **** + 4. Range objects |python-range| + 5. Window objects |python-window| + 6. Tab page objects |python-tabpage| +! 7. pyeval(), py3eval() Vim functions |python-pyeval| +! 8. Dynamic loading |python-dynamic| +! 9. Python 3 |python3| + + {Vi does not have any of these commands} + +--- 12,21 ---- + 4. Range objects |python-range| + 5. Window objects |python-window| + 6. Tab page objects |python-tabpage| +! 7. vim.bindeval objects |python-bindeval-objects| +! 8. pyeval(), py3eval() Vim functions |python-pyeval| +! 9. Dynamic loading |python-dynamic| +! 10. Python 3 |python3| + + {Vi does not have any of these commands} + +*************** +*** 171,217 **** + 'eval_expr', 'kind': 'f', 'filename': './src/eval.c'}] + + vim.bindeval(str) *python-bindeval* +! Like |python-eval|, but +! 1. if expression evaluates to |List| or |Dictionary| it is returned as +! vimlist or vimdictionary python type that are connected to original +! 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 + +--- 172,180 ---- + 'eval_expr', 'kind': 'f', 'filename': './src/eval.c'}] + + vim.bindeval(str) *python-bindeval* +! Like |python-eval|, but returns special objects described in +! |python-bindeval-objects|. These python objects let you modify (|List| +! or |Dictionary|) or call (|Funcref|) vim objecs. + + Error object of the "vim" module + +*************** +*** 497,509 **** + TabPage object type is available using "TabPage" attribute of vim module. + + ============================================================================== +! 7. pyeval() and py3eval() Vim functions *python-pyeval* + + To facilitate bi-directional interface, you can use |pyeval()| and |py3eval()| + functions to evaluate Python expressions and pass their values to VimL. + + ============================================================================== +! 8. Dynamic loading *python-dynamic* + + On MS-Windows the Python library can be loaded dynamically. The |:version| + output then includes |+python/dyn|. +--- 460,549 ---- + TabPage object type is available using "TabPage" attribute of vim module. + + ============================================================================== +! 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()| + functions to evaluate Python expressions and pass their values to VimL. + + ============================================================================== +! 9. Dynamic loading *python-dynamic* + + On MS-Windows the Python library can be loaded dynamically. The |:version| + output then includes |+python/dyn|. +*************** +*** 520,526 **** + sure edit "gvim.exe" and search for "python\d*.dll\c". + + ============================================================================== +! 9. Python 3 *python3* + + *:py3* *:python3* + The `:py3` and `:python3` commands work similar to `:python`. A simple check +--- 560,566 ---- + sure edit "gvim.exe" and search for "python\d*.dll\c". + + ============================================================================== +! 10. Python 3 *python3* + + *:py3* *:python3* + The `:py3` and `:python3` commands work similar to `:python`. A simple check +*** ../vim-7.3.1060/src/eval.c 2013-05-30 12:35:48.000000000 +0200 +--- src/eval.c 2013-05-30 12:52:11.000000000 +0200 +*************** +*** 10157,10162 **** +--- 10157,10218 ---- + } + + /* ++ * 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,10217 **** + } + 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; + + d1 = argvars[0].vval.v_dict; + d2 = argvars[1].vval.v_dict; +--- 10262,10270 ---- + } + else if (argvars[0].v_type == VAR_DICT && argvars[1].v_type == VAR_DICT) + { +! dict_T *d1, *d2; +! char_u *action; +! int i; + + d1 = argvars[0].vval.v_dict; + d2 = argvars[1].vval.v_dict; +*************** +*** 10238,10283 **** + 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); +! } +! } +! } + + copy_tv(&argvars[0], rettv); + } +--- 10291,10297 ---- + else + action = (char_u *)"force"; + +! dict_extend(d1, d2, action); + + copy_tv(&argvars[0], rettv); + } +*** ../vim-7.3.1060/src/if_py_both.h 2013-05-30 12:43:50.000000000 +0200 +--- src/if_py_both.h 2013-05-30 12:52:42.000000000 +0200 +*************** +*** 31,37 **** + #define INVALID_TABPAGE_VALUE ((tabpage_T *)(-1)) + + #define DICTKEY_DECL \ +! PyObject *dictkey_todecref; + #define DICTKEY_CHECK_EMPTY(err) \ + if (*key == NUL) \ + { \ +--- 31,37 ---- + #define INVALID_TABPAGE_VALUE ((tabpage_T *)(-1)) + + #define DICTKEY_DECL \ +! PyObject *dictkey_todecref = NULL; + #define DICTKEY_CHECK_EMPTY(err) \ + if (*key == NUL) \ + { \ +*************** +*** 63,68 **** +--- 63,69 ---- + + 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,888 **** + pylinkedlist_T ref; + } DictionaryObject; + + static PyObject * +! DictionaryNew(dict_T *dict) + { + DictionaryObject *self; + +! self = PyObject_NEW(DictionaryObject, &DictionaryType); + if (self == NULL) + return NULL; + self->dict = dict; +--- 878,893 ---- + pylinkedlist_T ref; + } DictionaryObject; + ++ static PyObject *DictionaryUpdate(DictionaryObject *, PyObject *, PyObject *); ++ ++ #define NEW_DICTIONARY(dict) DictionaryNew(&DictionaryType, dict) ++ + static PyObject * +! DictionaryNew(PyTypeObject *subtype, dict_T *dict) + { + DictionaryObject *self; + +! self = (DictionaryObject *) subtype->tp_alloc(subtype, 0); + if (self == NULL) + return NULL; + self->dict = dict; +*************** +*** 893,898 **** +--- 898,946 ---- + 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); ++ } ++ + static void + DictionaryDestructor(DictionaryObject *self) + { +*************** +*** 918,924 **** + { + if (val == NULL) + { +! PyErr_SetString(PyExc_AttributeError, _("Cannot delete DictionaryObject attributes")); + return -1; + } + +--- 966,973 ---- + { + if (val == NULL) + { +! PyErr_SetString(PyExc_AttributeError, +! _("cannot delete vim.Dictionary attributes")); + return -1; + } + +*************** +*** 926,932 **** + { + if (self->dict->dv_lock == VAR_FIXED) + { +! PyErr_SetString(PyExc_TypeError, _("Cannot modify fixed dictionary")); + return -1; + } + else +--- 975,981 ---- + { + if (self->dict->dv_lock == VAR_FIXED) + { +! PyErr_SetString(PyExc_TypeError, _("cannot modify fixed dictionary")); + return -1; + } + else +*************** +*** 943,949 **** + } + else + { +! PyErr_SetString(PyExc_AttributeError, _("Cannot set this attribute")); + return -1; + } + } +--- 992,998 ---- + } + else + { +! PyErr_SetString(PyExc_AttributeError, _("cannot set this attribute")); + return -1; + } + } +*************** +*** 954,979 **** + return ((PyInt) (self->dict->dv_hashtab.ht_used)); + } + + static PyObject * +! DictionaryItem(DictionaryObject *self, PyObject *keyObject) + { + char_u *key; + dictitem_T *di; + DICTKEY_DECL + + DICTKEY_GET(NULL, 0) + +! di = dict_find(self->dict, key, -1); + + DICTKEY_UNREF + +! if (di == NULL) + { +! PyErr_SetObject(PyExc_KeyError, keyObject); + return NULL; + } + +! return ConvertToPyObject(&di->di_tv); + } + + static PyInt +--- 1003,1172 ---- + 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 *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) + +! hi = hash_find(&dict->dv_hashtab, key); + + DICTKEY_UNREF + +! if (HASHITEM_EMPTY(hi)) + { +! 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; +! } +! +! 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,1033 **** + + if (di == NULL) + { +! di = dictitem_alloc(key); +! if (di == NULL) + { + PyErr_NoMemory(); + return -1; + } + di->di_tv.v_lock = 0; + + if (dict_add(dict, di) == FAIL) + { + DICTKEY_UNREF + vim_free(di); + PyErr_SetVim(_("failed to add key to dictionary")); + return -1; + } +--- 1209,1227 ---- + + 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,1062 **** + return 0; + } + + static PyObject * +! DictionaryListKeys(DictionaryObject *self) + { + dict_T *dict = self->dict; + long_u todo = dict->dv_hashtab.ht_used; + Py_ssize_t i = 0; + PyObject *r; + hashitem_T *hi; + + 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))); + --todo; + ++i; + } +--- 1236,1269 ---- + return 0; + } + ++ typedef PyObject *(*hi_to_py)(hashitem_T *); ++ + static PyObject * +! 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)) + { +! 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,1069 **** +--- 1271,1505 ---- + 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,1077 **** +--- 1508,1520 ---- + + 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,1554 **** + 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) + { + clear_tv(&args); + return NULL; +--- 1984,1990 ---- + selfdictObject = PyDict_GetItemString(kwargs, "self"); + if (selfdictObject != NULL) + { +! if (ConvertFromPyMapping(selfdictObject, &selfdicttv) == -1) + { + clear_tv(&args); + return NULL; +*************** +*** 1994,2000 **** + 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); + else if (strcmp(name, "window") == 0) + { + /* For current tab window.c does not bother to set or update tp_curwin +--- 2430,2436 ---- + else if (strcmp(name, "number") == 0) + return PyLong_FromLong((long) get_tab_number(self->tab)); + else if (strcmp(name, "vars") == 0) +! 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,2231 **** + return PyLong_FromLong((long)(W_WINCOL(self->win))); + #endif + else if (strcmp(name, "vars") == 0) +! return DictionaryNew(self->win->w_vars); + else if (strcmp(name, "options") == 0) + return OptionsNew(SREQ_WIN, self->win, (checkfun) CheckWindow, + (PyObject *) self); +--- 2661,2667 ---- + return PyLong_FromLong((long)(W_WINCOL(self->win))); + #endif + else if (strcmp(name, "vars") == 0) +! return NEW_DICTIONARY(self->win->w_vars); + else if (strcmp(name, "options") == 0) + return OptionsNew(SREQ_WIN, self->win, (checkfun) CheckWindow, + (PyObject *) self); +*************** +*** 3402,3408 **** + 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); + else if (strcmp(name, "options") == 0) + return OptionsNew(SREQ_BUF, self->buf, (checkfun) CheckBuffer, + (PyObject *) self); +--- 3838,3844 ---- + else if (strcmp(name, "number") == 0) + return Py_BuildValue(Py_ssize_t_fmt, self->buf->b_fnum); + else if (strcmp(name, "vars") == 0) +! return NEW_DICTIONARY(self->buf->b_vars); + else if (strcmp(name, "options") == 0) + return OptionsNew(SREQ_BUF, self->buf, (checkfun) CheckBuffer, + (PyObject *) self); +*************** +*** 4307,4312 **** +--- 4743,4778 ---- + } + + 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) + { + PyObject *lookup_dict; +*************** +*** 4322,4328 **** + static int + _ConvertFromPyObject(PyObject *obj, typval_T *tv, PyObject *lookup_dict) + { +! if (obj->ob_type == &DictionaryType) + { + tv->v_type = VAR_DICT; + tv->vval.v_dict = (((DictionaryObject *)(obj))->dict); +--- 4788,4794 ---- + static int + _ConvertFromPyObject(PyObject *obj, typval_T *tv, PyObject *lookup_dict) + { +! if (PyType_IsSubtype(obj->ob_type, &DictionaryType)) + { + tv->v_type = VAR_DICT; + tv->vval.v_dict = (((DictionaryObject *)(obj))->dict); +*************** +*** 4437,4443 **** + case VAR_LIST: + return ListNew(tv->vval.v_list); + case VAR_DICT: +! return DictionaryNew(tv->vval.v_dict); + case VAR_FUNC: + return FunctionNew(tv->vval.v_string == NULL + ? (char_u *)"" : tv->vval.v_string); +--- 4903,4909 ---- + case VAR_LIST: + return ListNew(tv->vval.v_list); + case VAR_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,4617 **** + DictionaryType.tp_name = "vim.dictionary"; + DictionaryType.tp_basicsize = sizeof(DictionaryObject); + DictionaryType.tp_dealloc = (destructor)DictionaryDestructor; + DictionaryType.tp_as_mapping = &DictionaryAsMapping; +! DictionaryType.tp_flags = Py_TPFLAGS_DEFAULT; + DictionaryType.tp_doc = "dictionary pushing modifications to vim structure"; + DictionaryType.tp_methods = DictionaryMethods; + #if PY_MAJOR_VERSION >= 3 + DictionaryType.tp_getattro = (getattrofunc)DictionaryGetattro; + DictionaryType.tp_setattro = (setattrofunc)DictionarySetattro; +--- 5074,5087 ---- + 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|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,4793 **** + 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, "options", + OptionsNew(SREQ_GLOBAL, NULL, dummy_check, NULL)); + return 0; +--- 5256,5263 ---- + return -1; + ADD_OBJECT(m, "error", VimError); + +! 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; +*** ../vim-7.3.1060/src/if_python3.c 2013-05-30 12:40:36.000000000 +0200 +--- src/if_python3.c 2013-05-30 12:47:48.000000000 +0200 +*************** +*** 96,101 **** +--- 96,102 ---- + #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,154 **** +--- 150,156 ---- + # 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,173 **** +--- 170,176 ---- + #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,274 **** +--- 272,278 ---- + 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,287 **** +--- 286,292 ---- + 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,430 **** +--- 430,436 ---- + {"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,440 **** +--- 441,447 ---- + {"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}, +*** ../vim-7.3.1060/src/if_python.c 2013-05-30 12:40:36.000000000 +0200 +--- src/if_python.c 2013-05-30 12:48:47.000000000 +0200 +*************** +*** 103,108 **** +--- 103,109 ---- + # define PyIntIntObjArgProc intintobjargproc + # define Py_ssize_t_fmt "i" + #endif ++ #define Py_bytes_fmt "s" + + /* Parser flags */ + #define single_input 256 +*************** +*** 187,192 **** +--- 188,194 ---- + # 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,212 **** +--- 209,215 ---- + # 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,232 **** +--- 230,236 ---- + # 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,323 **** +--- 322,328 ---- + 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,341 **** +--- 341,347 ---- + 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,359 **** +--- 360,366 ---- + 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,483 **** + {"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}, + {"PyTuple_GetItem", (PYTHON_PROC*)&dll_PyTuple_GetItem}, + {"PyTuple_Size", (PYTHON_PROC*)&dll_PyTuple_Size}, + {"PyTuple_Type", (PYTHON_PROC*)&dll_PyTuple_Type}, +--- 482,491 ---- + {"PyList_SetItem", (PYTHON_PROC*)&dll_PyList_SetItem}, + {"PyList_Size", (PYTHON_PROC*)&dll_PyList_Size}, + {"PyList_Type", (PYTHON_PROC*)&dll_PyList_Type}, + {"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,501 **** +--- 504,510 ---- + {"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,519 **** +--- 523,529 ---- + {"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,1125 **** + (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 +--- 1126,1133 ---- +*** ../vim-7.3.1060/src/proto/eval.pro 2013-05-30 12:35:48.000000000 +0200 +--- src/proto/eval.pro 2013-05-30 12:47:48.000000000 +0200 +*************** +*** 75,80 **** +--- 75,81 ---- + 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)); +*** ../vim-7.3.1060/src/testdir/test86.in 2013-05-30 12:26:52.000000000 +0200 +--- src/testdir/test86.in 2013-05-30 12:47:48.000000000 +0200 +*************** +*** 31,46 **** + :" + :" 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) + :for [key, val] in sort(items(d)) + : $put =string(key) . ' : ' . string(val) + : unlet key val +--- 31,52 ---- + :" + :" Extending Dictionary directly with different types + :let d = {} +! 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,66 **** +--- 66,85 ---- + :$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,203 **** +--- 217,225 ---- + 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,714 **** +--- 731,740 ---- + 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,723 **** +--- 744,759 ---- + :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) +*** ../vim-7.3.1060/src/testdir/test86.ok 2013-05-30 12:26:52.000000000 +0200 +--- src/testdir/test86.ok 2013-05-30 12:47:48.000000000 +0200 +*************** +*** 4,16 **** + 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' : {'a': 1} + '1' : 'asd' + 'b' : [1, 2, function('strlen')] + [0, function('strlen')] + [3] +! {'1': 'asd', 'b': [1, 2, function('strlen')]} + [0, 1, 2, 3] + [0, 1, 2, 3] + [0, 1, 3] +--- 4,32 ---- + Vim(put):E684: + [0, 'as''d', [1, 2, function('strlen'), {'a': 1}]] + [0, function('strlen'), [1, 2, function('strlen'), {'a': 1}]] +! ['-1', '0', '1', 'b'] +! ['asd', -1L, , ] +! [('-1', ), ('0', -1L), ('1', 'asd'), ('b', )] + '-1' : {'a': 1} ++ '0' : -1 + '1' : 'asd' + 'b' : [1, 2, function('strlen')] + [0, function('strlen')] + [3] +! [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,49 **** +--- 60,67 ---- + ValueError + TypeError + TypeError ++ KeyError ++ KeyError + d : locked:0;scope:0 + dl : locked:1;scope:0 + v: : locked:2;scope:1 +*************** +*** 387,396 **** + 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 + list:__dir__,__members__,extend,locked + function:__call__,__dir__,__members__,softspace + output:__dir__,__members__,flush,softspace,write,writelines + ' + abcdef + line : +--- 405,417 ---- + 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__,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,403 **** +--- 419,425 ---- + abc + line : + abc' ++ ['a', 'dup_a'] + (, error('abc',)) + (, error('def',)) + (, error('ghi',)) +*** ../vim-7.3.1060/src/testdir/test87.in 2013-05-30 12:26:52.000000000 +0200 +--- src/testdir/test87.in 2013-05-30 12:47:48.000000000 +0200 +*************** +*** 26,41 **** + :" + :" 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) + :for [key, val] in sort(items(d)) + : $put =string(key) . ' : ' . string(val) + : unlet key val +--- 26,47 ---- + :" + :" Extending Dictionary directly with different types + :let d = {} +! 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,61 **** +--- 61,80 ---- + :$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,215 **** + :py3 < messages +*************** +*** 696,701 **** +--- 705,720 ---- + :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) +*** ../vim-7.3.1060/src/testdir/test87.ok 2013-05-30 12:26:52.000000000 +0200 +--- src/testdir/test87.ok 2013-05-30 12:47:48.000000000 +0200 +*************** +*** 4,16 **** + 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' : {'a': 1} + '1' : 'asd' + 'b' : [1, 2, function('strlen')] + [0, function('strlen')] + [3] +! {'1': 'asd', 'b': [1, 2, function('strlen')]} + [0, 1, 2, 3] + [0, 1, 2, 3] + [0, 1, 3] +--- 4,32 ---- + Vim(put):E684: + [0, 'as''d', [1, 2, function('strlen'), {'a': 1}]] + [0, function('strlen'), [1, 2, function('strlen'), {'a': 1}]] +! [b'-1', b'0', b'1', b'b'] +! [-1, , , b'asd'] +! [(b'-1', ), (b'0', -1), (b'1', b'asd'), (b'b', )] + '-1' : {'a': 1} ++ '0' : -1 + '1' : 'asd' + 'b' : [1, 2, function('strlen')] + [0, function('strlen')] + [3] +! [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,49 **** +--- 60,67 ---- + ValueError + TypeError + TypeError ++ KeyError ++ KeyError + d : locked:0;scope:0 + dl : locked:1;scope:0 + v: : locked:2;scope:1 +*************** +*** 376,385 **** + 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 + list:__dir__,extend,locked + function:__call__,__dir__,softspace + output:__dir__,flush,softspace,write,writelines + ' + abcdef + line : +--- 394,406 ---- + 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__,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,392 **** +--- 408,414 ---- + abc + line : + abc' ++ ['a', 'dup_a'] + (, error('abc',)) + (, error('def',)) + (, error('ghi',)) +*** ../vim-7.3.1060/src/version.c 2013-05-30 12:43:50.000000000 +0200 +--- src/version.c 2013-05-30 12:59:48.000000000 +0200 +*************** +*** 730,731 **** +--- 730,733 ---- + { /* Add new patch number below this line */ ++ /**/ ++ 1061, + /**/ + +-- +How To Keep A Healthy Level Of Insanity: +4. Put your garbage can on your desk and label it "in". + + /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ +/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ +\\\ an exciting new programming language -- http://www.Zimbu.org /// + \\\ help me help AIDS victims -- http://ICCF-Holland.org ///