##// END OF EJS Templates
Merge pull request #10732 from takluyver/config-docs-linkable...
Thomas Kluyver -
r23834:57ab2296 merge
parent child Browse files
Show More
@@ -0,0 +1,17 b''
1 """Directives and roles for documenting traitlets config options.
2
3 ::
4
5 .. configtrait:: Application.log_datefmt
6
7 Description goes here.
8
9 Cross reference like this: :configtrait:`Application.log_datefmt`.
10 """
11 from sphinx.locale import l_
12 from sphinx.util.docfields import Field
13
14 def setup(app):
15 app.add_object_type('configtrait', 'configtrait', objname='Config option')
16 metadata = {'parallel_read_safe': True, 'parallel_write_safe': True}
17 return metadata
@@ -76,7 +76,7 b' source/interactive/magics-generated.txt: autogen_magics.py'
76
76
77 autoconfig: source/config/options/config-generated.txt
77 autoconfig: source/config/options/config-generated.txt
78
78
79 source/config/options/config-generated.txt:
79 source/config/options/config-generated.txt: autogen_config.py
80 $(PYTHON) autogen_config.py
80 $(PYTHON) autogen_config.py
81 @echo "Created docs for config options"
81 @echo "Created docs for config options"
82
82
@@ -4,13 +4,101 b' from os.path import join, dirname, abspath'
4
4
5 from IPython.terminal.ipapp import TerminalIPythonApp
5 from IPython.terminal.ipapp import TerminalIPythonApp
6 from ipykernel.kernelapp import IPKernelApp
6 from ipykernel.kernelapp import IPKernelApp
7 from traitlets import Undefined
8 from collections import defaultdict
7
9
8 here = abspath(dirname(__file__))
10 here = abspath(dirname(__file__))
9 options = join(here, 'source', 'config', 'options')
11 options = join(here, 'source', 'config', 'options')
10 generated = join(options, 'config-generated.txt')
12 generated = join(options, 'config-generated.txt')
11
13
14 from ipython_genutils.text import indent, dedent
15
16 def interesting_default_value(dv):
17 if (dv is None) or (dv is Undefined):
18 return False
19 if isinstance(dv, (str, list, tuple, dict, set)):
20 return bool(dv)
21 return True
22
23 def format_aliases(aliases):
24 fmted = []
25 for a in aliases:
26 dashes = '-' if len(a) == 1 else '--'
27 fmted.append('``%s%s``' % (dashes, a))
28 return ', '.join(fmted)
29
30 def class_config_rst_doc(cls, trait_aliases):
31 """Generate rST documentation for this class' config options.
32
33 Excludes traits defined on parent classes.
34 """
35 lines = []
36 classname = cls.__name__
37 for k, trait in sorted(cls.class_traits(config=True).items()):
38 ttype = trait.__class__.__name__
39
40 fullname = classname + '.' + trait.name
41 lines += ['.. configtrait:: ' + fullname,
42 ''
43 ]
44
45 help = trait.help.rstrip() or 'No description'
46 lines.append(indent(dedent(help), 4) + '\n')
47
48 # Choices or type
49 if 'Enum' in ttype:
50 # include Enum choices
51 lines.append(indent(
52 ':options: ' + ', '.join('``%r``' % x for x in trait.values), 4))
53 else:
54 lines.append(indent(':trait type: ' + ttype, 4))
55
56 # Default value
57 # Ignore boring default values like None, [] or ''
58 if interesting_default_value(trait.default_value):
59 try:
60 dvr = trait.default_value_repr()
61 except Exception:
62 dvr = None # ignore defaults we can't construct
63 if dvr is not None:
64 if len(dvr) > 64:
65 dvr = dvr[:61] + '...'
66 # Double up backslashes, so they get to the rendered docs
67 dvr = dvr.replace('\\n', '\\\\n')
68 lines.append(indent(':default: ``%s``' % dvr, 4))
69
70 # Command line aliases
71 if trait_aliases[fullname]:
72 fmt_aliases = format_aliases(trait_aliases[fullname])
73 lines.append(indent(':CLI option: ' + fmt_aliases, 4))
74
75 # Blank line
76 lines.append('')
77
78 return '\n'.join(lines)
79
80 def reverse_aliases(app):
81 """Produce a mapping of trait names to lists of command line aliases.
82 """
83 res = defaultdict(list)
84 for alias, trait in app.aliases.items():
85 res[trait].append(alias)
86
87 # Flags also often act as aliases for a boolean trait.
88 # Treat flags which set one trait to True as aliases.
89 for flag, (cfg, _) in app.flags.items():
90 if len(cfg) == 1:
91 classname = list(cfg)[0]
92 cls_cfg = cfg[classname]
93 if len(cls_cfg) == 1:
94 traitname = list(cls_cfg)[0]
95 if cls_cfg[traitname] is True:
96 res[classname+'.'+traitname].append(flag)
97
98 return res
12
99
13 def write_doc(name, title, app, preamble=None):
100 def write_doc(name, title, app, preamble=None):
101 trait_aliases = reverse_aliases(app)
14 filename = join(options, name+'.rst')
102 filename = join(options, name+'.rst')
15 with open(filename, 'w') as f:
103 with open(filename, 'w') as f:
16 f.write(title + '\n')
104 f.write(title + '\n')
@@ -18,7 +106,11 b' def write_doc(name, title, app, preamble=None):'
18 f.write('\n')
106 f.write('\n')
19 if preamble is not None:
107 if preamble is not None:
20 f.write(preamble + '\n\n')
108 f.write(preamble + '\n\n')
21 f.write(app.document_config_options())
109 #f.write(app.document_config_options())
110
111 for c in app._classes_inc_parents():
112 f.write(class_config_rst_doc(c, trait_aliases))
113 f.write('\n')
22
114
23
115
24 if __name__ == '__main__':
116 if __name__ == '__main__':
@@ -62,6 +62,7 b' extensions = ['
62 'sphinx.ext.napoleon', # to preprocess docstrings
62 'sphinx.ext.napoleon', # to preprocess docstrings
63 'github', # for easy GitHub links
63 'github', # for easy GitHub links
64 'magics',
64 'magics',
65 'configtraits',
65 ]
66 ]
66
67
67 if ON_RTD:
68 if ON_RTD:
General Comments 0
You need to be logged in to leave comments. Login now