Skip to content
This repository has been archived by the owner on Jan 13, 2024. It is now read-only.

Commit

Permalink
more unit test, better documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
sdpython committed Jul 9, 2017
1 parent ceca352 commit d8c184a
Show file tree
Hide file tree
Showing 15 changed files with 303 additions and 57 deletions.
6 changes: 4 additions & 2 deletions _doc/sphinxdoc/source/api/helpgen.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@ configuration
conversion
++++++++++

.. autosignature:: pyquickhelper.helpgen.sphinxm_convert_doc_helper.docstring2html

.. autosignature:: pyquickhelper.helpgen.pandoc_helper.latex2rst

.. autosignature:: pyquickhelper.helpgen.convert_doc_helper.rst2html
.. autosignature:: pyquickhelper.helpgen.sphinxm_convert_doc_helper.rst2html

specific
++++++++
Expand All @@ -25,5 +27,5 @@ specific
tweaking zone
+++++++++++++

.. autosignature:: pyquickhelper.helpgen.sphinx_custom_app.CustomSphinxApp
.. autosignature:: pyquickhelper.helpgen.sphinxm_custom_app.CustomSphinxApp
:members:
9 changes: 2 additions & 7 deletions _doc/sphinxdoc/source/api/index.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@

Short API
=========
API Summary
===========

.. toctree::
:maxdepth: 2
Expand All @@ -13,8 +13,3 @@ Short API
pycode
sphinxext
texthelper

API
===

:ref:`modindex`
8 changes: 4 additions & 4 deletions _doc/sphinxdoc/source/api/jupyter.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,6 @@ controls

.. autosignature:: pyquickhelper.ipythonhelper.html_forms.open_html_form

.. autosignature:: pyquickhelper.ipythonhelper.interact.StaticInteract
:members:

.. autosignature:: pyquickhelper.ipythonhelper.widgets.DropDownWidget
:members:

Expand All @@ -34,6 +31,9 @@ controls
.. autosignature:: pyquickhelper.ipythonhelper.widgets.RangeWidget
:members:

.. autosignature:: pyquickhelper.ipythonhelper.interact.StaticInteract
:members:

extensions
++++++++++

Expand Down Expand Up @@ -84,7 +84,7 @@ notebook

.. autosignature:: pyquickhelper.helpgen.utils_sphinx_config.NbImage

.. autosignature:: pyquickhelper.helpgen.sphinx_main.process_notebooks
.. autosignature:: pyquickhelper.helpgen.process_notebooks.process_notebooks

.. autosignature:: pyquickhelper.ipythonhelper.notebook_helper.read_nb

Expand Down
14 changes: 7 additions & 7 deletions _doc/sphinxdoc/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -169,10 +169,10 @@ Navigation
issues_todoextlist
indexmenu

