Repository: bab2min/tomotopy (language: python)

Issue:
pyLDAvis for PAModel visualization
Hello,
When I'm trying to visualize the distributions from PAModel with pyLDAvis, I use `get_sub_topic_dist()` for the documents distributions, like this:

`dt_dist = np.stack([doc.get_sub_topic_dist() for doc in mdl.docs])`

But I get this error:

`SystemError: \python\getargs.c:1463: bad argument to internal function`

How can I solve this?


Discussion / hints:
Hi @juneMJ 
Thank you for reporting the bug.
There was a bug at the internal C++ implementation of `get_sub_topic_dist()` method.
https://github.com/bab2min/tomotopy/blob/073c44334a0141e4831ede575ad66b26343ff81d/src/python/py_utils.cpp#L1200
Actually, it should take one argument `normalize` but it was declared as `METH_NOARGS`, which is causing the bug you reported.
I'll fix it asap.
Thank you again for your reporting.

Fix patch:
diff --git a/README.kr.rst b/README.kr.rst
index 9665d4c..01a85c8 100644
--- a/README.kr.rst
+++ b/README.kr.rst
@@ -305,6 +305,13 @@ tomotopy의 Python3 예제 코드는 https://github.com/bab2min/tomotopy/blob/ma
 
 역사
 -------
+* 0.12.4 (2023-01-22)
+    * New features
+        * macOS ARM64 아키텍처에 대한 지원을 추가했습니다.
+    * Bug fixes
+        * `tomotopy.Document.get_sub_topic_dist()`가 bad argument 예외를 발생시키는 문제를 해결했습니다.
+        * 예외 발생이 종종 크래시를 발생시키는 문제를 해결했습니다.
+
 * 0.12.3 (2022-07-19)
     * 기능 개선
         * 이제 `tomotopy.LDAModel.add_doc()`로 빈 문서를 삽입할 경우 예외를 발생시키는 대신 그냥 무시합니다. 새로 추가된 인자인 `ignore_empty_words`를 False로 설정할 경우 이전처럼 예외를 발생시킵니다.
diff --git a/README.rst b/README.rst
index d6f7e0c..ae94398 100644
--- a/README.rst
+++ b/README.rst
@@ -309,6 +309,13 @@ meaning you can use it for any reasonable purpose and remain in complete ownersh
 
 History
 -------
+* 0.12.4 (2023-01-22)
+    * New features
+        * Added support for macOS ARM64 architecture.
+    * Bug fixes
+        * Fixed an issue where `tomotopy.Document.get_sub_topic_dist()` raises a bad argument exception.
+        * Fixed an issue where exception raising sometimes causes crashes.
+
 * 0.12.3 (2022-07-19)
     * New features
         * Now, inserting an empty document using `tomotopy.LDAModel.add_doc()` just ignores it instead of raising an exception. If the newly added argument `ignore_empty_words` is set to False, an exception is raised as before.
diff --git a/document/document_header.html b/document/document_header.html
index 932b2d5..b665750 100644
--- a/document/document_header.html
+++ b/document/document_header.html
@@ -10,8 +10,9 @@
 <a class="homelink" rel="home" title="tomotopy Home" href="/tomotopy" style="display:block; font-size:2em; font-weight:bold; color:#555; padding-bottom:.5em; border-bottom:1px solid silver;"> <img src="/tomotopy/tomoto.png" alt="" style="height:1.5em;"> tomotopy </a>
 <a id='lang-en' href="../en/index.html">English</a> <a id='lang-kr' href="../kr/index.html">한국어</a> 
 <div id="version-link">
-<span>v0.12.3</span>
+<span>v0.12.4</span>
 <ul>
+	<li><a href='/tomotopy/v0.12.4/en'>v0.12.4</a></li>
 	<li><a href='/tomotopy/v0.12.3/en'>v0.12.3</a></li>
 	<li><a href='/tomotopy/v0.12.2/en'>v0.12.2</a></li>
 	<li><a href='/tomotopy/v0.12.1/en'>v0.12.1</a></li>
