|
a/src/python/recoll/pyrecoll.cpp |
|
b/src/python/recoll/pyrecoll.cpp |
|
... |
|
... |
72 |
if (self == 0)
|
72 |
if (self == 0)
|
73 |
return 0;
|
73 |
return 0;
|
74 |
return (PyObject *)self;
|
74 |
return (PyObject *)self;
|
75 |
}
|
75 |
}
|
76 |
|
76 |
|
|
|
77 |
PyDoc_STRVAR(doc_SearchDataObject,
|
|
|
78 |
"SearchData([type=AND|OR], [stemlang=somelanguage|null])\n"
|
|
|
79 |
"\n"
|
|
|
80 |
"A SearchData object describes a query. It has a number of global\n"
|
|
|
81 |
"parameters and a chain of search clauses.\n"
|
|
|
82 |
);
|
|
|
83 |
|
77 |
static int
|
84 |
static int
|
78 |
SearchData_init(recoll_SearchDataObject *self, PyObject *args, PyObject *kwargs)
|
85 |
SearchData_init(recoll_SearchDataObject *self, PyObject *args, PyObject *kwargs)
|
79 |
{
|
86 |
{
|
80 |
LOGDEB(("SearchData_init\n"));
|
87 |
LOGDEB(("SearchData_init\n"));
|
81 |
static const char* kwlist[] = {"type", NULL};
|
88 |
static const char* kwlist[] = {"type", "stemlang", NULL};
|
82 |
char *stp = 0;
|
89 |
char *stp = 0;
|
|
|
90 |
char *steml = 0;
|
83 |
|
91 |
|
84 |
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s", (char**)kwlist, &stp))
|
92 |
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|sz", (char**)kwlist,
|
|
|
93 |
&stp, &steml))
|
85 |
return -1;
|
94 |
return -1;
|
86 |
Rcl::SClType tp = Rcl::SCLT_AND;
|
95 |
Rcl::SClType tp = Rcl::SCLT_AND;
|
87 |
|
96 |
|
88 |
if (stp && strcasecmp(stp, "or")) {
|
97 |
if (stp && strcasecmp(stp, "or")) {
|
89 |
tp = Rcl::SCLT_OR;
|
98 |
tp = Rcl::SCLT_OR;
|
90 |
}
|
99 |
}
|
|
|
100 |
string stemlang;
|
|
|
101 |
if (steml) {
|
|
|
102 |
stemlang = steml;
|
|
|
103 |
} else {
|
|
|
104 |
stemlang = "english";
|
|
|
105 |
}
|
91 |
self->sd = RefCntr<Rcl::SearchData>(new Rcl::SearchData(tp, "english"));
|
106 |
self->sd = RefCntr<Rcl::SearchData>(new Rcl::SearchData(tp, stemlang));
|
92 |
return 0;
|
107 |
return 0;
|
93 |
}
|
108 |
}
|
94 |
|
109 |
|
95 |
/* Note: addclause necessite And/Or vient du fait que le string peut avoir
|
110 |
/* Note: addclause necessite And/Or vient du fait que le string peut avoir
|
96 |
plusieurs mots. A transferer dans l'i/f Python ou pas ? */
|
111 |
plusieurs mots. A transferer dans l'i/f Python ou pas ? */
|
97 |
PyDoc_STRVAR(doc_addclause,
|
112 |
PyDoc_STRVAR(doc_addclause,
|
98 |
"addclause(type='and'|'or'|'excl'|'phrase'|'near'|'sub',\n"
|
113 |
"addclause(type='and'|'or'|'filename'|'phrase'|'near'|'path'|'sub',\n"
|
99 |
" qstring=string, slack=int, field=string, stemming=1|0,\n"
|
114 |
" qstring=string, slack=int, field=string, stemming=1|0,\n"
|
100 |
" subSearch=SearchData)\n"
|
115 |
" subSearch=SearchData, exclude=0|1, anchorstart=0|1, anchorend=0|1,\n"
|
|
|
116 |
" casesens=0|1, diacsens=0|1)\n"
|
101 |
"Adds a simple clause to the SearchData And/Or chain, or a subquery\n"
|
117 |
"Adds a simple clause to the SearchData And/Or chain, or a subquery\n"
|
102 |
"defined by another SearchData object\n"
|
118 |
"defined by another SearchData object\n"
|
103 |
);
|
119 |
);
|
104 |
|
120 |
|
105 |
/* Forward declaration only, definition needs recoll_searchDataType */
|
121 |
/* Forward declaration only, definition needs recoll_searchDataType */
|
106 |
static PyObject *
|
122 |
static PyObject *
|
107 |
SearchData_addclause(recoll_SearchDataObject* self, PyObject *args,
|
123 |
SearchData_addclause(recoll_SearchDataObject* self, PyObject *args,
|
108 |
PyObject *kwargs);
|
124 |
PyObject *kwargs);
|
109 |
|
|
|
110 |
|
|
|
111 |
|
125 |
|
112 |
static PyMethodDef SearchData_methods[] = {
|
126 |
static PyMethodDef SearchData_methods[] = {
|
113 |
{"addclause", (PyCFunction)SearchData_addclause, METH_VARARGS|METH_KEYWORDS,
|
127 |
{"addclause", (PyCFunction)SearchData_addclause, METH_VARARGS|METH_KEYWORDS,
|
114 |
doc_addclause},
|
128 |
doc_addclause},
|
115 |
{NULL} /* Sentinel */
|
129 |
{NULL} /* Sentinel */
|
116 |
};
|
130 |
};
|
117 |
|
131 |
|
118 |
PyDoc_STRVAR(doc_SearchDataObject,
|
|
|
119 |
"SearchData()\n"
|
|
|
120 |
"\n"
|
|
|
121 |
"A SearchData object describes a query. It has a number of global\n"
|
|
|
122 |
"parameters and a chain of search clauses.\n"
|
|
|
123 |
);
|
|
|
124 |
static PyTypeObject recoll_SearchDataType = {
|
132 |
static PyTypeObject recoll_SearchDataType = {
|
125 |
PyObject_HEAD_INIT(NULL)
|
133 |
PyObject_HEAD_INIT(NULL)
|
126 |
0, /*ob_size*/
|
134 |
0, /*ob_size*/
|
127 |
"recoll.SearchData", /*tp_name*/
|
135 |
"recoll.SearchData", /*tp_name*/
|
128 |
sizeof(recoll_SearchDataObject), /*tp_basicsize*/
|
136 |
sizeof(recoll_SearchDataObject), /*tp_basicsize*/
|
|
... |
|
... |
172 |
LOGERR(("SearchData_addclause: not init??\n"));
|
180 |
LOGERR(("SearchData_addclause: not init??\n"));
|
173 |
PyErr_SetString(PyExc_AttributeError, "sd");
|
181 |
PyErr_SetString(PyExc_AttributeError, "sd");
|
174 |
return 0;
|
182 |
return 0;
|
175 |
}
|
183 |
}
|
176 |
static const char *kwlist[] = {"type", "qstring", "slack", "field",
|
184 |
static const char *kwlist[] = {"type", "qstring", "slack", "field",
|
177 |
"stemming", "subsearch", NULL};
|
185 |
"stemming", "subsearch",
|
|
|
186 |
"exclude", "anchorstart", "anchorend",
|
|
|
187 |
"casesens", "diacsens",
|
|
|
188 |
NULL};
|
178 |
char *tp = 0;
|
189 |
char *tp = 0;
|
179 |
char *qs = 0; // needs freeing
|
190 |
char *qs = 0; // needs freeing
|
180 |
int slack = 0;
|
191 |
int slack = 0;
|
181 |
char *fld = 0; // needs freeing
|
192 |
char *fld = 0; // needs freeing
|
182 |
int dostem = 1;
|
193 |
PyObject *dostem = 0;
|
183 |
recoll_SearchDataObject *sub = 0;
|
194 |
recoll_SearchDataObject *sub = 0;
|
|
|
195 |
PyObject *exclude = 0;
|
|
|
196 |
PyObject *anchorstart = 0;
|
|
|
197 |
PyObject *anchorend = 0;
|
|
|
198 |
PyObject *casesens = 0;
|
|
|
199 |
PyObject *diacsens = 0;
|
184 |
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ses|iesiO!", (char**)kwlist,
|
200 |
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ses|iesOO!OOOOO",
|
|
|
201 |
(char**)kwlist,
|
185 |
&tp, "utf-8", &qs, &slack,
|
202 |
&tp, "utf-8", &qs, &slack,
|
186 |
"utf-8", &fld, &dostem,
|
203 |
"utf-8", &fld, &dostem,
|
187 |
&recoll_SearchDataType, &sub))
|
204 |
&recoll_SearchDataType, &sub,
|
|
|
205 |
&exclude, &anchorstart, &anchorend,
|
|
|
206 |
&casesens, &diacsens
|
|
|
207 |
))
|
188 |
return 0;
|
208 |
return 0;
|
189 |
|
209 |
|
190 |
Rcl::SearchDataClause *cl = 0;
|
210 |
Rcl::SearchDataClause *cl = 0;
|
191 |
|
211 |
|
192 |
switch (tp[0]) {
|
212 |
switch (tp[0]) {
|
|
... |
|
... |
194 |
case 'A':
|
214 |
case 'A':
|
195 |
if (strcasecmp(tp, "and"))
|
215 |
if (strcasecmp(tp, "and"))
|
196 |
goto defaultcase;
|
216 |
goto defaultcase;
|
197 |
cl = new Rcl::SearchDataClauseSimple(Rcl::SCLT_AND, qs, fld?fld:"");
|
217 |
cl = new Rcl::SearchDataClauseSimple(Rcl::SCLT_AND, qs, fld?fld:"");
|
198 |
break;
|
218 |
break;
|
|
|
219 |
case 'f':
|
|
|
220 |
case 'F':
|
|
|
221 |
if (strcasecmp(tp, "filename"))
|
|
|
222 |
goto defaultcase;
|
|
|
223 |
cl = new Rcl::SearchDataClauseFilename(qs);
|
|
|
224 |
break;
|
199 |
case 'o':
|
225 |
case 'o':
|
200 |
case 'O':
|
226 |
case 'O':
|
201 |
if (strcasecmp(tp, "or"))
|
227 |
if (strcasecmp(tp, "or"))
|
202 |
goto defaultcase;
|
228 |
goto defaultcase;
|
203 |
cl = new Rcl::SearchDataClauseSimple(Rcl::SCLT_OR, qs, fld?fld:"");
|
229 |
cl = new Rcl::SearchDataClauseSimple(Rcl::SCLT_OR, qs, fld?fld:"");
|
204 |
break;
|
|
|
205 |
case 'e':
|
|
|
206 |
case 'E':
|
|
|
207 |
if (strcasecmp(tp, "excl"))
|
|
|
208 |
goto defaultcase;
|
|
|
209 |
cl = new Rcl::SearchDataClauseSimple(Rcl::SCLT_OR, qs, fld?fld:"");
|
|
|
210 |
cl->setexclude(true);
|
|
|
211 |
break;
|
230 |
break;
|
212 |
case 'n':
|
231 |
case 'n':
|
213 |
case 'N':
|
232 |
case 'N':
|
214 |
if (strcasecmp(tp, "near"))
|
233 |
if (strcasecmp(tp, "near"))
|
215 |
goto defaultcase;
|
234 |
goto defaultcase;
|
216 |
cl = new Rcl::SearchDataClauseDist(Rcl::SCLT_NEAR, qs, slack,
|
235 |
cl = new Rcl::SearchDataClauseDist(Rcl::SCLT_NEAR, qs, slack,
|
217 |
fld ? fld : "");
|
236 |
fld ? fld : "");
|
218 |
break;
|
237 |
break;
|
219 |
case 'p':
|
238 |
case 'p':
|
220 |
case 'P':
|
239 |
case 'P':
|
221 |
if (strcasecmp(tp, "phrase"))
|
240 |
if (!strcasecmp(tp, "phrase")) {
|
|
|
241 |
cl = new Rcl::SearchDataClauseDist(Rcl::SCLT_PHRASE, qs, slack,
|
|
|
242 |
fld ? fld : "");
|
|
|
243 |
} else if (!strcasecmp(tp, "path")) {
|
|
|
244 |
cl = new Rcl::SearchDataClausePath(qs);
|
|
|
245 |
} else {
|
222 |
goto defaultcase;
|
246 |
goto defaultcase;
|
223 |
cl = new Rcl::SearchDataClauseDist(Rcl::SCLT_PHRASE, qs, slack,
|
247 |
}
|
224 |
fld ? fld : "");
|
|
|
225 |
break;
|
248 |
break;
|
226 |
case 's':
|
249 |
case 's':
|
227 |
case 'S':
|
250 |
case 'S':
|
228 |
if (strcasecmp(tp, "sub"))
|
251 |
if (strcasecmp(tp, "sub"))
|
229 |
goto defaultcase;
|
252 |
goto defaultcase;
|
|
... |
|
... |
232 |
defaultcase:
|
255 |
defaultcase:
|
233 |
default:
|
256 |
default:
|
234 |
PyErr_SetString(PyExc_AttributeError, "Bad tp arg");
|
257 |
PyErr_SetString(PyExc_AttributeError, "Bad tp arg");
|
235 |
return 0;
|
258 |
return 0;
|
236 |
}
|
259 |
}
|
237 |
if (dostem == 0) {
|
|
|
238 |
cl->setModifiers(Rcl::SearchDataClause::SDCM_NOSTEMMING);
|
|
|
239 |
}
|
|
|
240 |
|
|
|
241 |
PyMem_Free(qs);
|
260 |
PyMem_Free(qs);
|
242 |
PyMem_Free(fld);
|
261 |
PyMem_Free(fld);
|
|
|
262 |
|
|
|
263 |
if (dostem != 0 && !PyObject_IsTrue(dostem)) {
|
|
|
264 |
cl->addModifier(Rcl::SearchDataClause::SDCM_NOSTEMMING);
|
|
|
265 |
}
|
|
|
266 |
if (exclude != 0 && !PyObject_IsTrue(exclude)) {
|
|
|
267 |
cl->setexclude(true);
|
|
|
268 |
}
|
|
|
269 |
if (anchorstart && PyObject_IsTrue(anchorstart)) {
|
|
|
270 |
cl->addModifier(Rcl::SearchDataClause::SDCM_ANCHORSTART);
|
|
|
271 |
}
|
|
|
272 |
if (anchorend && PyObject_IsTrue(anchorend)) {
|
|
|
273 |
cl->addModifier(Rcl::SearchDataClause::SDCM_ANCHOREND);
|
|
|
274 |
}
|
|
|
275 |
if (casesens && PyObject_IsTrue(casesens)) {
|
|
|
276 |
cl->addModifier(Rcl::SearchDataClause::SDCM_CASESENS);
|
|
|
277 |
}
|
|
|
278 |
if (diacsens && PyObject_IsTrue(diacsens)) {
|
|
|
279 |
cl->addModifier(Rcl::SearchDataClause::SDCM_DIACSENS);
|
|
|
280 |
}
|
243 |
self->sd->addClause(cl);
|
281 |
self->sd->addClause(cl);
|
244 |
Py_RETURN_NONE;
|
282 |
Py_RETURN_NONE;
|
245 |
}
|
283 |
}
|
246 |
|
284 |
|
247 |
|
285 |
|
|
... |
|
... |
1424 |
}
|
1462 |
}
|
1425 |
|
1463 |
|
1426 |
static PyObject *
|
1464 |
static PyObject *
|
1427 |
Db_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
1465 |
Db_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
1428 |
{
|
1466 |
{
|
1429 |
LOGDEB(("Db_new\n"));
|
|
|
1430 |
recoll_DbObject *self;
|
1467 |
recoll_DbObject *self;
|
1431 |
|
1468 |
|
1432 |
self = (recoll_DbObject *)type->tp_alloc(type, 0);
|
1469 |
self = (recoll_DbObject *)type->tp_alloc(type, 0);
|
1433 |
if (self == 0)
|
1470 |
if (self == 0)
|
1434 |
return 0;
|
1471 |
return 0;
|
|
... |
|
... |
1437 |
}
|
1474 |
}
|
1438 |
|
1475 |
|
1439 |
static int
|
1476 |
static int
|
1440 |
Db_init(recoll_DbObject *self, PyObject *args, PyObject *kwargs)
|
1477 |
Db_init(recoll_DbObject *self, PyObject *args, PyObject *kwargs)
|
1441 |
{
|
1478 |
{
|
1442 |
LOGDEB(("Db_init\n"));
|
|
|
1443 |
static const char *kwlist[] = {"confdir", "extra_dbs", "writable", NULL};
|
1479 |
static const char *kwlist[] = {"confdir", "extra_dbs", "writable", NULL};
|
1444 |
PyObject *extradbs = 0;
|
1480 |
PyObject *extradbs = 0;
|
1445 |
char *confdir = 0;
|
1481 |
char *confdir = 0;
|
1446 |
int writable = 0;
|
1482 |
int writable = 0;
|
1447 |
|
1483 |
|
|
... |
|
... |
1457 |
string cfd = confdir;
|
1493 |
string cfd = confdir;
|
1458 |
rclconfig = recollinit(0, 0, reason, &cfd);
|
1494 |
rclconfig = recollinit(0, 0, reason, &cfd);
|
1459 |
} else {
|
1495 |
} else {
|
1460 |
rclconfig = recollinit(0, 0, reason, 0);
|
1496 |
rclconfig = recollinit(0, 0, reason, 0);
|
1461 |
}
|
1497 |
}
|
|
|
1498 |
LOGDEB(("Db_init\n"));
|
|
|
1499 |
|
1462 |
if (rclconfig == 0) {
|
1500 |
if (rclconfig == 0) {
|
1463 |
PyErr_SetString(PyExc_EnvironmentError, reason.c_str());
|
1501 |
PyErr_SetString(PyExc_EnvironmentError, reason.c_str());
|
1464 |
return -1;
|
1502 |
return -1;
|
1465 |
}
|
1503 |
}
|
1466 |
if (!rclconfig->ok()) {
|
1504 |
if (!rclconfig->ok()) {
|
|
... |
|
... |
1784 |
//////////////////////////////////////////////////////////////////////////
|
1822 |
//////////////////////////////////////////////////////////////////////////
|
1785 |
// Module methods
|
1823 |
// Module methods
|
1786 |
static PyObject *
|
1824 |
static PyObject *
|
1787 |
recoll_connect(PyObject *self, PyObject *args, PyObject *kwargs)
|
1825 |
recoll_connect(PyObject *self, PyObject *args, PyObject *kwargs)
|
1788 |
{
|
1826 |
{
|
1789 |
LOGDEB(("recoll_connect\n"));
|
|
|
1790 |
recoll_DbObject *db = (recoll_DbObject *)
|
1827 |
recoll_DbObject *db = (recoll_DbObject *)
|
1791 |
PyObject_Call((PyObject *)&recoll_DbType, args, kwargs);
|
1828 |
PyObject_Call((PyObject *)&recoll_DbType, args, kwargs);
|
1792 |
return (PyObject *)db;
|
1829 |
return (PyObject *)db;
|
1793 |
}
|
1830 |
}
|
1794 |
|
1831 |
|
|
... |
|
... |
1818 |
#define PyMODINIT_FUNC void
|
1855 |
#define PyMODINIT_FUNC void
|
1819 |
#endif
|
1856 |
#endif
|
1820 |
PyMODINIT_FUNC
|
1857 |
PyMODINIT_FUNC
|
1821 |
initrecoll(void)
|
1858 |
initrecoll(void)
|
1822 |
{
|
1859 |
{
|
1823 |
string reason;
|
1860 |
// Note: we can't call recollinit here, because the confdir is only really
|
1824 |
rclconfig = recollinit(0, 0, reason, 0);
|
1861 |
// known when the first db object is created (it is an optional parameter).
|
1825 |
if (rclconfig == 0) {
|
1862 |
// Using a default here may end up with variables such as stripchars being
|
1826 |
PyErr_SetString(PyExc_EnvironmentError, reason.c_str());
|
1863 |
// wrong
|
1827 |
return;
|
|
|
1828 |
}
|
|
|
1829 |
if (!rclconfig->ok()) {
|
|
|
1830 |
PyErr_SetString(PyExc_EnvironmentError,
|
|
|
1831 |
"Recoll init error: bad environment ?");
|
|
|
1832 |
return;
|
|
|
1833 |
}
|
|
|
1834 |
|
1864 |
|
1835 |
PyObject* m;
|
1865 |
PyObject* m;
|
1836 |
m = Py_InitModule3("recoll", recollMethods,
|
1866 |
m = Py_InitModule3("recoll", recollMethods, "Recoll extension module.");
|
1837 |
"Recoll extension module.");
|
|
|
1838 |
|
1867 |
|
1839 |
if (PyType_Ready(&recoll_DbType) < 0)
|
1868 |
if (PyType_Ready(&recoll_DbType) < 0)
|
1840 |
return;
|
1869 |
return;
|
1841 |
Py_INCREF((PyObject*)&recoll_DbType);
|
1870 |
Py_INCREF((PyObject*)&recoll_DbType);
|
1842 |
PyModule_AddObject(m, "Db", (PyObject *)&recoll_DbType);
|
1871 |
PyModule_AddObject(m, "Db", (PyObject *)&recoll_DbType);
|