def class_get_trait_help(cls, trait, inst=None, helptext=None): """Get the helptext string for a single trait. :param inst: If given, it's current trait values will be used in place of the class default. :param helptext: If not given, uses the `help` attribute of the current trait. """ assert inst is None or isinstance(inst, cls) lines = [] header = f"--{cls.__name__}.{trait.name}" if isinstance(trait, (Container, Dict)): multiplicity = trait.metadata.get("multiplicity", "append") if isinstance(trait, Dict): sample_value = "<key-1>=<value-1>" else: sample_value = "<%s-item-1>" % trait.__class__.__name__.lower() if multiplicity == "append": header = f"{header}={sample_value}..." else: header = f"{header} {sample_value}..." else: header = f"{header}=<{trait.__class__.__name__}>" # header = "--%s.%s=<%s>" % (cls.__name__, trait.name, trait.__class__.__name__) lines.append(header) if helptext is None: helptext = trait.help if helptext != "": helptext = "\n".join(wrap_paragraphs(helptext, 76)) lines.append(indent(helptext)) if "Enum" in trait.__class__.__name__: # include Enum choices lines.append(indent("Choices: %s" % trait.info())) if inst is not None: lines.append(indent(f"Current: {getattr(inst, trait.name)!r}")) else: try: dvr = trait.default_value_repr() except Exception: dvr = None # ignore defaults we can't construct if dvr is not None: if len(dvr) > 64: dvr = dvr[:61] + "..." lines.append(indent("Default: %s" % dvr)) return "\n".join(lines)
def class_config_rst_doc(cls, trait_aliases): """Generate rST documentation for this class' config options. Excludes traits defined on parent classes. """ lines = [] classname = cls.__name__ for k, trait in sorted(cls.class_traits(config=True).items()): ttype = trait.__class__.__name__ fullname = classname + '.' + trait.name lines += ['.. configtrait:: ' + fullname, '' ] help = trait.help.rstrip() or "No description" lines.append(indent(dedent(help)) + "\n") # Choices or type if 'Enum' in ttype: # include Enum choices lines.append( indent(":options: " + ", ".join("``%r``" % x for x in trait.values)) ) else: lines.append(indent(":trait type: " + ttype)) # Default value # Ignore boring default values like None, [] or '' if interesting_default_value(trait.default_value): try: dvr = trait.default_value_repr() except Exception: dvr = None # ignore defaults we can't construct if dvr is not None: if len(dvr) > 64: dvr = dvr[:61] + '...' # Double up backslashes, so they get to the rendered docs dvr = dvr.replace("\\n", "\\\\n") lines.append(indent(":default: ``%s``" % dvr)) # Command line aliases if trait_aliases[fullname]: fmt_aliases = format_aliases(trait_aliases[fullname]) lines.append(indent(":CLI option: " + fmt_aliases)) # Blank line lines.append('') return '\n'.join(lines)
def class_get_trait_help(cls, trait, inst=None, helptext=None): """Get the helptext string for a single trait. :param inst: If given, it's current trait values will be used in place of the class default. :param helptext: If not given, uses the `help` attribute of the current trait. """ assert inst is None or isinstance(inst, cls) lines = [] header = "--%s.%s" % (cls.__name__, trait.name) if isinstance(trait, (Container, Dict)): multiplicity = trait.metadata.get('multiplicity', 'append') if isinstance(trait, Dict): sample_value = '<key-1>=<value-1>' else: sample_value = '<%s-item-1>' % trait.__class__.__name__.lower() if multiplicity == 'append': header = "%s=%s..." % (header, sample_value) else: header = "%s %s..." % (header, sample_value) else: header = '%s=<%s>' % (header, trait.__class__.__name__) #header = "--%s.%s=<%s>" % (cls.__name__, trait.name, trait.__class__.__name__) lines.append(header) if helptext is None: helptext = trait.help if helptext != '': helptext = '\n'.join(wrap_paragraphs(helptext, 76)) lines.append(indent(helptext)) if 'Enum' in trait.__class__.__name__: # include Enum choices lines.append(indent('Choices: %s' % trait.info())) if inst is not None: lines.append(indent("Current: %r" % (getattr(inst, trait.name), ))) else: try: dvr = trait.default_value_repr() except Exception: dvr = None # ignore defaults we can't construct if dvr is not None: if len(dvr) > 64: dvr = dvr[:61] + "..." lines.append(indent("Default: %s" % dvr)) return '\n'.join(lines)
def emit_examples(self): """Yield lines with the usage and examples. This usage string goes at the end of the command line help string and should contain examples of the application's usage. """ if self.examples: yield "Examples" yield "--------" yield '' yield indent(dedent(self.examples.strip())) yield ''
def class_config_rst_doc(cls): """Generate rST documentation for this class' config options. Excludes traits defined on parent classes. """ lines = [] classname = cls.__name__ for _, trait in sorted(cls.class_traits(config=True).items()): ttype = trait.__class__.__name__ termline = classname + "." + trait.name # Choices or type if "Enum" in ttype: # include Enum choices termline += " : " + trait.info_rst() else: termline += " : " + ttype lines.append(termline) # Default value try: dvr = trait.default_value_repr() except Exception: dvr = None # ignore defaults we can't construct if dvr is not None: if len(dvr) > 64: dvr = dvr[:61] + "..." # Double up backslashes, so they get to the rendered docs dvr = dvr.replace("\\n", "\\\\n") lines.append(indent("Default: ``%s``" % dvr)) lines.append("") help = trait.help or "No description" lines.append(indent(dedent(help))) # Blank line lines.append("") return "\n".join(lines)
def emit_flag_help(self): """Yield the lines for the flag part of the help.""" if not self.flags: return for flags, (cfg, fhelp) in self.flags.items(): try: if not isinstance(flags, tuple): flags = (flags,) # type:ignore[assignment] flags = sorted(flags, key=len) # type:ignore[assignment] flags = ", ".join(("--%s" if len(m) > 1 else "-%s") % m for m in flags) yield flags yield indent(dedent(fhelp.strip())) cfg_list = " ".join( f"--{clname}.{prop}={val}" for clname, props_dict in cfg.items() for prop, val in props_dict.items() ) cfg_txt = "Equivalent to: [%s]" % cfg_list yield indent(dedent(cfg_txt)) except Exception as ex: self.log.error("Failed collecting help-message for flag %r, due to: %s", flags, ex) raise
def emit_flag_help(self): """Yield the lines for the flag part of the help.""" if not self.flags: return for flags, (cfg, fhelp) in self.flags.items(): try: if not isinstance(flags, tuple): flags = (flags, ) flags = sorted(flags, key=len) flags = ', '.join( ('--%s' if len(m) > 1 else '-%s') % m for m in flags) yield flags yield indent(dedent(fhelp.strip())) cfg_list = ' '.join('--%s.%s=%s' % (clname, prop, val) for clname, props_dict in cfg.items() for prop, val in props_dict.items()) cfg_txt = "Equivalent to: [%s]" % cfg_list yield indent(dedent(cfg_txt)) except Exception as ex: self.log.error( 'Failed collecting help-message for flag %r, due to: %s', flags, ex) raise
def emit_subcommands_help(self): """Yield the lines for the subcommand part of the help.""" if not self.subcommands: return header = "Subcommands" yield header yield "=" * len(header) for p in wrap_paragraphs(self.subcommand_description.format(app=self.name)): yield p yield "" for subc, (_, help) in self.subcommands.items(): yield subc if help: yield indent(dedent(help.strip())) yield ""
def emit_alias_help(self): """Yield the lines for alias part of the help.""" if not self.aliases: return classdict = {} for cls in self.classes: # include all parents (up to, but excluding Configurable) in available names for c in cls.mro()[:-3]: classdict[c.__name__] = c for alias, longname in self.aliases.items(): try: if isinstance(longname, tuple): longname, fhelp = longname else: fhelp = None classname, traitname = longname.split('.')[-2:] longname = classname + '.' + traitname cls = classdict[classname] trait = cls.class_traits(config=True)[traitname] fhelp = cls.class_get_trait_help(trait, helptext=fhelp).splitlines() if not isinstance(alias, tuple): alias = (alias, ) alias = sorted(alias, key=len) alias = ', '.join( ('--%s' if len(m) > 1 else '-%s') % m for m in alias) # reformat first line fhelp[0] = fhelp[0].replace('--' + longname, alias) for l in fhelp: yield l yield indent("Equivalent to: [--%s]" % longname) except Exception as ex: self.log.error( 'Failed collecting help-message for alias %r, due to: %s', alias, ex) raise