diff --git a/src/python/PyUtils.h b/src/python/PyUtils.h
index aec7ad1..fe41592 100644
--- a/src/python/PyUtils.h
+++ b/src/python/PyUtils.h
@@ -1313,6 +1313,7 @@ namespace py
 			{
 				PyObject* exc, * val, * tb, * val2;
 				PyErr_Fetch(&exc, &val, &tb);
+				PyErr_NormalizeException(&exc, &val, &tb);
 				if (tb)
 				{
 					PyException_SetTraceback(val, tb);
@@ -1321,7 +1322,9 @@ namespace py
 				Py_DECREF(exc);
 				PyObject* et = e.pytype();
 				val2 = PyObject_CallFunctionObjArgs(et, py::UniqueObj{ buildPyValue(e.what()) }.get(), nullptr);
+				Py_INCREF(val);
 				PyException_SetCause(val2, val);
+				PyException_SetContext(val2, val);
 				PyErr_SetObject(et, val2);
 				Py_DECREF(val2);
 			}
@@ -1355,6 +1358,7 @@ namespace py
 			{
 				PyObject* exc, * val, * tb, * val2;
 				PyErr_Fetch(&exc, &val, &tb);
+				PyErr_NormalizeException(&exc, &val, &tb);
 				if (tb)
 				{
 					PyException_SetTraceback(val, tb);
@@ -1363,7 +1367,9 @@ namespace py
 				Py_DECREF(exc);
 				PyObject* et = e.pytype();
 				val2 = PyObject_CallFunctionObjArgs(et, py::UniqueObj{ buildPyValue(e.what()) }.get(), nullptr);
+				Py_INCREF(val);
 				PyException_SetCause(val2, val);
+				PyException_SetContext(val2, val);
 				PyErr_SetObject(et, val2);
 				Py_DECREF(val2);
 			}
diff --git a/src/python/py_utils.cpp b/src/python/py_utils.cpp
index 0c916be..88415fb 100644
--- a/src/python/py_utils.cpp
+++ b/src/python/py_utils.cpp
@@ -1197,7 +1197,7 @@ static PyMethodDef UtilsDocument_methods[] =
 	{ "get_topic_dist", (PyCFunction)Document_getTopicDist, METH_VARARGS | METH_KEYWORDS, Document_get_topic_dist__doc__ },
 #ifdef TM_PA
 	{ "get_sub_topics", (PyCFunction)Document_getSubTopics, METH_VARARGS | METH_KEYWORDS, Document_get_sub_topics__doc__ },
-	{ "get_sub_topic_dist", (PyCFunction)Document_getSubTopicDist, METH_NOARGS, Document_get_sub_topic_dist__doc__ },
+	{ "get_sub_topic_dist", (PyCFunction)Document_getSubTopicDist, METH_VARARGS | METH_KEYWORDS, Document_get_sub_topic_dist__doc__ },
 #endif
 	{ "get_words", (PyCFunction)Document_getWords, METH_VARARGS | METH_KEYWORDS, Document_get_words__doc__ },
 	{ "get_count_vector", (PyCFunction)Document_getCountVector, METH_NOARGS, Document_get_count_vector__doc__ },
diff --git a/tomotopy/_version.py b/tomotopy/_version.py
index c4e914a..0a44c27 100644
--- a/tomotopy/_version.py
+++ b/tomotopy/_version.py
@@ -1,1 +1,1 @@
-__version__ = '0.12.3'
+__version__ = '0.12.4'
diff --git a/tomotopy/documentation.kr.rst b/tomotopy/documentation.kr.rst
index dd260a9..89ad6b5 100644
--- a/tomotopy/documentation.kr.rst
+++ b/tomotopy/documentation.kr.rst
@@ -386,6 +386,13 @@ tomotopy의 Python3 예제 코드는 https://github.com/bab2min/tomotopy/blob/ma
 
 역사
 -------
+* 0.12.4 (2023-01-22)
+    * New features
+        * macOS ARM64 아키텍처에 대한 지원을 추가했습니다.
+    * Bug fixes
+        * `tomotopy.Document.get_sub_topic_dist()`가 bad argument 예외를 발생시키는 문제를 해결했습니다.
+        * 예외 발생이 종종 크래시를 발생시키는 문제를 해결했습니다.
+
 * 0.12.3 (2022-07-19)
     * 기능 개선
         * 이제 `tomotopy.LDAModel.add_doc()`로 빈 문서를 삽입할 경우 예외를 발생시키는 대신 그냥 무시합니다. 새로 추가된 인자인 `ignore_empty_words`를 False로 설정할 경우 이전처럼 예외를 발생시킵니다.
diff --git a/tomotopy/documentation.rst b/tomotopy/documentation.rst
index 01a484d..bf46de3 100644
--- a/tomotopy/documentation.rst
+++ b/tomotopy/documentation.rst
@@ -389,6 +389,13 @@ meaning you can use it for any reasonable purpose and remain in complete ownersh
 
 History
 -------
+* 0.12.4 (2023-01-22)
+    * New features
+        * Added support for macOS ARM64 architecture.
+    * Bug fixes
+        * Fixed an issue where `tomotopy.Document.get_sub_topic_dist()` raises a bad argument exception.
+        * Fixed an issue where exception raising sometimes causes crashes.
+
 * 0.12.3 (2022-07-19)
     * New features
         * Now, inserting an empty document using `tomotopy.LDAModel.add_doc()` just ignores it instead of raising an exception. If the newly added argument `ignore_empty_words` is set to False, an exception is raised as before.


Test patch:
diff --git a/test/unit_test.py b/test/unit_test.py
index 71aa672..9edd95f 100644
--- a/test/unit_test.py
+++ b/test/unit_test.py
@@ -247,6 +247,15 @@ def infer_together(cls, inputFile, mdFields, f, kargs, ps):
 
     mdl.infer(unseen_docs, parallel=ps, together=True)
 
+def test_issue_187_crash_exc():
+    mdl = tp.LDAModel(k=10)
+    exc = None
+    try:
+        mdl.add_doc([[0, 1]])
+    except Exception as e:
+        exc = e
+    assert isinstance(exc, ValueError)
+
 def train_raw_corpus(cls, inputFile, mdFields, f, kargs, ps):
     print('Test train with raw corpus')
     from nltk.stem.porter import PorterStemmer