autogen_config.py
127 lines
| 4.2 KiB
| text/x-python
|
PythonLexer
/ docs / autogen_config.py
Yaroslav Halchenko
|
r16197 | #!/usr/bin/env python | ||
Antony Lee
|
r24791 | import inspect | ||
Joyce Er
|
r26063 | from pathlib import Path | ||
Thomas Kluyver
|
r13459 | from IPython.terminal.ipapp import TerminalIPythonApp | ||
Thomas Kluyver
|
r21400 | from ipykernel.kernelapp import IPKernelApp | ||
Thomas Kluyver
|
r23831 | from traitlets import Undefined | ||
Thomas Kluyver
|
r23832 | from collections import defaultdict | ||
Thomas Kluyver
|
r13459 | |||
rushabh-v
|
r26152 | here = (Path(__file__)).parent | ||
options = here / "source" / "config" / "options" | ||||
generated = options / "config-generated.txt" | ||||
klonuo
|
r22516 | |||
Matthias Bussonnier
|
r24586 | import textwrap | ||
indent = lambda text,n: textwrap.indent(text,n*' ') | ||||
Thomas Kluyver
|
r23831 | |||
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 | ||||
Thomas Kluyver
|
r23832 | 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): | ||||
Thomas Kluyver
|
r23831 | """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__ | ||||
Thomas Kluyver
|
r23832 | fullname = classname + '.' + trait.name | ||
lines += ['.. configtrait:: ' + fullname, | ||||
Thomas Kluyver
|
r23831 | '' | ||
] | ||||
help = trait.help.rstrip() or 'No description' | ||||
Antony Lee
|
r24791 | lines.append(indent(inspect.cleandoc(help), 4) + '\n') | ||
Thomas Kluyver
|
r23831 | |||
# 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)) | ||||
Thomas Kluyver
|
r23832 | # Command line aliases | ||
if trait_aliases[fullname]: | ||||
fmt_aliases = format_aliases(trait_aliases[fullname]) | ||||
lines.append(indent(':CLI option: ' + fmt_aliases, 4)) | ||||
Thomas Kluyver
|
r23831 | # Blank line | ||
lines.append('') | ||||
return '\n'.join(lines) | ||||
Thomas Kluyver
|
r23832 | 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 | ||||
Min RK
|
r21590 | |||
Thomas Kluyver
|
r21400 | def write_doc(name, title, app, preamble=None): | ||
Thomas Kluyver
|
r23832 | trait_aliases = reverse_aliases(app) | ||
rushabh-v
|
r26166 | filename = options / (name + ".rst") | ||
gousaiyang
|
r27495 | with open(filename, "w", encoding="utf-8") as f: | ||
Philippe Blain
|
r28187 | f.write(".. _" + name + "_options:" + "\n\n") | ||
rushabh-v
|
r26152 | f.write(title + "\n") | ||
f.write(("=" * len(title)) + "\n") | ||||
f.write("\n") | ||||
Thomas Kluyver
|
r13459 | if preamble is not None: | ||
f.write(preamble + '\n\n') | ||||
Thomas Kluyver
|
r23831 | #f.write(app.document_config_options()) | ||
for c in app._classes_inc_parents(): | ||||
Thomas Kluyver
|
r23832 | f.write(class_config_rst_doc(c, trait_aliases)) | ||
Thomas Kluyver
|
r23831 | f.write('\n') | ||
Yaroslav Halchenko
|
r16197 | |||
Thomas Kluyver
|
r13459 | |||
if __name__ == '__main__': | ||||
Thomas Kluyver
|
r22615 | # Touch this file for the make target | ||
gousaiyang
|
r27495 | Path(generated).write_text("", encoding="utf-8") | ||
Yaroslav Halchenko
|
r16197 | |||
Thomas Kluyver
|
r21400 | 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`"), | ||||
MinRK
|
r18030 | ) | ||