@@ -510,9 +510,10 @@ class ClickDirective(rst.Directive):
510510 'commands' : directives .unchanged ,
511511 'show-nested' : directives .flag ,
512512 'hide-header' : directives .flag ,
513+ 'post-process' : directives .unchanged_required ,
513514 }
514515
515- def _load_module (self , module_path : str ) -> ty .Union [ click . Command , click . Group ] :
516+ def _load_module (self , module_path : str ) -> ty .Any :
516517 """Load the module."""
517518
518519 try :
@@ -541,14 +542,7 @@ def _load_module(self, module_path: str) -> ty.Union[click.Command, click.Group]
541542 'Module "{}" has no attribute "{}"' .format (module_name , attr_name )
542543 )
543544
544- parser = getattr (mod , attr_name )
545-
546- if not isinstance (parser , (click .Command , click .Group )):
547- raise self .error (
548- '"{}" of type "{}" is not click.Command or click.Group.'
549- '"click.BaseCommand"' .format (type (parser ), module_path )
550- )
551- return parser
545+ return getattr (mod , attr_name )
552546
553547 def _generate_nodes (
554548 self ,
@@ -620,13 +614,13 @@ def _generate_nodes(
620614 )
621615 )
622616 else :
623- commands = _filter_commands ( ctx , commands )
624- for command in commands :
617+ # We use the term "subcommand" here but these can be main commands as well
618+ for subcommand in _filter_commands ( ctx , commands ) :
625619 parent = ctx if not semantic_group else ctx .parent
626620 subcommand_nodes .extend (
627621 self ._generate_nodes (
628- command .name ,
629- command ,
622+ subcommand .name ,
623+ subcommand ,
630624 parent = parent ,
631625 nested = nested ,
632626 hide_header = False , # Hiding the header should not propagate to children
@@ -659,13 +653,37 @@ def _generate_nodes(
659653 section .append (node )
660654 final_nodes = [section ]
661655
656+ self ._post_process (command , final_nodes )
657+
662658 return final_nodes
663659
660+ def _post_process (
661+ self ,
662+ command : click .Command ,
663+ nodes : ty .List [nodes .section ],
664+ ) -> None :
665+ """Runs the post-processor, if any, for the given command and nodes.
666+
667+ If a post-processor for the created nodes was set via the
668+ :post-process: option, every set of nodes generated by the directive is
669+ run through the post-processor.
670+
671+ This allows for per-command customization of the output.
672+ """
673+ if self .postprocessor :
674+ self .postprocessor (command , nodes )
675+
664676 def run (self ) -> ty .Sequence [nodes .Element ]:
665677 self .env = self .state .document .settings .env
666678
667679 command = self ._load_module (self .arguments [0 ])
668680
681+ if not isinstance (command , (click .Command , click .Group )):
682+ raise self .error (
683+ '"{}" of type "{}" is not click.Command or click.Group.'
684+ '"click.BaseCommand"' .format (type (command ), self .arguments [0 ])
685+ )
686+
669687 if 'prog' not in self .options :
670688 raise self .error (':prog: must be specified' )
671689
@@ -674,6 +692,11 @@ def run(self) -> ty.Sequence[nodes.Element]:
674692 nested = self .options .get ('nested' )
675693 hide_header = 'hide-header' in self .options
676694
695+ self .postprocessor = None
696+ if 'post-process' in self .options :
697+ postprocessor_module_path = self .options .get ('post-process' )
698+ self .postprocessor = self ._load_module (postprocessor_module_path )
699+
677700 if show_nested :
678701 if nested :
679702 raise self .error (
0 commit comments