python (3.11.7)

(root)/
lib/
python3.11/
site-packages/
pip/
_vendor/
pygments/
sphinxext.py
       1  """
       2      pygments.sphinxext
       3      ~~~~~~~~~~~~~~~~~~
       4  
       5      Sphinx extension to generate automatic documentation of lexers,
       6      formatters and filters.
       7  
       8      :copyright: Copyright 2006-2023 by the Pygments team, see AUTHORS.
       9      :license: BSD, see LICENSE for details.
      10  """
      11  
      12  import sys
      13  
      14  from docutils import nodes
      15  from docutils.statemachine import ViewList
      16  from docutils.parsers.rst import Directive
      17  from sphinx.util.nodes import nested_parse_with_titles
      18  
      19  
      20  MODULEDOC = '''
      21  .. module:: %s
      22  
      23  %s
      24  %s
      25  '''
      26  
      27  LEXERDOC = '''
      28  .. class:: %s
      29  
      30      :Short names: %s
      31      :Filenames:   %s
      32      :MIME types:  %s
      33  
      34      %s
      35  
      36  '''
      37  
      38  FMTERDOC = '''
      39  .. class:: %s
      40  
      41      :Short names: %s
      42      :Filenames: %s
      43  
      44      %s
      45  
      46  '''
      47  
      48  FILTERDOC = '''
      49  .. class:: %s
      50  
      51      :Name: %s
      52  
      53      %s
      54  
      55  '''
      56  
      57  
      58  class ESC[4;38;5;81mPygmentsDoc(ESC[4;38;5;149mDirective):
      59      """
      60      A directive to collect all lexers/formatters/filters and generate
      61      autoclass directives for them.
      62      """
      63      has_content = False
      64      required_arguments = 1
      65      optional_arguments = 0
      66      final_argument_whitespace = False
      67      option_spec = {}
      68  
      69      def run(self):
      70          self.filenames = set()
      71          if self.arguments[0] == 'lexers':
      72              out = self.document_lexers()
      73          elif self.arguments[0] == 'formatters':
      74              out = self.document_formatters()
      75          elif self.arguments[0] == 'filters':
      76              out = self.document_filters()
      77          elif self.arguments[0] == 'lexers_overview':
      78              out = self.document_lexers_overview()
      79          else:
      80              raise Exception('invalid argument for "pygmentsdoc" directive')
      81          node = nodes.compound()
      82          vl = ViewList(out.split('\n'), source='')
      83          nested_parse_with_titles(self.state, vl, node)
      84          for fn in self.filenames:
      85              self.state.document.settings.record_dependencies.add(fn)
      86          return node.children
      87  
      88      def document_lexers_overview(self):
      89          """Generate a tabular overview of all lexers.
      90  
      91          The columns are the lexer name, the extensions handled by this lexer
      92          (or "None"), the aliases and a link to the lexer class."""
      93          from pip._vendor.pygments.lexers._mapping import LEXERS
      94          from pip._vendor.pygments.lexers import find_lexer_class
      95          out = []
      96  
      97          table = []
      98  
      99          def format_link(name, url):
     100              if url:
     101                  return f'`{name} <{url}>`_'
     102              return name
     103  
     104          for classname, data in sorted(LEXERS.items(), key=lambda x: x[1][1].lower()):
     105              lexer_cls = find_lexer_class(data[1])
     106              extensions = lexer_cls.filenames + lexer_cls.alias_filenames
     107  
     108              table.append({
     109                  'name': format_link(data[1], lexer_cls.url),
     110                  'extensions': ', '.join(extensions).replace('*', '\\*').replace('_', '\\') or 'None',
     111                  'aliases': ', '.join(data[2]),
     112                  'class': f'{data[0]}.{classname}'
     113              })
     114  
     115          column_names = ['name', 'extensions', 'aliases', 'class']
     116          column_lengths = [max([len(row[column]) for row in table if row[column]])
     117                            for column in column_names]
     118  
     119          def write_row(*columns):
     120              """Format a table row"""
     121              out = []
     122              for l, c in zip(column_lengths, columns):
     123                  if c:
     124                      out.append(c.ljust(l))
     125                  else:
     126                      out.append(' '*l)
     127  
     128              return ' '.join(out)
     129  
     130          def write_seperator():
     131              """Write a table separator row"""
     132              sep = ['='*c for c in column_lengths]
     133              return write_row(*sep)
     134  
     135          out.append(write_seperator())
     136          out.append(write_row('Name', 'Extension(s)', 'Short name(s)', 'Lexer class'))
     137          out.append(write_seperator())
     138          for row in table:
     139              out.append(write_row(
     140                  row['name'],
     141                  row['extensions'],
     142                  row['aliases'],
     143                  f':class:`~{row["class"]}`'))
     144          out.append(write_seperator())
     145  
     146          return '\n'.join(out)
     147  
     148      def document_lexers(self):
     149          from pip._vendor.pygments.lexers._mapping import LEXERS
     150          out = []
     151          modules = {}
     152          moduledocstrings = {}
     153          for classname, data in sorted(LEXERS.items(), key=lambda x: x[0]):
     154              module = data[0]
     155              mod = __import__(module, None, None, [classname])
     156              self.filenames.add(mod.__file__)
     157              cls = getattr(mod, classname)
     158              if not cls.__doc__:
     159                  print("Warning: %s does not have a docstring." % classname)
     160              docstring = cls.__doc__
     161              if isinstance(docstring, bytes):
     162                  docstring = docstring.decode('utf8')
     163              modules.setdefault(module, []).append((
     164                  classname,
     165                  ', '.join(data[2]) or 'None',
     166                  ', '.join(data[3]).replace('*', '\\*').replace('_', '\\') or 'None',
     167                  ', '.join(data[4]) or 'None',
     168                  docstring))
     169              if module not in moduledocstrings:
     170                  moddoc = mod.__doc__
     171                  if isinstance(moddoc, bytes):
     172                      moddoc = moddoc.decode('utf8')
     173                  moduledocstrings[module] = moddoc
     174  
     175          for module, lexers in sorted(modules.items(), key=lambda x: x[0]):
     176              if moduledocstrings[module] is None:
     177                  raise Exception("Missing docstring for %s" % (module,))
     178              heading = moduledocstrings[module].splitlines()[4].strip().rstrip('.')
     179              out.append(MODULEDOC % (module, heading, '-'*len(heading)))
     180              for data in lexers:
     181                  out.append(LEXERDOC % data)
     182  
     183          return ''.join(out)
     184  
     185      def document_formatters(self):
     186          from pip._vendor.pygments.formatters import FORMATTERS
     187  
     188          out = []
     189          for classname, data in sorted(FORMATTERS.items(), key=lambda x: x[0]):
     190              module = data[0]
     191              mod = __import__(module, None, None, [classname])
     192              self.filenames.add(mod.__file__)
     193              cls = getattr(mod, classname)
     194              docstring = cls.__doc__
     195              if isinstance(docstring, bytes):
     196                  docstring = docstring.decode('utf8')
     197              heading = cls.__name__
     198              out.append(FMTERDOC % (heading, ', '.join(data[2]) or 'None',
     199                                     ', '.join(data[3]).replace('*', '\\*') or 'None',
     200                                     docstring))
     201          return ''.join(out)
     202  
     203      def document_filters(self):
     204          from pip._vendor.pygments.filters import FILTERS
     205  
     206          out = []
     207          for name, cls in FILTERS.items():
     208              self.filenames.add(sys.modules[cls.__module__].__file__)
     209              docstring = cls.__doc__
     210              if isinstance(docstring, bytes):
     211                  docstring = docstring.decode('utf8')
     212              out.append(FILTERDOC % (cls.__name__, name, docstring))
     213          return ''.join(out)
     214  
     215  
     216  def setup(app):
     217      app.add_directive('pygmentsdoc', PygmentsDoc)