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