Show More
@@ -33,7 +33,11 b' from IPython.utils.traitlets import (' | |||||
33 | Unicode, List, Int, Enum, Dict, Instance |
|
33 | Unicode, List, Int, Enum, Dict, Instance | |
34 | ) |
|
34 | ) | |
35 | from IPython.utils.importstring import import_item |
|
35 | from IPython.utils.importstring import import_item | |
36 | from IPython.utils.text import indent |
|
36 | from IPython.utils.text import indent, wrap_paragraphs, dedent | |
|
37 | ||||
|
38 | #----------------------------------------------------------------------------- | |||
|
39 | # function for re-wrapping a helpstring | |||
|
40 | #----------------------------------------------------------------------------- | |||
37 |
|
41 | |||
38 | #----------------------------------------------------------------------------- |
|
42 | #----------------------------------------------------------------------------- | |
39 | # Descriptions for the various sections |
|
43 | # Descriptions for the various sections | |
@@ -44,6 +48,8 b" Flags are command-line arguments passed as '--<flag>'." | |||||
44 | These take no parameters, unlike regular key-value arguments. |
|
48 | These take no parameters, unlike regular key-value arguments. | |
45 | They are typically used for setting boolean flags, or enabling |
|
49 | They are typically used for setting boolean flags, or enabling | |
46 | modes that involve setting multiple options together. |
|
50 | modes that involve setting multiple options together. | |
|
51 | ||||
|
52 | Flags *always* begin with '--', never just one '-'. | |||
47 | """.strip() # trim newlines of front and back |
|
53 | """.strip() # trim newlines of front and back | |
48 |
|
54 | |||
49 | alias_description = """ |
|
55 | alias_description = """ | |
@@ -104,10 +110,18 b' class Application(SingletonConfigurable):' | |||||
104 | # this must be a dict of two-tuples, the first element being the Config/dict |
|
110 | # this must be a dict of two-tuples, the first element being the Config/dict | |
105 | # and the second being the help string for the flag |
|
111 | # and the second being the help string for the flag | |
106 | flags = Dict() |
|
112 | flags = Dict() | |
|
113 | def _flags_changed(self, name, old, new): | |||
|
114 | """ensure flags dict is valid""" | |||
|
115 | for key,value in new.iteritems(): | |||
|
116 | assert len(value) == 2, "Bad flag: %r:%s"%(key,value) | |||
|
117 | assert isinstance(value[0], (dict, Config)), "Bad flag: %r:%s"%(key,value) | |||
|
118 | assert isinstance(value[1], basestring), "Bad flag: %r:%s"%(key,value) | |||
|
119 | ||||
107 |
|
120 | |||
108 | # subcommands for launching other applications |
|
121 | # subcommands for launching other applications | |
109 | # if this is not empty, this will be a parent Application |
|
122 | # if this is not empty, this will be a parent Application | |
110 | # this must be a dict of two-tuples, the first element being the application class/import string |
|
123 | # this must be a dict of two-tuples, | |
|
124 | # the first element being the application class/import string | |||
111 | # and the second being the help string for the subcommand |
|
125 | # and the second being the help string for the subcommand | |
112 | subcommands = Dict() |
|
126 | subcommands = Dict() | |
113 | # parse_command_line will initialize a subapp, if requested |
|
127 | # parse_command_line will initialize a subapp, if requested | |
@@ -123,11 +137,6 b' class Application(SingletonConfigurable):' | |||||
123 | # options. |
|
137 | # options. | |
124 | self.classes.insert(0, self.__class__) |
|
138 | self.classes.insert(0, self.__class__) | |
125 |
|
139 | |||
126 | # ensure self.flags dict is valid |
|
|||
127 | for key,value in self.flags.iteritems(): |
|
|||
128 | assert len(value) == 2, "Bad flag: %r:%s"%(key,value) |
|
|||
129 | assert isinstance(value[0], (dict, Config)), "Bad flag: %r:%s"%(key,value) |
|
|||
130 | assert isinstance(value[1], basestring), "Bad flag: %r:%s"%(key,value) |
|
|||
131 | self.init_logging() |
|
140 | self.init_logging() | |
132 |
|
141 | |||
133 | def _config_changed(self, name, old, new): |
|
142 | def _config_changed(self, name, old, new): | |
@@ -170,14 +179,16 b' class Application(SingletonConfigurable):' | |||||
170 | self.log.setLevel(new) |
|
179 | self.log.setLevel(new) | |
171 |
|
180 | |||
172 | def print_alias_help(self): |
|
181 | def print_alias_help(self): | |
173 |
""" |
|
182 | """Print the alias part of the help.""" | |
174 | if not self.aliases: |
|
183 | if not self.aliases: | |
175 | return |
|
184 | return | |
176 |
|
185 | |||
177 | lines = ['Aliases'] |
|
186 | lines = ['Aliases'] | |
178 | lines.append('-'*len(lines[0])) |
|
187 | lines.append('-'*len(lines[0])) | |
179 | lines.append(self.alias_description) |
|
|||
180 | lines.append('') |
|
188 | lines.append('') | |
|
189 | for p in wrap_paragraphs(self.alias_description): | |||
|
190 | lines.append(p) | |||
|
191 | lines.append('') | |||
181 |
|
192 | |||
182 | classdict = {} |
|
193 | classdict = {} | |
183 | for cls in self.classes: |
|
194 | for cls in self.classes: | |
@@ -197,23 +208,25 b' class Application(SingletonConfigurable):' | |||||
197 | print '\n'.join(lines) |
|
208 | print '\n'.join(lines) | |
198 |
|
209 | |||
199 | def print_flag_help(self): |
|
210 | def print_flag_help(self): | |
200 |
""" |
|
211 | """Print the flag part of the help.""" | |
201 | if not self.flags: |
|
212 | if not self.flags: | |
202 | return |
|
213 | return | |
203 |
|
214 | |||
204 | lines = ['Flags'] |
|
215 | lines = ['Flags'] | |
205 | lines.append('-'*len(lines[0])) |
|
216 | lines.append('-'*len(lines[0])) | |
206 | lines.append(self.flag_description) |
|
|||
207 | lines.append('') |
|
217 | lines.append('') | |
|
218 | for p in wrap_paragraphs(self.flag_description): | |||
|
219 | lines.append(p) | |||
|
220 | lines.append('') | |||
208 |
|
221 | |||
209 | for m, (cfg,help) in self.flags.iteritems(): |
|
222 | for m, (cfg,help) in self.flags.iteritems(): | |
210 | lines.append('--'+m) |
|
223 | lines.append('--'+m) | |
211 |
lines.append(indent(help.strip() |
|
224 | lines.append(indent(dedent(help.strip()))) | |
212 | lines.append('') |
|
225 | lines.append('') | |
213 | print '\n'.join(lines) |
|
226 | print '\n'.join(lines) | |
214 |
|
227 | |||
215 | def print_subcommands(self): |
|
228 | def print_subcommands(self): | |
216 |
""" |
|
229 | """Print the subcommand part of the help.""" | |
217 | if not self.subcommands: |
|
230 | if not self.subcommands: | |
218 | return |
|
231 | return | |
219 |
|
232 | |||
@@ -222,14 +235,14 b' class Application(SingletonConfigurable):' | |||||
222 | for subc, (cls,help) in self.subcommands.iteritems(): |
|
235 | for subc, (cls,help) in self.subcommands.iteritems(): | |
223 | lines.append("%s : %s"%(subc, cls)) |
|
236 | lines.append("%s : %s"%(subc, cls)) | |
224 | if help: |
|
237 | if help: | |
225 |
lines.append(indent(help.strip() |
|
238 | lines.append(indent(dedent(help.strip()))) | |
226 | lines.append('') |
|
239 | lines.append('') | |
227 | print '\n'.join(lines) |
|
240 | print '\n'.join(lines) | |
228 |
|
241 | |||
229 | def print_help(self, classes=False): |
|
242 | def print_help(self, classes=False): | |
230 | """Print the help for each Configurable class in self.classes. |
|
243 | """Print the help for each Configurable class in self.classes. | |
231 |
|
244 | |||
232 | If classes=False (the default), only flags and aliases are printed |
|
245 | If classes=False (the default), only flags and aliases are printed. | |
233 | """ |
|
246 | """ | |
234 | self.print_subcommands() |
|
247 | self.print_subcommands() | |
235 | self.print_flag_help() |
|
248 | self.print_flag_help() | |
@@ -239,8 +252,10 b' class Application(SingletonConfigurable):' | |||||
239 | if self.classes: |
|
252 | if self.classes: | |
240 | print "Class parameters" |
|
253 | print "Class parameters" | |
241 | print "----------------" |
|
254 | print "----------------" | |
242 | print self.keyvalue_description |
|
|||
243 |
|
255 | |||
|
256 | for p in wrap_paragraphs(self.keyvalue_description): | |||
|
257 | print p | |||
|
258 | ||||
244 |
|
259 | |||
245 | for cls in self.classes: |
|
260 | for cls in self.classes: | |
246 | cls.class_print_help() |
|
261 | cls.class_print_help() | |
@@ -251,8 +266,9 b' class Application(SingletonConfigurable):' | |||||
251 |
|
266 | |||
252 | def print_description(self): |
|
267 | def print_description(self): | |
253 | """Print the application description.""" |
|
268 | """Print the application description.""" | |
254 |
|
|
269 | for p in wrap_paragraphs(self.description): | |
255 |
|
270 | print p | ||
|
271 | ||||
256 |
|
272 | |||
257 | def print_version(self): |
|
273 | def print_version(self): | |
258 | """Print the version string.""" |
|
274 | """Print the version string.""" | |
@@ -269,7 +285,7 b' class Application(SingletonConfigurable):' | |||||
269 | self.config = newconfig |
|
285 | self.config = newconfig | |
270 |
|
286 | |||
271 | def initialize_subcommand(self, subc, argv=None): |
|
287 | def initialize_subcommand(self, subc, argv=None): | |
272 | """Initialize a subcommand with argv""" |
|
288 | """Initialize a subcommand with argv.""" | |
273 | subapp,help = self.subcommands.get(subc) |
|
289 | subapp,help = self.subcommands.get(subc) | |
274 |
|
290 | |||
275 | if isinstance(subapp, basestring): |
|
291 | if isinstance(subapp, basestring): | |
@@ -330,7 +346,7 b' class Application(SingletonConfigurable):' | |||||
330 | #----------------------------------------------------------------------------- |
|
346 | #----------------------------------------------------------------------------- | |
331 |
|
347 | |||
332 | def boolean_flag(name, configurable, set_help='', unset_help=''): |
|
348 | def boolean_flag(name, configurable, set_help='', unset_help=''): | |
333 |
""" |
|
349 | """Helper for building basic --trait, --no-trait flags. | |
334 |
|
350 | |||
335 | Parameters |
|
351 | Parameters | |
336 | ---------- |
|
352 | ---------- | |
@@ -360,3 +376,4 b" def boolean_flag(name, configurable, set_help='', unset_help=''):" | |||||
360 | setter = {cls : {trait : True}} |
|
376 | setter = {cls : {trait : True}} | |
361 | unsetter = {cls : {trait : False}} |
|
377 | unsetter = {cls : {trait : False}} | |
362 | return {name : (setter, set_help), 'no-'+name : (unsetter, unset_help)} |
|
378 | return {name : (setter, set_help), 'no-'+name : (unsetter, unset_help)} | |
|
379 |
@@ -21,12 +21,12 b' Authors:' | |||||
21 | # Imports |
|
21 | # Imports | |
22 | #----------------------------------------------------------------------------- |
|
22 | #----------------------------------------------------------------------------- | |
23 |
|
23 | |||
24 | from copy import deepcopy |
|
|||
25 | import datetime |
|
24 | import datetime | |
|
25 | from copy import deepcopy | |||
26 |
|
26 | |||
27 | from loader import Config |
|
27 | from loader import Config | |
28 | from IPython.utils.traitlets import HasTraits, Instance |
|
28 | from IPython.utils.traitlets import HasTraits, Instance | |
29 | from IPython.utils.text import indent |
|
29 | from IPython.utils.text import indent, wrap_paragraphs | |
30 |
|
30 | |||
31 |
|
31 | |||
32 | #----------------------------------------------------------------------------- |
|
32 | #----------------------------------------------------------------------------- | |
@@ -51,7 +51,7 b' class Configurable(HasTraits):' | |||||
51 | created = None |
|
51 | created = None | |
52 |
|
52 | |||
53 | def __init__(self, **kwargs): |
|
53 | def __init__(self, **kwargs): | |
54 | """Create a conigurable given a config config. |
|
54 | """Create a configurable given a config config. | |
55 |
|
55 | |||
56 | Parameters |
|
56 | Parameters | |
57 | ---------- |
|
57 | ---------- | |
@@ -153,27 +153,31 b' class Configurable(HasTraits):' | |||||
153 |
|
153 | |||
154 | @classmethod |
|
154 | @classmethod | |
155 | def class_get_trait_help(cls, trait): |
|
155 | def class_get_trait_help(cls, trait): | |
156 | """Get the help string for a single """ |
|
156 | """Get the help string for a single trait.""" | |
157 | lines = [] |
|
157 | lines = [] | |
158 | header = "%s.%s : %s" % (cls.__name__, trait.name, trait.__class__.__name__) |
|
158 | header = "%s.%s : %s" % (cls.__name__, trait.name, trait.__class__.__name__) | |
|
159 | lines.append(header) | |||
159 | try: |
|
160 | try: | |
160 | dvr = repr(trait.get_default_value()) |
|
161 | dvr = repr(trait.get_default_value()) | |
161 | except Exception: |
|
162 | except Exception: | |
162 | dvr = None # ignore defaults we can't construct |
|
163 | dvr = None # ignore defaults we can't construct | |
163 | if dvr is not None: |
|
164 | if dvr is not None: | |
164 | header += ' [default: %s]'%dvr |
|
165 | if len(dvr) > 64: | |
165 | lines.append(header) |
|
166 | dvr = dvr[:61]+'...' | |
|
167 | lines.append(indent('Default: %s'%dvr, 4)) | |||
|
168 | if 'Enum' in trait.__class__.__name__: | |||
|
169 | # include Enum choices | |||
|
170 | lines.append(indent('Choices: %r'%(trait.values,))) | |||
166 |
|
171 | |||
167 | help = trait.get_metadata('help') |
|
172 | help = trait.get_metadata('help') | |
168 | if help is not None: |
|
173 | if help is not None: | |
169 | lines.append(indent(help.strip(), flatten=True)) |
|
174 | help = '\n'.join(wrap_paragraphs(help, 76)) | |
170 | if 'Enum' in trait.__class__.__name__: |
|
175 | lines.append(indent(help, 4)) | |
171 | # include Enum choices |
|
|||
172 | lines.append(indent('Choices: %r'%(trait.values,), flatten=True)) |
|
|||
173 | return '\n'.join(lines) |
|
176 | return '\n'.join(lines) | |
174 |
|
177 | |||
175 | @classmethod |
|
178 | @classmethod | |
176 | def class_print_help(cls): |
|
179 | def class_print_help(cls): | |
|
180 | """Get the help string for a single trait and print it.""" | |||
177 | print cls.class_get_help() |
|
181 | print cls.class_get_help() | |
178 |
|
182 | |||
179 |
|
183 |
@@ -19,6 +19,7 b' import __main__' | |||||
19 | import os |
|
19 | import os | |
20 | import re |
|
20 | import re | |
21 | import shutil |
|
21 | import shutil | |
|
22 | import textwrap | |||
22 | from string import Formatter |
|
23 | from string import Formatter | |
23 |
|
24 | |||
24 | from IPython.external.path import path |
|
25 | from IPython.external.path import path | |
@@ -520,6 +521,58 b' def format_screen(strng):' | |||||
520 | strng = par_re.sub('',strng) |
|
521 | strng = par_re.sub('',strng) | |
521 | return strng |
|
522 | return strng | |
522 |
|
523 | |||
|
524 | def dedent(text): | |||
|
525 | """Equivalent of textwrap.dedent that ignores unindented first line. | |||
|
526 | ||||
|
527 | This means it will still dedent strings like: | |||
|
528 | '''foo | |||
|
529 | is a bar | |||
|
530 | ''' | |||
|
531 | ||||
|
532 | For use in wrap_paragraphs. | |||
|
533 | """ | |||
|
534 | ||||
|
535 | if text.startswith('\n'): | |||
|
536 | # text starts with blank line, don't ignore the first line | |||
|
537 | return textwrap.dedent(text) | |||
|
538 | ||||
|
539 | # split first line | |||
|
540 | splits = text.split('\n',1) | |||
|
541 | if len(splits) == 1: | |||
|
542 | # only one line | |||
|
543 | return textwrap.dedent(text) | |||
|
544 | ||||
|
545 | first, rest = splits | |||
|
546 | # dedent everything but the first line | |||
|
547 | rest = textwrap.dedent(rest) | |||
|
548 | return '\n'.join([first, rest]) | |||
|
549 | ||||
|
550 | def wrap_paragraphs(text, ncols=80): | |||
|
551 | """Wrap multiple paragraphs to fit a specified width. | |||
|
552 | ||||
|
553 | This is equivalent to textwrap.wrap, but with support for multiple | |||
|
554 | paragraphs, as separated by empty lines. | |||
|
555 | ||||
|
556 | Returns | |||
|
557 | ------- | |||
|
558 | ||||
|
559 | list of complete paragraphs, wrapped to fill `ncols` columns. | |||
|
560 | """ | |||
|
561 | paragraph_re = re.compile(r'\n(\s*\n)+', re.MULTILINE) | |||
|
562 | text = dedent(text).strip() | |||
|
563 | paragraphs = paragraph_re.split(text)[::2] # every other entry is space | |||
|
564 | out_ps = [] | |||
|
565 | indent_re = re.compile(r'\n\s+', re.MULTILINE) | |||
|
566 | for p in paragraphs: | |||
|
567 | # presume indentation that survives dedent is meaningful formatting, | |||
|
568 | # so don't fill unless text is flush. | |||
|
569 | if indent_re.search(p) is None: | |||
|
570 | # wrap paragraph | |||
|
571 | p = textwrap.fill(p, ncols) | |||
|
572 | out_ps.append(p) | |||
|
573 | return out_ps | |||
|
574 | ||||
|
575 | ||||
523 |
|
576 | |||
524 | class EvalFormatter(Formatter): |
|
577 | class EvalFormatter(Formatter): | |
525 | """A String Formatter that allows evaluation of simple expressions. |
|
578 | """A String Formatter that allows evaluation of simple expressions. |
General Comments 0
You need to be logged in to leave comments.
Login now