~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/Documentation/sphinx/maintainers_include.py

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /Documentation/sphinx/maintainers_include.py (Version linux-6.12-rc7) and /Documentation/sphinx/maintainers_include.py (Version linux-6.10.14)


  1 #!/usr/bin/env python                               1 #!/usr/bin/env python
  2 # SPDX-License-Identifier: GPL-2.0                  2 # SPDX-License-Identifier: GPL-2.0
  3 # -*- coding: utf-8; mode: python -*-               3 # -*- coding: utf-8; mode: python -*-
  4 # pylint: disable=R0903, C0330, R0914, R0912,       4 # pylint: disable=R0903, C0330, R0914, R0912, E0401
  5                                                     5 
  6 u"""                                                6 u"""
  7     maintainers-include                             7     maintainers-include
  8     ~~~~~~~~~~~~~~~~~~~                             8     ~~~~~~~~~~~~~~~~~~~
  9                                                     9 
 10     Implementation of the ``maintainers-includ     10     Implementation of the ``maintainers-include`` reST-directive.
 11                                                    11 
 12     :copyright:  Copyright (C) 2019  Kees Cook<     12     :copyright:  Copyright (C) 2019  Kees Cook <keescook@chromium.org>
 13     :license:    GPL Version 2, June 1991 see      13     :license:    GPL Version 2, June 1991 see linux/COPYING for details.
 14                                                    14 
 15     The ``maintainers-include`` reST-directive     15     The ``maintainers-include`` reST-directive performs extensive parsing
 16     specific to the Linux kernel's standard "M     16     specific to the Linux kernel's standard "MAINTAINERS" file, in an
 17     effort to avoid needing to heavily mark up     17     effort to avoid needing to heavily mark up the original plain text.
 18 """                                                18 """
 19                                                    19 
 20 import sys                                         20 import sys
 21 import re                                          21 import re
 22 import os.path                                     22 import os.path
 23                                                    23 
 24 from docutils import statemachine                  24 from docutils import statemachine
 25 from docutils.utils.error_reporting import Err     25 from docutils.utils.error_reporting import ErrorString
 26 from docutils.parsers.rst import Directive         26 from docutils.parsers.rst import Directive
 27 from docutils.parsers.rst.directives.misc impo     27 from docutils.parsers.rst.directives.misc import Include
 28                                                    28 
 29 __version__  = '1.0'                               29 __version__  = '1.0'
 30                                                    30 
 31 def setup(app):                                    31 def setup(app):
 32     app.add_directive("maintainers-include", M     32     app.add_directive("maintainers-include", MaintainersInclude)
 33     return dict(                                   33     return dict(
 34         version = __version__,                     34         version = __version__,
 35         parallel_read_safe = True,                 35         parallel_read_safe = True,
 36         parallel_write_safe = True                 36         parallel_write_safe = True
 37     )                                              37     )
 38                                                    38 
 39 class MaintainersInclude(Include):                 39 class MaintainersInclude(Include):
 40     u"""MaintainersInclude (``maintainers-incl     40     u"""MaintainersInclude (``maintainers-include``) directive"""
 41     required_arguments = 0                         41     required_arguments = 0
 42                                                    42 
 43     def parse_maintainers(self, path):             43     def parse_maintainers(self, path):
 44         """Parse all the MAINTAINERS lines int     44         """Parse all the MAINTAINERS lines into ReST for human-readability"""
 45                                                    45 
 46         result = list()                            46         result = list()
 47         result.append(".. _maintainers:")          47         result.append(".. _maintainers:")
 48         result.append("")                          48         result.append("")
 49                                                    49 
 50         # Poor man's state machine.                50         # Poor man's state machine.
 51         descriptions = False                       51         descriptions = False
 52         maintainers = False                        52         maintainers = False
 53         subsystems = False                         53         subsystems = False
 54                                                    54 
 55         # Field letter to field name mapping.      55         # Field letter to field name mapping.
 56         field_letter = None                        56         field_letter = None
 57         fields = dict()                            57         fields = dict()
 58                                                    58 
 59         prev = None                                59         prev = None
 60         field_prev = ""                            60         field_prev = ""
 61         field_content = ""                         61         field_content = ""
 62                                                    62 
 63         for line in open(path):                    63         for line in open(path):
 64             # Have we reached the end of the p     64             # Have we reached the end of the preformatted Descriptions text?
 65             if descriptions and line.startswit     65             if descriptions and line.startswith('Maintainers'):
 66                 descriptions = False               66                 descriptions = False
 67                 # Ensure a blank line followin     67                 # Ensure a blank line following the last "|"-prefixed line.
 68                 result.append("")                  68                 result.append("")
 69                                                    69 
 70             # Start subsystem processing? This     70             # Start subsystem processing? This is to skip processing the text
 71             # between the Maintainers heading      71             # between the Maintainers heading and the first subsystem name.
 72             if maintainers and not subsystems:     72             if maintainers and not subsystems:
 73                 if re.search('^[A-Z0-9]', line     73                 if re.search('^[A-Z0-9]', line):
 74                     subsystems = True              74                     subsystems = True
 75                                                    75 
 76             # Drop needless input whitespace.      76             # Drop needless input whitespace.
 77             line = line.rstrip()                   77             line = line.rstrip()
 78                                                    78 
 79             # Linkify all non-wildcard refs to     79             # Linkify all non-wildcard refs to ReST files in Documentation/.
 80             pat = r'(Documentation/([^\s\?\*]*     80             pat = r'(Documentation/([^\s\?\*]*)\.rst)'
 81             m = re.search(pat, line)               81             m = re.search(pat, line)
 82             if m:                                  82             if m:
 83                 # maintainers.rst is in a subd     83                 # maintainers.rst is in a subdirectory, so include "../".
 84                 line = re.sub(pat, ':doc:`%s <     84                 line = re.sub(pat, ':doc:`%s <../%s>`' % (m.group(2), m.group(2)), line)
 85                                                    85 
 86             # Check state machine for output r     86             # Check state machine for output rendering behavior.
 87             output = None                          87             output = None
 88             if descriptions:                       88             if descriptions:
 89                 # Escape the escapes in prefor     89                 # Escape the escapes in preformatted text.
 90                 output = "| %s" % (line.replac     90                 output = "| %s" % (line.replace("\\", "\\\\"))
 91                 # Look for and record field le     91                 # Look for and record field letter to field name mappings:
 92                 #   R: Designated *reviewer*: <     92                 #   R: Designated *reviewer*: FullName <address@domain>
 93                 m = re.search(r"\s(\S):\s", li     93                 m = re.search(r"\s(\S):\s", line)
 94                 if m:                              94                 if m:
 95                     field_letter = m.group(1)      95                     field_letter = m.group(1)
 96                 if field_letter and not field_     96                 if field_letter and not field_letter in fields:
 97                     m = re.search(r"\*([^\*]+)     97                     m = re.search(r"\*([^\*]+)\*", line)
 98                     if m:                          98                     if m:
 99                         fields[field_letter] =     99                         fields[field_letter] = m.group(1)
100             elif subsystems:                      100             elif subsystems:
101                 # Skip empty lines: subsystem     101                 # Skip empty lines: subsystem parser adds them as needed.
102                 if len(line) == 0:                102                 if len(line) == 0:
103                     continue                      103                     continue
104                 # Subsystem fields are batched    104                 # Subsystem fields are batched into "field_content"
105                 if line[1] != ':':                105                 if line[1] != ':':
106                     # Render a subsystem entry    106                     # Render a subsystem entry as:
107                     #   SUBSYSTEM NAME            107                     #   SUBSYSTEM NAME
108                     #   ~~~~~~~~~~~~~~            108                     #   ~~~~~~~~~~~~~~
109                                                   109 
110                     # Flush pending field cont    110                     # Flush pending field content.
111                     output = field_content + "    111                     output = field_content + "\n\n"
112                     field_content = ""            112                     field_content = ""
113                                                   113 
114                     # Collapse whitespace in s    114                     # Collapse whitespace in subsystem name.
115                     heading = re.sub(r"\s+", "    115                     heading = re.sub(r"\s+", " ", line)
116                     output = output + "%s\n%s"    116                     output = output + "%s\n%s" % (heading, "~" * len(heading))
117                     field_prev = ""               117                     field_prev = ""
118                 else:                             118                 else:
119                     # Render a subsystem field    119                     # Render a subsystem field as:
120                     #   :Field: entry             120                     #   :Field: entry
121                     #           entry...          121                     #           entry...
122                     field, details = line.spli    122                     field, details = line.split(':', 1)
123                     details = details.strip()     123                     details = details.strip()
124                                                   124 
125                     # Mark paths (and regexes)    125                     # Mark paths (and regexes) as literal text for improved
126                     # readability and to escap    126                     # readability and to escape any escapes.
127                     if field in ['F', 'N', 'X'    127                     if field in ['F', 'N', 'X', 'K']:
128                         # But only if not alre    128                         # But only if not already marked :)
129                         if not ':doc:' in deta    129                         if not ':doc:' in details:
130                             details = '``%s``'    130                             details = '``%s``' % (details)
131                                                   131 
132                     # Comma separate email fie    132                     # Comma separate email field continuations.
133                     if field == field_prev and    133                     if field == field_prev and field_prev in ['M', 'R', 'L']:
134                         field_content = field_    134                         field_content = field_content + ","
135                                                   135 
136                     # Do not repeat field name    136                     # Do not repeat field names, so that field entries
137                     # will be collapsed togeth    137                     # will be collapsed together.
138                     if field != field_prev:       138                     if field != field_prev:
139                         output = field_content    139                         output = field_content + "\n"
140                         field_content = ":%s:"    140                         field_content = ":%s:" % (fields.get(field, field))
141                     field_content = field_cont    141                     field_content = field_content + "\n\t%s" % (details)
142                     field_prev = field            142                     field_prev = field
143             else:                                 143             else:
144                 output = line                     144                 output = line
145                                                   145 
146             # Re-split on any added newlines i    146             # Re-split on any added newlines in any above parsing.
147             if output != None:                    147             if output != None:
148                 for separated in output.split(    148                 for separated in output.split('\n'):
149                     result.append(separated)      149                     result.append(separated)
150                                                   150 
151             # Update the state machine when we    151             # Update the state machine when we find heading separators.
152             if line.startswith('----------'):     152             if line.startswith('----------'):
153                 if prev.startswith('Descriptio    153                 if prev.startswith('Descriptions'):
154                     descriptions = True           154                     descriptions = True
155                 if prev.startswith('Maintainer    155                 if prev.startswith('Maintainers'):
156                     maintainers = True            156                     maintainers = True
157                                                   157 
158             # Retain previous line for state m    158             # Retain previous line for state machine transitions.
159             prev = line                           159             prev = line
160                                                   160 
161         # Flush pending field contents.           161         # Flush pending field contents.
162         if field_content != "":                   162         if field_content != "":
163             for separated in field_content.spl    163             for separated in field_content.split('\n'):
164                 result.append(separated)          164                 result.append(separated)
165                                                   165 
166         output = "\n".join(result)                166         output = "\n".join(result)
167         # For debugging the pre-rendered resul    167         # For debugging the pre-rendered results...
168         #print(output, file=open("/tmp/MAINTAI    168         #print(output, file=open("/tmp/MAINTAINERS.rst", "w"))
169                                                   169 
170         self.state_machine.insert_input(          170         self.state_machine.insert_input(
171           statemachine.string2lines(output), p    171           statemachine.string2lines(output), path)
172                                                   172 
173     def run(self):                                173     def run(self):
174         """Include the MAINTAINERS file as par    174         """Include the MAINTAINERS file as part of this reST file."""
175         if not self.state.document.settings.fi    175         if not self.state.document.settings.file_insertion_enabled:
176             raise self.warning('"%s" directive    176             raise self.warning('"%s" directive disabled.' % self.name)
177                                                   177 
178         # Walk up source path directories to f    178         # Walk up source path directories to find Documentation/../
179         path = self.state_machine.document.att    179         path = self.state_machine.document.attributes['source']
180         path = os.path.realpath(path)             180         path = os.path.realpath(path)
181         tail = path                               181         tail = path
182         while tail != "Documentation" and tail    182         while tail != "Documentation" and tail != "":
183             (path, tail) = os.path.split(path)    183             (path, tail) = os.path.split(path)
184                                                   184 
185         # Append "MAINTAINERS"                    185         # Append "MAINTAINERS"
186         path = os.path.join(path, "MAINTAINERS    186         path = os.path.join(path, "MAINTAINERS")
187                                                   187 
188         try:                                      188         try:
189             self.state.document.settings.recor    189             self.state.document.settings.record_dependencies.add(path)
190             lines = self.parse_maintainers(pat    190             lines = self.parse_maintainers(path)
191         except IOError as error:                  191         except IOError as error:
192             raise self.severe('Problems with "    192             raise self.severe('Problems with "%s" directive path:\n%s.' %
193                       (self.name, ErrorString(    193                       (self.name, ErrorString(error)))
194                                                   194 
195         return []                                 195         return []
                                                      

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php