[asterisk-commits] mjordan: branch mjordan/trunk-python r423237 - in /team/mjordan/trunk-python/...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue Sep 16 17:42:12 CDT 2014


Author: mjordan
Date: Tue Sep 16 17:42:09 2014
New Revision: 423237

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=423237
Log:
Add some pbx python stuff

Added:
    team/mjordan/trunk-python/pbx/pbx_python.c   (with props)
    team/mjordan/trunk-python/pbx/python/
    team/mjordan/trunk-python/pbx/python/include/
    team/mjordan/trunk-python/pbx/python/py_channel.c   (with props)
    team/mjordan/trunk-python/pbx/python/py_context.c   (with props)

Added: team/mjordan/trunk-python/pbx/pbx_python.c
URL: http://svnview.digium.com/svn/asterisk/team/mjordan/trunk-python/pbx/pbx_python.c?view=auto&rev=423237
==============================================================================
--- team/mjordan/trunk-python/pbx/pbx_python.c (added)
+++ team/mjordan/trunk-python/pbx/pbx_python.c Tue Sep 16 17:42:09 2014
@@ -1,0 +1,350 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 1999 - 2014, Digium, Inc.
+ *
+ * Matt Jordan <mjordan at digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! 
+ * \file
+ *
+ * \author Matt Jordan <mjordan at digium.com>
+ * \brief Python PBX Switch
+ *
+ */
+
+//	<depend>python</depend>
+
+/*** MODULEINFO
+	<support_level>extended</support_level>
+ ***/
+
+#include <python2.7/Python.h>
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include "asterisk/module.h"
+#include "asterisk/paths.h"
+#include "asterisk/astobj2.h"
+
+/*! The python extensions module to load */
+#define EXTENSIONS_MODULE "extensions"
+
+/*! The name of the entity registering extensions */
+#define REGISTRAR "pbx_python"
+
+/*! \brief Current state of the Python extensions */
+struct pbx_python_state {
+	/*! The extensions.py module */
+	PyObject *extensions_module;
+};
+
+AO2_GLOBAL_OBJ_STATIC(global_state);
+
+struct asterisk_ContextObject {
+	PyObject_HEAD
+	PyObject *name;
+	PyObject *extensions;
+	PyObject *includes;
+	PyObject *switches;
+	PyObject *hints;
+};
+
+static PyObject *asterisk_ContextObject_new(
+	PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+	RAII_VAR(struct asterisk_ContextObject *, self, NULL, py_safe_unref);
+
+	self = type->tp_alloc(type, 0);
+	if (!self) {
+		return NULL;
+	}
+
+	self->name = PyString_FromString("");
+	if (!self->name) {
+		return NULL;
+	}
+
+	self->extensions = PyList_New(0);
+	if (!self->extensions) {
+		return NULL;
+	}
+
+	self->includes = PyList_New(0);
+	if (!self->includes) {
+		return NULL;
+	}
+
+	self->switches = PyList_New(0);
+	if (!self->switches) {
+		return NULL;
+	}
+
+	self->hints = PyList_New(0);
+	if (!self->hints) {
+		return NULL;
+	}
+
+	Py_INCREF(self);
+	return self;
+}
+
+static int asterisk_ContextObject_init(asterisk_ContextObject *self,
+	PyObject *args, PyObject *kwds)
+{
+	PyObject *name;
+	static char *kwlist[] = {"name", NULL};
+
+	if (!PyArg_ParseTupleAndKeywords(args, kwds, "S", kwlist, &name)) {
+		return -1;
+	}
+
+	if (name) {
+		PyObject *tmp = self->name;
+		Py_INCREF(name);
+		self->name = name;
+		Py_XDECREF(tmp);
+	}
+
+	return 0;
+}
+
+static PyTypeObject asterisk_ContextType {
+	PyObject_HEAD_INIT(NULL)
+	0,                         /* ob_size */
+	"asterisk.Context",        /* tp_name */
+	sizeof(asterisk_ContextObject),
+    0,                         /* tp_itemsize */
+    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 */
+    "Aserisk PBX Context",     /* tp_doc */
+    0,		               /* tp_traverse */
+    0,		               /* tp_clear */
+    0,		               /* tp_richcompare */
+    0,		               /* tp_weaklistoffset */
+    0,		               /* tp_iter */
+    0,		               /* tp_iternext */
+    Noddy_methods,             /* tp_methods */
+    Noddy_members,             /* tp_members */
+    Noddy_getseters,           /* tp_getset */
+    0,                         /* tp_base */
+    0,                         /* tp_dict */
+    0,                         /* tp_descr_get */
+    0,                         /* tp_descr_set */
+    0,                         /* tp_dictoffset */
+    (initproc)asterisk_ContextObject_init,      /* tp_init */
+    0,                         /* tp_alloc */
+    asterisk_ContextObject_new,                 /* tp_new */
+
+
+};
+
+static PyMethodDef asterisk_methods[] = {
+	{NULL}	/* Sentinel */
+};
+
+
+
+
+
+
+/*! \brief Destructor for a \ref pbx_python_state object */
+static void pbx_python_state_dtor(void *obj)
+{
+	struct pbx_python_state *state = obj;
+
+	Py_DECREF(state->extensions_module);
+}
+
+/*! \brief Constructor for a \ref pbx_python_state object */
+static struct pbx_python_state *pbx_python_state_create(void)
+{
+	struct pbx_python_state *state;
+
+	state = ao2_alloc(sizeof(*state), pbx_python_state_dtor);
+
+	return state;
+}
+
+/*! \internal \brief Safely unref a PyObject */
+static void py_safe_unref(void *obj)
+{
+	Py_XDECREF((PyObject *)obj);
+}
+
+/*! \internal \brief Log a python exception that just occurred */
+static void py_log_exception(void)
+{
+	PyObject *py_exc = NULL, *py_exc_str = NULL;
+	PyObject *py_val = NULL, *py_val_str = NULL;
+	PyObject *py_tb = NULL;
+
+	if (!PyErr_Occurred()) {
+		return;
+	}
+
+	PyErr_Fetch(&py_exc, &py_val, &py_tb);
+	PyErr_NormalizeException(&py_exc, &py_val, &py_tb);
+	if (py_exc) {
+		py_exc_str = PyObject_Str(py_exc);
+	}
+	if (py_val) {
+		py_val_str = PyObject_Str(py_val);
+	}
+
+	ast_log(AST_LOG_ERROR, "%s%s%s%s\n",
+	        py_exc_str ? "Python exception thrown: " : "",
+	        py_exc_str ? PyString_AsString(py_exc_str) : "",
+	        py_exc_str ? "; " : "",
+	        py_val_str ? PyString_AsString(py_val_str) : "");
+
+	py_safe_unref(py_exc_str);
+	py_safe_unref(py_val_str);
+	PyErr_Restore(py_exc, py_val, py_tb);
+}
+
+static int unload_module(void)
+{
+//	ast_context_destroy(NULL, REGISTRAR);
+
+	ao2_t_global_obj_release(global_state, "pbx_python module unload");
+
+	Py_Finalize();
+
+	return 0;
+}
+
+/*! \internal \brief Load and process the extensions python module
+ *
+ * This will replace the \ref global_state object with whatever state
+ * is created from the \file extensions Python module. The existing
+ * contexts will be swapped out with whatever is created as a result
+ * of loading the new Python module.
+ *
+ * \retval 0 on success
+ * \retval 1 on failure
+ */
+static int load_extensions_module(void)
+{
+	RAII_VAR(struct pbx_python_state *, old_state,
+	         ao2_t_global_obj_ref(global_state, "load extensions"), ao2_cleanup);
+	RAII_VAR(PyObject *, py_load_func, NULL, py_safe_unref);
+	RAII_VAR(PyObject *, py_load_func_return, NULL, py_safe_unref);
+	RAII_VAR(PyObject *, py_extensions_module, NULL, py_safe_unref);
+	RAII_VAR(struct pbx_python_state *, new_state, NULL, ao2_cleanup);
+
+	new_state = pbx_python_state_create();
+	if (!new_state) {
+		return 1;
+	}
+
+	if (!old_state) {
+		char *config_path = ast_strdupa(ast_config_AST_CONFIG_DIR);
+
+		/* Set the python path to our config directory so we
+		 * can find the extensions.py module
+		 */
+		PySys_SetPath(config_path);
+
+		py_extensions_module = PyImport_ImportModule(EXTENSIONS_MODULE);
+		if (!py_extensions_module) {
+			py_log_exception();
+			return 1;
+		}
+
+		new_state->extensions_module = py_extensions_module;
+		Py_INCREF(new_state->extensions_module);
+	} else {
+		PyObject *py_new_module;
+
+		py_new_module = PyImport_ReloadModule(old_state->extensions_module);
+		if (!py_new_module) {
+			py_log_exception();
+			return 1;
+		}
+		new_state->extensions_module = py_new_module;
+	}
+
+	py_load_func = PyObject_GetAttrString(new_state->extensions_module, "load_module");
+	if (!py_load_func || !PyCallable_Check(py_load_func)) {
+		py_log_exception();
+		return 1;
+	}
+
+	py_load_func_return = PyObject_CallObject(py_load_func, NULL);
+	if (!py_load_func_return || py_load_func_return == Py_False) {
+		ast_log(AST_LOG_ERROR, "Python module '%s' load_module function returned False; declining load\n",
+		        EXTENSIONS_MODULE);
+		return 1;
+	}
+
+	/* This is safe, since we already hold a reference to old_state.
+	 * Note that we need to use the value returned to avoid a
+	 * compilation warning. */
+	old_state = ao2_t_global_obj_replace(global_state, new_state, "Load state into global container");
+	if (old_state) {
+		ao2_t_ref(old_state, -1, "Discard old state");
+	}
+
+	ast_verb(2, "Python module '%s' loaded successfully\n", EXTENSIONS_MODULE);
+	return 0;
+}
+
+static int reload(void)
+{
+	if (load_extensions_module()) {
+		return AST_MODULE_LOAD_DECLINE;
+	}
+	return AST_MODULE_LOAD_SUCCESS;
+}
+
+static int load_module(void)
+{
+
+	Py_Initialize();
+	PyEval_InitThreads();
+
+	/* Note that because we are in the module load routine,
+	 * it should be safe to load the Python module using the
+	 * default main thread state
+	 */
+	if (load_extensions_module()) {
+		return AST_MODULE_LOAD_DECLINE;
+	}
+
+	return AST_MODULE_LOAD_SUCCESS;
+}
+
+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "Python PBX Switch",
+	.load = load_module,
+	.unload = unload_module,
+	.reload = reload,
+);
+

Propchange: team/mjordan/trunk-python/pbx/pbx_python.c
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: team/mjordan/trunk-python/pbx/pbx_python.c
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Propchange: team/mjordan/trunk-python/pbx/pbx_python.c
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: team/mjordan/trunk-python/pbx/python/py_channel.c
URL: http://svnview.digium.com/svn/asterisk/team/mjordan/trunk-python/pbx/python/py_channel.c?view=auto&rev=423237
==============================================================================
    (empty)

Propchange: team/mjordan/trunk-python/pbx/python/py_channel.c
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: team/mjordan/trunk-python/pbx/python/py_channel.c
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Propchange: team/mjordan/trunk-python/pbx/python/py_channel.c
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: team/mjordan/trunk-python/pbx/python/py_context.c
URL: http://svnview.digium.com/svn/asterisk/team/mjordan/trunk-python/pbx/python/py_context.c?view=auto&rev=423237
==============================================================================
    (empty)

Propchange: team/mjordan/trunk-python/pbx/python/py_context.c
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: team/mjordan/trunk-python/pbx/python/py_context.c
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Propchange: team/mjordan/trunk-python/pbx/python/py_context.c
------------------------------------------------------------------------------
    svn:mime-type = text/plain




More information about the asterisk-commits mailing list