summaryrefslogtreecommitdiffstats
path: root/glib/pygspawn.c
diff options
context:
space:
mode:
authorJohan Dahlin <johan@gnome.org>2008-07-20 10:43:41 +0000
committerJohan Dahlin <johan@src.gnome.org>2008-07-20 10:43:41 +0000
commit6628e24baebc6dd40f9e76d10391ea5c06d3398a (patch)
tree68b587325b10d5616381c508609702027db8ba74 /glib/pygspawn.c
parentaf2dfa166520a243ea05ff7d4bd5a1fa103d8e0b (diff)
downloadpygobject-6628e24baebc6dd40f9e76d10391ea5c06d3398a.tar.gz
pygobject-6628e24baebc6dd40f9e76d10391ea5c06d3398a.tar.xz
pygobject-6628e24baebc6dd40f9e76d10391ea5c06d3398a.zip
Add glib bindings, currently not installed or used. Add some internal API
2008-07-20 Johan Dahlin <johan@gnome.org> * Makefile.am: * configure.ac: * glib/Makefile.am: * glib/__init__.py: * glib/glibmodule.c (pyg_destroy_notify), (get_handler_priority), (pyg_handler_marshal), (pyg_idle_add), (pyg_timeout_add), (pyg_timeout_add_seconds), (iowatch_marshal), (pyg_io_add_watch), (pyg_source_remove), (pyg_main_context_default), (child_watch_func), (child_watch_dnotify), (pyg_child_watch_add), (pyg_markup_escape_text), (pyg_get_current_time), (pyg_main_depth), (pyg_filename_display_name), (pyg_filename_display_basename), (pyg_filename_from_utf8), (pyg_get_application_name), (pyg_set_application_name), (pyg_get_prgname), (pyg_set_prgname), (pyg_register_api), (pyg_register_error), (pyg_register_version_tuples), (init_glib): * glib/pyglib-private.h: * glib/pyglib.c (pyglib_init), (pyglib_init_internal), (pyglib_gil_state_ensure), (pyglib_gil_state_release), (pyglib_enable_threads), (pyglib_gil_state_ensure_py23), (pyglib_gil_state_release_py23), (pyglib_error_check): * glib/pyglib.h: * glib/pygspawn.c (pyg_pid_close), (pyg_pid_free), (pyg_pid_tp_init), (pyg_pid_new), (_pyg_spawn_async_callback), (pyglib_spawn_async), (pyg_spawn_register_types): * glib/pygspawn.h: Add glib bindings, currently not installed or used. Add some internal API and move over a couple of functions from the gobject module. Still very much a work in progress. svn path=/trunk/; revision=839
Diffstat (limited to 'glib/pygspawn.c')
-rw-r--r--glib/pygspawn.c297
1 files changed, 297 insertions, 0 deletions
diff --git a/glib/pygspawn.c b/glib/pygspawn.c
new file mode 100644
index 0000000..08c40aa
--- /dev/null
+++ b/glib/pygspawn.c
@@ -0,0 +1,297 @@
+/* -*- Mode: C; c-basic-offset: 4 -*-
+ * pyglib - Python bindings for GLib toolkit.
+ * Copyright (C) 1998-2003 James Henstridge
+ * 2004-2008 Johan Dahlin
+ *
+ * pygspawn.c: wrapper for the glib library.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+#include <Python.h>
+#include <glib/gspawn.h>
+
+#include "pyglib.h"
+#include "pyglib-private.h"
+
+struct _PyGChildSetupData {
+ PyObject *func;
+ PyObject *data;
+};
+
+static PyObject *
+pyg_pid_close(PyIntObject *self, PyObject *args, PyObject *kwargs)
+{
+ g_spawn_close_pid((GPid) self->ob_ival);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyMethodDef pyg_pid_methods[] = {
+ { "close", (PyCFunction)pyg_pid_close, METH_NOARGS },
+ { NULL, NULL, 0 }
+};
+
+static void
+pyg_pid_free(PyIntObject *gpid)
+{
+ g_spawn_close_pid((GPid) gpid->ob_ival);
+ PyInt_Type.tp_free((void *) gpid);
+}
+
+static int
+pyg_pid_tp_init(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+ PyErr_SetString(PyExc_TypeError, "glib.Pid cannot be manually instantiated");
+ return -1;
+}
+
+static PyTypeObject PyGPid_Type = {
+ PyObject_HEAD_INIT(NULL)
+ 0,
+ "glib.Pid",
+ sizeof(PyIntObject),
+ 0,
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+ 0, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ pyg_pid_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ pyg_pid_tp_init, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+ (freefunc)pyg_pid_free, /* tp_free */
+ 0, /* tp_is_gc */
+};
+
+PyObject *
+pyg_pid_new(GPid pid)
+{
+ PyIntObject *pygpid;
+ pygpid = PyObject_NEW(PyIntObject, &PyGPid_Type);
+
+ pygpid->ob_ival = pid;
+ return (PyObject *) pygpid;
+}
+
+static void
+_pyg_spawn_async_callback(gpointer user_data)
+{
+ struct _PyGChildSetupData *data;
+ PyObject *retval;
+ PyGILState_STATE gil;
+
+ data = (struct _PyGChildSetupData *) user_data;
+ gil = pyglib_gil_state_ensure();
+ if (data->data)
+ retval = PyObject_CallFunction(data->func, "O", data->data);
+ else
+ retval = PyObject_CallFunction(data->func, NULL);
+ if (retval)
+ Py_DECREF(retval);
+ else
+ PyErr_Print();
+ Py_DECREF(data->func);
+ Py_XDECREF(data->data);
+ g_free(data);
+ pyglib_gil_state_release(gil);
+}
+
+PyObject *
+pyglib_spawn_async(PyObject *object, PyObject *args, PyObject *kwargs)
+{
+ static char *kwlist[] = { "argv", "envp", "working_directory", "flags",
+ "child_setup", "user_data", "standard_input",
+ "standard_output", "standard_error", NULL };
+ PyObject *pyargv, *pyenvp = NULL;
+ char **argv, **envp = NULL;
+ PyObject *func = Py_None, *user_data = NULL;
+ char *working_directory = NULL;
+ int flags = 0, _stdin = -1, _stdout = -1, _stderr = -1;
+ PyObject *pystdin = NULL, *pystdout = NULL, *pystderr = NULL;
+ gint *standard_input, *standard_output, *standard_error;
+ struct _PyGChildSetupData *callback_data = NULL;
+ GError *error = NULL;
+ GPid child_pid = -1;
+ Py_ssize_t len, i;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OsiOOOOO:glib.spawn_async",
+ kwlist,
+ &pyargv, &pyenvp, &working_directory, &flags,
+ &func, &user_data,
+ &pystdin, &pystdout, &pystderr))
+ return NULL;
+
+ if (pystdin && PyObject_IsTrue(pystdin))
+ standard_input = &_stdin;
+ else
+ standard_input = NULL;
+
+ if (pystdout && PyObject_IsTrue(pystdout))
+ standard_output = &_stdout;
+ else
+ standard_output = NULL;
+
+ if (pystderr && PyObject_IsTrue(pystderr))
+ standard_error = &_stderr;
+ else
+ standard_error = NULL;
+
+ /* parse argv */
+ if (!PySequence_Check(pyargv)) {
+ PyErr_SetString(PyExc_TypeError,
+ "glib.spawn_async: "
+ "first argument must be a sequence of strings");
+ return NULL;
+ }
+ len = PySequence_Length(pyargv);
+ argv = g_new0(char *, len + 1);
+ for (i = 0; i < len; ++i) {
+ PyObject *tmp = PySequence_ITEM(pyargv, i);
+ if (!PyString_Check(tmp)) {
+ PyErr_SetString(PyExc_TypeError,
+ "glib.spawn_async: "
+ "first argument must be a sequence of strings");
+ g_free(argv);
+ Py_XDECREF(tmp);
+ return NULL;
+ }
+ argv[i] = PyString_AsString(tmp);
+ Py_DECREF(tmp);
+ }
+
+ /* parse envp */
+ if (pyenvp) {
+ if (!PySequence_Check(pyenvp)) {
+ PyErr_SetString(PyExc_TypeError,
+ "glib.spawn_async: "
+ "second argument must be a sequence of strings");
+ g_free(argv);
+ return NULL;
+ }
+ len = PySequence_Length(pyenvp);
+ envp = g_new0(char *, len + 1);
+ for (i = 0; i < len; ++i) {
+ PyObject *tmp = PySequence_ITEM(pyenvp, i);
+ if (!PyString_Check(tmp)) {
+ PyErr_SetString(PyExc_TypeError,
+ "glib.spawn_async: "
+ "second argument must be a sequence of strings");
+ g_free(envp);
+ Py_XDECREF(tmp);
+ g_free(argv);
+ return NULL;
+ }
+ envp[i] = PyString_AsString(tmp);
+ Py_DECREF(tmp);
+ }
+ }
+
+ if (func != Py_None) {
+ if (!PyCallable_Check(func)) {
+ PyErr_SetString(PyExc_TypeError, "child_setup parameter must be callable or None");
+ g_free(argv);
+ if (envp)
+ g_free(envp);
+ return NULL;
+ }
+ callback_data = g_new(struct _PyGChildSetupData, 1);
+ callback_data->func = func;
+ callback_data->data = user_data;
+ Py_INCREF(callback_data->func);
+ if (callback_data->data)
+ Py_INCREF(callback_data->data);
+ }
+
+ if (!g_spawn_async_with_pipes(working_directory, argv, envp, flags,
+ (func != Py_None ? _pyg_spawn_async_callback : NULL),
+ callback_data, &child_pid,
+ standard_input,
+ standard_output,
+ standard_error,
+ &error))
+
+
+ {
+ g_free(argv);
+ if (envp) g_free(envp);
+ if (callback_data) {
+ Py_DECREF(callback_data->func);
+ Py_XDECREF(callback_data->data);
+ g_free(callback_data);
+ }
+ pyglib_error_check(&error);
+ return NULL;
+ }
+ g_free(argv);
+ if (envp) g_free(envp);
+
+ if (standard_input)
+ pystdin = PyInt_FromLong(*standard_input);
+ else {
+ Py_INCREF(Py_None);
+ pystdin = Py_None;
+ }
+
+ if (standard_output)
+ pystdout = PyInt_FromLong(*standard_output);
+ else {
+ Py_INCREF(Py_None);
+ pystdout = Py_None;
+ }
+
+ if (standard_error)
+ pystderr = PyInt_FromLong(*standard_error);
+ else {
+ Py_INCREF(Py_None);
+ pystderr = Py_None;
+ }
+
+ return Py_BuildValue("NNNN", pyg_pid_new(child_pid), pystdin, pystdout, pystderr);
+}
+
+void
+pyg_spawn_register_types(PyObject *d)
+{
+ PyGPid_Type.tp_base = &PyInt_Type;
+ PYGLIB_REGISTER_TYPE(d, PyGPid_Type, "Pid");
+}