File indexing completed on 2025-01-19 04:00:00
0001 import os 0002 import argparse 0003 from importlib.machinery import SourceFileLoader 0004 0005 root = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 0006 doxpath = os.path.join(root, "docs", "dox") 0007 doxfile = os.path.join(doxpath, "scripts.dox") 0008 scriptpath = os.path.join(root, "bin") 0009 0010 os.makedirs(doxpath, exist_ok=True) 0011 0012 0013 scripts = [] 0014 0015 for scriptfilename in os.listdir(scriptpath): 0016 if scriptfilename.endswith(".py"): 0017 module = SourceFileLoader( 0018 os.path.splitext(scriptfilename)[0], 0019 os.path.join(scriptpath, scriptfilename) 0020 ).load_module() 0021 if hasattr(module, "parser"): 0022 scripts.append(module) 0023 0024 0025 class DoxyHelpFormatter(argparse.HelpFormatter): 0026 class _Section(argparse.HelpFormatter._Section): 0027 def format_help(self): 0028 join = self.formatter._join_parts 0029 item_help = join([func(*args) for func, args in self.items]) 0030 0031 # return nothing if the section was empty 0032 if not item_help: 0033 return '' 0034 0035 # add the heading if the section was non-empty 0036 if self.heading is not argparse.SUPPRESS and self.heading is not None: 0037 heading = r""" 0038 \subsubsection script_{name}_{id} {heading} 0039 0040 """.format( 0041 name=script.__name__, 0042 id=self.heading.lower().replace(" ", "_"), 0043 heading=self.heading 0044 ) 0045 else: 0046 heading = '' 0047 0048 # join the section-initial newline, the heading and the help 0049 return join(['\n', heading, item_help, '\n']) 0050 0051 def __init__(self, *a, **kw): 0052 super().__init__(*a, **kw) 0053 self.sectioned = False 0054 0055 def start_section(self, heading): 0056 self.sectioned = True 0057 return super().start_section(heading) 0058 0059 def _indent(self): 0060 pass 0061 0062 def _dedent(self): 0063 pass 0064 0065 def _format_usage(self, usage, actions, groups, prefix): 0066 return r""" 0067 \subsection script_{name}_usage Usage 0068 0069 \code{{.unparsed}} 0070 {usage} 0071 \endcode 0072 0073 \subsection script_{name}_options Options 0074 0075 """.format( 0076 name=script.__name__, 0077 usage=super()._format_usage(usage, actions, groups, "").strip(), 0078 ) 0079 0080 def _metavar_formatter(self, action, default_metavar, doxyfy=False): 0081 wrapper = super()._metavar_formatter(action, default_metavar) 0082 0083 if action.metavar is not None: 0084 result = action.metavar 0085 else: 0086 result = default_metavar 0087 0088 if doxyfy: 0089 result = "@em @<%s@>" % result.lower() 0090 else: 0091 result = "<%s>" % result.lower() 0092 0093 def format(tuple_size): 0094 return (result, ) * tuple_size 0095 return format 0096 0097 def _format_args(self, action, default_metavar, doxyfy=False): 0098 get_metavar = self._metavar_formatter(action, default_metavar, doxyfy) 0099 if action.nargs is None: 0100 result = '%s' % get_metavar(1) 0101 elif action.nargs == argparse.OPTIONAL: 0102 result = '[%s]' % get_metavar(1) 0103 elif action.nargs == argparse.ZERO_OR_MORE: 0104 result = '[%s [%s ...]]' % get_metavar(2) 0105 elif action.nargs == argparse.ONE_OR_MORE: 0106 result = '%s [%s ...]' % get_metavar(2) 0107 elif action.nargs == argparse.REMAINDER: 0108 result = '...' 0109 elif action.nargs == argparse.PARSER: 0110 result = '%s ...' % get_metavar(1) 0111 else: 0112 formats = ['%s' for _ in range(action.nargs)] 0113 result = ' '.join(formats) % get_metavar(action.nargs) 0114 return result 0115 0116 def _format_action_invocation(self, action, doxyfy=False): 0117 if not action.option_strings: 0118 default = self._get_default_metavar_for_positional(action) 0119 metavar, = self._metavar_formatter(action, default, doxyfy)(1) 0120 return metavar 0121 else: 0122 os = ", ".join( 0123 ("@p " if doxyfy else "") + option_string.replace("--", "\\--") 0124 for option_string in action.option_strings 0125 ) 0126 default = self._get_default_metavar_for_optional(action) 0127 args_string = self._format_args(action, default, doxyfy) 0128 0129 os += " " + args_string 0130 0131 if action.default is not None and action.default is not argparse.SUPPRESS: 0132 os += " =%s%s" % ( 0133 "@c " if doxyfy else "", 0134 action.default 0135 ) 0136 0137 return os 0138 0139 def _format_action(self, action): 0140 out = "@par " 0141 0142 out += self._format_action_invocation(action, True) + "\n@parblock\n" 0143 0144 if action.help: 0145 out += self._expand_help(action) + "\n\n" 0146 0147 if action.choices: 0148 out += "@b Choices:\n" 0149 for c in action.choices: 0150 out += "@li @c %s\n" % c 0151 out += "\n" 0152 0153 #for subaction in self._iter_indented_subactions(action): 0154 #parts.append(self._format_action(subaction)) 0155 0156 return out + "@endparblock \n\n" 0157 0158 def add_text(self, text): 0159 if self.sectioned: 0160 return super().add_text(text) 0161 0162 0163 with open(doxfile, "w") as outf: 0164 outf.write(r""" 0165 /** 0166 \page scripts Scripts 0167 \brief Script files 0168 0169 |Script|Description| 0170 |---|---| 0171 """) 0172 0173 for script in scripts: 0174 outf.write("| \\subpage script_%s | %s |\n" % ( 0175 script.__name__, 0176 script.parser.description.strip().splitlines()[0] 0177 )) 0178 0179 outf.write("\n\n") 0180 0181 for script in scripts: 0182 parser = script.parser 0183 parser.prog = os.path.basename(script.__file__) 0184 parser.formatter_class = DoxyHelpFormatter 0185 outf.write(r""" 0186 \page script_{name} {name}.py 0187 0188 \section script_{name}_brief {name}.py 0189 0190 {brief} 0191 0192 {help} 0193 """.format( 0194 name=script.__name__, 0195 brief=parser.description, 0196 help=parser.format_help(), 0197 )) 0198 0199 outf.write("\n") 0200 0201 outf.write("\n*/")