mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
Create ipasphinx package for Sphinx plugins
Sphinx is extensible with plugins that can add new syntax, roles, directives, domains, and more. Signed-off-by: Christian Heimes <cheimes@redhat.com> Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
This commit is contained in:
parent
87408ee755
commit
e00dc40fea
@ -3,7 +3,7 @@ NULL =
|
|||||||
ACLOCAL_AMFLAGS = -I m4
|
ACLOCAL_AMFLAGS = -I m4
|
||||||
|
|
||||||
if ENABLE_SERVER
|
if ENABLE_SERVER
|
||||||
IPASERVER_SUBDIRS = ipaserver
|
IPASERVER_SUBDIRS = ipaserver ipasphinx
|
||||||
SERVER_SUBDIRS = daemons init install
|
SERVER_SUBDIRS = daemons init install
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
@ -598,6 +598,7 @@ AC_CONFIG_FILES([
|
|||||||
ipalib/Makefile
|
ipalib/Makefile
|
||||||
ipaplatform/Makefile
|
ipaplatform/Makefile
|
||||||
ipapython/Makefile
|
ipapython/Makefile
|
||||||
|
ipasphinx/Makefile
|
||||||
ipaserver/Makefile
|
ipaserver/Makefile
|
||||||
ipatests/Makefile
|
ipatests/Makefile
|
||||||
ipatests/man/Makefile
|
ipatests/man/Makefile
|
||||||
|
@ -10,9 +10,10 @@
|
|||||||
# add these directories to sys.path here. If the directory is relative to the
|
# add these directories to sys.path here. If the directory is relative to the
|
||||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||||
#
|
#
|
||||||
# import os
|
import os
|
||||||
# import sys
|
import sys
|
||||||
# sys.path.insert(0, os.path.abspath('.'))
|
# insert parent directory with ipalib and ipasphinx
|
||||||
|
sys.path.insert(0, os.path.abspath('..'))
|
||||||
|
|
||||||
|
|
||||||
# -- Project information -----------------------------------------------------
|
# -- Project information -----------------------------------------------------
|
||||||
@ -35,10 +36,10 @@ master_doc = 'index'
|
|||||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||||
# ones.
|
# ones.
|
||||||
extensions = [
|
extensions = [
|
||||||
|
'ipasphinx.ipabase',
|
||||||
'sphinx.ext.autodoc',
|
'sphinx.ext.autodoc',
|
||||||
'sphinx.ext.intersphinx',
|
'sphinx.ext.intersphinx',
|
||||||
'sphinx.ext.viewcode',
|
'sphinx.ext.viewcode',
|
||||||
'sphinx.ext.githubpages',
|
|
||||||
'm2r',
|
'm2r',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -1,6 +1,28 @@
|
|||||||
# m2r is not compatible with Sphinx 3.x
|
## m2r is not compatible with Sphinx 3.x yet
|
||||||
sphinx < 3.0
|
sphinx < 3.0
|
||||||
|
|
||||||
# convert markdown to rest
|
## convert markdown to rest
|
||||||
m2r
|
m2r
|
||||||
|
|
||||||
|
## ipa dependencies
|
||||||
|
dnspython
|
||||||
|
jwcrypto
|
||||||
|
netaddr
|
||||||
|
qrcode
|
||||||
|
six
|
||||||
|
pyasn1
|
||||||
|
pyasn1-modules
|
||||||
|
requests
|
||||||
|
|
||||||
|
## C libraries with binary wheels
|
||||||
|
cffi
|
||||||
|
cryptography
|
||||||
|
lxml
|
||||||
|
|
||||||
|
## C libraries without binaries wheels
|
||||||
|
# gssapi
|
||||||
|
# dbus-python
|
||||||
|
# python-ldap
|
||||||
|
|
||||||
|
## No sufficient PyPI packages
|
||||||
|
# dogtag-pki
|
||||||
|
@ -819,6 +819,9 @@ make %{?_smp_mflags} check VERBOSE=yes LIBDIR=%{_libdir}
|
|||||||
|
|
||||||
%make_install
|
%make_install
|
||||||
|
|
||||||
|
# don't package ipasphinx for now
|
||||||
|
rm -rf %{buildroot}%{python3_sitelib}/ipasphinx*
|
||||||
|
|
||||||
%if 0%{?with_ipatests}
|
%if 0%{?with_ipatests}
|
||||||
mv %{buildroot}%{_bindir}/ipa-run-tests %{buildroot}%{_bindir}/ipa-run-tests-%{python3_version}
|
mv %{buildroot}%{_bindir}/ipa-run-tests %{buildroot}%{_bindir}/ipa-run-tests-%{python3_version}
|
||||||
mv %{buildroot}%{_bindir}/ipa-test-config %{buildroot}%{_bindir}/ipa-test-config-%{python3_version}
|
mv %{buildroot}%{_bindir}/ipa-test-config %{buildroot}%{_bindir}/ipa-test-config-%{python3_version}
|
||||||
|
@ -510,14 +510,17 @@ class API(ReadOnly):
|
|||||||
level = logging.INFO
|
level = logging.INFO
|
||||||
if self.env.debug: # pylint: disable=using-constant-test
|
if self.env.debug: # pylint: disable=using-constant-test
|
||||||
level = logging.DEBUG
|
level = logging.DEBUG
|
||||||
try:
|
if self.env.log is not None:
|
||||||
handler = logging.FileHandler(self.env.log)
|
try:
|
||||||
except IOError as e:
|
handler = logging.FileHandler(self.env.log)
|
||||||
logger.error('Cannot open log file %r: %s', self.env.log, e)
|
except IOError as e:
|
||||||
return
|
logger.error('Cannot open log file %r: %s', self.env.log, e)
|
||||||
handler.setLevel(level)
|
else:
|
||||||
handler.setFormatter(ipa_log_manager.Formatter(LOGGING_FORMAT_FILE))
|
handler.setLevel(level)
|
||||||
root_logger.addHandler(handler)
|
handler.setFormatter(
|
||||||
|
ipa_log_manager.Formatter(LOGGING_FORMAT_FILE)
|
||||||
|
)
|
||||||
|
root_logger.addHandler(handler)
|
||||||
|
|
||||||
def build_global_parser(self, parser=None, context=None):
|
def build_global_parser(self, parser=None, context=None):
|
||||||
"""
|
"""
|
||||||
|
@ -304,6 +304,10 @@ class Gettext(LazyText):
|
|||||||
def format(self, *args, **kwargs):
|
def format(self, *args, **kwargs):
|
||||||
return unicode(self).format(*args, **kwargs)
|
return unicode(self).format(*args, **kwargs)
|
||||||
|
|
||||||
|
def expandtabs(self, tabsize=8):
|
||||||
|
"""Compatibility for sphinx prepare_docstring()"""
|
||||||
|
return str(self).expandtabs(tabsize)
|
||||||
|
|
||||||
|
|
||||||
@six.python_2_unicode_compatible
|
@six.python_2_unicode_compatible
|
||||||
class FixMe(Gettext):
|
class FixMe(Gettext):
|
||||||
@ -524,6 +528,10 @@ class ConcatenatedLazyText:
|
|||||||
else:
|
else:
|
||||||
return ConcatenatedLazyText(*[other] + self.components)
|
return ConcatenatedLazyText(*[other] + self.components)
|
||||||
|
|
||||||
|
def expandtabs(self, tabsize=8):
|
||||||
|
"""Compatibility for sphinx prepare_docstring()"""
|
||||||
|
return str(self).expandtabs(tabsize)
|
||||||
|
|
||||||
|
|
||||||
class GettextFactory:
|
class GettextFactory:
|
||||||
"""
|
"""
|
||||||
|
1
ipasphinx/Makefile.am
Normal file
1
ipasphinx/Makefile.am
Normal file
@ -0,0 +1 @@
|
|||||||
|
include $(top_srcdir)/Makefile.python.am
|
0
ipasphinx/__init__.py
Normal file
0
ipasphinx/__init__.py
Normal file
173
ipasphinx/ipabase.py
Normal file
173
ipasphinx/ipabase.py
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2020 FreeIPA Contributors see COPYING for license
|
||||||
|
#
|
||||||
|
"""IPA API initialization for Sphinx
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from sphinx.util import progress_message
|
||||||
|
from sphinx.ext.autodoc import mock as autodoc_mock
|
||||||
|
|
||||||
|
HERE = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
ROOT = os.path.abspath(os.path.join(HERE, os.pardir))
|
||||||
|
VERSION_M4 = os.path.abspath(os.path.join(ROOT, "VERSION.m4"))
|
||||||
|
|
||||||
|
if ROOT not in sys.path:
|
||||||
|
sys.path.insert(0, ROOT)
|
||||||
|
|
||||||
|
|
||||||
|
ipa_mock_imports = [
|
||||||
|
# no binary wheels available
|
||||||
|
"dbus",
|
||||||
|
"gssapi",
|
||||||
|
"ldap",
|
||||||
|
"ldif", # python-ldap
|
||||||
|
"ldapurl", # python-ldap
|
||||||
|
# dogtag-pki is client-only
|
||||||
|
"pki",
|
||||||
|
# PyPI packages not available
|
||||||
|
"pyhbac",
|
||||||
|
"pysss",
|
||||||
|
"pysss_murmur",
|
||||||
|
"pysss_nss_idmap",
|
||||||
|
"samba",
|
||||||
|
"SSSDConfig",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def parse_version_m4(filename=VERSION_M4):
|
||||||
|
"""Poor man's macro parser for VERSION.m4
|
||||||
|
"""
|
||||||
|
def_re = re.compile(r"^define\(([\w]+)+,\s*(.*)\)\s*$")
|
||||||
|
defs = {}
|
||||||
|
|
||||||
|
with open(filename) as f:
|
||||||
|
for line in f:
|
||||||
|
mo = def_re.match(line)
|
||||||
|
if mo is not None:
|
||||||
|
k, v = mo.groups()
|
||||||
|
try:
|
||||||
|
v = int(v)
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
defs[k] = v
|
||||||
|
|
||||||
|
defs["IPA_NUM_VERSION"] = (
|
||||||
|
"{IPA_VERSION_MAJOR:d}"
|
||||||
|
"{IPA_VERSION_MINOR:02d}"
|
||||||
|
"{IPA_VERSION_RELEASE:02d}"
|
||||||
|
).format(**defs)
|
||||||
|
|
||||||
|
defs["IPA_API_VERSION"] = (
|
||||||
|
"{IPA_API_VERSION_MAJOR}.{IPA_API_VERSION_MINOR}"
|
||||||
|
).format(**defs)
|
||||||
|
|
||||||
|
if defs["IPA_VERSION_IS_GIT_SNAPSHOT"] == "yes":
|
||||||
|
defs["IPA_GIT_VERSION"] = ".dev"
|
||||||
|
else:
|
||||||
|
defs["IPA_GIT_VERSION"] = ""
|
||||||
|
|
||||||
|
defs["IPA_VERSION"] = (
|
||||||
|
"{IPA_VERSION_MAJOR}."
|
||||||
|
"{IPA_VERSION_MINOR}."
|
||||||
|
"{IPA_VERSION_RELEASE}"
|
||||||
|
"{IPA_VERSION_PRE_RELEASE}"
|
||||||
|
"{IPA_GIT_VERSION}"
|
||||||
|
).format(**defs)
|
||||||
|
return defs
|
||||||
|
|
||||||
|
|
||||||
|
def fake_ipaython_version(defs):
|
||||||
|
"""Fake ipapython.version module
|
||||||
|
|
||||||
|
We don't want and cannot run autoconf on read the docs. Fake the auto-
|
||||||
|
generated ipapython.version module.
|
||||||
|
"""
|
||||||
|
|
||||||
|
class FakeIpapythonVersion:
|
||||||
|
__name__ = "ipapython.version"
|
||||||
|
|
||||||
|
VERSION = defs["IPA_VERSION"]
|
||||||
|
VENDOR_VERSION = defs["IPA_VERSION"]
|
||||||
|
NUM_VERSION = defs["IPA_NUM_VERSION"]
|
||||||
|
API_VERSION = defs["IPA_API_VERSION"]
|
||||||
|
DEFAULT_PLUGINS = frozenset()
|
||||||
|
|
||||||
|
fake = FakeIpapythonVersion()
|
||||||
|
sys.modules[fake.__name__] = fake
|
||||||
|
|
||||||
|
|
||||||
|
def init_api(
|
||||||
|
context="doc",
|
||||||
|
domain="ipa.example",
|
||||||
|
server="server.ipa.example",
|
||||||
|
in_server=True,
|
||||||
|
):
|
||||||
|
import ipalib
|
||||||
|
|
||||||
|
ipalib.api.bootstrap(
|
||||||
|
context=context,
|
||||||
|
in_server=in_server,
|
||||||
|
logdir=None,
|
||||||
|
log=None,
|
||||||
|
domain=domain,
|
||||||
|
realm=domain.upper(),
|
||||||
|
server=server,
|
||||||
|
)
|
||||||
|
ipalib.api.finalize()
|
||||||
|
return ipalib.api
|
||||||
|
|
||||||
|
|
||||||
|
def inject_mock_imports(app, config):
|
||||||
|
"""Add additional module mocks for ipaserver
|
||||||
|
"""
|
||||||
|
mock_imports = set(getattr(config, "autodoc_mock_imports", []))
|
||||||
|
mock_imports.update(ipa_mock_imports)
|
||||||
|
config.autodoc_mock_imports = list(mock_imports)
|
||||||
|
|
||||||
|
# ldap is a mocked package
|
||||||
|
# ensure that ipapython.dn still use ctypes wrappers for str2dn/dn2str
|
||||||
|
# otherwise api won't be able to initialize properly
|
||||||
|
import ipapython.dn
|
||||||
|
|
||||||
|
assert ipapython.dn.str2dn("cn=ipa") == [[("cn", "ipa", 1)]]
|
||||||
|
|
||||||
|
|
||||||
|
def init_ipalib_api(app, config):
|
||||||
|
"""Initialize ipalib.api
|
||||||
|
|
||||||
|
1. Parse VERSION.m4
|
||||||
|
2. Create fake ipapython.version module
|
||||||
|
3. Initialize the API with mocked imports
|
||||||
|
"""
|
||||||
|
defs = parse_version_m4()
|
||||||
|
fake_ipaython_version(defs)
|
||||||
|
|
||||||
|
with progress_message("initializing ipalib.api"):
|
||||||
|
with autodoc_mock(config.autodoc_mock_imports):
|
||||||
|
init_api(
|
||||||
|
context=config.ipa_context,
|
||||||
|
domain=config.ipa_domain,
|
||||||
|
server=config.ipa_server_fqdn,
|
||||||
|
in_server=config.ipa_in_server,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def setup(app):
|
||||||
|
app.setup_extension("sphinx.ext.autodoc")
|
||||||
|
|
||||||
|
app.add_config_value("ipa_context", "doc", "env")
|
||||||
|
app.add_config_value("ipa_domain", "ipa.example", "env")
|
||||||
|
app.add_config_value("ipa_server_fqdn", "server.ipa.example", "env")
|
||||||
|
app.add_config_value("ipa_in_server", True, "env")
|
||||||
|
|
||||||
|
app.connect("config-inited", inject_mock_imports)
|
||||||
|
app.connect("config-inited", init_ipalib_api)
|
||||||
|
|
||||||
|
return {
|
||||||
|
"version": "0.1",
|
||||||
|
"parallel_read_safe": True,
|
||||||
|
"parallel_write_safe": True,
|
||||||
|
}
|
21
ipasphinx/setup.py
Normal file
21
ipasphinx/setup.py
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2020 FreeIPA Contributors see COPYING for license
|
||||||
|
#
|
||||||
|
"""Sphinx documentation plugins for IPA
|
||||||
|
"""
|
||||||
|
from os.path import abspath, dirname
|
||||||
|
import sys
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
# include ../ for ipasetup.py
|
||||||
|
sys.path.append(dirname(dirname(abspath(__file__))))
|
||||||
|
from ipasetup import ipasetup # noqa: E402
|
||||||
|
|
||||||
|
ipasetup(
|
||||||
|
name="ipasphinx",
|
||||||
|
doc=__doc__,
|
||||||
|
package_dir={"ipasphinx": ""},
|
||||||
|
packages=["ipasphinx"],
|
||||||
|
# m2r is not compatible with Sphinx 3.x yet
|
||||||
|
install_requires=["ipaserver", "ipalib", "sphinx < 3.0", "m2r"],
|
||||||
|
)
|
Loading…
Reference in New Issue
Block a user