+----------------------+---------------------+---------------------+--------------------+------------------------+------------------------------------------------+
| :ref:`l-modules` | :ref:`l-functions` | :ref:`l-classes` | :ref:`l-methods` | :ref:`l-staticmethods` | :ref:`l-properties` |
+----------------------+---------------------+---------------------+--------------------+------------------------+------------------------------------------------+
| :ref:`modindex` | :ref:`l-EX2` | :ref:`search` | :ref:`l-license` | :ref:`l-changes` | :ref:`l-README` |
+----------------------+---------------------+---------------------+--------------------+------------------------+------------------------------------------------+
| :ref:`genindex` | :ref:`l-FAQ2` | :ref:`l-notebooks` | :ref:`l-NB2` | :ref:`l-statcode` | `Unit Test Coverage <coverage/index.html>`_ |
+----------------------+---------------------+---------------------+--------------------+------------------------+------------------------------------------------+
+------------------------+---------------------+---------------------+--------------------+------------------------+------------------------------------------------+
| :ref:`l-modules` | :ref:`l-functions` | :ref:`l-classes` | :ref:`l-methods` | :ref:`l-staticmethods` | :ref:`l-properties` |
+------------------------+---------------------+---------------------+--------------------+------------------------+------------------------------------------------+
| :ref:`API <modindex>` | :ref:`l-EX2` | :ref:`search` | :ref:`l-license` | :ref:`l-changes` | :ref:`l-README` |
+------------------------+---------------------+---------------------+--------------------+------------------------+------------------------------------------------+
| :ref:`genindex` | :ref:`l-FAQ2` | :ref:`l-notebooks` | :ref:`l-NB2` | :ref:`l-statcode` | `Unit Test Coverage <coverage/index.html>`_ |
+------------------------+---------------------+---------------------+--------------------+------------------------+------------------------------------------------+
1 change: 1 addition & 0 deletions _unittests/ut_sphinxext/datadoc/exdocassert2.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
def onefunction(a, b):
"""
Return the addition of ``a+b``.
Second line should be aligned.
:param a: first element
:param c: second element
Expand Down
41 changes: 40 additions & 1 deletion _unittests/ut_sphinxext/test_autosignature.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
import src

from src.pyquickhelper.loghelper.flog import fLOG
from src.pyquickhelper.sphinxext.sphinx_docassert_extension import import_object
from src.pyquickhelper.sphinxext.import_object_helper import import_object
from src.pyquickhelper.helpgen import rst2html


Expand Down Expand Up @@ -152,6 +152,45 @@ def test_autosignature_class_onemethod(self):
if "Return the addition of" not in html[0]:
raise Exception(html[0])

def test_autosignature_class_onemethod2(self):
fLOG(
__file__,
self._testMethodName,
OutputPrint=__name__ == "__main__")

this = os.path.abspath(os.path.dirname(__file__))
data = os.path.join(this, "datadoc")
sys.path.append(data)

newstring = ["AAAAAAAAAAAAAAAA",
"",
".. autosignature:: exdocassert2.onefunction",
"",
"CCCCCCCCCCCCCCCC"]
newstring = "\n".join(newstring)
htmls = rst2html(newstring, layout="sphinx_body")
sys.path.pop()

html = htmls.split("CCCCCCCCCCCCCCCC")
if "onefunction" not in html[0]:
raise Exception(html[0])
if "<strong>a</strong>" in html[0]:
raise Exception(html[0])
if ":param a:" in html[0]:
raise Exception(html[0])
if "`" in html[0]:
raise Exception(html[0])
if "if a and b have different types" in html[0]:
raise Exception(html[0])
if "Return the addition of" not in html[0]:
raise Exception(html[0])
if "Second line should be aligned." not in html[0]:
raise Exception(html[0])
if "<p>Return the addition of" not in html[0]:
raise Exception(html[0])
if "should be aligned.</p>" not in html[0]:
raise Exception(html[0])


if __name__ == "__main__":
unittest.main()
53 changes: 53 additions & 0 deletions _unittests/ut_sphinxext/test_docassert.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,59 @@ def __len__(self):
if nb == 0:
raise Exception("not the right warning")

def test_docassert_html_method(self):
fLOG(
__file__,
self._testMethodName,
OutputPrint=__name__ == "__main__")

class MyStream:
def __init__(self):
self.rows = []

def write(self, text):
fLOG(
"[warning*] {0} - '{1}'".format(len(self), text.strip("\n\r ")))
self.rows.append(text)

def getvalue(self):
return "\n".join(self.rows)

def __len__(self):
return len(self.rows)

logger1 = getLogger("MockSphinxApp")
logger2 = getLogger("docassert")
log_capture_string = MyStream() # StringIO()
ch = logging.StreamHandler(log_capture_string)
ch.setLevel(logging.DEBUG)
logger1.logger.addHandler(ch)
logger2.logger.addHandler(ch)
logger2.warning("try")

this = os.path.abspath(os.path.dirname(__file__))
data = os.path.join(this, "datadoc")
sys.path.append(data)
obj, name = import_object("exsig.clex.onemethod", "method")
newstring = ".. automethod:: exsig.clex.onemethod"
html = rst2html(newstring)
self.assertTrue(html is not None)
sys.path.pop()
fLOG(len(log_capture_string))

lines = log_capture_string.getvalue().split("\n")
if len(lines) == 0:
raise Exception("no warning")
nb = 0
for line in lines:
if "'onemethod' has no parameter 'c'" in line:
nb += 1
if nb == 0:
raise Exception("not the right warning")
for line in lines:
if "'onemethod' has undocumented parameters 'b, self'" in line:
raise Exception(line)


if __name__ == "__main__":
unittest.main()
45 changes: 44 additions & 1 deletion _unittests/ut_sphinxext/test_import_any_object.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
import src

from src.pyquickhelper.loghelper.flog import fLOG
from src.pyquickhelper.sphinxext.import_object_helper import import_any_object
from src.pyquickhelper.sphinxext.import_object_helper import import_any_object, import_object


class TestImportAnyObject(unittest.TestCase):
Expand Down Expand Up @@ -53,13 +53,56 @@ def test_import_any_object_benchmark(self):
data = os.path.join(this, "datadoc")
sys.path.append(data)
name = "src.pyquickhelper.benchhelper.grid_benchmark.GridBenchMark.bench_experiment"
import_object(name, "method")
obj, name, kind = import_any_object(name)
sys.path.pop()
self.assertTrue(obj is not None)
# self.assertTrue(obj.(4, 5), 9)
self.assertEqual(name, "bench_experiment")
self.assertEqual(kind, "method")

def test_import_any_object_static(self):
fLOG(
__file__,
self._testMethodName,
OutputPrint=__name__ == "__main__")

this = os.path.abspath(os.path.dirname(__file__))
data = os.path.join(this, "datadoc")
sys.path.append(data)
name = "src.pyquickhelper.filehelper.transfer_api.TransferAPI_FileInfo.read_json"
try:
import_object(name, "method")
self.assertTrue(False)
except TypeError as e:
pass
import_object(name, "staticmethod")
obj, name, kind = import_any_object(name)
sys.path.pop()
self.assertTrue(obj is not None)
# self.assertTrue(obj.(4, 5), 9)
self.assertEqual(name, "read_json")
self.assertEqual(kind, "staticmethod")

def test_import_any_object_property(self):
fLOG(
__file__,
self._testMethodName,
OutputPrint=__name__ == "__main__")

this = os.path.abspath(os.path.dirname(__file__))
data = os.path.join(this, "datadoc")
sys.path.append(data)
name = "src.pyquickhelper.benchhelper.benchmark.BenchMark.Name"
import_object(name, "property")

obj, name, kind = import_any_object(name)
sys.path.pop()
self.assertTrue(obj is not None)
# self.assertTrue(obj.(4, 5), 9)
self.assertEqual(name, "Name")
self.assertEqual(kind, "property")


if __name__ == "__main__":
unittest.main()
2 changes: 1 addition & 1 deletion src/pyquickhelper/ipythonhelper/helper_in_notebook.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def add_notebook_menu(menu_id="my_id_menu_nb", raw=False, format="html", header=

def load_extension(name):
"""
See `load_extension <http://www.xavierdupre.fr/app/pyquickhelper/helpsphinx/jyquickhelper/helpers_in_notebook.html>`_.
See `load_extension <http://www.xavierdupre.fr/app/jyquickhelper/helpsphinx/jyquickhelper/helper_in_notebook.html#jyquickhelper.helper_in_notebook.load_extension>`_.
"""
warnings.warn("The function has been moved to jyquickhelper.")
from jyquickhelper.helper_in_notebook import load_extension as _load_extension
Expand Down
2 changes: 1 addition & 1 deletion src/pyquickhelper/ipythonhelper/notebook_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ def writes(nb, **kwargs):

def upgrade_notebook(filename, encoding="utf8"):
"""
converts a notebook from version 2 to 3
Converts a notebook from version 2 to latest.
@param filename filename
@param encoding encoding
Expand Down
56 changes: 51 additions & 5 deletions src/pyquickhelper/sphinxext/import_object_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,17 @@
import inspect
from typing import Tuple
import warnings
import sys


