mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Breno Rodrigues Alves <breno3011alves@gmail.com>
To: linux-kernel@vger.kernel.org
Cc: Andy Whitcroft <apw@canonical.com>, Joe Perches <joe@perches.com>,
	Dwaipayan Ray <dwaipayanray1@gmail.com>,
	Lukas Bulwahn <lukas.bulwahn@gmail.com>,
	Breno Rodrigues Alves <breno3011alves@gmail.com>
Subject: [RFC PATCH 6/7] scripts: convert parse-maintainers.pl to Python
Date: Sun, 18 Oct 2026 08:28:37 -0300	[thread overview]
Message-ID: <20261018112838.16355-7-breno3011alves@gmail.com> (raw)
In-Reply-To: <20261018112838.16355-1-breno3011alves@gmail.com>

Faithful re-implementation of parse-maintainers.pl in Python 3
(stdlib only). Same section parsing, same --order preferred
ordering, same --input/--output/--section behavior.

Verified byte-for-byte identical to the Perl version on the
kernel MAINTAINERS file (30,222 lines).

Signed-off-by: Breno Rodrigues Alves <breno3011alves@gmail.com>
---
 scripts/parse-maintainers.py | 136 +++++++++++++++++++++++++++++++++++
 1 file changed, 136 insertions(+)
 create mode 100755 scripts/parse-maintainers.py

