mirror of
https://github.com/rkd77/elinks.git
synced 2024-12-04 14:46:47 -05:00
Fixes to the Python scripting by M. Levinson
This commit is contained in:
parent
29fb051fc9
commit
6c8f532692
3
AUTHORS
3
AUTHORS
@ -331,6 +331,9 @@ Len Lattanzi <Len_Lattanzi@StanfordAlumni.org>
|
||||
M. K. Srikant <srix@vsnl.com>
|
||||
Small fix in forms
|
||||
|
||||
M. Levinson <levinsm@users.sourceforge.net>
|
||||
Python scripting fixes
|
||||
|
||||
Marco Bodrato <bodrato@linuz.sns.it>
|
||||
Twinterm support
|
||||
|
||||
|
@ -1,13 +1,8 @@
|
||||
If you want to use Python scripting with ELinks add
|
||||
--with-python to the configure invocation copy hooks.py to ~/.elinks
|
||||
When your Python installation is your own build, you could give prefix
|
||||
to the configure, eg.
|
||||
--with-python=/usr/local when Python binary is placed in /usr/local/bin, etc.
|
||||
If you want to use Python scripting with ELinks, add --with-python to the
|
||||
configure invocation and copy hooks.py to your ~/.elinks directory.
|
||||
|
||||
When 'configure' cannot find -lpython make symbolic link to the appropriate
|
||||
library, eg.
|
||||
# cd /usr/local/lib
|
||||
# ln -s libpython2.4.so.1.0 libpython.so
|
||||
If configure cannot find Python you can supply a path, e.g.
|
||||
--with-python=/usr/local/bin if your Python binary is in /usr/local/bin, etc.
|
||||
|
||||
For the present hooks.py is not very usable. You are welcome to make it better.
|
||||
Good Luck!
|
||||
|
@ -4,7 +4,6 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "scripting/python/core.h"
|
||||
#include <Python.h>
|
||||
|
||||
#include <stdio.h>
|
||||
@ -14,24 +13,91 @@
|
||||
|
||||
#include "config/home.h"
|
||||
#include "main/module.h"
|
||||
#include "scripting/scripting.h"
|
||||
#include "scripting/python/core.h"
|
||||
#include "scripting/python/python.h"
|
||||
#include "util/env.h"
|
||||
#include "util/file.h"
|
||||
#include "util/string.h"
|
||||
|
||||
|
||||
PyObject *pDict, *pModule;
|
||||
PyObject *pDict = NULL, *pModule = NULL;
|
||||
|
||||
/* Error reporting. */
|
||||
|
||||
void
|
||||
alert_python_error(struct session *ses)
|
||||
{
|
||||
unsigned char *msg = "(no traceback available)";
|
||||
PyObject *err_type = NULL, *err_value = NULL, *err_traceback = NULL;
|
||||
PyObject *tb_module = NULL;
|
||||
PyObject *tb_dict;
|
||||
PyObject *format_function;
|
||||
PyObject *msg_list = NULL;
|
||||
PyObject *empty_string = NULL;
|
||||
PyObject *join_method = NULL;
|
||||
PyObject *msg_string = NULL;
|
||||
unsigned char *temp;
|
||||
|
||||
/*
|
||||
* Retrieve the current error indicator and use the format_exception()
|
||||
* function in Python's traceback module to produce an informative
|
||||
* error message. It returns a list of Python string objects.
|
||||
*/
|
||||
PyErr_Fetch(&err_type, &err_value, &err_traceback);
|
||||
PyErr_NormalizeException(&err_type, &err_value, &err_traceback);
|
||||
if (!err_traceback) goto end;
|
||||
|
||||
tb_module = PyImport_ImportModule("traceback");
|
||||
if (!tb_module) goto end;
|
||||
|
||||
tb_dict = PyModule_GetDict(tb_module);
|
||||
format_function = PyDict_GetItemString(tb_dict, "format_exception");
|
||||
if (!format_function || !PyCallable_Check(format_function)) goto end;
|
||||
|
||||
msg_list = PyObject_CallFunction(format_function, "OOO",
|
||||
err_type, err_value, err_traceback);
|
||||
if (!msg_list) goto end;
|
||||
|
||||
/*
|
||||
* Use the join() method of an empty Python string to join the list
|
||||
* of strings into one Python string containing the entire error
|
||||
* message. Then get the contents of the Python string.
|
||||
*/
|
||||
empty_string = PyString_FromString("");
|
||||
if (!empty_string) goto end;
|
||||
|
||||
join_method = PyObject_GetAttrString(empty_string, "join");
|
||||
if (!join_method || !PyCallable_Check(join_method)) goto end;
|
||||
|
||||
msg_string = PyObject_CallFunction(join_method, "O", msg_list);
|
||||
if (!msg_string) goto end;
|
||||
|
||||
temp = (unsigned char *)PyString_AsString(msg_string);
|
||||
if (temp) msg = temp;
|
||||
|
||||
end:
|
||||
report_scripting_error(&python_scripting_module, ses, msg);
|
||||
|
||||
Py_XDECREF(err_type);
|
||||
Py_XDECREF(err_value);
|
||||
Py_XDECREF(err_traceback);
|
||||
Py_XDECREF(tb_module);
|
||||
Py_XDECREF(msg_list);
|
||||
Py_XDECREF(empty_string);
|
||||
Py_XDECREF(join_method);
|
||||
Py_XDECREF(msg_string);
|
||||
|
||||
/* In case another error occurred while reporting the original error: */
|
||||
PyErr_Clear();
|
||||
}
|
||||
|
||||
void
|
||||
cleanup_python(struct module *module)
|
||||
{
|
||||
if (Py_IsInitialized()) {
|
||||
if (pModule) {
|
||||
Py_DECREF(pModule);
|
||||
}
|
||||
if (PyErr_Occurred()) {
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
}
|
||||
Py_XDECREF(pDict);
|
||||
Py_XDECREF(pModule);
|
||||
Py_Finalize();
|
||||
}
|
||||
}
|
||||
@ -44,15 +110,25 @@ init_python(struct module *module)
|
||||
if (!python_path) return;
|
||||
env_set("PYTHONPATH", python_path, -1);
|
||||
mem_free(python_path);
|
||||
|
||||
/* Treat warnings as errors so they can be caught and handled;
|
||||
* otherwise they would be printed to stderr.
|
||||
*
|
||||
* NOTE: PySys_ResetWarnOptions() and PySys_AddWarnOption() have been
|
||||
* available and stable for many years but they're not officially
|
||||
* documented as part of Python's public API, so in theory these two
|
||||
* functions might no longer be available in some hypothetical future
|
||||
* version of Python. */
|
||||
PySys_ResetWarnOptions();
|
||||
PySys_AddWarnOption("error");
|
||||
|
||||
Py_Initialize();
|
||||
pModule = PyImport_ImportModule("hooks");
|
||||
|
||||
if (pModule) {
|
||||
pDict = PyModule_GetDict(pModule);
|
||||
Py_INCREF(pDict);
|
||||
} else {
|
||||
if (PyErr_Occurred()) {
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
}
|
||||
alert_python_error(NULL);
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,9 @@
|
||||
#define EL__SCRIPTING_PYTHON_CORE_H
|
||||
|
||||
struct module;
|
||||
struct session;
|
||||
|
||||
void alert_python_error(struct session *ses);
|
||||
void init_python(struct module *module);
|
||||
void cleanup_python(struct module *module);
|
||||
|
||||
|
@ -32,29 +32,29 @@ do_script_hook_goto_url(struct session *ses, unsigned char **url)
|
||||
|
||||
if (pFunc && PyCallable_Check(pFunc)) {
|
||||
PyObject *pValue;
|
||||
unsigned char *str;
|
||||
unsigned char *current_url;
|
||||
|
||||
if (!ses || !have_location(ses)) {
|
||||
str = NULL;
|
||||
current_url = NULL;
|
||||
} else {
|
||||
str = struri(cur_loc(ses)->vs.uri);
|
||||
current_url = struri(cur_loc(ses)->vs.uri);
|
||||
}
|
||||
|
||||
pValue = PyObject_CallFunction(pFunc, "ss", *url, str);
|
||||
if (pValue && (pValue != Py_None)) {
|
||||
const unsigned char *res = PyString_AsString(pValue);
|
||||
pValue = PyObject_CallFunction(pFunc, "ss", *url, current_url);
|
||||
if (pValue) {
|
||||
if (pValue != Py_None) {
|
||||
const unsigned char *str;
|
||||
unsigned char *new_url;
|
||||
|
||||
if (res) {
|
||||
unsigned char *new_url = stracpy((unsigned char *)res);
|
||||
|
||||
if (new_url) mem_free_set(url, new_url);
|
||||
str = PyString_AsString(pValue);
|
||||
if (str) {
|
||||
new_url = stracpy((unsigned char *)str);
|
||||
if (new_url) mem_free_set(url, new_url);
|
||||
}
|
||||
}
|
||||
Py_DECREF(pValue);
|
||||
} else {
|
||||
if (PyErr_Occurred()) {
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
}
|
||||
alert_python_error(ses);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -72,26 +72,26 @@ script_hook_goto_url(va_list ap, void *data)
|
||||
}
|
||||
|
||||
static void
|
||||
do_script_hook_follow_url(unsigned char **url)
|
||||
do_script_hook_follow_url(struct session *ses, unsigned char **url)
|
||||
{
|
||||
PyObject *pFunc = PyDict_GetItemString(pDict, "follow_url_hook");
|
||||
|
||||
if (pFunc && PyCallable_Check(pFunc)) {
|
||||
PyObject *pValue = PyObject_CallFunction(pFunc, "s", *url);
|
||||
if (pValue && (pValue != Py_None)) {
|
||||
const unsigned char *str = PyString_AsString(pValue);
|
||||
unsigned char *new_url;
|
||||
if (pValue) {
|
||||
if (pValue != Py_None) {
|
||||
const unsigned char *str;
|
||||
unsigned char *new_url;
|
||||
|
||||
if (str) {
|
||||
new_url = stracpy((unsigned char *)str);
|
||||
if (new_url) mem_free_set(url, new_url);
|
||||
str = PyString_AsString(pValue);
|
||||
if (str) {
|
||||
new_url = stracpy((unsigned char *)str);
|
||||
if (new_url) mem_free_set(url, new_url);
|
||||
}
|
||||
}
|
||||
Py_DECREF(pValue);
|
||||
} else {
|
||||
if (PyErr_Occurred()) {
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
}
|
||||
alert_python_error(ses);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -100,15 +100,17 @@ static enum evhook_status
|
||||
script_hook_follow_url(va_list ap, void *data)
|
||||
{
|
||||
unsigned char **url = va_arg(ap, unsigned char **);
|
||||
struct session *ses = va_arg(ap, struct session *);
|
||||
|
||||
if (pDict && *url)
|
||||
do_script_hook_follow_url(url);
|
||||
do_script_hook_follow_url(ses, url);
|
||||
|
||||
return EVENT_HOOK_STATUS_NEXT;
|
||||
}
|
||||
|
||||
static void
|
||||
do_script_hook_pre_format_html(unsigned char *url, struct cache_entry *cached,
|
||||
do_script_hook_pre_format_html(struct session *ses, unsigned char *url,
|
||||
struct cache_entry *cached,
|
||||
struct fragment *fragment)
|
||||
{
|
||||
PyObject *pFunc = PyDict_GetItemString(pDict, "pre_format_html_hook");
|
||||
@ -118,21 +120,21 @@ do_script_hook_pre_format_html(unsigned char *url, struct cache_entry *cached,
|
||||
fragment->data,
|
||||
fragment->length);
|
||||
|
||||
if (pValue && (pValue != Py_None)) {
|
||||
const unsigned char *str = PyString_AsString(pValue);
|
||||
if (pValue) {
|
||||
if (pValue != Py_None) {
|
||||
const unsigned char *str;
|
||||
int len;
|
||||
|
||||
if (str) {
|
||||
int len = PyString_Size(pValue); /* strlen(str); */
|
||||
|
||||
add_fragment(cached, 0, str, len);
|
||||
normalize_cache_entry(cached, len);
|
||||
str = PyString_AsString(pValue);
|
||||
if (str) {
|
||||
len = PyString_Size(pValue);
|
||||
add_fragment(cached, 0, str, len);
|
||||
normalize_cache_entry(cached, len);
|
||||
}
|
||||
}
|
||||
Py_DECREF(pValue);
|
||||
} else {
|
||||
if (PyErr_Occurred()) {
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
}
|
||||
alert_python_error(ses);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -146,7 +148,7 @@ script_hook_pre_format_html(va_list ap, void *data)
|
||||
unsigned char *url = struri(cached->uri);
|
||||
|
||||
if (pDict && ses && url && cached->length && *fragment->data)
|
||||
do_script_hook_pre_format_html(url, cached, fragment);
|
||||
do_script_hook_pre_format_html(ses, url, cached, fragment);
|
||||
|
||||
return EVENT_HOOK_STATUS_NEXT;
|
||||
}
|
||||
@ -159,20 +161,21 @@ do_script_hook_get_proxy(unsigned char **new_proxy_url, unsigned char *url)
|
||||
if (pFunc && PyCallable_Check(pFunc)) {
|
||||
PyObject *pValue = PyObject_CallFunction(pFunc, "s", url);
|
||||
|
||||
if (pValue && (pValue != Py_None)) {
|
||||
const unsigned char *str = PyString_AsString(pValue);
|
||||
if (pValue) {
|
||||
if (pValue != Py_None) {
|
||||
const unsigned char *str;
|
||||
unsigned char *new_url;
|
||||
|
||||
if (str) {
|
||||
unsigned char *new_url = stracpy((unsigned char *)str);
|
||||
|
||||
if (new_url) mem_free_set(new_proxy_url, new_url);
|
||||
str = PyString_AsString(pValue);
|
||||
if (str) {
|
||||
new_url = stracpy((unsigned char *)str);
|
||||
if (new_url) mem_free_set(new_proxy_url,
|
||||
new_url);
|
||||
}
|
||||
}
|
||||
Py_DECREF(pValue);
|
||||
} else {
|
||||
if (PyErr_Occurred()) {
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
}
|
||||
alert_python_error(NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -198,14 +201,9 @@ do_script_hook_quit(void)
|
||||
PyObject *pValue = PyObject_CallFunction(pFunc, NULL);
|
||||
|
||||
if (pValue) {
|
||||
if (pValue != Py_None) {
|
||||
Py_DECREF(pValue);
|
||||
}
|
||||
Py_DECREF(pValue);
|
||||
} else {
|
||||
if (PyErr_Occurred()) {
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
}
|
||||
alert_python_error(NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -24,10 +24,14 @@
|
||||
#include "scripting/ruby/ruby.h"
|
||||
#include "scripting/smjs/smjs.h"
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
|
||||
/* Error reporting. */
|
||||
|
||||
#if defined(CONFIG_SCRIPTING_RUBY) || defined(CONFIG_SCRIPTING_SPIDERMONKEY)
|
||||
#if defined(CONFIG_SCRIPTING_RUBY) || defined(CONFIG_SCRIPTING_SPIDERMONKEY) || defined(CONFIG_SCRIPTING_PYTHON)
|
||||
void
|
||||
report_scripting_error(struct module *module, struct session *ses,
|
||||
unsigned char *msg)
|
||||
@ -38,6 +42,7 @@ report_scripting_error(struct module *module, struct session *ses,
|
||||
if (!ses) {
|
||||
if (list_empty(terminals)) {
|
||||
usrerror("[%s error] %s", module->name, msg);
|
||||
sleep(3);
|
||||
return;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user