1
0
mirror of https://github.com/rkd77/elinks.git synced 2024-06-15 23:35:34 +00:00

Fixes to the Python scripting by M. Levinson

This commit is contained in:
Witold Filipczyk 2006-07-24 18:52:25 +02:00 committed by Witold Filipczyk
parent 29fb051fc9
commit 6c8f532692
6 changed files with 158 additions and 79 deletions

View File

@ -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

View File

@ -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!

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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);
}
}
}

View File

@ -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;
}