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