|
|
#!/usr/bin/env python
|
|
|
|
|
|
import inspect
|
|
|
from pathlib import Path
|
|
|
from IPython.terminal.ipapp import TerminalIPythonApp
|
|
|
from ipykernel.kernelapp import IPKernelApp
|
|
|
from traitlets import Undefined
|
|
|
from collections import defaultdict
|
|
|
|
|
|
here = (Path(__file__)).parent
|
|
|
options = here / "source" / "config" / "options"
|
|
|
generated = options / "config-generated.txt"
|
|
|
|
|
|
import textwrap
|
|
|
indent = lambda text,n: textwrap.indent(text,n*' ')
|
|
|
|
|
|
|
|
|
def interesting_default_value(dv):
|
|
|
if (dv is None) or (dv is Undefined):
|
|
|
return False
|
|
|
if isinstance(dv, (str, list, tuple, dict, set)):
|
|
|
return bool(dv)
|
|
|
return True
|
|
|
|
|
|
def format_aliases(aliases):
|
|
|
fmted = []
|
|
|
for a in aliases:
|
|
|
dashes = '-' if len(a) == 1 else '--'
|
|
|
fmted.append('``%s%s``' % (dashes, a))
|
|
|
return ', '.join(fmted)
|
|
|
|
|
|
def class_config_rst_doc(cls, trait_aliases):
|
|
|
"""Generate rST documentation for this class' config options.
|
|
|
|
|
|
Excludes traits defined on parent classes.
|
|
|
"""
|
|
|
lines = []
|
|
|
classname = cls.__name__
|
|
|
for k, trait in sorted(cls.class_traits(config=True).items()):
|
|
|
ttype = trait.__class__.__name__
|
|
|
|
|
|
fullname = classname + '.' + trait.name
|
|
|
lines += ['.. configtrait:: ' + fullname,
|
|
|
''
|
|
|
]
|
|
|
|
|
|
help = trait.help.rstrip() or 'No description'
|
|
|
lines.append(indent(inspect.cleandoc(help), 4) + '\n')
|
|
|
|
|
|
# Choices or type
|
|
|
if 'Enum' in ttype:
|
|
|
# include Enum choices
|
|
|
lines.append(indent(
|
|
|
':options: ' + ', '.join('``%r``' % x for x in trait.values), 4))
|
|
|
else:
|
|
|
lines.append(indent(':trait type: ' + ttype, 4))
|
|
|
|
|
|
# Default value
|
|
|
# Ignore boring default values like None, [] or ''
|
|
|
if interesting_default_value(trait.default_value):
|
|
|
try:
|
|
|
dvr = trait.default_value_repr()
|
|
|
except Exception:
|
|
|
dvr = None # ignore defaults we can't construct
|
|
|
if dvr is not None:
|
|
|
if len(dvr) > 64:
|
|
|
dvr = dvr[:61] + '...'
|
|
|
# Double up backslashes, so they get to the rendered docs
|
|
|
dvr = dvr.replace('\\n', '\\\\n')
|
|
|
lines.append(indent(':default: ``%s``' % dvr, 4))
|
|
|
|
|
|
# Command line aliases
|
|
|
if trait_aliases[fullname]:
|
|
|
fmt_aliases = format_aliases(trait_aliases[fullname])
|
|
|
lines.append(indent(':CLI option: ' + fmt_aliases, 4))
|
|
|
|
|
|
# Blank line
|
|
|
lines.append('')
|
|
|
|
|
|
return '\n'.join(lines)
|
|
|
|
|
|
def reverse_aliases(app):
|
|
|
"""Produce a mapping of trait names to lists of command line aliases.
|
|
|
"""
|
|
|
res = defaultdict(list)
|
|
|
for alias, trait in app.aliases.items():
|
|
|
res[trait].append(alias)
|
|
|
|
|
|
# Flags also often act as aliases for a boolean trait.
|
|
|
# Treat flags which set one trait to True as aliases.
|
|
|
for flag, (cfg, _) in app.flags.items():
|
|
|
if len(cfg) == 1:
|
|
|
classname = list(cfg)[0]
|
|
|
cls_cfg = cfg[classname]
|
|
|
if len(cls_cfg) == 1:
|
|
|
traitname = list(cls_cfg)[0]
|
|
|
if cls_cfg[traitname] is True:
|
|
|
res[classname+'.'+traitname].append(flag)
|
|
|
|
|
|
return res
|
|
|
|
|
|
def write_doc(name, title, app, preamble=None):
|
|
|
trait_aliases = reverse_aliases(app)
|
|
|
filename = options / (name + ".rst")
|
|
|
with open(filename, "w", encoding="utf-8") as f:
|
|
|
f.write(".. _" + name + "_options:" + "\n\n")
|
|
|
f.write(title + "\n")
|
|
|
f.write(("=" * len(title)) + "\n")
|
|
|
f.write("\n")
|
|
|
if preamble is not None:
|
|
|
f.write(preamble + '\n\n')
|
|
|
#f.write(app.document_config_options())
|
|
|
|
|
|
for c in app._classes_inc_parents():
|
|
|
f.write(class_config_rst_doc(c, trait_aliases))
|
|
|
f.write('\n')
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
# Touch this file for the make target
|
|
|
Path(generated).write_text("", encoding="utf-8")
|
|
|
|
|
|
write_doc('terminal', 'Terminal IPython options', TerminalIPythonApp())
|
|
|
write_doc('kernel', 'IPython kernel options', IPKernelApp(),
|
|
|
preamble=("These options can be used in :file:`ipython_kernel_config.py`. "
|
|
|
"The kernel also respects any options in `ipython_config.py`"),
|
|
|
)
|
|
|
|