changeset 4319:b79f3c3a584c v7.3.909

updated for version 7.3.909 Problem: Duplicate Python code. Solution: Move more items to if_py_both.h. (ZyX) Also avoid compiler warnings for missing initializers.
author Bram Moolenaar <bram@vim.org>
date Wed, 24 Apr 2013 13:39:15 +0200
parents f19b589e1e8d
children 4c7931bbf78a
files src/if_py_both.h src/if_python.c src/if_python3.c src/version.c
diffstat 4 files changed, 503 insertions(+), 775 deletions(-) [+]
line wrap: on
line diff
--- a/src/if_py_both.h
+++ b/src/if_py_both.h
@@ -542,6 +542,14 @@ typedef struct
  * Buffer list object - Implementation
  */
 
+typedef struct
+{
+    PyObject_HEAD
+} BufListObject;
+
+static PyTypeObject BufListType;
+static PySequenceMethods WinListAsSeq;
+
     static PyInt
 BufListLength(PyObject *self UNUSED)
 {
@@ -578,6 +586,11 @@ typedef struct
     win_T	*win;
 } WindowObject;
 
+static struct PyMethodDef WindowMethods[] = {
+    /* name,	    function,		calling,    documentation */
+    { NULL,	    NULL,		0,	    NULL }
+};
+
 static int ConvertFromPyObject(PyObject *, typval_T *);
 static int _ConvertFromPyObject(PyObject *, typval_T *, PyObject *);
 
@@ -642,6 +655,16 @@ typedef struct
     pylinkedlist_T	ref;
 } DictionaryObject;
 
+static PyInt DictionaryAssItem(PyObject *, PyObject *, PyObject *);
+static PyInt DictionaryLength(PyObject *);
+static PyObject *DictionaryItem(PyObject *, PyObject *);
+
+static PyMappingMethods DictionaryAsMapping = {
+    (lenfunc)       DictionaryLength,
+    (binaryfunc)    DictionaryItem,
+    (objobjargproc) DictionaryAssItem,
+};
+
     static PyObject *
 DictionaryNew(dict_T *dict)
 {
@@ -658,6 +681,17 @@ DictionaryNew(dict_T *dict)
     return (PyObject *)(self);
 }
 
