[Xcb] [PATCH] Make xpybConn a base type

Julien Danjou julien at danjou.info
Wed Dec 30 10:18:17 PST 2009


Signed-off-by: Julien Danjou <julien at danjou.info>
---

Currently it's impossible to inherits from a xpyb X connection. I've made some change
so you can create it with Connection() like we can with xcb.connect(). Therefore, it's also
possible to inherits from Connection.

As far as I can tell, it works fine, but I'm a newbie, so please review deeply.

 src/conn.c   |   89 ++++++++++++++++++++++++++++++++++++++++++++++++----------
 src/conn.h   |    3 ++
 src/module.c |   79 ++++++---------------------------------------------
 3 files changed, 87 insertions(+), 84 deletions(-)

diff --git a/src/conn.c b/src/conn.c
index 6720e3b..ddc262e 100644
--- a/src/conn.c
+++ b/src/conn.c
@@ -25,26 +25,40 @@ xpybConn_invalid(xpybConn *self)
     return 0;
 }
 
-xpybConn *
-xpybConn_create(PyObject *core_type)
+static int
+xpyb_parse_auth(const char *authstr, int authlen, xcb_auth_info_t *auth)
 {
-    xpybConn *self;
+    int i = 0;
 
-    self = PyObject_New(xpybConn, &xpybConn_type);
-    if (self == NULL)
-	return NULL;
+    while (i < authlen && authstr[i] != ':')
+	i++;
+
+    if (i >= authlen) {
+	PyErr_SetString(xpybExcept_base, "Auth string must take the form '<name>:<data>'.");
+	return -1;
+    }
 
+    auth->name = (char *)authstr;
+    auth->namelen = i++;
+    auth->data = (char *)authstr + i;
+    auth->datalen = authlen - i;
+    return 0;
+}
+
+int
+xpybConn_init_struct(xpybConn *self, PyObject *core_type)
+{
     self->core = PyObject_CallFunctionObjArgs(core_type, self, NULL);
     if (self->core == NULL)
-	goto err;
+        return -1;
 
     self->dict = PyDict_New();
     if (self->dict == NULL)
-	goto err;
+        return -1;
 
-    self->extcache = PyDict_New();
+   self->extcache = PyDict_New();
     if (self->extcache == NULL)
-	goto err;
+        return -1;
 
     self->wrapped = 0;
     self->setup = NULL;
@@ -52,11 +66,55 @@ xpybConn_create(PyObject *core_type)
     self->events_len = 0;
     self->errors = NULL;
     self->errors_len = 0;
-    return self;
+    return 0;
+}
 
-err:
-    Py_DECREF(self);
-    return NULL;
+int
+xpybConn_init(xpybConn *self, PyObject *args, PyObject *kw)
+{
+    static char *kwlist[] = { "display", "fd", "auth", NULL };
+    const char *displayname = NULL, *authstr = NULL;
+    xcb_auth_info_t auth, *authptr = NULL;
+    int authlen, fd = -1;
+
+    /* Make sure core was set. */
+    if (xpybModule_core == NULL) {
+	PyErr_SetString(xpybExcept_base, "No core protocol object has been set.  Did you import xcb.xproto?");
+        return -1;
+    }
+
+    /* Parse arguments and allocate new connection object */
+    if (!PyArg_ParseTupleAndKeywords(args, kw, "|ziz#", kwlist, &displayname,
+				     &fd, &authstr, &authlen))
+        return -1;
+
+    /* Set up authorization */
+    if (authstr != NULL) {
+	if (xpyb_parse_auth(authstr, authlen, &auth) < 0)
+            return -1;
+	authptr = &auth;
+    }
+
+    /* Connect to display */
+    if (fd >= 0)
+	self->conn = xcb_connect_to_fd(fd, authptr);
+    else if (authptr)
+	self->conn = xcb_connect_to_display_with_auth_info(displayname, authptr, &self->pref_screen);
+    else
+	self->conn = xcb_connect(displayname, &self->pref_screen);
+
+    if (xcb_connection_has_error(self->conn)) {
+	PyErr_SetString(xpybExcept_conn, "Failed to connect to X server.");
+        return -1;
+    }
+
+    xpybConn_init_struct(self, (PyObject *)xpybModule_core);
+
+    /* Load extensions */
+    if (xpybConn_setup(self) < 0)
+	return -1;
+
+    return 0;
 }
 
 static xpybExt *
