Python module: python3 compatibility
This commit is contained in:
parent
3e8989e096
commit
33833c5b22
@ -81,6 +81,7 @@ src/index/alldeps.stamp
|
|||||||
src/index/recollindex
|
src/index/recollindex
|
||||||
src/internfile/alldeps
|
src/internfile/alldeps
|
||||||
src/kde/kioslave/kio_recoll/builddir
|
src/kde/kioslave/kio_recoll/builddir
|
||||||
|
src/lib/Makefile
|
||||||
src/lib/alldeps
|
src/lib/alldeps
|
||||||
src/lib/librecoll.a
|
src/lib/librecoll.a
|
||||||
src/lib/librecoll.so*
|
src/lib/librecoll.so*
|
||||||
|
|||||||
@ -51,7 +51,7 @@ Extractor_dealloc(rclx_ExtractorObject *self)
|
|||||||
{
|
{
|
||||||
LOGDEB(("Extractor_dealloc\n"));
|
LOGDEB(("Extractor_dealloc\n"));
|
||||||
delete self->xtr;
|
delete self->xtr;
|
||||||
self->ob_type->tp_free((PyObject*)self);
|
Py_TYPE(self)->tp_free((PyObject*)self);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
@ -191,8 +191,8 @@ Extractor_idoctofile(rclx_ExtractorObject* self, PyObject *args,
|
|||||||
}
|
}
|
||||||
if (outfile.empty())
|
if (outfile.empty())
|
||||||
temp->setnoremove(1);
|
temp->setnoremove(1);
|
||||||
PyObject *result = outfile.empty() ? PyString_FromString(temp->filename()) :
|
PyObject *result = outfile.empty() ? PyBytes_FromString(temp->filename()) :
|
||||||
PyString_FromString(outfile.c_str());
|
PyBytes_FromString(outfile.c_str());
|
||||||
return (PyObject *)result;
|
return (PyObject *)result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,8 +211,7 @@ PyDoc_STRVAR(doc_ExtractorObject,
|
|||||||
"object.\n"
|
"object.\n"
|
||||||
);
|
);
|
||||||
static PyTypeObject rclx_ExtractorType = {
|
static PyTypeObject rclx_ExtractorType = {
|
||||||
PyObject_HEAD_INIT(NULL)
|
PyVarObject_HEAD_INIT(NULL, 0)
|
||||||
0, /*ob_size*/
|
|
||||||
"rclextract.Extractor", /*tp_name*/
|
"rclextract.Extractor", /*tp_name*/
|
||||||
sizeof(rclx_ExtractorObject), /*tp_basicsize*/
|
sizeof(rclx_ExtractorObject), /*tp_basicsize*/
|
||||||
0, /*tp_itemsize*/
|
0, /*tp_itemsize*/
|
||||||
@ -253,17 +252,56 @@ static PyTypeObject rclx_ExtractorType = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
///////////////////////////////////// Module-level stuff
|
///////////////////////////////////// Module-level stuff
|
||||||
static PyMethodDef rclxMethods[] = {
|
static PyMethodDef rclextract_methods[] = {
|
||||||
{NULL, NULL, 0, NULL} /* Sentinel */
|
{NULL, NULL, 0, NULL} /* Sentinel */
|
||||||
};
|
};
|
||||||
PyDoc_STRVAR(rclx_doc_string,
|
PyDoc_STRVAR(rclx_doc_string,
|
||||||
"This is an interface to the Recoll text extraction features.");
|
"This is an interface to the Recoll text extraction features.");
|
||||||
|
|
||||||
#ifndef PyMODINIT_FUNC /* declarations for DLL import/export */
|
struct module_state {
|
||||||
#define PyMODINIT_FUNC void
|
PyObject *error;
|
||||||
|
};
|
||||||
|
|
||||||
|
#if PY_MAJOR_VERSION >= 3
|
||||||
|
#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m))
|
||||||
|
#else
|
||||||
|
#define GETSTATE(m) (&_state)
|
||||||
|
static struct module_state _state;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if PY_MAJOR_VERSION >= 3
|
||||||
|
static int rclextract_traverse(PyObject *m, visitproc visit, void *arg) {
|
||||||
|
Py_VISIT(GETSTATE(m)->error);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rclextract_clear(PyObject *m) {
|
||||||
|
Py_CLEAR(GETSTATE(m)->error);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct PyModuleDef moduledef = {
|
||||||
|
PyModuleDef_HEAD_INIT,
|
||||||
|
"rclextract",
|
||||||
|
NULL,
|
||||||
|
sizeof(struct module_state),
|
||||||
|
rclextract_methods,
|
||||||
|
NULL,
|
||||||
|
rclextract_traverse,
|
||||||
|
rclextract_clear,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
#define INITERROR return NULL
|
||||||
|
|
||||||
|
extern "C" PyObject *
|
||||||
|
PyInit_rclextract(void)
|
||||||
|
|
||||||
|
#else
|
||||||
|
#define INITERROR return
|
||||||
PyMODINIT_FUNC
|
PyMODINIT_FUNC
|
||||||
initrclextract(void)
|
initrclextract(void)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
// We run recollinit. It's responsible for initializing some static data
|
// We run recollinit. It's responsible for initializing some static data
|
||||||
// which is distinct from pyrecoll's as we're separately dlopened
|
// which is distinct from pyrecoll's as we're separately dlopened
|
||||||
@ -271,33 +309,53 @@ initrclextract(void)
|
|||||||
rclconfig = recollinit(0, 0, reason, 0);
|
rclconfig = recollinit(0, 0, reason, 0);
|
||||||
if (rclconfig == 0) {
|
if (rclconfig == 0) {
|
||||||
PyErr_SetString(PyExc_EnvironmentError, reason.c_str());
|
PyErr_SetString(PyExc_EnvironmentError, reason.c_str());
|
||||||
return;
|
INITERROR;
|
||||||
}
|
}
|
||||||
if (!rclconfig->ok()) {
|
if (!rclconfig->ok()) {
|
||||||
PyErr_SetString(PyExc_EnvironmentError,
|
PyErr_SetString(PyExc_EnvironmentError,
|
||||||
"Recoll init error: bad environment ?");
|
"Recoll init error: bad environment ?");
|
||||||
return;
|
INITERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject* m = Py_InitModule("rclextract", rclxMethods);
|
#if PY_MAJOR_VERSION >= 3
|
||||||
PyModule_AddStringConstant(m, "__doc__", rclx_doc_string);
|
PyObject *module = PyModule_Create(&moduledef);
|
||||||
|
#else
|
||||||
|
PyObject *module = Py_InitModule("rclextract", rclextract_methods);
|
||||||
|
#endif
|
||||||
|
if (module == NULL)
|
||||||
|
INITERROR;
|
||||||
|
|
||||||
|
struct module_state *st = GETSTATE(module);
|
||||||
|
// The first parameter is a char *. Hopefully we don't initialize
|
||||||
|
// modules too often...
|
||||||
|
st->error = PyErr_NewException(strdup("rclextract.Error"), NULL, NULL);
|
||||||
|
if (st->error == NULL) {
|
||||||
|
Py_DECREF(module);
|
||||||
|
INITERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyModule_AddStringConstant(module, "__doc__", rclx_doc_string);
|
||||||
|
|
||||||
if (PyType_Ready(&rclx_ExtractorType) < 0)
|
if (PyType_Ready(&rclx_ExtractorType) < 0)
|
||||||
return;
|
INITERROR;
|
||||||
Py_INCREF(&rclx_ExtractorType);
|
Py_INCREF(&rclx_ExtractorType);
|
||||||
PyModule_AddObject(m, "Extractor", (PyObject *)&rclx_ExtractorType);
|
PyModule_AddObject(module, "Extractor", (PyObject *)&rclx_ExtractorType);
|
||||||
|
|
||||||
#if PY_MAJOR_VERSION >= 2 && PY_MINOR_VERSION >= 7
|
#if PY_MAJOR_VERSION >= 3 || (PY_MAJOR_VERSION >= 2 && PY_MINOR_VERSION >= 7)
|
||||||
recoll_DocType = (PyObject*)PyCapsule_Import(PYRECOLL_PACKAGE "recoll.doctypeptr", 0);
|
recoll_DocType = (PyObject*)PyCapsule_Import(PYRECOLL_PACKAGE "recoll.doctypeptr", 0);
|
||||||
#else
|
#else
|
||||||
PyObject *module = PyImport_ImportModule(PYRECOLL_PACKAGE "recoll");
|
PyObject *module = PyImport_ImportModule(PYRECOLL_PACKAGE "recoll");
|
||||||
if (module != NULL) {
|
if (module != NULL) {
|
||||||
PyObject *cobject = PyObject_GetAttrString(module, "_C_API");
|
PyObject *cobject = PyObject_GetAttrString(module, "_C_API");
|
||||||
if (cobject == NULL)
|
if (cobject == NULL)
|
||||||
return;
|
INITERROR;
|
||||||
if (PyCObject_Check(cobject))
|
if (PyCObject_Check(cobject))
|
||||||
recoll_DocType = (PyObject*)PyCObject_AsVoidPtr(cobject);
|
recoll_DocType = (PyObject*)PyCObject_AsVoidPtr(cobject);
|
||||||
Py_DECREF(cobject);
|
Py_DECREF(cobject);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if PY_MAJOR_VERSION >= 3
|
||||||
|
return module;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@ -47,6 +47,10 @@ static set<Rcl::Doc *> the_docs;
|
|||||||
|
|
||||||
static RclConfig *rclconfig;
|
static RclConfig *rclconfig;
|
||||||
|
|
||||||
|
#if PY_MAJOR_VERSION >=3
|
||||||
|
# define Py_TPFLAGS_HAVE_ITER 0
|
||||||
|
#endif
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
/// SEARCHDATA SearchData code
|
/// SEARCHDATA SearchData code
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -59,7 +63,7 @@ static void
|
|||||||
SearchData_dealloc(recoll_SearchDataObject *self)
|
SearchData_dealloc(recoll_SearchDataObject *self)
|
||||||
{
|
{
|
||||||
LOGDEB(("SearchData_dealloc\n"));
|
LOGDEB(("SearchData_dealloc\n"));
|
||||||
self->ob_type->tp_free((PyObject*)self);
|
Py_TYPE(self)->tp_free((PyObject*)self);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
@ -130,8 +134,7 @@ static PyMethodDef SearchData_methods[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static PyTypeObject recoll_SearchDataType = {
|
static PyTypeObject recoll_SearchDataType = {
|
||||||
PyObject_HEAD_INIT(NULL)
|
PyVarObject_HEAD_INIT(NULL, 0)
|
||||||
0, /*ob_size*/
|
|
||||||
"recoll.SearchData", /*tp_name*/
|
"recoll.SearchData", /*tp_name*/
|
||||||
sizeof(recoll_SearchDataObject), /*tp_basicsize*/
|
sizeof(recoll_SearchDataObject), /*tp_basicsize*/
|
||||||
0, /*tp_itemsize*/
|
0, /*tp_itemsize*/
|
||||||
@ -293,7 +296,7 @@ Doc_dealloc(recoll_DocObject *self)
|
|||||||
if (self->doc)
|
if (self->doc)
|
||||||
the_docs.erase(self->doc);
|
the_docs.erase(self->doc);
|
||||||
deleteZ(self->doc);
|
deleteZ(self->doc);
|
||||||
self->ob_type->tp_free((PyObject*)self);
|
Py_TYPE(self)->tp_free((PyObject*)self);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
@ -463,22 +466,41 @@ static PyMethodDef Doc_methods[] = {
|
|||||||
{NULL} /* Sentinel */
|
{NULL} /* Sentinel */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Note that this returns None if the attribute is not found instead of raising
|
||||||
|
// an exception as would be standard. We don't change it to keep existing code
|
||||||
|
// working.
|
||||||
static PyObject *
|
static PyObject *
|
||||||
Doc_getattr(recoll_DocObject *self, char *name)
|
Doc_getattro(recoll_DocObject *self, PyObject *nameobj)
|
||||||
{
|
{
|
||||||
LOGDEB1(("Doc_getattr: name [%s]\n", name));
|
if (self->doc == 0 || the_docs.find(self->doc) == the_docs.end()) {
|
||||||
if (self->doc == 0 ||
|
|
||||||
the_docs.find(self->doc) == the_docs.end()) {
|
|
||||||
PyErr_SetString(PyExc_AttributeError, "doc");
|
PyErr_SetString(PyExc_AttributeError, "doc");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
string key = rclconfig->fieldCanon(string(name));
|
|
||||||
|
|
||||||
// Handle special cases, then check this is not a method then
|
|
||||||
// try retrieving key value from the meta array
|
|
||||||
|
|
||||||
string value;
|
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
string value;
|
||||||
|
string key;
|
||||||
|
char *name = 0;
|
||||||
|
PyObject* utf8o = 0;
|
||||||
|
|
||||||
|
if (PyUnicode_Check(nameobj)) {
|
||||||
|
utf8o = PyUnicode_AsUTF8String(nameobj);
|
||||||
|
if (utf8o == 0) {
|
||||||
|
LOGERR(("Doc_getattro: encoding name to utf8 failed\n"));
|
||||||
|
PyErr_SetString(PyExc_AttributeError, "name??");
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
}
|
||||||
|
name = PyBytes_AsString(utf8o);
|
||||||
|
Py_DECREF(utf8o);
|
||||||
|
} else if (PyBytes_Check(nameobj)) {
|
||||||
|
name = PyBytes_AsString(nameobj);
|
||||||
|
} else {
|
||||||
|
PyErr_SetString(PyExc_AttributeError, "name not unicode nor string??");
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
key = rclconfig->fieldCanon(string(name));
|
||||||
|
|
||||||
switch (key.at(0)) {
|
switch (key.at(0)) {
|
||||||
case 'u':
|
case 'u':
|
||||||
if (!key.compare(Rcl::Doc::keyurl)) {
|
if (!key.compare(Rcl::Doc::keyurl)) {
|
||||||
@ -533,48 +555,46 @@ Doc_getattr(recoll_DocObject *self, char *name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!found) {
|
if (!found) {
|
||||||
PyObject *meth = Py_FindMethod(Doc_methods, (PyObject*)self,
|
// This will look up a method name (we have no other standard
|
||||||
key.c_str());
|
// attributes)
|
||||||
|
PyObject *meth = PyObject_GenericGetAttr((PyObject*)self, nameobj);
|
||||||
if (meth) {
|
if (meth) {
|
||||||
return meth;
|
return meth;
|
||||||
} else {
|
|
||||||
PyErr_Clear();
|
|
||||||
}
|
}
|
||||||
|
PyErr_Clear();
|
||||||
|
// Else look for another attribute
|
||||||
if (self->doc->getmeta(key, 0)) {
|
if (self->doc->getmeta(key, 0)) {
|
||||||
value = self->doc->meta[key];
|
value = self->doc->meta[key];
|
||||||
found = true;
|
found = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!found) {
|
if (found) {
|
||||||
LOGDEB(("Doc_getattr: name [%s] key [%s] Not found\n",
|
LOGDEB1(("Doc_getattro: [%s] -> [%s]\n", key.c_str(), value.c_str()));
|
||||||
name, key.c_str()));
|
// Return a python unicode object
|
||||||
Py_RETURN_NONE;
|
return PyUnicode_Decode(value.c_str(), value.size(), "utf-8",
|
||||||
|
"replace");
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGDEB1(("Doc_getattr: [%s] (%s) -> [%s]\n",
|
Py_RETURN_NONE;
|
||||||
name, key.c_str(), value.c_str()));
|
|
||||||
// Return a python unicode object
|
|
||||||
PyObject* res = PyUnicode_Decode(value.c_str(), value.size(), "utf-8",
|
|
||||||
"replace");
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
Doc_setattr(recoll_DocObject *self, char *name, PyObject *value)
|
Doc_setattr(recoll_DocObject *self, char *name, PyObject *value)
|
||||||
{
|
{
|
||||||
if (self->doc == 0 ||
|
if (self->doc == 0 || the_docs.find(self->doc) == the_docs.end()) {
|
||||||
the_docs.find(self->doc) == the_docs.end()) {
|
|
||||||
PyErr_SetString(PyExc_AttributeError, "doc??");
|
PyErr_SetString(PyExc_AttributeError, "doc??");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
LOGDEB1(("Doc_setmeta: doc %p\n", self->doc));
|
LOGDEB1(("Doc_setmeta: doc %p\n", self->doc));
|
||||||
|
|
||||||
|
#if PY_MAJOR_VERSION < 3
|
||||||
if (PyString_Check(value)) {
|
if (PyString_Check(value)) {
|
||||||
value = PyUnicode_FromObject(value);
|
value = PyUnicode_FromObject(value);
|
||||||
if (value == 0)
|
if (value == 0)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!PyUnicode_Check(value)) {
|
if (!PyUnicode_Check(value)) {
|
||||||
PyErr_SetString(PyExc_AttributeError, "value not str/unicode??");
|
PyErr_SetString(PyExc_AttributeError, "value not str/unicode??");
|
||||||
@ -591,8 +611,8 @@ Doc_setattr(recoll_DocObject *self, char *name, PyObject *value)
|
|||||||
PyErr_SetString(PyExc_AttributeError, "value??");
|
PyErr_SetString(PyExc_AttributeError, "value??");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
char* uvalue = PyBytes_AsString(putf8);
|
||||||
char* uvalue = PyString_AsString(putf8);
|
Py_DECREF(putf8);
|
||||||
string key = rclconfig->fieldCanon(string(name));
|
string key = rclconfig->fieldCanon(string(name));
|
||||||
|
|
||||||
LOGDEB0(("Doc_setattr: [%s] (%s) -> [%s]\n", key.c_str(), name, uvalue));
|
LOGDEB0(("Doc_setattr: [%s] (%s) -> [%s]\n", key.c_str(), name, uvalue));
|
||||||
@ -690,14 +710,13 @@ PyDoc_STRVAR(doc_DocObject,
|
|||||||
" keywords (both)\n"
|
" keywords (both)\n"
|
||||||
);
|
);
|
||||||
static PyTypeObject recoll_DocType = {
|
static PyTypeObject recoll_DocType = {
|
||||||
PyObject_HEAD_INIT(NULL)
|
PyVarObject_HEAD_INIT(NULL, 0)
|
||||||
0, /*ob_size*/
|
|
||||||
"recoll.Doc", /*tp_name*/
|
"recoll.Doc", /*tp_name*/
|
||||||
sizeof(recoll_DocObject), /*tp_basicsize*/
|
sizeof(recoll_DocObject), /*tp_basicsize*/
|
||||||
0, /*tp_itemsize*/
|
0, /*tp_itemsize*/
|
||||||
(destructor)Doc_dealloc, /*tp_dealloc*/
|
(destructor)Doc_dealloc, /*tp_dealloc*/
|
||||||
0, /*tp_print*/
|
0, /*tp_print*/
|
||||||
(getattrfunc)Doc_getattr, /*tp_getattr*/
|
0, /*tp_getattr*/
|
||||||
(setattrfunc)Doc_setattr, /*tp_setattr*/
|
(setattrfunc)Doc_setattr, /*tp_setattr*/
|
||||||
0, /*tp_compare*/
|
0, /*tp_compare*/
|
||||||
0, /*tp_repr*/
|
0, /*tp_repr*/
|
||||||
@ -707,7 +726,7 @@ static PyTypeObject recoll_DocType = {
|
|||||||
0, /*tp_hash */
|
0, /*tp_hash */
|
||||||
0, /*tp_call*/
|
0, /*tp_call*/
|
||||||
0, /*tp_str*/
|
0, /*tp_str*/
|
||||||
0, /*tp_getattro*/
|
(getattrofunc)Doc_getattro,/*tp_getattro*/
|
||||||
0, /*tp_setattro*/
|
0, /*tp_setattro*/
|
||||||
0, /*tp_as_buffer*/
|
0, /*tp_as_buffer*/
|
||||||
Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
|
Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
|
||||||
@ -768,7 +787,7 @@ Query_dealloc(recoll_QueryObject *self)
|
|||||||
{
|
{
|
||||||
LOGDEB(("Query_dealloc\n"));
|
LOGDEB(("Query_dealloc\n"));
|
||||||
Query_close(self);
|
Query_close(self);
|
||||||
self->ob_type->tp_free((PyObject*)self);
|
Py_TYPE(self)->tp_free((PyObject*)self);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
@ -1118,7 +1137,7 @@ public:
|
|||||||
PyObject *res1 = res;
|
PyObject *res1 = res;
|
||||||
if (PyUnicode_Check(res))
|
if (PyUnicode_Check(res))
|
||||||
res1 = PyUnicode_AsUTF8String(res);
|
res1 = PyUnicode_AsUTF8String(res);
|
||||||
return PyString_AsString(res1);
|
return PyBytes_AsString(res1);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual string endMatch()
|
virtual string endMatch()
|
||||||
@ -1131,7 +1150,7 @@ public:
|
|||||||
PyObject *res1 = res;
|
PyObject *res1 = res;
|
||||||
if (PyUnicode_Check(res))
|
if (PyUnicode_Check(res))
|
||||||
res1 = PyUnicode_AsUTF8String(res);
|
res1 = PyUnicode_AsUTF8String(res);
|
||||||
return PyString_AsString(res1);
|
return PyBytes_AsString(res1);
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject *m_methods;
|
PyObject *m_methods;
|
||||||
@ -1393,8 +1412,7 @@ PyDoc_STRVAR(doc_QueryObject,
|
|||||||
"They must be created by the Db.query() method.\n"
|
"They must be created by the Db.query() method.\n"
|
||||||
);
|
);
|
||||||
static PyTypeObject recoll_QueryType = {
|
static PyTypeObject recoll_QueryType = {
|
||||||
PyObject_HEAD_INIT(NULL)
|
PyVarObject_HEAD_INIT(NULL, 0)
|
||||||
0, /*ob_size*/
|
|
||||||
"recoll.Query", /*tp_name*/
|
"recoll.Query", /*tp_name*/
|
||||||
sizeof(recoll_QueryObject), /*tp_basicsize*/
|
sizeof(recoll_QueryObject), /*tp_basicsize*/
|
||||||
0, /*tp_itemsize*/
|
0, /*tp_itemsize*/
|
||||||
@ -1458,7 +1476,7 @@ Db_dealloc(recoll_DbObject *self)
|
|||||||
{
|
{
|
||||||
LOGDEB(("Db_dealloc\n"));
|
LOGDEB(("Db_dealloc\n"));
|
||||||
Db_close(self);
|
Db_close(self);
|
||||||
self->ob_type->tp_free((PyObject*)self);
|
Py_TYPE(self)->tp_free((PyObject*)self);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
@ -1530,7 +1548,7 @@ Db_init(recoll_DbObject *self, PyObject *args, PyObject *kwargs)
|
|||||||
}
|
}
|
||||||
for (int i = 0; i < dbcnt; i++) {
|
for (int i = 0; i < dbcnt; i++) {
|
||||||
PyObject *item = PySequence_GetItem(extradbs, i);
|
PyObject *item = PySequence_GetItem(extradbs, i);
|
||||||
char *s = PyString_AsString(item);
|
char *s = PyBytes_AsString(item);
|
||||||
Py_DECREF(item);
|
Py_DECREF(item);
|
||||||
if (!s) {
|
if (!s) {
|
||||||
PyErr_SetString(PyExc_TypeError,
|
PyErr_SetString(PyExc_TypeError,
|
||||||
@ -1857,8 +1875,7 @@ PyDoc_STRVAR(doc_DbObject,
|
|||||||
"writable decides if we can index new data through this connection\n"
|
"writable decides if we can index new data through this connection\n"
|
||||||
);
|
);
|
||||||
static PyTypeObject recoll_DbType = {
|
static PyTypeObject recoll_DbType = {
|
||||||
PyObject_HEAD_INIT(NULL)
|
PyVarObject_HEAD_INIT(NULL, 0)
|
||||||
0, /*ob_size*/
|
|
||||||
"recoll.Db", /*tp_name*/
|
"recoll.Db", /*tp_name*/
|
||||||
sizeof(recoll_DbObject), /*tp_basicsize*/
|
sizeof(recoll_DbObject), /*tp_basicsize*/
|
||||||
0, /*tp_itemsize*/
|
0, /*tp_itemsize*/
|
||||||
@ -1920,7 +1937,7 @@ PyDoc_STRVAR(doc_connect,
|
|||||||
"writable decides if we can index new data through this connection\n"
|
"writable decides if we can index new data through this connection\n"
|
||||||
);
|
);
|
||||||
|
|
||||||
static PyMethodDef recollMethods[] = {
|
static PyMethodDef recoll_methods[] = {
|
||||||
{"connect", (PyCFunction)recoll_connect, METH_VARARGS|METH_KEYWORDS,
|
{"connect", (PyCFunction)recoll_connect, METH_VARARGS|METH_KEYWORDS,
|
||||||
doc_connect},
|
doc_connect},
|
||||||
|
|
||||||
@ -1931,50 +1948,110 @@ static PyMethodDef recollMethods[] = {
|
|||||||
PyDoc_STRVAR(pyrecoll_doc_string,
|
PyDoc_STRVAR(pyrecoll_doc_string,
|
||||||
"This is an interface to the Recoll full text indexer.");
|
"This is an interface to the Recoll full text indexer.");
|
||||||
|
|
||||||
#ifndef PyMODINIT_FUNC /* declarations for DLL import/export */
|
struct module_state {
|
||||||
#define PyMODINIT_FUNC void
|
PyObject *error;
|
||||||
|
};
|
||||||
|
|
||||||
|
#if PY_MAJOR_VERSION >= 3
|
||||||
|
#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m))
|
||||||
|
#else
|
||||||
|
#define GETSTATE(m) (&_state)
|
||||||
|
static struct module_state _state;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if PY_MAJOR_VERSION >= 3
|
||||||
|
static int recoll_traverse(PyObject *m, visitproc visit, void *arg) {
|
||||||
|
Py_VISIT(GETSTATE(m)->error);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int recoll_clear(PyObject *m) {
|
||||||
|
Py_CLEAR(GETSTATE(m)->error);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct PyModuleDef moduledef = {
|
||||||
|
PyModuleDef_HEAD_INIT,
|
||||||
|
"recoll",
|
||||||
|
NULL,
|
||||||
|
sizeof(struct module_state),
|
||||||
|
recoll_methods,
|
||||||
|
NULL,
|
||||||
|
recoll_traverse,
|
||||||
|
recoll_clear,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
#define INITERROR return NULL
|
||||||
|
|
||||||
|
extern "C" PyObject *
|
||||||
|
PyInit_recoll(void)
|
||||||
|
|
||||||
|
#else
|
||||||
|
#define INITERROR return
|
||||||
|
|
||||||
PyMODINIT_FUNC
|
PyMODINIT_FUNC
|
||||||
initrecoll(void)
|
initrecoll(void)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
// Note: we can't call recollinit here, because the confdir is only really
|
// Note: we can't call recollinit here, because the confdir is only really
|
||||||
// known when the first db object is created (it is an optional parameter).
|
// known when the first db object is created (it is an optional parameter).
|
||||||
// Using a default here may end up with variables such as stripchars being
|
// Using a default here may end up with variables such as stripchars being
|
||||||
// wrong
|
// wrong
|
||||||
|
|
||||||
PyObject* m;
|
#if PY_MAJOR_VERSION >= 3
|
||||||
m = Py_InitModule3("recoll", recollMethods, "Recoll extension module.");
|
PyObject *module = PyModule_Create(&moduledef);
|
||||||
|
#else
|
||||||
|
PyObject *module = Py_InitModule("recoll", recoll_methods);
|
||||||
|
#endif
|
||||||
|
if (module == NULL)
|
||||||
|
INITERROR;
|
||||||
|
|
||||||
|
struct module_state *st = GETSTATE(module);
|
||||||
|
// The first parameter is a char *. Hopefully we don't initialize
|
||||||
|
// modules too often...
|
||||||
|
st->error = PyErr_NewException(strdup("recoll.Error"), NULL, NULL);
|
||||||
|
if (st->error == NULL) {
|
||||||
|
Py_DECREF(module);
|
||||||
|
INITERROR;
|
||||||
|
}
|
||||||
|
|
||||||
if (PyType_Ready(&recoll_DbType) < 0)
|
if (PyType_Ready(&recoll_DbType) < 0)
|
||||||
return;
|
INITERROR;
|
||||||
Py_INCREF((PyObject*)&recoll_DbType);
|
Py_INCREF((PyObject*)&recoll_DbType);
|
||||||
PyModule_AddObject(m, "Db", (PyObject *)&recoll_DbType);
|
PyModule_AddObject(module, "Db", (PyObject *)&recoll_DbType);
|
||||||
|
|
||||||
if (PyType_Ready(&recoll_QueryType) < 0)
|
if (PyType_Ready(&recoll_QueryType) < 0)
|
||||||
return;
|
INITERROR;
|
||||||
Py_INCREF((PyObject*)&recoll_QueryType);
|
Py_INCREF((PyObject*)&recoll_QueryType);
|
||||||
PyModule_AddObject(m, "Query", (PyObject *)&recoll_QueryType);
|
PyModule_AddObject(module, "Query", (PyObject *)&recoll_QueryType);
|
||||||
|
|
||||||
if (PyType_Ready(&recoll_DocType) < 0)
|
if (PyType_Ready(&recoll_DocType) < 0)
|
||||||
return;
|
INITERROR;
|
||||||
Py_INCREF((PyObject*)&recoll_DocType);
|
Py_INCREF((PyObject*)&recoll_DocType);
|
||||||
PyModule_AddObject(m, "Doc", (PyObject *)&recoll_DocType);
|
PyModule_AddObject(module, "Doc", (PyObject *)&recoll_DocType);
|
||||||
|
|
||||||
if (PyType_Ready(&recoll_SearchDataType) < 0)
|
if (PyType_Ready(&recoll_SearchDataType) < 0)
|
||||||
return;
|
INITERROR;
|
||||||
Py_INCREF((PyObject*)&recoll_SearchDataType);
|
Py_INCREF((PyObject*)&recoll_SearchDataType);
|
||||||
PyModule_AddObject(m, "SearchData", (PyObject *)&recoll_SearchDataType);
|
PyModule_AddObject(module, "SearchData",
|
||||||
PyModule_AddStringConstant(m, "__doc__",
|
(PyObject *)&recoll_SearchDataType);
|
||||||
|
PyModule_AddStringConstant(module, "__doc__",
|
||||||
pyrecoll_doc_string);
|
pyrecoll_doc_string);
|
||||||
|
|
||||||
PyObject *doctypecobject;
|
PyObject *doctypecobject;
|
||||||
|
|
||||||
#if PY_MAJOR_VERSION >= 2 && PY_MINOR_VERSION >= 7
|
#if PY_MAJOR_VERSION >= 3 || (PY_MAJOR_VERSION >= 2 && PY_MINOR_VERSION >= 7)
|
||||||
// Export a few pointers for the benefit of other recoll python modules
|
// Export a few pointers for the benefit of other recoll python modules
|
||||||
doctypecobject=
|
doctypecobject=
|
||||||
PyCapsule_New(&recoll_DocType, PYRECOLL_PACKAGE "recoll.doctypeptr", 0);
|
PyCapsule_New(&recoll_DocType, PYRECOLL_PACKAGE "recoll.doctypeptr", 0);
|
||||||
#else
|
#else
|
||||||
doctypecobject = PyCObject_FromVoidPtr(&recoll_DocType, NULL);
|
doctypecobject = PyCObject_FromVoidPtr(&recoll_DocType, NULL);
|
||||||
#endif
|
#endif
|
||||||
PyModule_AddObject(m, "doctypeptr", doctypecobject);
|
|
||||||
|
PyModule_AddObject(module, "doctypeptr", doctypecobject);
|
||||||
|
|
||||||
|
#if PY_MAJOR_VERSION >= 3
|
||||||
|
return module;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@ -53,20 +53,20 @@ class ConfSimple:
|
|||||||
value = value.strip()
|
value = value.strip()
|
||||||
#print "Name:", nm, "Value:", value
|
#print "Name:", nm, "Value:", value
|
||||||
|
|
||||||
if not self.submaps.has_key(submapkey):
|
if not submapkey in self.submaps:
|
||||||
self.submaps[submapkey] = {}
|
self.submaps[submapkey] = {}
|
||||||
self.submaps[submapkey][nm] = value
|
self.submaps[submapkey][nm] = value
|
||||||
|
|
||||||
def get(self, nm, sk = ''):
|
def get(self, nm, sk = ''):
|
||||||
'''Returns None if not found, empty string if found empty'''
|
'''Returns None if not found, empty string if found empty'''
|
||||||
if not self.submaps.has_key(sk):
|
if not sk in self.submaps:
|
||||||
return None
|
return None
|
||||||
if not self.submaps[sk].has_key(nm):
|
if not nm in self.submaps[sk]:
|
||||||
return None
|
return None
|
||||||
return self.submaps[sk][nm]
|
return self.submaps[sk][nm]
|
||||||
|
|
||||||
def getNames(self, sk = ''):
|
def getNames(self, sk = ''):
|
||||||
if not self.submaps.has_key(sk):
|
if not sk in self.submaps:
|
||||||
return None
|
return None
|
||||||
return self.submaps[sk].keys()
|
return self.submaps[sk].keys()
|
||||||
|
|
||||||
@ -141,7 +141,7 @@ class RclConfig:
|
|||||||
# Find configuration directory
|
# Find configuration directory
|
||||||
if argcnf is not None:
|
if argcnf is not None:
|
||||||
self.confdir = os.path.abspath(argcnf)
|
self.confdir = os.path.abspath(argcnf)
|
||||||
elif os.environ.has_key("RECOLL_CONFDIR"):
|
elif "RECOLL_CONFDIR" in os.environ:
|
||||||
self.confdir = os.environ["RECOLL_CONFDIR"]
|
self.confdir = os.environ["RECOLL_CONFDIR"]
|
||||||
else:
|
else:
|
||||||
self.confdir = os.path.expanduser("~/.recoll")
|
self.confdir = os.path.expanduser("~/.recoll")
|
||||||
@ -150,7 +150,7 @@ class RclConfig:
|
|||||||
# "configure" in the C code. We can only do our best. Have to
|
# "configure" in the C code. We can only do our best. Have to
|
||||||
# choose a preference order. Use RECOLL_DATADIR if the order is wrong
|
# choose a preference order. Use RECOLL_DATADIR if the order is wrong
|
||||||
self.datadir = None
|
self.datadir = None
|
||||||
if os.environ.has_key("RECOLL_DATADIR"):
|
if "RECOLL_DATADIR" in os.environ:
|
||||||
self.datadir = os.environ["RECOLL_DATADIR"]
|
self.datadir = os.environ["RECOLL_DATADIR"]
|
||||||
else:
|
else:
|
||||||
dirs = ("/opt/local", "/usr", "/usr/local")
|
dirs = ("/opt/local", "/usr", "/usr/local")
|
||||||
@ -164,11 +164,11 @@ class RclConfig:
|
|||||||
self.cdirs = []
|
self.cdirs = []
|
||||||
|
|
||||||
# Additional config directory, values override user ones
|
# Additional config directory, values override user ones
|
||||||
if os.environ.has_key("RECOLL_CONFTOP"):
|
if "RECOLL_CONFTOP" in os.environ:
|
||||||
self.cdirs.append(os.environ["RECOLL_CONFTOP"])
|
self.cdirs.append(os.environ["RECOLL_CONFTOP"])
|
||||||
self.cdirs.append(self.confdir)
|
self.cdirs.append(self.confdir)
|
||||||
# Additional config directory, overrides system's, overridden by user's
|
# Additional config directory, overrides system's, overridden by user's
|
||||||
if os.environ.has_key("RECOLL_CONFMID"):
|
if "RECOLL_CONFMID" in os.environ:
|
||||||
self.cdirs.append(os.environ["RECOLL_CONFMID"])
|
self.cdirs.append(os.environ["RECOLL_CONFMID"])
|
||||||
self.cdirs.append(os.path.join(self.datadir, "examples"))
|
self.cdirs.append(os.path.join(self.datadir, "examples"))
|
||||||
|
|
||||||
@ -195,4 +195,4 @@ class RclExtraDbs:
|
|||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
config = RclConfig()
|
config = RclConfig()
|
||||||
print config.getConfParam("topdirs")
|
print(config.getConfParam("topdirs"))
|
||||||
|
|||||||
@ -8,7 +8,7 @@ top = os.path.join('..', '..')
|
|||||||
library_dirs = [os.path.join(top, 'lib')]
|
library_dirs = [os.path.join(top, 'lib')]
|
||||||
libraries = ['recoll']
|
libraries = ['recoll']
|
||||||
|
|
||||||
if os.environ.has_key('libdir') and os.environ['libdir'] != "":
|
if 'libdir' in os.environ and os.environ['libdir'] != "":
|
||||||
runtime_library_dirs = [os.path.join(os.environ['libdir'], 'recoll')]
|
runtime_library_dirs = [os.path.join(os.environ['libdir'], 'recoll')]
|
||||||
else:
|
else:
|
||||||
runtime_library_dirs = [os.path.join('@prefix@', 'lib', 'recoll')]
|
runtime_library_dirs = [os.path.join('@prefix@', 'lib', 'recoll')]
|
||||||
@ -18,7 +18,7 @@ localdefs = os.path.join(top, 'mk', 'localdefs')
|
|||||||
try:
|
try:
|
||||||
lines = open(localdefs, 'r').readlines()
|
lines = open(localdefs, 'r').readlines()
|
||||||
except:
|
except:
|
||||||
print 'You need to build recoll first. Use configure --enable-pic'
|
print('You need to build recoll first. Use configure --enable-pic')
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
picok = False
|
picok = False
|
||||||
for line in lines:
|
for line in lines:
|
||||||
@ -26,7 +26,7 @@ for line in lines:
|
|||||||
picok = True
|
picok = True
|
||||||
break
|
break
|
||||||
if not picok:
|
if not picok:
|
||||||
print 'You need to rebuild recoll with PIC enabled. Use configure --enable-pic and make clean'
|
print('You need to rebuild recoll with PIC enabled. Use configure --enable-pic and make clean')
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -9,6 +9,11 @@ import sys
|
|||||||
import locale
|
import locale
|
||||||
from getopt import getopt
|
from getopt import getopt
|
||||||
|
|
||||||
|
if sys.version_info[0] >= 3:
|
||||||
|
ISP3 = True
|
||||||
|
else:
|
||||||
|
ISP3 = False
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from recoll import recoll
|
from recoll import recoll
|
||||||
from recoll import rclextract
|
from recoll import rclextract
|
||||||
@ -21,7 +26,7 @@ allmeta = ("title", "keywords", "abstract", "url", "mimetype", "mtime",
|
|||||||
"ipath", "fbytes", "dbytes", "relevancyrating")
|
"ipath", "fbytes", "dbytes", "relevancyrating")
|
||||||
|
|
||||||
def Usage():
|
def Usage():
|
||||||
print >> sys.stderr, "Usage: recollq.py [-c conf] [-i extra_index] <recoll query>"
|
print("Usage: recollq.py [-c conf] [-i extra_index] <recoll query>")
|
||||||
sys.exit(1);
|
sys.exit(1);
|
||||||
|
|
||||||
class ptrmeths:
|
class ptrmeths:
|
||||||
@ -44,6 +49,12 @@ def extractofile(doc, outfilename=""):
|
|||||||
ofilename=outfilename)
|
ofilename=outfilename)
|
||||||
return outfilename
|
return outfilename
|
||||||
|
|
||||||
|
def utf8string(s):
|
||||||
|
if ISP3:
|
||||||
|
return s
|
||||||
|
else:
|
||||||
|
return s.encode('utf8')
|
||||||
|
|
||||||
def doquery(db, q):
|
def doquery(db, q):
|
||||||
# Get query object
|
# Get query object
|
||||||
query = db.query()
|
query = db.query()
|
||||||
@ -51,14 +62,13 @@ def doquery(db, q):
|
|||||||
|
|
||||||
# Parse/run input query string
|
# Parse/run input query string
|
||||||
nres = query.execute(q, stemming = 0, stemlang="english")
|
nres = query.execute(q, stemming = 0, stemlang="english")
|
||||||
qs = u"Xapian query: [%s]" % query.getxquery()
|
qs = "Xapian query: [%s]" % query.getxquery()
|
||||||
print(qs.encode("utf-8"))
|
print(utf8string(qs))
|
||||||
groups = query.getgroups()
|
groups = query.getgroups()
|
||||||
print "Groups:", groups
|
|
||||||
m = ptrmeths(groups)
|
m = ptrmeths(groups)
|
||||||
|
|
||||||
# Print results:
|
# Print results:
|
||||||
print "Result count: ", nres, query.rowcount
|
print("Result count: %d %d" % (nres, query.rowcount))
|
||||||
if nres > 20:
|
if nres > 20:
|
||||||
nres = 20
|
nres = 20
|
||||||
#results = query.fetchmany(nres)
|
#results = query.fetchmany(nres)
|
||||||
@ -68,24 +78,24 @@ def doquery(db, q):
|
|||||||
doc = query.fetchone()
|
doc = query.fetchone()
|
||||||
rownum = query.next if type(query.next) == int else \
|
rownum = query.next if type(query.next) == int else \
|
||||||
query.rownumber
|
query.rownumber
|
||||||
print rownum, ":",
|
print("%d:"%(rownum,))
|
||||||
#for k,v in doc.items().items():
|
#for k,v in doc.items().items():
|
||||||
#print "KEY:", k.encode('utf-8'), "VALUE", v.encode('utf-8')
|
#print "KEY:", utf8string(k), "VALUE", utf8string(v)
|
||||||
#continue
|
#continue
|
||||||
#outfile = extractofile(doc)
|
#outfile = extractofile(doc)
|
||||||
#print "outfile:", outfile, "url", doc.url.encode("utf-8")
|
#print "outfile:", outfile, "url", utf8string(doc.url)
|
||||||
for k in ("title", "mtime", "author"):
|
for k in ("title", "mtime", "author"):
|
||||||
value = getattr(doc, k)
|
value = getattr(doc, k)
|
||||||
# value = doc.get(k)
|
# value = doc.get(k)
|
||||||
if value is None:
|
if value is None:
|
||||||
print k, ":", "(None)"
|
print("%s: (None)"%(k,))
|
||||||
else:
|
else:
|
||||||
print k, ":", value.encode('utf-8')
|
print("%s : %s"%(k, utf8string(value)))
|
||||||
#doc.setbinurl(bytearray("toto"))
|
#doc.setbinurl(bytearray("toto"))
|
||||||
#burl = doc.getbinurl(); print "Bin URL :", doc.getbinurl()
|
#burl = doc.getbinurl(); print("Bin URL : [%s]"%(doc.getbinurl(),))
|
||||||
abs = query.makedocabstract(doc, methods=m)
|
abs = query.makedocabstract(doc, methods=m)
|
||||||
print abs.encode('utf-8')
|
print(utf8string(abs))
|
||||||
print
|
print('')
|
||||||
# fulldoc = extract(doc)
|
# fulldoc = extract(doc)
|
||||||
# print "FULLDOC MIMETYPE", fulldoc.mimetype, "TEXT:", fulldoc.text.encode("utf-8")
|
# print "FULLDOC MIMETYPE", fulldoc.mimetype, "TEXT:", fulldoc.text.encode("utf-8")
|
||||||
|
|
||||||
@ -109,20 +119,19 @@ for opt,val in options:
|
|||||||
elif opt == "-i":
|
elif opt == "-i":
|
||||||
extra_dbs.append(val)
|
extra_dbs.append(val)
|
||||||
else:
|
else:
|
||||||
print >> sys.stderr, "Bad opt: ", opt
|
print("Bad opt: %s"%(opt,))
|
||||||
Usage()
|
Usage()
|
||||||
|
|
||||||
# The query should be in the remaining arg(s)
|
# The query should be in the remaining arg(s)
|
||||||
if len(args) == 0:
|
if len(args) == 0:
|
||||||
print >> sys.stderr, "No query found in command line"
|
print("No query found in command line")
|
||||||
Usage()
|
Usage()
|
||||||
q = u''
|
q = ''
|
||||||
for word in args:
|
for word in args:
|
||||||
q += word.decode(localecharset) + u' '
|
q += word + ' '
|
||||||
|
|
||||||
print "QUERY: [", q, "]"
|
print("QUERY: [%s]"%(q,))
|
||||||
db = recoll.connect(confdir=confdir,
|
db = recoll.connect(confdir=confdir, extra_dbs=extra_dbs)
|
||||||
extra_dbs=extra_dbs)
|
|
||||||
db.setAbstractParams(maxchars=maxchars, contextwords=contextwords)
|
db.setAbstractParams(maxchars=maxchars, contextwords=contextwords)
|
||||||
|
|
||||||
doquery(db, q)
|
doquery(db, q)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user