+    static void
+DictionaryDestructor(PyObject *self)
+{
+    DictionaryObject	*this = ((DictionaryObject *) (self));
+
+    pyll_remove(&this->ref, &lastdict);
+    dict_unref(this->dict);
+
+    DESTRUCTOR_FINISH(self);
+}
+
     static int
 pydict_to_tv(PyObject *obj, typval_T *tv, PyObject *lookupDict)
 {
@@ -804,9 +838,11 @@ pymap_to_tv(PyObject *obj, typval_T *tv,
     return 0;
 }
 
-    static PyInt
-DictionarySetattr(DictionaryObject *self, char *name, PyObject *val)
+    static int
+DictionarySetattr(PyObject *self, char *name, PyObject *val)
 {
+    DictionaryObject *this = (DictionaryObject *)(self);
+
     if (val == NULL)
     {
 	PyErr_SetString(PyExc_AttributeError, _("Cannot delete DictionaryObject attributes"));
@@ -815,7 +851,7 @@ DictionarySetattr(DictionaryObject *self
 
     if (strcmp(name, "locked") == 0)
     {
-	if (self->dict->dv_lock == VAR_FIXED)
+	if (this->dict->dv_lock == VAR_FIXED)
 	{
 	    PyErr_SetString(PyExc_TypeError, _("Cannot modify fixed dictionary"));
 	    return -1;
@@ -829,9 +865,9 @@ DictionarySetattr(DictionaryObject *self
 	    }
 
 	    if (val == Py_True)
-		self->dict->dv_lock = VAR_LOCKED;
+		this->dict->dv_lock = VAR_LOCKED;
 	    else
-		self->dict->dv_lock = 0;
+		this->dict->dv_lock = 0;
 	}
 	return 0;
     }
@@ -963,6 +999,8 @@ static struct PyMethodDef DictionaryMeth
 };
 
 static PyTypeObject ListType;
+static PySequenceMethods ListAsSeq;
+static PyMappingMethods ListAsMapping;
 
 typedef struct
 {
@@ -987,6 +1025,17 @@ ListNew(list_T *list)
     return (PyObject *)(self);
 }
 
+    static void
+ListDestructor(PyObject *self)
+{
+    ListObject *this = (ListObject *)(self);
+
+    pyll_remove(&this->ref, &lastlist);
+    list_unref(this->list);
+
+    DESTRUCTOR_FINISH(self);
+}
+
     static int
 list_py_concat(list_T *l, PyObject *obj, PyObject *lookupDict)
 {
@@ -1307,8 +1356,10 @@ ListConcatInPlace(PyObject *self, PyObje
 }
 
     static int
-ListSetattr(ListObject *self, char *name, PyObject *val)
+ListSetattr(PyObject *self, char *name, PyObject *val)
 {
+    ListObject *this = (ListObject *)(self);
+
     if (val == NULL)
     {
 	PyErr_SetString(PyExc_AttributeError, _("Cannot delete DictionaryObject attributes"));
@@ -1317,7 +1368,7 @@ ListSetattr(ListObject *self, char *name
 
     if (strcmp(name, "locked") == 0)
     {
-	if (self->list->lv_lock == VAR_FIXED)
+	if (this->list->lv_lock == VAR_FIXED)
 	{
 	    PyErr_SetString(PyExc_TypeError, _("Cannot modify fixed list"));
 	    return -1;
@@ -1331,9 +1382,9 @@ ListSetattr(ListObject *self, char *name
 	    }
 
 	    if (val == Py_True)
-		self->list->lv_lock = VAR_LOCKED;
+		this->list->lv_lock = VAR_LOCKED;
 	    else
-		self->list->lv_lock = 0;
+		this->list->lv_lock = 0;
 	}
 	return 0;
     }
@@ -1376,6 +1427,17 @@ FunctionNew(char_u *name)
     return (PyObject *)(self);
 }
 
+    static void
+FunctionDestructor(PyObject *self)
+{
+    FunctionObject	*this = (FunctionObject *) (self);
+
+    func_unref(this->name);
+    PyMem_Del(this->name);
+
+    DESTRUCTOR_FINISH(self);
+}
+
     static PyObject *
 FunctionCall(PyObject *self, PyObject *argsObject, PyObject *kwargs)
 {
@@ -1451,6 +1513,45 @@ CheckWindow(WindowObject *this)
 
 static int WindowSetattr(PyObject *, char *, PyObject *);
 static PyObject *WindowRepr(PyObject *);
+static PyTypeObject WindowType;
+
+    static PyObject *
+WindowAttr(WindowObject *this, char *name)
+{
+    if (strcmp(name, "buffer") == 0)
+	return (PyObject *)BufferNew(this->win->w_buffer);
+    else if (strcmp(name, "cursor") == 0)
+    {
+	pos_T *pos = &this->win->w_cursor;
+
+	return Py_BuildValue("(ll)", (long)(pos->lnum), (long)(pos->col));
+    }
+    else if (strcmp(name, "height") == 0)
+	return Py_BuildValue("l", (long)(this->win->w_height));
+#ifdef FEAT_VERTSPLIT
+    else if (strcmp(name, "width") == 0)
+	return Py_BuildValue("l", (long)(W_WIDTH(this->win)));
+#endif
+    else if (strcmp(name,"__members__") == 0)
+	return Py_BuildValue("[sss]", "buffer", "cursor", "height");
+    else
+	return NULL;
+}
+
+    static void
+WindowDestructor(PyObject *self)
+{
+    WindowObject *this = (WindowObject *)(self);
+
+    if (this->win && this->win != INVALID_WINDOW_VALUE)
+#if PY_MAJOR_VERSION >= 3
+	this->win->w_python3_ref = NULL;
+#else
+	this->win->w_python_ref = NULL;
+#endif
+
+    DESTRUCTOR_FINISH(self);
+}
 
     static int
 WindowSetattr(PyObject *self, char *name, PyObject *val)
@@ -1579,6 +1680,15 @@ WindowRepr(PyObject *self)
 /*
  * Window list object - Implementation
  */
+
+typedef struct
+{
+    PyObject_HEAD
+} WinListObject;
+
+static PyTypeObject WinListType;
+static PySequenceMethods BufListAsSeq;
+
     static PyInt
 WinListLength(PyObject *self UNUSED)
 {
@@ -2310,10 +2420,11 @@ RBAppend(BufferObject *self, PyObject *a
     return Py_None;
 }
 
-
-/* Buffer object - Definitions
+/* Range object - Definitions
  */
 
+static PyTypeObject RangeType;
+
 typedef struct
 {
     PyObject_HEAD
@@ -2322,6 +2433,10 @@ typedef struct
     PyInt end;
 } RangeObject;
 
+static void RangeDestructor(PyObject *);
+static PySequenceMethods RangeAsSeq;
+static PyMappingMethods RangeAsMapping;
+
     static PyObject *
 RangeNew(buf_T *buf, PyInt start, PyInt end)
 {
@@ -2346,6 +2461,46 @@ RangeNew(buf_T *buf, PyInt start, PyInt 
     return (PyObject *)(self);
 }
 
+    static void
+RangeDestructor(PyObject *self)
+{
+    Py_DECREF(((RangeObject *)(self))->buf);
+    DESTRUCTOR_FINISH(self);
+}
+
+static PyTypeObject BufferType;
+static PyObject *BufferRepr(PyObject *);
+static PySequenceMethods BufferAsSeq;
+static PyMappingMethods BufferAsMapping;
+
+    static void
+BufferDestructor(PyObject *self)
+{
+    BufferObject *this = (BufferObject *)(self);
+
+    if (this->buf && this->buf != INVALID_BUFFER_VALUE)
+#if PY_MAJOR_VERSION >= 3
+	this->buf->b_python3_ref = NULL;
+#else
+	this->buf->b_python_ref = NULL;
+#endif
+
+    DESTRUCTOR_FINISH(self);
+}
+
+    static PyObject *
+BufferAttr(BufferObject *this, char *name)
+{
+    if (strcmp(name, "name") == 0)
+	return Py_BuildValue("s", this->buf->b_ffname);
+    else if (strcmp(name, "number") == 0)
+	return Py_BuildValue(Py_ssize_t_fmt, this->buf->b_fnum);
+    else if (strcmp(name,"__members__") == 0)
+	return Py_BuildValue("[ss]", "name", "number");
+    else
+	return NULL;
+}
+
     static PyObject *
 BufferAppend(PyObject *self, PyObject *args)
 {
@@ -2409,6 +2564,35 @@ BufferRange(PyObject *self, PyObject *ar
     return RangeNew(((BufferObject *)(self))->buf, start, end);
 }
 
+    static PyObject *
+BufferRepr(PyObject *self)
+{
+    static char repr[100];
+    BufferObject *this = (BufferObject *)(self);
+
+    if (this->buf == INVALID_BUFFER_VALUE)
+    {
+	vim_snprintf(repr, 100, _("<buffer object (deleted) at %p>"), (self));
+	return PyString_FromString(repr);
+    }
+    else
+    {
+	char *name = (char *)this->buf->b_fname;
+	PyInt len;
+
+	if (name == NULL)
+	    name = "";
+	len = strlen(name);
+
+	if (len > 35)
+	    name = name + (35 - len);
+
+	vim_snprintf(repr, 100, "<buffer %s%s>", len > 35 ? "..." : "", name);
+
+	return PyString_FromString(repr);
+    }
+}
+
 static struct PyMethodDef BufferMethods[] = {
     /* name,	    function,		calling,    documentation */
     {"append",	    BufferAppend,	1,	    "Append data to Vim buffer" },
@@ -2497,6 +2681,49 @@ static struct PyMethodDef RangeMethods[]
     { NULL,	    NULL,		0,	    NULL }
 };
 
+/* Current items object - Implementation
+ */
+
+static PyInt RangeStart;
+static PyInt RangeEnd;
+
+    static PyObject *
+CurrentGetattr(PyObject *self UNUSED, char *name)
+{
+    if (strcmp(name, "buffer") == 0)
+	return (PyObject *)BufferNew(curbuf);
+    else if (strcmp(name, "window") == 0)
+	return (PyObject *)WindowNew(curwin);
+    else if (strcmp(name, "line") == 0)
+	return GetBufferLine(curbuf, (PyInt)curwin->w_cursor.lnum);
+    else if (strcmp(name, "range") == 0)
+	return RangeNew(curbuf, RangeStart, RangeEnd);
+    else if (strcmp(name,"__members__") == 0)
+	return Py_BuildValue("[ssss]", "buffer", "window", "line", "range");
+    else
+    {
+	PyErr_SetString(PyExc_AttributeError, name);
+	return NULL;
+    }
+}
+
+    static int
+CurrentSetattr(PyObject *self UNUSED, char *name, PyObject *value)
+{
+    if (strcmp(name, "line") == 0)
+    {
+	if (SetBufferLine(curbuf, (PyInt)curwin->w_cursor.lnum, value, NULL) == FAIL)
+	    return -1;
+
+	return 0;
+    }
+    else
+    {
+	PyErr_SetString(PyExc_AttributeError, name);
+	return -1;
+    }
+}
+
     static void
 set_ref_in_py(const int copyID)
 {
@@ -2770,3 +2997,169 @@ ConvertToPyObject(typval_T *tv)
 	    return NULL;
     }
 }
+
+typedef struct
+{
+    PyObject_HEAD
+} CurrentObject;
+static PyTypeObject CurrentType;
+
+    static void
+init_structs(void)
+{
+    vim_memset(&OutputType, 0, sizeof(OutputType));
+    OutputType.tp_name = "vim.message";
+    OutputType.tp_basicsize = sizeof(OutputObject);
+    OutputType.tp_flags = Py_TPFLAGS_DEFAULT;
+    OutputType.tp_doc = "vim message object";
+    OutputType.tp_methods = OutputMethods;
+#if PY_MAJOR_VERSION >= 3
+    OutputType.tp_getattro = OutputGetattro;
+    OutputType.tp_setattro = OutputSetattro;
+    OutputType.tp_alloc = call_PyType_GenericAlloc;
+    OutputType.tp_new = call_PyType_GenericNew;
+    OutputType.tp_free = call_PyObject_Free;
+#else
+    OutputType.tp_getattr = OutputGetattr;
+    OutputType.tp_setattr = OutputSetattr;
+#endif
+
+    vim_memset(&BufferType, 0, sizeof(BufferType));
+    BufferType.tp_name = "vim.buffer";
+    BufferType.tp_basicsize = sizeof(BufferType);
+    BufferType.tp_dealloc = BufferDestructor;
+    BufferType.tp_repr = BufferRepr;
+    BufferType.tp_as_sequence = &BufferAsSeq;
+    BufferType.tp_as_mapping = &BufferAsMapping;
+    BufferType.tp_flags = Py_TPFLAGS_DEFAULT;
+    BufferType.tp_doc = "vim buffer object";
+    BufferType.tp_methods = BufferMethods;
+#if PY_MAJOR_VERSION >= 3
+    BufferType.tp_getattro = BufferGetattro;
+    BufferType.tp_alloc = call_PyType_GenericAlloc;
+    BufferType.tp_new = call_PyType_GenericNew;
+    BufferType.tp_free = call_PyObject_Free;
+#else
+    BufferType.tp_getattr = BufferGetattr;
+#endif
+
+    vim_memset(&WindowType, 0, sizeof(WindowType));
+    WindowType.tp_name = "vim.window";
+    WindowType.tp_basicsize = sizeof(WindowObject);
+    WindowType.tp_dealloc = WindowDestructor;
+    WindowType.tp_repr = WindowRepr;
+    WindowType.tp_flags = Py_TPFLAGS_DEFAULT;
+    WindowType.tp_doc = "vim Window object";
+    WindowType.tp_methods = WindowMethods;
+#if PY_MAJOR_VERSION >= 3
+    WindowType.tp_getattro = WindowGetattro;
+    WindowType.tp_setattro = WindowSetattro;
+    WindowType.tp_alloc = call_PyType_GenericAlloc;
+    WindowType.tp_new = call_PyType_GenericNew;
+    WindowType.tp_free = call_PyObject_Free;
+#else
+    WindowType.tp_getattr = WindowGetattr;
+    WindowType.tp_setattr = WindowSetattr;
+#endif
+
+    vim_memset(&BufListType, 0, sizeof(BufListType));
+    BufListType.tp_name = "vim.bufferlist";
+    BufListType.tp_basicsize = sizeof(BufListObject);
+    BufListType.tp_as_sequence = &BufListAsSeq;
+    BufListType.tp_flags = Py_TPFLAGS_DEFAULT;
+    BufferType.tp_doc = "vim buffer list";
+
+    vim_memset(&WinListType, 0, sizeof(WinListType));
+    WinListType.tp_name = "vim.windowlist";
+    WinListType.tp_basicsize = sizeof(WinListType);
+    WinListType.tp_as_sequence = &WinListAsSeq;
+    WinListType.tp_flags = Py_TPFLAGS_DEFAULT;
+    WinListType.tp_doc = "vim window list";
+
+    vim_memset(&RangeType, 0, sizeof(RangeType));
+    RangeType.tp_name = "vim.range";
+    RangeType.tp_basicsize = sizeof(RangeObject);
+    RangeType.tp_dealloc = RangeDestructor;
+    RangeType.tp_repr = RangeRepr;
+    RangeType.tp_as_sequence = &RangeAsSeq;
+    RangeType.tp_as_mapping = &RangeAsMapping;
+    RangeType.tp_flags = Py_TPFLAGS_DEFAULT;
+    RangeType.tp_doc = "vim Range object";
+    RangeType.tp_methods = RangeMethods;
+#if PY_MAJOR_VERSION >= 3
+    RangeType.tp_getattro = RangeGetattro;
+    RangeType.tp_alloc = call_PyType_GenericAlloc;
+    RangeType.tp_new = call_PyType_GenericNew;
+    RangeType.tp_free = call_PyObject_Free;
+#else
+    RangeType.tp_getattr = RangeGetattr;
+#endif
+
+    vim_memset(&CurrentType, 0, sizeof(CurrentType));
+    CurrentType.tp_name = "vim.currentdata";
+    CurrentType.tp_basicsize = sizeof(CurrentObject);
+    CurrentType.tp_flags = Py_TPFLAGS_DEFAULT;
+    CurrentType.tp_doc = "vim current object";
+#if PY_MAJOR_VERSION >= 3
+    CurrentType.tp_getattro = CurrentGetattro;
+    CurrentType.tp_setattro = CurrentSetattro;
+#else
+    CurrentType.tp_getattr = CurrentGetattr;
+    CurrentType.tp_setattr = CurrentSetattr;
+#endif
+
+    vim_memset(&DictionaryType, 0, sizeof(DictionaryType));
+    DictionaryType.tp_name = "vim.dictionary";
+    DictionaryType.tp_basicsize = sizeof(DictionaryObject);
+    DictionaryType.tp_dealloc = 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 = DictionaryGetattro;
+    DictionaryType.tp_setattro = DictionarySetattro;
+#else
+    DictionaryType.tp_getattr = DictionaryGetattr;
+    DictionaryType.tp_setattr = DictionarySetattr;
+#endif
+
+    vim_memset(&ListType, 0, sizeof(ListType));
+    ListType.tp_name = "vim.list";
+    ListType.tp_dealloc = ListDestructor;
+    ListType.tp_basicsize = sizeof(ListObject);
+    ListType.tp_as_sequence = &ListAsSeq;
+    ListType.tp_as_mapping = &ListAsMapping;
+    ListType.tp_flags = Py_TPFLAGS_DEFAULT;
+    ListType.tp_doc = "list pushing modifications to vim structure";
+    ListType.tp_methods = ListMethods;
+#if PY_MAJOR_VERSION >= 3
+    ListType.tp_getattro = ListGetattro;
+    ListType.tp_setattro = ListSetattro;
+#else
+    ListType.tp_getattr = ListGetattr;
+    ListType.tp_setattr = ListSetattr;
+#endif
+
+    vim_memset(&FunctionType, 0, sizeof(FunctionType));
+    FunctionType.tp_name = "vim.list";
+    FunctionType.tp_basicsize = sizeof(FunctionObject);
+    FunctionType.tp_dealloc = FunctionDestructor;
+    FunctionType.tp_call = FunctionCall;
+    FunctionType.tp_flags = Py_TPFLAGS_DEFAULT;
+    FunctionType.tp_doc = "object that calls vim function";
+    FunctionType.tp_methods = FunctionMethods;
+#if PY_MAJOR_VERSION >= 3
+    FunctionType.tp_getattro = FunctionGetattro;
+#else
+    FunctionType.tp_getattr = FunctionGetattr;
+#endif
+
+#if PY_MAJOR_VERSION >= 3
+    vim_memset(&vimmodule, 0, sizeof(vimmodule));
+    vimmodule.m_name = "vim";
+    vimmodule.m_doc = "Vim Python interface\n";
+    vimmodule.m_size = -1;
+    vimmodule.m_methods = VimMethods;
+#endif
+}
--- a/src/if_python.c
+++ b/src/if_python.c
@@ -87,6 +87,7 @@ struct PyMethodDef { Py_ssize_t a; };
 # define Py_ssize_t_fmt "n"
 #else
 # define PyInt int
+# define lenfunc inquiry
 # define PyInquiry inquiry
 # define PyIntArgFunc intargfunc
 # define PyIntIntArgFunc intintargfunc
@@ -600,8 +601,6 @@ static PyObject *WindowNew(win_T *);
 static PyObject *DictionaryNew(dict_T *);
 static PyObject *LineToString(const char *);
 
-static PyTypeObject RangeType;
-
 static int initialised = 0;
 #define PYINITIALISED initialised
 
@@ -617,6 +616,16 @@ static int initialised = 0;
 #define DICTKEY_UNREF
 #define DICTKEY_DECL
 
+#define DESTRUCTOR_FINISH(self) Py_DECREF(self);
+
+static PyObject *OutputGetattr(PyObject *, char *);
+static PyObject *BufferGetattr(PyObject *, char *);
+static PyObject *WindowGetattr(PyObject *, char *);
+static PyObject *RangeGetattr(PyObject *, char *);
+static PyObject *DictionaryGetattr(PyObject *, char*);
+static PyObject *ListGetattr(PyObject *, char *);
+static PyObject *FunctionGetattr(PyObject *, char *);
+
 /*
  * Include the code shared with if_python3.c
  */
@@ -627,9 +636,6 @@ static int initialised = 0;
  * Internal function prototypes.
  */
 
-static PyInt RangeStart;
-static PyInt RangeEnd;
-
 static PyObject *globals;
 
 static void PythonIO_Flush(void);
@@ -1003,19 +1009,12 @@ static int ConvertFromPyObject(PyObject 
 
 #define WindowType_Check(obj) ((obj)->ob_type == &WindowType)
 
-static void WindowDestructor(PyObject *);
-static PyObject *WindowGetattr(PyObject *, char *);
-
 /* Buffer type - Implementation functions
  * --------------------------------------
  */
 
 #define BufferType_Check(obj) ((obj)->ob_type == &BufferType)
 
-static void BufferDestructor(PyObject *);
-static PyObject *BufferGetattr(PyObject *, char *);
-static PyObject *BufferRepr(PyObject *);
-
 static PyInt BufferLength(PyObject *);
 static PyObject *BufferItem(PyObject *, PyInt);
 static PyObject *BufferSlice(PyObject *, PyInt, PyInt);
@@ -1035,9 +1034,6 @@ static PyInt RangeAssSlice(PyObject *, P
  * -----------------------------------------------
  */
 
-static PyObject *CurrentGetattr(PyObject *, char *);
-static int CurrentSetattr(PyObject *, char *, PyObject *);
-
 static PySequenceMethods BufferAsSeq = {
     (PyInquiry)		BufferLength,	    /* sq_length,    len(x)   */
     (binaryfunc)	0,		    /* BufferConcat, sq_concat, x+y */
@@ -1045,30 +1041,12 @@ static PySequenceMethods BufferAsSeq = {
     (PyIntArgFunc)	BufferItem,	    /* sq_item,      x[i]     */
     (PyIntIntArgFunc)	BufferSlice,	    /* sq_slice,     x[i:j]   */
     (PyIntObjArgProc)	BufferAssItem,	    /* sq_ass_item,  x[i]=v   */
-    (PyIntIntObjArgProc)	BufferAssSlice,     /* sq_ass_slice, x[i:j]=v */
-};
-
-static PyTypeObject BufferType = {
-    PyObject_HEAD_INIT(0)
-    0,
-    "buffer",
-    sizeof(BufferObject),
+    (PyIntIntObjArgProc) BufferAssSlice,    /* sq_ass_slice, x[i:j]=v */
+    (objobjproc)	0,
+#if PY_MAJOR_VERSION >= 2
+    (binaryfunc)	0,
     0,
-
-    (destructor)    BufferDestructor,	/* tp_dealloc,	refcount==0  */
-    (printfunc)     0,			/* tp_print,	print x      */
-    (getattrfunc)   BufferGetattr,	/* tp_getattr,	x.attr	     */
-    (setattrfunc)   0,			/* tp_setattr,	x.attr=v     */
-    (cmpfunc)	    0,			/* tp_compare,	x>y	     */
-    (reprfunc)	    BufferRepr,		/* tp_repr,	`x`, print x */
-
-    0,		    /* as number */
-    &BufferAsSeq,   /* as sequence */
-    0,		    /* as mapping */
-
-    (hashfunc) 0,			/* tp_hash, dict(x) */
-    (ternaryfunc) 0,			/* tp_call, x()     */
-    (reprfunc) 0,			/* tp_str,  str(x)  */
+#endif
 };
 
 /* Buffer object - Implementation
@@ -1110,64 +1088,21 @@ BufferNew(buf_T *buf)
     return (PyObject *)(self);
 }
 
-    static void
-BufferDestructor(PyObject *self)
-{
-    BufferObject *this = (BufferObject *)(self);
-
-    if (this->buf && this->buf != INVALID_BUFFER_VALUE)
-	this->buf->b_python_ref = NULL;
-
-    Py_DECREF(self);
-}
-
     static PyObject *
 BufferGetattr(PyObject *self, char *name)
 {
-    BufferObject *this = (BufferObject *)(self);
+    PyObject *r;
 
-    if (CheckBuffer(this))
+    if (CheckBuffer((BufferObject *)(self)))
 	return NULL;
 
-    if (strcmp(name, "name") == 0)
-	return Py_BuildValue("s", this->buf->b_ffname);
-    else if (strcmp(name, "number") == 0)
-	return Py_BuildValue(Py_ssize_t_fmt, this->buf->b_fnum);
-    else if (strcmp(name,"__members__") == 0)
-	return Py_BuildValue("[ss]", "name", "number");
+    r = BufferAttr((BufferObject *)(self), name);
+    if (r || PyErr_Occurred())
+	return r;
     else
 	return Py_FindMethod(BufferMethods, self, name);
 }
 
-    static PyObject *
-BufferRepr(PyObject *self)
-{
-    static char repr[100];
-    BufferObject *this = (BufferObject *)(self);
-
-    if (this->buf == INVALID_BUFFER_VALUE)
-    {
-	vim_snprintf(repr, 100, _("<buffer object (deleted) at %p>"), (self));
-	return PyString_FromString(repr);
-    }
-    else
-    {
-	char *name = (char *)this->buf->b_fname;
-	PyInt len;
-
-	if (name == NULL)
-	    name = "";
-	len = strlen(name);
-
-	if (len > 35)
-	    name = name + (35 - len);
-
-	vim_snprintf(repr, 100, "<buffer %s%s>", len > 35 ? "..." : "", name);
-
-	return PyString_FromString(repr);
-    }
-}
-
 /******************/
 
     static PyInt
@@ -1211,25 +1146,23 @@ BufferAssSlice(PyObject *self, PyInt lo,
 }
 
 static PySequenceMethods RangeAsSeq = {
-    (PyInquiry)		RangeLength,	    /* sq_length,    len(x)   */
-    (binaryfunc)	0, /* RangeConcat, */	     /* sq_concat,    x+y      */
-    (PyIntArgFunc)	0, /* RangeRepeat, */	     /* sq_repeat,    x*n      */
-    (PyIntArgFunc)	RangeItem,	    /* sq_item,      x[i]     */
-    (PyIntIntArgFunc)	RangeSlice,	    /* sq_slice,     x[i:j]   */
-    (PyIntObjArgProc)	RangeAssItem,	    /* sq_ass_item,  x[i]=v   */
-    (PyIntIntObjArgProc)	RangeAssSlice,	    /* sq_ass_slice, x[i:j]=v */
+    (PyInquiry)		RangeLength,	      /* sq_length,    len(x)   */
+    (binaryfunc)	0, /* RangeConcat, */ /* sq_concat,    x+y      */
+    (PyIntArgFunc)	0, /* RangeRepeat, */ /* sq_repeat,    x*n      */
+    (PyIntArgFunc)	RangeItem,	      /* sq_item,      x[i]     */
+    (PyIntIntArgFunc)	RangeSlice,	      /* sq_slice,     x[i:j]   */
+    (PyIntObjArgProc)	RangeAssItem,	      /* sq_ass_item,  x[i]=v   */
+    (PyIntIntObjArgProc) RangeAssSlice,	      /* sq_ass_slice, x[i:j]=v */
+    (objobjproc)	0,
+#if PY_MAJOR_VERSION >= 2
+    (binaryfunc)	0,
+    0,
+#endif
 };
 
 /* Line range object - Implementation
  */
 
-    static void
-RangeDestructor(PyObject *self)
-{
-    Py_DECREF(((RangeObject *)(self))->buf);
-    Py_DECREF(self);
-}
-
     static PyObject *
 RangeGetattr(PyObject *self, char *name)
 {
@@ -1264,11 +1197,6 @@ RangeAssSlice(PyObject *self, PyInt lo, 
 /* Buffer list object - Definitions
  */
 
-typedef struct
-{
-    PyObject_HEAD
-} BufListObject;
-
 static PySequenceMethods BufListAsSeq = {
     (PyInquiry)		BufListLength,	    /* sq_length,    len(x)   */
     (binaryfunc)	0,		    /* sq_concat,    x+y      */
@@ -1276,61 +1204,12 @@ static PySequenceMethods BufListAsSeq = 
     (PyIntArgFunc)	BufListItem,	    /* sq_item,      x[i]     */
     (PyIntIntArgFunc)	0,		    /* sq_slice,     x[i:j]   */
     (PyIntObjArgProc)	0,		    /* sq_ass_item,  x[i]=v   */
-    (PyIntIntObjArgProc)	0,		    /* sq_ass_slice, x[i:j]=v */
-};
-
-static PyTypeObject BufListType = {
-    PyObject_HEAD_INIT(0)
-    0,
-    "buffer list",
-    sizeof(BufListObject),
+    (PyIntIntObjArgProc) 0,		    /* sq_ass_slice, x[i:j]=v */
+    (objobjproc)	0,
+#if PY_MAJOR_VERSION >= 2
+    (binaryfunc)	0,
     0,
-
-    (destructor)    0,			/* tp_dealloc,	refcount==0  */
-    (printfunc)     0,			/* tp_print,	print x      */
-    (getattrfunc)   0,			/* tp_getattr,	x.attr	     */
-    (setattrfunc)   0,			/* tp_setattr,	x.attr=v     */
-    (cmpfunc)	    0,			/* tp_compare,	x>y	     */
-    (reprfunc)	    0,			/* tp_repr,	`x`, print x */
-
-    0,		    /* as number */
-    &BufListAsSeq,  /* as sequence */
-    0,		    /* as mapping */
-
-    (hashfunc) 0,			/* tp_hash, dict(x) */
-    (ternaryfunc) 0,			/* tp_call, x()     */
-    (reprfunc) 0,			/* tp_str,  str(x)  */
-};
-
-/* Window object - Definitions
- */
-
-static struct PyMethodDef WindowMethods[] = {
-    /* name,	    function,		calling,    documentation */
-    { NULL,	    NULL,		0,	    NULL }
-};
-
-static PyTypeObject WindowType = {
-    PyObject_HEAD_INIT(0)
-    0,
-    "window",
-    sizeof(WindowObject),
-    0,
-
-    (destructor)    WindowDestructor,	/* tp_dealloc,	refcount==0  */
-    (printfunc)     0,			/* tp_print,	print x      */
-    (getattrfunc)   WindowGetattr,	/* tp_getattr,	x.attr	     */
-    (setattrfunc)   WindowSetattr,	/* tp_setattr,	x.attr=v     */
-    (cmpfunc)	    0,			/* tp_compare,	x>y	     */
-    (reprfunc)	    WindowRepr,		/* tp_repr,	`x`, print x */
-
-    0,		    /* as number */
-    0,		    /* as sequence */
-    0,		    /* as mapping */
-
-    (hashfunc) 0,			/* tp_hash, dict(x) */
-    (ternaryfunc) 0,			/* tp_call, x()     */
-    (reprfunc) 0,			/* tp_str,  str(x)  */
+#endif
 };
 
 /* Window object - Implementation
@@ -1370,41 +1249,17 @@ WindowNew(win_T *win)
     return (PyObject *)(self);
 }
 
-    static void
-WindowDestructor(PyObject *self)
-{
-    WindowObject *this = (WindowObject *)(self);
-
-    if (this->win && this->win != INVALID_WINDOW_VALUE)
-	this->win->w_python_ref = NULL;
-
-    Py_DECREF(self);
-}
-
     static PyObject *
 WindowGetattr(PyObject *self, char *name)
 {
-    WindowObject *this = (WindowObject *)(self);
+    PyObject *r;
 
-    if (CheckWindow(this))
+    if (CheckWindow((WindowObject *)(self)))
 	return NULL;
 
-    if (strcmp(name, "buffer") == 0)
-	return (PyObject *)BufferNew(this->win->w_buffer);
-    else if (strcmp(name, "cursor") == 0)
-    {
-	pos_T *pos = &this->win->w_cursor;
-
-	return Py_BuildValue("(ll)", (long)(pos->lnum), (long)(pos->col));
-    }
-    else if (strcmp(name, "height") == 0)
-	return Py_BuildValue("l", (long)(this->win->w_height));
-#ifdef FEAT_VERTSPLIT
-    else if (strcmp(name, "width") == 0)
-	return Py_BuildValue("l", (long)(W_WIDTH(this->win)));
-#endif
-    else if (strcmp(name,"__members__") == 0)
-	return Py_BuildValue("[sss]", "buffer", "cursor", "height");
+    r = WindowAttr((WindowObject *)(self), name);
+    if (r || PyErr_Occurred())
+	return r;
     else
 	return Py_FindMethod(WindowMethods, self, name);
 }
@@ -1412,12 +1267,6 @@ WindowGetattr(PyObject *self, char *name
 /* Window list object - Definitions
  */
 
-typedef struct
-{
-    PyObject_HEAD
-}
-WinListObject;
-
 static PySequenceMethods WinListAsSeq = {
     (PyInquiry)		WinListLength,	    /* sq_length,    len(x)   */
     (binaryfunc)	0,		    /* sq_concat,    x+y      */
@@ -1425,102 +1274,14 @@ static PySequenceMethods WinListAsSeq = 
     (PyIntArgFunc)	WinListItem,	    /* sq_item,      x[i]     */
     (PyIntIntArgFunc)	0,		    /* sq_slice,     x[i:j]   */
     (PyIntObjArgProc)	0,		    /* sq_ass_item,  x[i]=v   */
-    (PyIntIntObjArgProc)	0,		    /* sq_ass_slice, x[i:j]=v */
-};
-
-static PyTypeObject WinListType = {
-    PyObject_HEAD_INIT(0)
-    0,
-    "window list",
-    sizeof(WinListObject),
-    0,
-
-    (destructor)    0,			/* tp_dealloc,	refcount==0  */
-    (printfunc)     0,			/* tp_print,	print x      */
-    (getattrfunc)   0,			/* tp_getattr,	x.attr	     */
-    (setattrfunc)   0,			/* tp_setattr,	x.attr=v     */
-    (cmpfunc)	    0,			/* tp_compare,	x>y	     */
-    (reprfunc)	    0,			/* tp_repr,	`x`, print x */
-
-    0,		    /* as number */
-    &WinListAsSeq,  /* as sequence */
-    0,		    /* as mapping */
-
-    (hashfunc) 0,			/* tp_hash, dict(x) */
-    (ternaryfunc) 0,			/* tp_call, x()     */
-    (reprfunc) 0,			/* tp_str,  str(x)  */
-};
-
-/* Current items object - Definitions
- */
-
-typedef struct
-{
-    PyObject_HEAD
-} CurrentObject;
-
-static PyTypeObject CurrentType = {
-    PyObject_HEAD_INIT(0)
-    0,
-    "current data",
-    sizeof(CurrentObject),
+    (PyIntIntObjArgProc) 0,		    /* sq_ass_slice, x[i:j]=v */
+    (objobjproc)	0,
+#if PY_MAJOR_VERSION >= 2
+    (binaryfunc)	0,
     0,
-
-    (destructor)    0,			/* tp_dealloc,	refcount==0  */
-    (printfunc)     0,			/* tp_print,	print x      */
-    (getattrfunc)   CurrentGetattr,	/* tp_getattr,	x.attr	     */
-    (setattrfunc)   CurrentSetattr,	/* tp_setattr,	x.attr=v     */
-    (cmpfunc)	    0,			/* tp_compare,	x>y	     */
-    (reprfunc)	    0,			/* tp_repr,	`x`, print x */
-
-    0,		    /* as number */
-    0,		    /* as sequence */
-    0,		    /* as mapping */
-
-    (hashfunc) 0,			/* tp_hash, dict(x) */
-    (ternaryfunc) 0,			/* tp_call, x()     */
-    (reprfunc) 0,			/* tp_str,  str(x)  */
+#endif
 };
 
-/* Current items object - Implementation
- */
-    static PyObject *
-CurrentGetattr(PyObject *self UNUSED, char *name)
-{
-    if (strcmp(name, "buffer") == 0)
-	return (PyObject *)BufferNew(curbuf);
-    else if (strcmp(name, "window") == 0)
-	return (PyObject *)WindowNew(curwin);
-    else if (strcmp(name, "line") == 0)
-	return GetBufferLine(curbuf, (PyInt)curwin->w_cursor.lnum);
-    else if (strcmp(name, "range") == 0)
-	return RangeNew(curbuf, RangeStart, RangeEnd);
-    else if (strcmp(name,"__members__") == 0)
-	return Py_BuildValue("[ssss]", "buffer", "window", "line", "range");
-    else
-    {
-	PyErr_SetString(PyExc_AttributeError, name);
-	return NULL;
-    }
-}
-
-    static int
-CurrentSetattr(PyObject *self UNUSED, char *name, PyObject *value)
-{
-    if (strcmp(name, "line") == 0)
-    {
-	if (SetBufferLine(curbuf, (PyInt)curwin->w_cursor.lnum, value, NULL) == FAIL)
-	    return -1;
-
-	return 0;
-    }
-    else
-    {
-	PyErr_SetString(PyExc_AttributeError, name);
-	return -1;
-    }
-}
-
 /* External interface
  */
 
@@ -1642,49 +1403,6 @@ LineToString(const char *str)
     return result;
 }
 
-static void DictionaryDestructor(PyObject *);
-static PyObject *DictionaryGetattr(PyObject *, char*);
-
-static PyMappingMethods DictionaryAsMapping = {
-    (PyInquiry)		DictionaryLength,
-    (binaryfunc)	DictionaryItem,
-    (objobjargproc)	DictionaryAssItem,
-};
-
-static PyTypeObject DictionaryType = {
-    PyObject_HEAD_INIT(0)
-    0,
-    "vimdictionary",
-    sizeof(DictionaryObject),
-    0,
-
-    (destructor)  DictionaryDestructor,
-    (printfunc)   0,
-    (getattrfunc) DictionaryGetattr,
-    (setattrfunc) DictionarySetattr,
-    (cmpfunc)     0,
-    (reprfunc)    0,
-
-    0,			    /* as number */
-    0,			    /* as sequence */
-    &DictionaryAsMapping,   /* as mapping */
-
-    (hashfunc)    0,
-    (ternaryfunc) 0,
-    (reprfunc)    0,
-};
-
-    static void
-DictionaryDestructor(PyObject *self)
-{
-    DictionaryObject	*this = ((DictionaryObject *) (self));
-
-    pyll_remove(&this->ref, &lastdict);
-    dict_unref(this->dict);
-
-    Py_DECREF(self);
-}
-
     static PyObject *
 DictionaryGetattr(PyObject *self, char *name)
 {
@@ -1698,9 +1416,6 @@ DictionaryGetattr(PyObject *self, char *
     return Py_FindMethod(DictionaryMethods, self, name);
 }
 
-static void ListDestructor(PyObject *);
-static PyObject *ListGetattr(PyObject *, char *);
-
 static PySequenceMethods ListAsSeq = {
     (PyInquiry)			ListLength,
     (binaryfunc)		0,
@@ -1716,40 +1431,6 @@ static PySequenceMethods ListAsSeq = {
 #endif
 };
 
-static PyTypeObject ListType = {
-    PyObject_HEAD_INIT(0)
-    0,
-    "vimlist",
-    sizeof(ListObject),
-    0,
-
-    (destructor)  ListDestructor,
-    (printfunc)   0,
-    (getattrfunc) ListGetattr,
-    (setattrfunc) ListSetattr,
-    (cmpfunc)     0,
-    (reprfunc)    0,
-
-    0,			    /* as number */
-    &ListAsSeq,		    /* as sequence */
-    0,			    /* as mapping */
-
-    (hashfunc)    0,
-    (ternaryfunc) 0,
-    (reprfunc)    0,
-};
-
-    static void
-ListDestructor(PyObject *self)
-{
-    ListObject	*this = ((ListObject *) (self));
-
-    pyll_remove(&this->ref, &lastlist);
-    list_unref(this->list);
-
-    Py_DECREF(self);
-}
-
     static PyObject *
 ListGetattr(PyObject *self, char *name)
 {
@@ -1759,43 +1440,6 @@ ListGetattr(PyObject *self, char *name)
     return Py_FindMethod(ListMethods, self, name);
 }
 
-static void FunctionDestructor(PyObject *);
-static PyObject *FunctionGetattr(PyObject *, char *);
-
-static PyTypeObject FunctionType = {
-    PyObject_HEAD_INIT(0)
-    0,
-    "vimfunction",
-    sizeof(FunctionObject),
-    0,
-
-    (destructor)  FunctionDestructor,
-    (printfunc)   0,
-    (getattrfunc) FunctionGetattr,
-    (setattrfunc) 0,
-    (cmpfunc)     0,
-    (reprfunc)    0,
-
-    0,			    /* as number */
-    0,			    /* as sequence */
-    0,			    /* as mapping */
-
-    (hashfunc)    0,
-    (ternaryfunc) FunctionCall,
-    (reprfunc)    0,
-};
-
-    static void
-FunctionDestructor(PyObject *self)
-{
-    FunctionObject	*this = (FunctionObject *) (self);
-
-    func_unref(this->name);
-    PyMem_Del(this->name);
-
-    Py_DECREF(self);
-}
-
     static PyObject *
 FunctionGetattr(PyObject *self, char *name)
 {
@@ -1839,21 +1483,3 @@ set_ref_in_python (int copyID)
 {
     set_ref_in_py(copyID);
 }
-
-    static void
-init_structs(void)
-{
-    vim_memset(&OutputType, 0, sizeof(OutputType));
-    OutputType.tp_name = "message";
-    OutputType.tp_basicsize = sizeof(OutputObject);
-    OutputType.tp_getattr = OutputGetattr;
-    OutputType.tp_setattr = OutputSetattr;
-
-    vim_memset(&RangeType, 0, sizeof(RangeType));
-    RangeType.tp_name = "range";
-    RangeType.tp_basicsize = sizeof(RangeObject);
-    RangeType.tp_dealloc = RangeDestructor;
-    RangeType.tp_getattr = RangeGetattr;
-    RangeType.tp_repr = RangeRepr;
-    RangeType.tp_as_sequence = &RangeAsSeq;
-}
--- a/src/if_python3.c
+++ b/src/if_python3.c
@@ -91,6 +91,7 @@ static void init_structs(void);
 #define PyInt_Check(obj) PyLong_Check(obj)
 #define PyInt_FromLong(i) PyLong_FromLong(i)
 #define PyInt_AsLong(obj) PyLong_AsLong(obj)
+#define Py_ssize_t_fmt "n"
 
 #if defined(DYNAMIC_PYTHON3) || defined(PROTO)
 
@@ -588,8 +589,6 @@ static PyObject *WindowNew(win_T *);
 static PyObject *LineToString(const char *);
 static PyObject *BufferDir(PyObject *, PyObject *);
 
-static PyTypeObject RangeType;
-
 static int py3initialised = 0;
 
 #define PYINITIALISED py3initialised
@@ -620,17 +619,7 @@ static int py3initialised = 0;
     if (bytes != NULL) \
 	Py_XDECREF(bytes);
 
-/*
- * Include the code shared with if_python.c
- */
-#include "if_py_both.h"
-
-#define GET_ATTR_STRING(name, nameobj) \
-    char	*name = ""; \
-    if (PyUnicode_Check(nameobj)) \
-	name = _PyUnicode_AsString(nameobj)
-
-#define PY3OBJ_DELETED(obj) (obj->ob_base.ob_refcnt<=0)
+#define DESTRUCTOR_FINISH(self) Py_TYPE(self)->tp_free((PyObject*)self);
 
     static void
 call_PyObject_Free(void *p)
@@ -654,13 +643,38 @@ call_PyType_GenericAlloc(PyTypeObject *t
     return PyType_GenericAlloc(type,nitems);
 }
 
+static PyObject *OutputGetattro(PyObject *, PyObject *);
+static int OutputSetattro(PyObject *, PyObject *, PyObject *);
+static PyObject *BufferGetattro(PyObject *, PyObject *);
+static PyObject *WindowGetattro(PyObject *, PyObject *);
+static int WindowSetattro(PyObject *, PyObject *, PyObject *);
+static PyObject *RangeGetattro(PyObject *, PyObject *);
+static PyObject *CurrentGetattro(PyObject *, PyObject *);
+static int CurrentSetattro(PyObject *, PyObject *, PyObject *);
+static PyObject *DictionaryGetattro(PyObject *, PyObject *);
+static int DictionarySetattro(PyObject *, PyObject *, PyObject *);
+static PyObject *ListGetattro(PyObject *, PyObject *);
+static int ListSetattro(PyObject *, PyObject *, PyObject *);
+static PyObject *FunctionGetattro(PyObject *, PyObject *);
+
+static struct PyModuleDef vimmodule;
+
+/*
+ * Include the code shared with if_python.c
+ */
+#include "if_py_both.h"
+
+#define GET_ATTR_STRING(name, nameobj) \
+    char	*name = ""; \
+    if (PyUnicode_Check(nameobj)) \
+	name = _PyUnicode_AsString(nameobj)
+
+#define PY3OBJ_DELETED(obj) (obj->ob_base.ob_refcnt<=0)
+
 /******************************************************
  * Internal function prototypes.
  */
 
-static Py_ssize_t RangeStart;
-static Py_ssize_t RangeEnd;
-
 static PyObject *globals;
 
 static int PythonIO_Init(void);
@@ -1046,7 +1060,7 @@ static PySequenceMethods BufferAsSeq = {
     0,					    /* sq_inplace_repeat */
 };
 
-PyMappingMethods BufferAsMapping = {
+static PyMappingMethods BufferAsMapping = {
     /* mp_length	*/ (lenfunc)BufferLength,
     /* mp_subscript     */ (binaryfunc)BufferSubscript,
     /* mp_ass_subscript */ (objobjargproc)BufferAsSubscript,
@@ -1056,8 +1070,6 @@ PyMappingMethods BufferAsMapping = {
 /* Buffer object - Definitions
  */
 
-static PyTypeObject BufferType;
-
     static PyObject *
 BufferNew(buf_T *buf)
 {
@@ -1094,31 +1106,19 @@ BufferNew(buf_T *buf)
     return (PyObject *)(self);
 }
 
-    static void
-BufferDestructor(PyObject *self)
-{
-    BufferObject *this = (BufferObject *)(self);
-
-    if (this->buf && this->buf != INVALID_BUFFER_VALUE)
-	this->buf->b_python3_ref = NULL;
-
-    Py_TYPE(self)->tp_free((PyObject*)self);
-}
-
     static PyObject *
 BufferGetattro(PyObject *self, PyObject*nameobj)
 {
-    BufferObject *this = (BufferObject *)(self);
+    PyObject *r;
 
     GET_ATTR_STRING(name, nameobj);
 
-    if (CheckBuffer(this))
+    if (CheckBuffer((BufferObject *)(self)))
 	return NULL;
 
-    if (strcmp(name, "name") == 0)
-	return Py_BuildValue("s", this->buf->b_ffname);
-    else if (strcmp(name, "number") == 0)
-	return Py_BuildValue("n", this->buf->b_fnum);
+    r = BufferAttr((BufferObject *)(self), name);
+    if (r || PyErr_Occurred())
+	return r;
     else
 	return PyObject_GenericGetAttr(self, nameobj);
 }
@@ -1130,35 +1130,6 @@ BufferDir(PyObject *self UNUSED, PyObjec
 						   "append", "mark", "range");
 }
 
-    static PyObject *
-BufferRepr(PyObject *self)
-{
-    static char repr[100];
-    BufferObject *this = (BufferObject *)(self);
-
-    if (this->buf == INVALID_BUFFER_VALUE)
-    {
-	vim_snprintf(repr, 100, _("<buffer object (deleted) at %p>"), (self));
-	return PyUnicode_FromString(repr);
-    }
-    else
-    {
-	char *name = (char *)this->buf->b_fname;
-	Py_ssize_t len;
-
-	if (name == NULL)
-	    name = "";
-	len = strlen(name);
-
-	if (len > 35)
-	    name = name + (35 - len);
-
-	vim_snprintf(repr, 100, "<buffer %s%s>", len > 35 ? "..." : "", name);
-
-	return PyUnicode_FromString(repr);
-    }
-}
-
 /******************/
 
     static Py_ssize_t
@@ -1255,7 +1226,7 @@ static PySequenceMethods RangeAsSeq = {
     0,					 /* sq_inplace_repeat */
 };
 
-PyMappingMethods RangeAsMapping = {
+static PyMappingMethods RangeAsMapping = {
     /* mp_length	*/ (lenfunc)RangeLength,
     /* mp_subscript     */ (binaryfunc)RangeSubscript,
     /* mp_ass_subscript */ (objobjargproc)RangeAsSubscript,
@@ -1264,13 +1235,6 @@ PyMappingMethods RangeAsMapping = {
 /* Line range object - Implementation
  */
 
-    static void
-RangeDestructor(PyObject *self)
-{
-    Py_DECREF(((RangeObject *)(self))->buf);
-    Py_TYPE(self)->tp_free((PyObject*)self);
-}
-
     static PyObject *
 RangeGetattro(PyObject *self, PyObject *nameobj)
 {
@@ -1358,15 +1322,9 @@ RangeAsSubscript(PyObject *self, PyObjec
     }
 }
 
-
 /* Buffer list object - Definitions
  */
 
-typedef struct
-{
-    PyObject_HEAD
-} BufListObject;
-
 static PySequenceMethods BufListAsSeq = {
     (lenfunc)		BufListLength,	    /* sq_length,    len(x)   */
     (binaryfunc)	0,		    /* sq_concat,    x+y      */
@@ -1380,18 +1338,6 @@ static PySequenceMethods BufListAsSeq = 
     0,					    /* sq_inplace_repeat */
 };
 
-static PyTypeObject BufListType;
-
-/* Window object - Definitions
- */
-
-static struct PyMethodDef WindowMethods[] = {
-    /* name,	    function,		calling,    documentation */
-    { NULL,	    NULL,		0,	    NULL }
-};
-
-static PyTypeObject WindowType;
-
 /* Window object - Implementation
  */
 
@@ -1429,43 +1375,19 @@ WindowNew(win_T *win)
     return (PyObject *)(self);
 }
 
-    static void
-WindowDestructor(PyObject *self)
-{
-    WindowObject *this = (WindowObject *)(self);
-
-    if (this->win && this->win != INVALID_WINDOW_VALUE)
-	this->win->w_python3_ref = NULL;
-
-    Py_TYPE(self)->tp_free((PyObject*)self);
-}
-
     static PyObject *
 WindowGetattro(PyObject *self, PyObject *nameobj)
 {
-    WindowObject *this = (WindowObject *)(self);
+    PyObject *r;
 
     GET_ATTR_STRING(name, nameobj);
 
-    if (CheckWindow(this))
+    if (CheckWindow((WindowObject *)(self)))
 	return NULL;
 
-    if (strcmp(name, "buffer") == 0)
-	return (PyObject *)BufferNew(this->win->w_buffer);
-    else if (strcmp(name, "cursor") == 0)
-    {
-	pos_T *pos = &this->win->w_cursor;
-
-	return Py_BuildValue("(ll)", (long)(pos->lnum), (long)(pos->col));
-    }
-    else if (strcmp(name, "height") == 0)
-	return Py_BuildValue("l", (long)(this->win->w_height));
-#ifdef FEAT_VERTSPLIT
-    else if (strcmp(name, "width") == 0)
-	return Py_BuildValue("l", (long)(W_WIDTH(this->win)));
-#endif
-    else if (strcmp(name,"__members__") == 0)
-	return Py_BuildValue("[sss]", "buffer", "cursor", "height");
+    r = WindowAttr((WindowObject *)(self), name);
+    if (r || PyErr_Occurred())
+	return r;
     else
 	return PyObject_GenericGetAttr(self, nameobj);
 }
@@ -1481,12 +1403,6 @@ WindowSetattro(PyObject *self, PyObject 
 /* Window list object - Definitions
  */
 
-typedef struct
-{
-    PyObject_HEAD
-}
-WinListObject;
-
 static PySequenceMethods WinListAsSeq = {
     (lenfunc)	     WinListLength,	    /* sq_length,    len(x)   */
     (binaryfunc)     0,			    /* sq_concat,    x+y      */
@@ -1500,61 +1416,20 @@ static PySequenceMethods WinListAsSeq = 
     0,					    /* sq_inplace_repeat */
 };
 
-static PyTypeObject WinListType;
-
-/* Current items object - Definitions
- */
-
-typedef struct
-{
-    PyObject_HEAD
-} CurrentObject;
-
-static PyTypeObject CurrentType;
-
 /* Current items object - Implementation
  */
     static PyObject *
-CurrentGetattro(PyObject *self UNUSED, PyObject *nameobj)
+CurrentGetattro(PyObject *self, PyObject *nameobj)
 {
     GET_ATTR_STRING(name, nameobj);
-
-    if (strcmp(name, "buffer") == 0)
-	return (PyObject *)BufferNew(curbuf);
-    else if (strcmp(name, "window") == 0)
-	return (PyObject *)WindowNew(curwin);
-    else if (strcmp(name, "line") == 0)
-	return GetBufferLine(curbuf, (Py_ssize_t)curwin->w_cursor.lnum);
-    else if (strcmp(name, "range") == 0)
-	return RangeNew(curbuf, RangeStart, RangeEnd);
-    else if (strcmp(name,"__members__") == 0)
-	return Py_BuildValue("[ssss]", "buffer", "window", "line", "range");
-    else
-    {
-	PyErr_SetString(PyExc_AttributeError, name);
-	return NULL;
-    }
+    return CurrentGetattr(self, name);
 }
 
     static int
-CurrentSetattro(PyObject *self UNUSED, PyObject *nameobj, PyObject *value)
+CurrentSetattro(PyObject *self, PyObject *nameobj, PyObject *value)
 {
-    char *name = "";
-    if (PyUnicode_Check(nameobj))
-	name = _PyUnicode_AsString(nameobj);
-
-    if (strcmp(name, "line") == 0)
-    {
-	if (SetBufferLine(curbuf, (Py_ssize_t)curwin->w_cursor.lnum, value, NULL) == FAIL)
-	    return -1;
-
-	return 0;
-    }
-    else
-    {
-	PyErr_SetString(PyExc_AttributeError, name);
-	return -1;
-    }
+    GET_ATTR_STRING(name, nameobj);
+    return CurrentSetattr(self, name, value);
 }
 
 /* Dictionary object - Definitions
@@ -1562,12 +1437,6 @@ CurrentSetattro(PyObject *self UNUSED, P
 
 static PyInt DictionaryLength(PyObject *);
 
-static PyMappingMethods DictionaryAsMapping = {
-    /* mp_length	*/ (lenfunc) DictionaryLength,
-    /* mp_subscript     */ (binaryfunc) DictionaryItem,
-    /* mp_ass_subscript */ (objobjargproc) DictionaryAssItem,
-};
-
     static PyObject *
 DictionaryGetattro(PyObject *self, PyObject *nameobj)
 {
@@ -1587,20 +1456,7 @@ DictionaryGetattro(PyObject *self, PyObj
 DictionarySetattro(PyObject *self, PyObject *nameobj, PyObject *val)
 {
     GET_ATTR_STRING(name, nameobj);
-    return DictionarySetattr((DictionaryObject *) self, name, val);
-}
-
-static PyTypeObject DictionaryType;
-
-    static void
-DictionaryDestructor(PyObject *self)
-{
-    DictionaryObject *this = (DictionaryObject *)(self);
-
-    pyll_remove(&this->ref, &lastdict);
-    dict_unref(this->dict);
-
-    Py_TYPE(self)->tp_free((PyObject*)self);
+    return DictionarySetattr(self, name, val);
 }
 
 /* List object - Definitions
@@ -1631,8 +1487,6 @@ static PyMappingMethods ListAsMapping = 
     /* mp_ass_subscript */ (objobjargproc) ListAsSubscript,
 };
 
-static PyTypeObject ListType;
-
     static PyObject *
 ListSubscript(PyObject *self, PyObject* idxObject)
 {
@@ -1696,34 +1550,12 @@ ListGetattro(PyObject *self, PyObject *n
 ListSetattro(PyObject *self, PyObject *nameobj, PyObject *val)
 {
     GET_ATTR_STRING(name, nameobj);
-    return ListSetattr((ListObject *) self, name, val);
-}
-
-    static void
-ListDestructor(PyObject *self)
-{
-    ListObject *this = (ListObject *)(self);
-
-    pyll_remove(&this->ref, &lastlist);
-    list_unref(this->list);
-
-    Py_TYPE(self)->tp_free((PyObject*)self);
+    return ListSetattr(self, name, val);
 }
 
 /* Function object - Definitions
  */
 
-    static void
-FunctionDestructor(PyObject *self)
-{
-    FunctionObject	*this = (FunctionObject *) (self);
-
-    func_unref(this->name);
-    PyMem_Del(this->name);
-
-    Py_TYPE(self)->tp_free((PyObject*)self);
-}
-
     static PyObject *
 FunctionGetattro(PyObject *self, PyObject *nameobj)
 {
@@ -1779,10 +1611,6 @@ static CurrentObject TheCurrent =
     PyObject_HEAD_INIT(&CurrentType)
 };
 
-PyDoc_STRVAR(vim_module_doc,"vim python interface\n");
-
-static struct PyModuleDef vimmodule;
-
     static PyObject *
 Py3Init_vim(void)
 {
@@ -1898,124 +1726,3 @@ set_ref_in_python3 (int copyID)
 {
     set_ref_in_py(copyID);
 }
-
-    static void
-init_structs(void)
-{
-    vim_memset(&OutputType, 0, sizeof(OutputType));
-    OutputType.tp_name = "vim.message";
-    OutputType.tp_basicsize = sizeof(OutputObject);
-    OutputType.tp_getattro = OutputGetattro;
-    OutputType.tp_setattro = OutputSetattro;
-    OutputType.tp_flags = Py_TPFLAGS_DEFAULT;
-    OutputType.tp_doc = "vim message object";
-    OutputType.tp_methods = OutputMethods;
-    OutputType.tp_alloc = call_PyType_GenericAlloc;
-    OutputType.tp_new = call_PyType_GenericNew;
-    OutputType.tp_free = call_PyObject_Free;
-
-    vim_memset(&BufferType, 0, sizeof(BufferType));
-    BufferType.tp_name = "vim.buffer";
-    BufferType.tp_basicsize = sizeof(BufferType);
-    BufferType.tp_dealloc = BufferDestructor;
-    BufferType.tp_repr = BufferRepr;
-    BufferType.tp_as_sequence = &BufferAsSeq;
-    BufferType.tp_as_mapping = &BufferAsMapping;
-    BufferType.tp_getattro = BufferGetattro;
-    BufferType.tp_flags = Py_TPFLAGS_DEFAULT;
-    BufferType.tp_doc = "vim buffer object";
-    BufferType.tp_methods = BufferMethods;
-    BufferType.tp_alloc = call_PyType_GenericAlloc;
-    BufferType.tp_new = call_PyType_GenericNew;
-    BufferType.tp_free = call_PyObject_Free;
-
-    vim_memset(&WindowType, 0, sizeof(WindowType));
-    WindowType.tp_name = "vim.window";
-    WindowType.tp_basicsize = sizeof(WindowObject);
-    WindowType.tp_dealloc = WindowDestructor;
-    WindowType.tp_repr = WindowRepr;
-    WindowType.tp_getattro = WindowGetattro;
-    WindowType.tp_setattro = WindowSetattro;
-    WindowType.tp_flags = Py_TPFLAGS_DEFAULT;
-    WindowType.tp_doc = "vim Window object";
-    WindowType.tp_methods = WindowMethods;
-    WindowType.tp_alloc = call_PyType_GenericAlloc;
-    WindowType.tp_new = call_PyType_GenericNew;
-    WindowType.tp_free = call_PyObject_Free;
-
-    vim_memset(&BufListType, 0, sizeof(BufListType));
-    BufListType.tp_name = "vim.bufferlist";
-    BufListType.tp_basicsize = sizeof(BufListObject);
-    BufListType.tp_as_sequence = &BufListAsSeq;
-    BufListType.tp_flags = Py_TPFLAGS_DEFAULT;
-    BufferType.tp_doc = "vim buffer list";
-
-    vim_memset(&WinListType, 0, sizeof(WinListType));
-    WinListType.tp_name = "vim.windowlist";
-    WinListType.tp_basicsize = sizeof(WinListType);
-    WinListType.tp_as_sequence = &WinListAsSeq;
-    WinListType.tp_flags = Py_TPFLAGS_DEFAULT;
-    WinListType.tp_doc = "vim window list";
-
-    vim_memset(&RangeType, 0, sizeof(RangeType));
-    RangeType.tp_name = "vim.range";
-    RangeType.tp_basicsize = sizeof(RangeObject);
-    RangeType.tp_dealloc = RangeDestructor;
-    RangeType.tp_repr = RangeRepr;
-    RangeType.tp_as_sequence = &RangeAsSeq;
-    RangeType.tp_as_mapping = &RangeAsMapping;
-    RangeType.tp_getattro = RangeGetattro;
-    RangeType.tp_flags = Py_TPFLAGS_DEFAULT;
-    RangeType.tp_doc = "vim Range object";
-    RangeType.tp_methods = RangeMethods;
-    RangeType.tp_alloc = call_PyType_GenericAlloc;
-    RangeType.tp_new = call_PyType_GenericNew;
-    RangeType.tp_free = call_PyObject_Free;
-
-    vim_memset(&CurrentType, 0, sizeof(CurrentType));
-    CurrentType.tp_name = "vim.currentdata";
-    CurrentType.tp_basicsize = sizeof(CurrentObject);
-    CurrentType.tp_getattro = CurrentGetattro;
-    CurrentType.tp_setattro = CurrentSetattro;
-    CurrentType.tp_flags = Py_TPFLAGS_DEFAULT;
-    CurrentType.tp_doc = "vim current object";
-
-    vim_memset(&DictionaryType, 0, sizeof(DictionaryType));
-    DictionaryType.tp_name = "vim.dictionary";
-    DictionaryType.tp_basicsize = sizeof(DictionaryObject);
-    DictionaryType.tp_getattro = DictionaryGetattro;
-    DictionaryType.tp_setattro = DictionarySetattro;
-    DictionaryType.tp_dealloc = 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;
-
-    vim_memset(&ListType, 0, sizeof(ListType));
-    ListType.tp_name = "vim.list";
-    ListType.tp_dealloc = ListDestructor;
-    ListType.tp_basicsize = sizeof(ListObject);
-    ListType.tp_getattro = ListGetattro;
-    ListType.tp_setattro = ListSetattro;
-    ListType.tp_as_sequence = &ListAsSeq;
-    ListType.tp_as_mapping = &ListAsMapping;
-    ListType.tp_flags = Py_TPFLAGS_DEFAULT;
-    ListType.tp_doc = "list pushing modifications to vim structure";
-    ListType.tp_methods = ListMethods;
-
-    vim_memset(&FunctionType, 0, sizeof(FunctionType));
-    FunctionType.tp_name = "vim.list";
-    FunctionType.tp_basicsize = sizeof(FunctionObject);
-    FunctionType.tp_getattro = FunctionGetattro;
-    FunctionType.tp_dealloc = FunctionDestructor;
-    FunctionType.tp_call = FunctionCall;
-    FunctionType.tp_flags = Py_TPFLAGS_DEFAULT;
-    FunctionType.tp_doc = "object that calls vim function";
-    FunctionType.tp_methods = FunctionMethods;
-
-    vim_memset(&vimmodule, 0, sizeof(vimmodule));
-    vimmodule.m_name = "vim";
-    vimmodule.m_doc = vim_module_doc;
-    vimmodule.m_size = -1;
-    vimmodule.m_methods = VimMethods;
-}
--- a/src/version.c
+++ b/src/version.c
@@ -729,6 +729,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    909,
+/**/
     908,
 /**/
     907,