##// END OF EJS Templates
Merge pull request #12663 from rushabh-v/pl-a_c
Matthias Bussonnier -
r26180:106a8419 merge
parent child Browse files
Show More
@@ -1,127 +1,126 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2
2
3 from os.path import join, dirname, abspath
4 import inspect
3 import inspect
5 from pathlib import Path
4 from pathlib import Path
6 from IPython.terminal.ipapp import TerminalIPythonApp
5 from IPython.terminal.ipapp import TerminalIPythonApp
7 from ipykernel.kernelapp import IPKernelApp
6 from ipykernel.kernelapp import IPKernelApp
8 from traitlets import Undefined
7 from traitlets import Undefined
9 from collections import defaultdict
8 from collections import defaultdict
10
9
11 here = abspath(dirname(__file__))
10 here = (Path(__file__)).parent
12 options = join(here, 'source', 'config', 'options')
11 options = here / "source" / "config" / "options"
13 generated = join(options, 'config-generated.txt')
12 generated = options / "config-generated.txt"
14
13
15 import textwrap
14 import textwrap
16 indent = lambda text,n: textwrap.indent(text,n*' ')
15 indent = lambda text,n: textwrap.indent(text,n*' ')
17
16
18
17
19 def interesting_default_value(dv):
18 def interesting_default_value(dv):
20 if (dv is None) or (dv is Undefined):
19 if (dv is None) or (dv is Undefined):
21 return False
20 return False
22 if isinstance(dv, (str, list, tuple, dict, set)):
21 if isinstance(dv, (str, list, tuple, dict, set)):
23 return bool(dv)
22 return bool(dv)
24 return True
23 return True
25
24
26 def format_aliases(aliases):
25 def format_aliases(aliases):
27 fmted = []
26 fmted = []
28 for a in aliases:
27 for a in aliases:
29 dashes = '-' if len(a) == 1 else '--'
28 dashes = '-' if len(a) == 1 else '--'
30 fmted.append('``%s%s``' % (dashes, a))
29 fmted.append('``%s%s``' % (dashes, a))
31 return ', '.join(fmted)
30 return ', '.join(fmted)
32
31
33 def class_config_rst_doc(cls, trait_aliases):
32 def class_config_rst_doc(cls, trait_aliases):
34 """Generate rST documentation for this class' config options.
33 """Generate rST documentation for this class' config options.
35
34
36 Excludes traits defined on parent classes.
35 Excludes traits defined on parent classes.
37 """
36 """
38 lines = []
37 lines = []
39 classname = cls.__name__
38 classname = cls.__name__
40 for k, trait in sorted(cls.class_traits(config=True).items()):
39 for k, trait in sorted(cls.class_traits(config=True).items()):
41 ttype = trait.__class__.__name__
40 ttype = trait.__class__.__name__
42
41
43 fullname = classname + '.' + trait.name
42 fullname = classname + '.' + trait.name
44 lines += ['.. configtrait:: ' + fullname,
43 lines += ['.. configtrait:: ' + fullname,
45 ''
44 ''
46 ]
45 ]
47
46
48 help = trait.help.rstrip() or 'No description'
47 help = trait.help.rstrip() or 'No description'
49 lines.append(indent(inspect.cleandoc(help), 4) + '\n')
48 lines.append(indent(inspect.cleandoc(help), 4) + '\n')
50
49
51 # Choices or type
50 # Choices or type
52 if 'Enum' in ttype:
51 if 'Enum' in ttype:
53 # include Enum choices
52 # include Enum choices
54 lines.append(indent(
53 lines.append(indent(
55 ':options: ' + ', '.join('``%r``' % x for x in trait.values), 4))
54 ':options: ' + ', '.join('``%r``' % x for x in trait.values), 4))
56 else:
55 else:
57 lines.append(indent(':trait type: ' + ttype, 4))
56 lines.append(indent(':trait type: ' + ttype, 4))
58
57
59 # Default value
58 # Default value
60 # Ignore boring default values like None, [] or ''
59 # Ignore boring default values like None, [] or ''
61 if interesting_default_value(trait.default_value):
60 if interesting_default_value(trait.default_value):
62 try:
61 try:
63 dvr = trait.default_value_repr()
62 dvr = trait.default_value_repr()
64 except Exception:
63 except Exception:
65 dvr = None # ignore defaults we can't construct
64 dvr = None # ignore defaults we can't construct
66 if dvr is not None:
65 if dvr is not None:
67 if len(dvr) > 64:
66 if len(dvr) > 64:
68 dvr = dvr[:61] + '...'
67 dvr = dvr[:61] + '...'
69 # Double up backslashes, so they get to the rendered docs
68 # Double up backslashes, so they get to the rendered docs
70 dvr = dvr.replace('\\n', '\\\\n')
69 dvr = dvr.replace('\\n', '\\\\n')
71 lines.append(indent(':default: ``%s``' % dvr, 4))
70 lines.append(indent(':default: ``%s``' % dvr, 4))
72
71
73 # Command line aliases
72 # Command line aliases
74 if trait_aliases[fullname]:
73 if trait_aliases[fullname]:
75 fmt_aliases = format_aliases(trait_aliases[fullname])
74 fmt_aliases = format_aliases(trait_aliases[fullname])
76 lines.append(indent(':CLI option: ' + fmt_aliases, 4))
75 lines.append(indent(':CLI option: ' + fmt_aliases, 4))
77
76
78 # Blank line
77 # Blank line
79 lines.append('')
78 lines.append('')
80
79
81 return '\n'.join(lines)
80 return '\n'.join(lines)
82
81
83 def reverse_aliases(app):
82 def reverse_aliases(app):
84 """Produce a mapping of trait names to lists of command line aliases.
83 """Produce a mapping of trait names to lists of command line aliases.
85 """
84 """
86 res = defaultdict(list)
85 res = defaultdict(list)
87 for alias, trait in app.aliases.items():
86 for alias, trait in app.aliases.items():
88 res[trait].append(alias)
87 res[trait].append(alias)
89
88
90 # Flags also often act as aliases for a boolean trait.
89 # Flags also often act as aliases for a boolean trait.
91 # Treat flags which set one trait to True as aliases.
90 # Treat flags which set one trait to True as aliases.
92 for flag, (cfg, _) in app.flags.items():
91 for flag, (cfg, _) in app.flags.items():
93 if len(cfg) == 1:
92 if len(cfg) == 1:
94 classname = list(cfg)[0]
93 classname = list(cfg)[0]
95 cls_cfg = cfg[classname]
94 cls_cfg = cfg[classname]
96 if len(cls_cfg) == 1:
95 if len(cls_cfg) == 1:
97 traitname = list(cls_cfg)[0]
96 traitname = list(cls_cfg)[0]
98 if cls_cfg[traitname] is True:
97 if cls_cfg[traitname] is True:
99 res[classname+'.'+traitname].append(flag)
98 res[classname+'.'+traitname].append(flag)
100
99
101 return res
100 return res
102
101
103 def write_doc(name, title, app, preamble=None):
102 def write_doc(name, title, app, preamble=None):
104 trait_aliases = reverse_aliases(app)
103 trait_aliases = reverse_aliases(app)
105 filename = join(options, name+'.rst')
104 filename = options / (name + ".rst")
106 with open(filename, 'w') as f:
105 with open(filename, "w") as f:
107 f.write(title + '\n')
106 f.write(title + "\n")
108 f.write(('=' * len(title)) + '\n')
107 f.write(("=" * len(title)) + "\n")
109 f.write('\n')
108 f.write("\n")
110 if preamble is not None:
109 if preamble is not None:
111 f.write(preamble + '\n\n')
110 f.write(preamble + '\n\n')
112 #f.write(app.document_config_options())
111 #f.write(app.document_config_options())
113
112
114 for c in app._classes_inc_parents():
113 for c in app._classes_inc_parents():
115 f.write(class_config_rst_doc(c, trait_aliases))
114 f.write(class_config_rst_doc(c, trait_aliases))
116 f.write('\n')
115 f.write('\n')
117
116
118
117
119 if __name__ == '__main__':
118 if __name__ == '__main__':
120 # Touch this file for the make target
119 # Touch this file for the make target
121 Path(generated).write_text("")
120 Path(generated).write_text("")
122
121
123 write_doc('terminal', 'Terminal IPython options', TerminalIPythonApp())
122 write_doc('terminal', 'Terminal IPython options', TerminalIPythonApp())
124 write_doc('kernel', 'IPython kernel options', IPKernelApp(),
123 write_doc('kernel', 'IPython kernel options', IPKernelApp(),
125 preamble=("These options can be used in :file:`ipython_kernel_config.py`. "
124 preamble=("These options can be used in :file:`ipython_kernel_config.py`. "
126 "The kernel also respects any options in `ipython_config.py`"),
125 "The kernel also respects any options in `ipython_config.py`"),
127 )
126 )
General Comments 0
You need to be logged in to leave comments. Login now