Ejemplo n.º 1
0
    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)
Ejemplo n.º 2
0
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)
Ejemplo n.º 3
0
    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)
Ejemplo n.º 4
0
    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 ''
Ejemplo n.º 5
0
    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)
Ejemplo n.º 6
0
    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
Ejemplo n.º 7
0
    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
Ejemplo n.º 8
0
    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 ""
Ejemplo n.º 9
0
    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