Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use sphinx-apidoc to create API reference #309

Merged
merged 12 commits into from Aug 4, 2020
Merged
6 changes: 6 additions & 0 deletions .gitignore
Expand Up @@ -16,9 +16,14 @@ libs
*.pyd
MANIFEST

doc/api/lxml*.rst
doc/api/_build/
doc/s5/lxml-ep2008.html
src/lxml/includes/lxml-version.h
src/lxml/*.html
src/lxml/html/*.c
src/lxml/_elementpath.c
src/lxml/builder.c
src/lxml/etree.c
src/lxml/etree.h
src/lxml/etree_api.h
Expand All @@ -27,3 +32,4 @@ src/lxml/lxml.etree.h
src/lxml/lxml.etree_api.h
src/lxml/objectify.c
src/lxml/lxml.objectify.c
src/lxml/sax.c
11 changes: 9 additions & 2 deletions .travis.yml
Expand Up @@ -29,8 +29,15 @@ env:

matrix:
include:
- python: 3.7
env: STATIC_DEPS=false EXTRA_DEPS="coverage<5"
- python: 3.8
env:
- STATIC_DEPS=false
- EXTRA_DEPS="docutils pygments sphinx sphinx-rtd-theme"
script: make html
- python: 3.8
env:
- STATIC_DEPS=false
- EXTRA_DEPS="coverage<5"
- python: 3.8
env:
- STATIC_DEPS=true
Expand Down
41 changes: 21 additions & 20 deletions Makefile
Expand Up @@ -105,34 +105,33 @@ ftest_build: build
ftest_inplace: inplace
$(PYTHON) test.py -f $(TESTFLAGS) $(TESTOPTS)

apihtml: inplace
rm -fr doc/html/api
@[ -x "`which epydoc`" ] \
&& (cd src && echo "Generating API docs ..." && \
PYTHONPATH=. epydoc -v --docformat "restructuredtext en" \
-o ../doc/html/api --exclude='[.]html[.]tests|[.]_' \
--exclude-introspect='[.]usedoctest' \
--name "lxml API" --url / lxml/) \
|| (echo "not generating epydoc API documentation")
apidoc: clean docclean
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is what needs the inplace lxml build as a dependency, not the other targets, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sphinx-apidoc appears to only scan files, which is how I read:

Warning

sphinx-apidoc generates source files that use sphinx.ext.autodoc to document all found modules. If any modules have side effects on import, these will be executed by autodoc when sphinx-build is run.

If you document scripts (as opposed to library modules), make sure their main routine is protected by a if __name__ == '__main__' condition.

https://www.sphinx-doc.org/en/master/man/sphinx-apidoc.html

and the build inplace causes sphinx-apidoc to create duplicate entries

e.g.

--- lxml.rst
+++ lxml.rst
@@ -18,11 +18,16 @@
 
    lxml.ElementInclude
    lxml._elementpath
+   lxml._elementpath
+   lxml.builder
    lxml.builder
    lxml.cssselect
    lxml.doctestcompare
    lxml.etree
+   lxml.etree
    lxml.objectify
+   lxml.objectify
+   lxml.sax
    lxml.sax
 
 Module contents

Looks like excluding .so files avoids this, by adding "*.so":

sphinx-apidoc -e -P -T -o doc/api src/lxml "*includes" "*tests" "*pyclasslookup.py" "*usedoctest.py" "*html/_html5builder.py" "*.so"

That's a possibility but still needs a separate apidoc target to support apidf as well. I'm not sure if it gains anything?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The duplication seems to be because there is a system copy of lxml installed. But without a system lxml, sphinx-apidoc appears to work without compiling lxml.

@[ -x "`which sphinx-apidoc`" ] \
&& (echo "Generating API docs ..." && \
sphinx-apidoc -e -P -T -o doc/api src/lxml \
"*includes" "*tests" "*pyclasslookup.py" "*usedoctest.py" "*html/_html5builder.py") \
|| (echo "not generating Sphinx autodoc API rst files")

apihtml: apidoc inplace
@[ -x "`which sphinx-build`" ] \
&& (echo "Generating API docs ..." && \
make -C doc/api html) \
|| (echo "not generating Sphinx autodoc API documentation")

website: inplace
PYTHONPATH=src:$(PYTHONPATH) $(PYTHON) doc/mkhtml.py doc/html . ${LXMLVERSION}

html: inplace website apihtml s5
html: apihtml inplace website s5

s5:
$(MAKE) -C doc/s5 slides

apipdf: inplace
rm -fr doc/pdf
mkdir -p doc/pdf
@[ -x "`which epydoc`" ] \
&& (cd src && echo "Generating API docs ..." && \
PYTHONPATH=. epydoc -v --latex --docformat "restructuredtext en" \
-o ../doc/pdf --exclude='([.]html)?[.]tests|[.]_' \
--exclude-introspect='html[.]clean|[.]usedoctest' \
--name "lxml API" --url / lxml/) \
|| (echo "not generating epydoc API documentation")
apipdf: apidoc inplace
rm -fr doc/api/_build
@[ -x "`which sphinx-build`" ] \
&& (echo "Generating API PDF docs ..." && \
make -C doc/api latexpdf) \
|| (echo "not generating Sphinx autodoc API PDF documentation")

pdf: apipdf
$(PYTHON) doc/mklatex.py doc/pdf . ${LXMLVERSION}
Expand Down Expand Up @@ -164,6 +163,8 @@ docclean:
$(MAKE) -C doc/s5 clean
rm -f doc/html/*.html
rm -fr doc/html/api
rm -f doc/api/lxml*.rst
rm -fr doc/api/_build
rm -fr doc/pdf

realclean: clean docclean
Expand Down
23 changes: 23 additions & 0 deletions doc/api/Makefile
@@ -0,0 +1,23 @@
# Minimal makefile for Sphinx documentation
#

# You can set these variables from the command line, and also
# from the environment for the first two.
SPHINXOPTS ?=
SPHINXBUILD ?= sphinx-build
SOURCEDIR = .
BUILDDIR = _build

# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

html:
@$(SPHINXBUILD) -b html "$(SOURCEDIR)" -d "$(BUILDDIR)/doctrees" ../html/api $(SPHINXOPTS) $(O)

.PHONY: help Makefile

# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
58 changes: 58 additions & 0 deletions doc/api/conf.py
@@ -0,0 +1,58 @@
import os
import sys
sys.path.insert(0, os.path.abspath('../../src'))
# For soupparser in lxml.html.ElementSoup module:
sys.path.insert(1, os.path.abspath('../../src/lxml/html'))
scoder marked this conversation as resolved.
Show resolved Hide resolved

from lxml import __version__ as lxml_version

# -- Project information -----------------------------------------------------

project = 'lxml'
copyright = '2020, lxml dev team'
author = 'lxml dev team'
version = lxml_version


# -- General configuration ---------------------------------------------------

extensions = [
'sphinx.ext.autodoc',
'sphinx.ext.viewcode',
'sphinx_rtd_theme',
]

language = 'en'

exclude_patterns = ['_build']


# -- Options for HTML output -------------------------------------------------

html_theme = 'sphinx_rtd_theme'

html_logo = '../html/python-xml.png'

# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
#html_static_path = ['_static']

html_theme_options = {
'collapse_navigation': False,
'titles_only': True,
}

# -- Extension configuration -------------------------------------------------

autodoc_default_options = {
'ignore-module-all': True,
'private-members': True,
}

autodoc_member_order = 'groupwise'

# -- Options for todo extension ----------------------------------------------

# If true, `todo` and `todoList` produce output, else they produce nothing.
#todo_include_todos = True
14 changes: 14 additions & 0 deletions doc/api/index.rst
@@ -0,0 +1,14 @@
lxml API Reference
==================

.. toctree::
:maxdepth: 4

lxml

Indices and tables
==================

* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`
2 changes: 1 addition & 1 deletion src/lxml/classlookup.pxi
Expand Up @@ -504,7 +504,7 @@ cdef class PythonElementClassLookup(FallbackElementClassLookup):
`lxml.etree` API (such as XPath, extended slicing or some
iteration methods).

See http://codespeak.net/lxml/element_classes.html
See https://lxml.de/element_classes.html
"""
def __cinit__(self):
self._lookup_function = _python_class_lookup
Expand Down
2 changes: 1 addition & 1 deletion src/lxml/html/__init__.py
Expand Up @@ -37,7 +37,7 @@
'document_fromstring', 'fragment_fromstring', 'fragments_fromstring', 'fromstring',
'tostring', 'Element', 'defs', 'open_in_browser', 'submit_form',
'find_rel_links', 'find_class', 'make_links_absolute',
'resolve_base_href', 'iterlinks', 'rewrite_links', 'open_in_browser', 'parse']
'resolve_base_href', 'iterlinks', 'rewrite_links', 'parse']


import copy
Expand Down