|
a/src/python/recoll/pyrecoll.cpp |
|
b/src/python/recoll/pyrecoll.cpp |
|
... |
|
... |
426 |
"UTF-8", "replace"));
|
426 |
"UTF-8", "replace"));
|
427 |
}
|
427 |
}
|
428 |
return pdict;
|
428 |
return pdict;
|
429 |
}
|
429 |
}
|
430 |
|
430 |
|
431 |
PyDoc_STRVAR(doc_Doc_get,
|
431 |
static bool docget(recoll_DocObject *self, const string& key, string& value)
|
432 |
"get(key) -> value\n"
|
|
|
433 |
"Retrieve the named doc attribute\n"
|
|
|
434 |
);
|
|
|
435 |
static PyObject *
|
|
|
436 |
Doc_get(recoll_DocObject *self, PyObject *args)
|
|
|
437 |
{
|
432 |
{
|
438 |
LOGDEB0("Doc_get\n" );
|
|
|
439 |
char *sutf8 = 0; // needs freeing
|
|
|
440 |
if (!PyArg_ParseTuple(args, "es:Doc_get",
|
|
|
441 |
"utf-8", &sutf8)) {
|
|
|
442 |
return 0;
|
|
|
443 |
}
|
|
|
444 |
string key(sutf8);
|
|
|
445 |
PyMem_Free(sutf8);
|
|
|
446 |
|
|
|
447 |
if (self->doc == 0 ||
|
|
|
448 |
the_docs.find(self->doc) == the_docs.end()) {
|
|
|
449 |
PyErr_SetString(PyExc_AttributeError, "doc??");
|
|
|
450 |
return 0;
|
|
|
451 |
}
|
|
|
452 |
string value;
|
|
|
453 |
bool found = false;
|
|
|
454 |
|
|
|
455 |
//
|
433 |
//
|
456 |
if (!key.compare("xdocid")) {
|
434 |
if (!key.compare("xdocid")) {
|
457 |
char cid[30];
|
435 |
char cid[30];
|
458 |
sprintf(cid, "%lu", (unsigned long)self->doc->xdocid);
|
436 |
sprintf(cid, "%lu", (unsigned long)self->doc->xdocid);
|
459 |
value = cid;
|
437 |
value = cid;
|
460 |
found = true;
|
438 |
return true;
|
461 |
} else {
|
439 |
} else {
|
462 |
if (self->doc->getmeta(key, 0)) {
|
440 |
if (self->doc->getmeta(key, 0)) {
|
463 |
value = self->doc->meta[key];
|
441 |
value = self->doc->meta[key];
|
464 |
found = true;
|
442 |
return true;
|
465 |
}
|
443 |
}
|
466 |
}
|
444 |
}
|
|
|
445 |
return false;
|
|
|
446 |
}
|
|
|
447 |
|
|
|
448 |
PyDoc_STRVAR(doc_Doc_get,
|
|
|
449 |
"get(key) -> value\n"
|
|
|
450 |
"Retrieve the named doc attribute\n"
|
|
|
451 |
);
|
|
|
452 |
static PyObject *
|
|
|
453 |
Doc_get(recoll_DocObject *self, PyObject *args)
|
|
|
454 |
{
|
|
|
455 |
LOGDEB0("Doc_get\n" );
|
|
|
456 |
if (self->doc == 0 || the_docs.find(self->doc) == the_docs.end()) {
|
|
|
457 |
PyErr_SetString(PyExc_AttributeError, "doc??");
|
|
|
458 |
return 0;
|
|
|
459 |
}
|
|
|
460 |
char *sutf8 = 0; // needs freeing
|
|
|
461 |
if (!PyArg_ParseTuple(args, "es:Doc_get", "utf-8", &sutf8)) {
|
|
|
462 |
return 0;
|
|
|
463 |
}
|
|
|
464 |
string key(sutf8);
|
|
|
465 |
PyMem_Free(sutf8);
|
|
|
466 |
|
|
|
467 |
string value;
|
|
|
468 |
bool found = docget(self, key, value);
|
467 |
|
469 |
|
468 |
if (found) {
|
470 |
if (found) {
|
469 |
return PyUnicode_Decode(value.c_str(),
|
471 |
return PyUnicode_Decode(value.c_str(), value.size(), "UTF-8", "replace");
|
470 |
value.size(),
|
|
|
471 |
"UTF-8", "replace");
|
|
|
472 |
}
|
472 |
}
|
473 |
|
473 |
|
474 |
Py_RETURN_NONE;
|
474 |
Py_RETURN_NONE;
|
475 |
}
|
475 |
}
|
476 |
|
476 |
|
|
... |
|
... |
478 |
{"getbinurl", (PyCFunction)Doc_getbinurl, METH_NOARGS, doc_Doc_getbinurl},
|
478 |
{"getbinurl", (PyCFunction)Doc_getbinurl, METH_NOARGS, doc_Doc_getbinurl},
|
479 |
{"setbinurl", (PyCFunction)Doc_setbinurl, METH_O, doc_Doc_setbinurl},
|
479 |
{"setbinurl", (PyCFunction)Doc_setbinurl, METH_O, doc_Doc_setbinurl},
|
480 |
{"keys", (PyCFunction)Doc_keys, METH_NOARGS, doc_Doc_keys},
|
480 |
{"keys", (PyCFunction)Doc_keys, METH_NOARGS, doc_Doc_keys},
|
481 |
{"items", (PyCFunction)Doc_items, METH_NOARGS, doc_Doc_items},
|
481 |
{"items", (PyCFunction)Doc_items, METH_NOARGS, doc_Doc_items},
|
482 |
{"get", (PyCFunction)Doc_get, METH_VARARGS, doc_Doc_get},
|
482 |
{"get", (PyCFunction)Doc_get, METH_VARARGS, doc_Doc_get},
|
|
|
483 |
|
483 |
{NULL} /* Sentinel */
|
484 |
{NULL} /* Sentinel */
|
484 |
};
|
485 |
};
|
485 |
|
486 |
|
486 |
// Note that this returns None if the attribute is not found instead of raising
|
487 |
// Note that this returns None if the attribute is not found instead of raising
|
487 |
// an exception as would be standard. We don't change it to keep existing code
|
488 |
// an exception as would be standard. We don't change it to keep existing code
|
488 |
// working.
|
489 |
// working.
|
489 |
static PyObject *
|
490 |
static PyObject *
|
490 |
Doc_getattro(recoll_DocObject *self, PyObject *nameobj)
|
491 |
Doc_getattro(recoll_DocObject *self, PyObject *nameobj)
|
491 |
{
|
492 |
{
|
492 |
LOGDEB0("Doc_getattro\n" );
|
|
|
493 |
if (self->doc == 0 || the_docs.find(self->doc) == the_docs.end()) {
|
493 |
if (self->doc == 0 || the_docs.find(self->doc) == the_docs.end()) {
|
494 |
PyErr_SetString(PyExc_AttributeError, "doc");
|
494 |
PyErr_SetString(PyExc_AttributeError, "doc");
|
495 |
return 0;
|
495 |
return 0;
|
496 |
}
|
496 |
}
|
497 |
|
497 |
|
|
... |
|
... |
516 |
PyErr_SetString(PyExc_AttributeError, "name not unicode nor string??");
|
516 |
PyErr_SetString(PyExc_AttributeError, "name not unicode nor string??");
|
517 |
Py_RETURN_NONE;
|
517 |
Py_RETURN_NONE;
|
518 |
}
|
518 |
}
|
519 |
|
519 |
|
520 |
key = rclconfig->fieldQCanon(string(name));
|
520 |
key = rclconfig->fieldQCanon(string(name));
|
|
|
521 |
LOGDEB1("Doc_getattro: key: " << key << endl);
|
521 |
|
522 |
|
522 |
switch (key.at(0)) {
|
523 |
switch (key.at(0)) {
|
523 |
case 'u':
|
524 |
case 'u':
|
524 |
if (!key.compare(Rcl::Doc::keyurl)) {
|
525 |
if (!key.compare(Rcl::Doc::keyurl)) {
|
525 |
value = self->doc->url; found = true;
|
526 |
value = self->doc->url; found = true;
|
|
... |
|
... |
594 |
found = true;
|
595 |
found = true;
|
595 |
}
|
596 |
}
|
596 |
}
|
597 |
}
|
597 |
|
598 |
|
598 |
if (found) {
|
599 |
if (found) {
|
599 |
LOGDEB1("Doc_getattro: [" << (key) << "] -> [" << (value) << "]\n" );
|
600 |
LOGDEB1("Doc_getattro: [" << key << "] -> [" << value << "]\n");
|
600 |
// Return a python unicode object
|
601 |
// Return a python unicode object
|
601 |
return PyUnicode_Decode(value.c_str(), value.size(), "utf-8",
|
602 |
return PyUnicode_Decode(value.c_str(), value.size(), "utf-8",
|
602 |
"replace");
|
603 |
"replace");
|
603 |
}
|
604 |
}
|
604 |
|
605 |
|
|
... |
|
... |
640 |
return -1;
|
641 |
return -1;
|
641 |
}
|
642 |
}
|
642 |
char* uvalue = PyBytes_AsString(putf8);
|
643 |
char* uvalue = PyBytes_AsString(putf8);
|
643 |
string key = rclconfig->fieldQCanon(string(name));
|
644 |
string key = rclconfig->fieldQCanon(string(name));
|
644 |
|
645 |
|
645 |
LOGDEB0("Doc_setattr: doc " << (self->doc) << " [" << (key) << "] (" << (name) << ") -> [" << (uvalue) << "]\n" );
|
646 |
LOGDEB0("Doc_setattr: doc " << self->doc << " [" << key << "] (" << name <<
|
|
|
647 |
") -> [" << uvalue << "]\n");
|
646 |
|
648 |
|
647 |
// We set the value in the meta array in all cases. Good idea ? or do it
|
649 |
// We set the value in the meta array in all cases. Good idea ? or do it
|
648 |
// only for fields without a dedicated Doc:: entry?
|
650 |
// only for fields without a dedicated Doc:: entry?
|
649 |
self->doc->meta[key] = uvalue;
|
651 |
self->doc->meta[key] = uvalue;
|
650 |
switch (key.at(0)) {
|
652 |
switch (key.at(0)) {
|
|
... |
|
... |
698 |
break;
|
700 |
break;
|
699 |
}
|
701 |
}
|
700 |
Py_DECREF(putf8);
|
702 |
Py_DECREF(putf8);
|
701 |
return 0;
|
703 |
return 0;
|
702 |
}
|
704 |
}
|
|
|
705 |
|
|
|
706 |
static Py_ssize_t
|
|
|
707 |
Doc_length(recoll_DocObject *self)
|
|
|
708 |
{
|
|
|
709 |
if (self->doc == 0 || the_docs.find(self->doc) == the_docs.end()) {
|
|
|
710 |
PyErr_SetString(PyExc_AttributeError, "doc??");
|
|
|
711 |
return -1;
|
|
|
712 |
}
|
|
|
713 |
return self->doc->meta.size();
|
|
|
714 |
}
|
|
|
715 |
|
|
|
716 |
static PyObject *
|
|
|
717 |
Doc_subscript(recoll_DocObject *self, PyObject *key)
|
|
|
718 |
{
|
|
|
719 |
if (self->doc == 0 || the_docs.find(self->doc) == the_docs.end()) {
|
|
|
720 |
PyErr_SetString(PyExc_AttributeError, "doc??");
|
|
|
721 |
return NULL;
|
|
|
722 |
}
|
|
|
723 |
char *name = 0;
|
|
|
724 |
if (PyUnicode_Check(key)) {
|
|
|
725 |
PyObject* utf8o = PyUnicode_AsUTF8String(key);
|
|
|
726 |
if (utf8o == 0) {
|
|
|
727 |
LOGERR("Doc_getitemo: encoding name to utf8 failed\n" );
|
|
|
728 |
PyErr_SetString(PyExc_AttributeError, "name??");
|
|
|
729 |
Py_RETURN_NONE;
|
|
|
730 |
}
|
|
|
731 |
name = PyBytes_AsString(utf8o);
|
|
|
732 |
Py_DECREF(utf8o);
|
|
|
733 |
} else if (PyBytes_Check(key)) {
|
|
|
734 |
name = PyBytes_AsString(key);
|
|
|
735 |
} else {
|
|
|
736 |
PyErr_SetString(PyExc_AttributeError, "key not unicode nor string??");
|
|
|
737 |
Py_RETURN_NONE;
|
|
|
738 |
}
|
|
|
739 |
|
|
|
740 |
string skey = rclconfig->fieldQCanon(string(name));
|
|
|
741 |
string value;
|
|
|
742 |
bool found = docget(self, skey, value);
|
|
|
743 |
|
|
|
744 |
if (found) {
|
|
|
745 |
return PyUnicode_Decode(value.c_str(), value.size(), "UTF-8", "replace");
|
|
|
746 |
}
|
|
|
747 |
|
|
|
748 |
Py_RETURN_NONE;
|
|
|
749 |
}
|
|
|
750 |
|
|
|
751 |
static PyMappingMethods doc_as_mapping = {
|
|
|
752 |
(lenfunc)Doc_length, /*mp_length*/
|
|
|
753 |
(binaryfunc)Doc_subscript, /*mp_subscript*/
|
|
|
754 |
(objobjargproc)0, /*mp_ass_subscript*/
|
|
|
755 |
};
|
703 |
|
756 |
|
704 |
|
757 |
|
705 |
PyDoc_STRVAR(doc_DocObject,
|
758 |
PyDoc_STRVAR(doc_DocObject,
|
706 |
"Doc()\n"
|
759 |
"Doc()\n"
|
707 |
"\n"
|
760 |
"\n"
|
|
... |
|
... |
743 |
"recoll.Doc", /*tp_name*/
|
796 |
"recoll.Doc", /*tp_name*/
|
744 |
sizeof(recoll_DocObject), /*tp_basicsize*/
|
797 |
sizeof(recoll_DocObject), /*tp_basicsize*/
|
745 |
0, /*tp_itemsize*/
|
798 |
0, /*tp_itemsize*/
|
746 |
(destructor)Doc_dealloc, /*tp_dealloc*/
|
799 |
(destructor)Doc_dealloc, /*tp_dealloc*/
|
747 |
0, /*tp_print*/
|
800 |
0, /*tp_print*/
|
748 |
0, /*tp_getattr*/
|
801 |
0, /*tp_getattr*/
|
749 |
(setattrfunc)Doc_setattr, /*tp_setattr*/
|
802 |
(setattrfunc)Doc_setattr, /*tp_setattr*/
|
750 |
0, /*tp_compare*/
|
803 |
0, /*tp_compare*/
|
751 |
0, /*tp_repr*/
|
804 |
0, /*tp_repr*/
|
752 |
0, /*tp_as_number*/
|
805 |
0, /*tp_as_number*/
|
753 |
0, /*tp_as_sequence*/
|
806 |
0, /*tp_as_sequence*/
|
754 |
0, /*tp_as_mapping*/
|
807 |
&doc_as_mapping, /*tp_as_mapping */
|
755 |
0, /*tp_hash */
|
808 |
0, /*tp_hash */
|
756 |
0, /*tp_call*/
|
809 |
0, /*tp_call*/
|
757 |
0, /*tp_str*/
|
810 |
0, /*tp_str*/
|
758 |
(getattrofunc)Doc_getattro,/*tp_getattro*/
|
811 |
(getattrofunc)Doc_getattro,/*tp_getattro*/
|
759 |
0, /*tp_setattro*/
|
812 |
0, /*tp_setattro*/
|
760 |
0, /*tp_as_buffer*/
|
813 |
0, /*tp_as_buffer*/
|
761 |
Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
|
814 |
Py_TPFLAGS_DEFAULT, /*tp_flags*/
|
762 |
doc_DocObject, /* tp_doc */
|
815 |
doc_DocObject, /* tp_doc */
|
763 |
0, /* tp_traverse */
|
816 |
0, /* tp_traverse */
|
764 |
0, /* tp_clear */
|
817 |
0, /* tp_clear */
|
765 |
0, /* tp_richcompare */
|
818 |
0, /* tp_richcompare */
|
766 |
0, /* tp_weaklistoffset */
|
819 |
0, /* tp_weaklistoffset */
|