diff --git a/scripts/parse-maintainers.py b/scripts/parse-maintainers.py
new file mode 100755
index 000000000..520f66ab8
--- /dev/null
+++ b/scripts/parse-maintainers.py
@@ -0,0 +1,136 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: GPL-2.0
+#
+# Sort MAINTAINERS file sections alphabetically.
+
+import argparse
+import re
+import sys
+from functools import cmp_to_key
+
+PREFERRED_ORDER = 'MRLSWQBCPTFXNK'
+
+
+def by_category_cmp(a, b):
+    aa = a.upper().replace('THE REST', 'ZZZZZZ')
+    bb = b.upper().replace('THE REST', 'ZZZZZZ')
+    return (aa > bb) - (aa < bb)
+
+
+def by_pattern_cmp(a, b):
+    a1 = a[0].upper() if a else ''
+    b1 = b[0].upper() if b else ''
+    ai = PREFERRED_ORDER.find(a1)
+    bi = PREFERRED_ORDER.find(b1)
+    if ai < 0:
+        ai = 1000
+    if bi < 0:
+        bi = 1000
+    if (a1 == 'F' and b1 == 'F') or (a1 == 'X' and b1 == 'X'):
+        return (a > b) - (a < b)
+    if ai < bi:
+        return -1
+    if ai == bi:
+        return 0
+    return 1
+
+
+def trim(s):
+    return s.strip()
+
+
+def alpha_output(ref, filename, order):
+    if not ref:
+        return
+    with open(filename, 'w') as f:
+        sep = None
+        for key in sorted(ref.keys(), key=cmp_to_key(by_category_cmp)):
+            if key == ' ':
+                f.write(ref[key])
+            else:
+                if sep is None:
+                    sep = '\n'
+                else:
+                    f.write(sep)
+                f.write(key + '\n')
+                patterns = ref[key].split('\n')
+                if order:
+                    patterns = sorted(patterns, key=cmp_to_key(by_pattern_cmp))
+                for p in patterns:
+                    if p:
+                        f.write(p + '\n')
+
+
+def file_input(ref, filename):
+    lastline = ''
+    case = ' '
+    ref[case] = ''
+
+    with open(filename) as f:
+        lines = f.readlines()
+
+    for line in lines:
+        m = re.match(r'^([A-Z]):\s*(.*)', line)
+        if m:
+            line = m.group(1) + ':\t' + trim(m.group(2)) + '\n'
+            if lastline == '':
+                ref[case] += line
+                continue
+            case = trim(lastline)
+            if case in ref:
+                sys.exit(f"Header '{case}' already exists")
+            ref[case] = line
+            lastline = ''
+            continue
+
+        if case == ' ':
+            ref[case] += lastline
+            lastline = line
+            continue
+        if trim(lastline) != '':
+            sys.exit(f"Odd non-pattern line '{lastline}' for '{case}'")
+        lastline = line
+
+    ref[case] += lastline
+
+
+def main(argv):
+    p = argparse.ArgumentParser(add_help=False)
+    p.add_argument('--input', default='MAINTAINERS')
+    p.add_argument('--output', default='MAINTAINERS.new')
+    p.add_argument('--section', default='SECTION.new')
+    p.add_argument('--order', action='store_true', default=False)
+    p.add_argument('-h', '--help', '--usage', action='store_true')
+    p.add_argument('patterns', nargs='*')
+    args = p.parse_args(argv)
+
+    if args.help:
+        print_usage()
+        return 0
+
+    hash_ = {}
+    file_input(hash_, args.input)
+
+    new_hash = {}
+    for pattern in args.patterns:
+        for key in list(hash_.keys()):
+            if re.search(pattern, key) or re.search(pattern, hash_[key]):
+                new_hash[key] = hash_[key]
+                del hash_[key]
+
+    alpha_output(hash_, args.output, args.order)
+    alpha_output(new_hash, args.section, args.order)
+    return 0
+
+
+def print_usage():
+    print(f'''usage: {sys.argv[0]} [options] <pattern matching regexes>
+
+  --input => MAINTAINERS file to read (default: MAINTAINERS)
+  --output => sorted MAINTAINERS file to write (default: MAINTAINERS.new)
+  --section => new sorted MAINTAINERS file to write (default: SECTION.new)
+  --order => Use the preferred section content output ordering (default: 0)''')
+
+
+if __name__ == '__main__':
+    sys.exit(main(sys.argv[1:]))
\ No newline at end of file
-- 
2.43.0


  parent reply	other threads:[~2026-10-18 11:28 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-18 11:28 [RFC PATCH 0/7] scripts: convert remaining Perl utilities in scripts/ Breno Rodrigues Alves
2026-10-18 11:28 ` [RFC PATCH 1/7] scripts: convert checkstack.pl to Python Breno Rodrigues Alves
2026-10-18 11:28 ` [RFC PATCH 2/7] scripts: convert extract-module-sig.pl " Breno Rodrigues Alves
2026-10-18 11:28 ` [RFC PATCH 3/7] scripts: convert extract-sys-certs.pl " Breno Rodrigues Alves
2026-10-18 11:28 ` [RFC PATCH 4/7] scripts: convert headerdep.pl " Breno Rodrigues Alves
2026-10-18 11:28 ` [RFC PATCH 5/7] scripts: convert kconfig-sym-check.pl " Breno Rodrigues Alves
2026-10-18 11:28 ` Breno Rodrigues Alves [this message]
2026-10-18 11:28 ` [RFC PATCH 7/7] scripts: convert streamline_config.pl " Breno Rodrigues Alves
2026-10-18 13:57 ` [RFC PATCH v2 0/7] scripts: convert remaining Perl utilities in scripts/ Breno Rodrigues Alves
2026-10-18 13:57   ` [RFC PATCH v2 1/7] scripts: convert checkstack.pl to Python Breno Rodrigues Alves
2026-10-18 13:57   ` [RFC PATCH v2 2/7] scripts: convert extract-module-sig.pl " Breno Rodrigues Alves
2026-10-18 13:57   ` [RFC PATCH v2 3/7] scripts: convert extract-sys-certs.pl " Breno Rodrigues Alves
2026-10-18 13:57   ` [RFC PATCH v2 4/7] scripts: convert headerdep.pl " Breno Rodrigues Alves
2026-10-18 13:57   ` [RFC PATCH v2 5/7] scripts: convert kconfig-sym-check.pl " Breno Rodrigues Alves
2026-10-18 13:57   ` [RFC PATCH v2 6/7] scripts: convert parse-maintainers.pl " Breno Rodrigues Alves
2026-10-18 13:57   ` [RFC PATCH v2 7/7] scripts: convert streamline_config.pl " Breno Rodrigues Alves

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261018112838.16355-7-breno3011alves@gmail.com \
    --to=breno3011alves@gmail.com \
    --cc=apw@canonical.com \
    --cc=dwaipayanray1@gmail.com \
    --cc=joe@perches.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lukas.bulwahn@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®