@@ -511,7 +569,8 @@ PyTypeObject xpybConn_type = {
     .tp_basicsize = sizeof(xpybConn),
     .tp_new = xpybConn_new,
     .tp_dealloc = (destructor)xpybConn_dealloc,
-    .tp_flags = Py_TPFLAGS_DEFAULT,
+    .tp_init = (initproc)xpybConn_init,
+    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
     .tp_doc = "XCB connection object",
     .tp_methods = xpybConn_methods,
     .tp_members = xpybConn_members,
diff --git a/src/conn.h b/src/conn.h
index 672f411..a46ef6c 100644
--- a/src/conn.h
+++ b/src/conn.h
@@ -24,4 +24,7 @@ int xpybConn_setup(xpybConn *self);
 
 int xpybConn_modinit(PyObject *m);
 
+int xpybConn_init_struct(xpybConn *self, PyObject *core_type);
+int xpybConn_init(xpybConn *self, PyObject *args, PyObject *kw);
+
 #endif
diff --git a/src/module.c b/src/module.c
index 6ef4644..ba5165f 100644
--- a/src/module.c
+++ b/src/module.c
@@ -33,85 +33,21 @@ PyObject *xpybModule_ext_errors;
 
 
 /*
- * Helpers
- */
-
-static int
-xpyb_parse_auth(const char *authstr, int authlen, xcb_auth_info_t *auth)
-{
-    int i = 0;
-
-    while (i < authlen && authstr[i] != ':')
-	i++;
-
-    if (i >= authlen) {
-	PyErr_SetString(xpybExcept_base, "Auth string must take the form '<name>:<data>'.");
-	return -1;
-    }
-
-    auth->name = (char *)authstr;
-    auth->namelen = i++;
-    auth->data = (char *)authstr + i;
-    auth->datalen = authlen - i;
-    return 0;
-}
-
-/*
  * Module functions
  */
 
 static PyObject *
 xpyb_connect(PyObject *self, PyObject *args, PyObject *kw)
 {
-    static char *kwlist[] = { "display", "fd", "auth", NULL };
-    const char *displayname = NULL, *authstr = NULL;
-    xcb_auth_info_t auth, *authptr = NULL;
-    xpybConn *conn;
-    int authlen, fd = -1;
-
-    /* Make sure core was set. */
-    if (xpybModule_core == NULL) {
-	PyErr_SetString(xpybExcept_base, "No core protocol object has been set.  Did you import xcb.xproto?");
-	return NULL;
-    }
+    xpybConn *conn = PyObject_New(xpybConn, &xpybConn_type);
 
-    /* Parse arguments and allocate new connection object */
-    if (!PyArg_ParseTupleAndKeywords(args, kw, "|ziz#", kwlist, &displayname,
-				     &fd, &authstr, &authlen))
-	return NULL;
-
-    conn = xpybConn_create((PyObject *)xpybModule_core);
     if (conn == NULL)
 	return NULL;
 
-    /* Set up authorization */
-    if (authstr != NULL) {
-	if (xpyb_parse_auth(authstr, authlen, &auth) < 0)
-	    goto err;
-	authptr = &auth;
-    }
-
-    /* Connect to display */
-    if (fd >= 0)
-	conn->conn = xcb_connect_to_fd(fd, authptr);
-    else if (authptr)
-	conn->conn = xcb_connect_to_display_with_auth_info(displayname, authptr, &conn->pref_screen);
-    else
-	conn->conn = xcb_connect(displayname, &conn->pref_screen);
+    if(xpybConn_init(conn, args, kw) < 0)
+        return NULL;
 
-    if (xcb_connection_has_error(conn->conn)) {
-	PyErr_SetString(xpybExcept_conn, "Failed to connect to X server.");
-	goto err;
-    }
-
-    /* Load extensions */
-    if (xpybConn_setup(conn) < 0)
-	goto err;
-
-    return (PyObject *)conn;
-err:
-    Py_DECREF(conn);
-    return NULL;
+    return (PyObject *) conn;
 }
 
 static PyObject *
@@ -131,10 +67,15 @@ xpyb_wrap(PyObject *self, PyObject *args)
     if (!PyArg_ParseTuple(args, "O", &obj))
 	return NULL;
 
-    conn = xpybConn_create((PyObject *)xpybModule_core);
+    /* Create Python object */
+    conn = PyObject_New(xpybConn, &xpybConn_type);
     if (conn == NULL)
 	return NULL;
 
+    /* Init struct of that Python object */
+    if (xpybConn_init_struct(conn, (PyObject *)xpybModule_core) < 0)
+        return NULL;
+
     /* Get our pointer */
     raw = PyLong_AsVoidPtr(obj);
     if (!raw || PyErr_Occurred()) {
-- 
1.6.5.7



More information about the Xcb mailing list