| 247 | } |
| 248 | |
| 249 | size_t CorpusObject::addDoc(PyObject* words, PyObject* raw, PyObject* userData, PyObject* additionalKwargs) |
| 250 | { |
| 251 | if (!isIndependent()) |
| 252 | throw py::RuntimeError{ "Cannot modify the corpus bound to a topic model." }; |
| 253 | tomoto::RawDoc doc; |
| 254 | |
| 255 | py::UniqueObj stopwords{ PyObject_GetAttrString((PyObject*)this, "_stopwords") }; |
| 256 | |
| 257 | if (PyObject_HasAttrString((PyObject*)this, "_tokenizer") |
| 258 | && PyObject_IsTrue(py::UniqueObj{ PyObject_GetAttrString((PyObject*)this, "_tokenizer") }.get())) |
| 259 | { |
| 260 | if (words && words != Py_None) throw py::ValueError{ "only `raw` is required when `tokenizer` is provided." }; |
| 261 | if (!PyObject_IsTrue(raw)) return py::buildPyValue(-1); |
| 262 | |
| 263 | py::UniqueObj tokenizer{ PyObject_GetAttrString((PyObject*)this, "_tokenizer") }; |
| 264 | |
| 265 | py::UniqueObj args{ PyTuple_New(1) }; |
| 266 | Py_INCREF(raw); |
| 267 | PyTuple_SetItem(args.get(), 0, raw); |
| 268 | py::UniqueObj kwargs{ PyDict_New() }; |
| 269 | PyDict_SetItemString(kwargs.get(), "user_data", userData); |
| 270 | |
| 271 | py::UniqueObj ret{ PyObject_Call(tokenizer.get(), args.get(), kwargs.get())}; |
| 272 | if (!ret) throw py::ExcPropagation{}; |
| 273 | py::foreach<PyObject*>(ret.get(), [&](PyObject* t) |
| 274 | { |
| 275 | if (PyUnicode_Check(t)) |
| 276 | { |
| 277 | doc.words.emplace_back(vocab->vocabs->add(py::toCpp<std::string>(t))); |
| 278 | } |
| 279 | else if (t == Py_None) |
| 280 | { |
| 281 | doc.words.emplace_back(tomoto::non_vocab_id); |
| 282 | } |
| 283 | else if (PyTuple_Size(t) == 3) |
| 284 | { |
| 285 | PyObject* word = PyTuple_GetItem(t, 0); |
| 286 | PyObject* pos = PyTuple_GetItem(t, 1); |
| 287 | PyObject* len = PyTuple_GetItem(t, 2); |
| 288 | if (!((PyUnicode_Check(word) || word == Py_None) && PyLong_Check(pos) && PyLong_Check(len))) throw py::ValueError{ "`tokenizer` must return an iterable of `str` or `tuple` of (`str`, `int`, `int`)." }; |
| 289 | bool isStopword = false; |
| 290 | if (stopwords.get() != Py_None) |
| 291 | { |
| 292 | py::UniqueObj stopRet{ PyObject_CallObject(stopwords.get(), py::buildPyTuple(word).get())}; |
| 293 | if (!stopRet) throw py::ExcPropagation{}; |
| 294 | isStopword = PyObject_IsTrue(stopRet.get()); |
| 295 | } |
| 296 | else if (word == Py_None) |
| 297 | { |
| 298 | isStopword = true; |
| 299 | } |
| 300 | doc.words.emplace_back(isStopword ? tomoto::non_vocab_id : vocab->vocabs->add(py::toCpp<std::string>(word))); |
| 301 | doc.origWordPos.emplace_back(PyLong_AsLong(pos)); |
| 302 | doc.origWordLen.emplace_back(PyLong_AsLong(len)); |
| 303 | } |
| 304 | else |
| 305 | { |
| 306 | throw py::ValueError{ "`tokenizer` must return an iterable of `str` or `tuple` of (`str`, `int`, `int`)." }; |
nothing calls this directly
no test coverage detected