Search code examples
pythonpython-click

How to add multiple blank lines to the end of the usage message produced by the Python click module?


I have a question that's somewhat similar to this SO Q&A, however I want to add additional blank lines to an epilog at the end of the output generated by click.

I have the following code:

EPILOG='\n' + '-' * 20

 class SpecialEpilog(click.Group):
     def format_epilog(self, ctx, formatter):
         if self.epilog:
             formatter.write_paragraph()
             for line in self.epilog.split('\n'):
                 formatter.write_text(line)

 #------------------
 @click.group(cls=SpecialEpilog, epilog=EPILOG, invoke_without_command=True)
 def cli():
     """Wraps cloud.tenable.com Nessus API calls in useful ways

     \b
     The CLI provides access to these subcommands:
         - agent
         - os
         - vuln

     Each subcommand can perform useful API queries within their respective domain.
     """
     pass

 #------------------
 # main
 cli.add_command(os)
 cli.add_command(agent)
 cli.add_command(vuln)

This produces the following usage output:

Usage: nessus_query [OPTIONS] COMMAND [ARGS]...



  Wraps cloud.tenable.com Nessus API calls in useful ways

  The CLI provides access to these subcommands:
      - agent
      - os
      - vuln

  Each subcommand can perform useful API queries within their respective
  domain.

Options:
  --help  Show this message and exit.

Commands:
  agent  API calls focusing on assets' details - Works...
  os     API calls focusing on operating systems -...
  vuln   API calls focusing on vulnerabilities - Works...


--------------------
$ myprompt>

My question:

I cannot figure out a method which doesn't require printable characters. If I remove the dash sequence above, the newline characters (\n) no longer get displayed. In other words the above usage goes to this:

...
Commands:
  agent  API calls focusing on assets' details - Works...
  os     API calls focusing on operating systems -...
  vuln   API calls focusing on vulnerabilities - Works...
$ myprompt>

Solution

  • The issue is that click does an optimization to remove any blank lines at the end of the help. The behavior is in click.Command.get_help() and can be overridden like:

    Code:

    class SpecialEpilog(click.Group):
    
        def get_help(self, ctx):
            """ standard get help, but without rstrip """
            formatter = ctx.make_formatter()
            self.format_help(ctx, formatter)
            return formatter.getvalue()
    

    Test Code:

    import click
    
    EPILOG = '\n\n'
    
    class SpecialEpilog(click.Group):
        def format_epilog(self, ctx, formatter):
            if self.epilog:
                formatter.write_paragraph()
                for line in self.epilog.split('\n'):
                    formatter.write_text(line)
    
        def get_help(self, ctx):
            """ standard get help, but without rstrip """
            formatter = ctx.make_formatter()
            self.format_help(ctx, formatter)
            return formatter.getvalue()
    
    @click.group(cls=SpecialEpilog, epilog=EPILOG, invoke_without_command=True)
    def cli():
        pass
    
    @cli.command()
    def os(*args, **kwargs):
        pass
    
    @cli.command()
    def agent(*args, **kwargs):
        pass
    
    cli(['--help'])
    

    But all I need is blanks, not an epilog:

    If all you need is some blank lines, then we can ignore the epilog altogether and simply modify get_help() to add same like:

    class AddSomeBlanksToHelp(click.Group):
    
        def get_help(self, ctx):
            return super(AddSomeBlanksToHelp, self).get_help(ctx) + '\n\n'
    
    @click.group(cls=AddSomeBlanksToHelp, invoke_without_command=True)