class _Types:
@property
def prop(self):
pass

@staticmethod
def stat(self):
pass


def import_object(docname, kind, use_init=True) -> Tuple[object, str]:
Expand All @@ -23,7 +34,7 @@ def import_object(docname, kind, use_init=True) -> Tuple[object, str]:
spl = docname.split(".")
name = spl[-1]
context = {}
if kind != "method":
if kind not in ("method", "property", "staticmethod"):
modname = ".".join(spl[:-1])
code = 'from {0} import {1}\nmyfunc = {1}'.format(modname, name)
codeobj = compile(code, 'conf{0}.py'.format(kind), 'exec')
Expand All @@ -46,13 +57,48 @@ def import_object(docname, kind, use_init=True) -> Tuple[object, str]:
if not inspect.isfunction(myfunc):
raise TypeError("'{0}' is not a function".format(docname))
name = spl[-1]
elif kind == "property":
if not inspect.isclass(myfunc):
raise TypeError("'{0}' is not a class".format(docname))
myfunc = getattr(myfunc, spl[-1])
if inspect.isfunction(myfunc) or inspect.ismethod(myfunc):
raise TypeError(
"'{0}' is not a property - {1}".format(docname, myfunc))
if myfunc.__class__ is not _Types.prop.__class__:
raise TypeError(
"'{0}' is not a property(*) - {1}".format(docname, myfunc))
if not isinstance(myfunc, property):
raise TypeError(
"'{0}' is not a static property(**) - {1}".format(docname, myfunc))
name = spl[-1]
elif kind == "method":
if not inspect.isclass(myfunc):
raise TypeError("'{0}' is not a class".format(docname))
myfunc = getattr(myfunc, spl[-1])
if not inspect.isfunction(myfunc) and not inspect.ismethod(myfunc):
raise TypeError(
"'{0}' is not a method - {1}".format(docname, myfunc))
if isinstance(myfunc, staticmethod):
raise TypeError(
"'{0}' is not a method(*) - {1}".format(docname, myfunc))
if sys.version_info >= (3, 4):
if len(myfunc.__code__.co_varnames) == 0:
raise TypeError(
"'{0}' is not a method(**) - {1}".format(docname, myfunc))
elif myfunc.__code__.co_varnames[0] != 'self':
raise TypeError(
"'{0}' is not a method(***) - {1}".format(docname, myfunc))
name = spl[-1]
elif kind == "staticmethod":
if not inspect.isclass(myfunc):
raise TypeError("'{0}' is not a class".format(docname))
myfunc = getattr(myfunc, spl[-1])
if not inspect.isfunction(myfunc) and not inspect.ismethod(myfunc):
raise TypeError(
"'{0}' is not a static method - {1}".format(docname, myfunc))
if myfunc.__class__ is not _Types.stat.__class__:
raise TypeError(
"'{0}' is not a static method(*) - {1}".format(docname, myfunc))
name = spl[-1]
elif kind == "class":
if not inspect.isclass(myfunc):
Expand Down Expand Up @@ -80,15 +126,15 @@ def import_any_object(docname, use_init=True) -> Tuple[object, str, str]:
myfunc = None
name = None
excs = []
for kind in ("function", "method", "class"):
for kind in ("function", "method", "staticmethod", "property", "class"):
try:
myfunc, name = import_object(docname, kind, use_init=use_init)
return myfunc, name, kind
except Exception as e:
# not this kind
excs.append(e)
excs.append((kind, e))

sec = "\n".join("{0}-{1}".format(type(e), e).replace("\n", " ")
for e in excs)
sec = "\n".join("{0}-{1}-{2}".format(k, type(e), e).replace("\n", " ")
for k, e in excs)
raise ImportError(
"Unable to import '{0}'. Exceptions met:\n----\n{1}\n----".format(docname, sec))
Loading

0 comments on commit d8c184a

Please sign in to comment.