jenkins-bot has submitted this change. ( 
https://gerrit.wikimedia.org/r/c/pywikibot/core/+/1162628?usp=email )

Change subject: [tests] Add a copyright fixer as pre-commit hook
......................................................................

[tests] Add a copyright fixer as pre-commit hook

- Add a local copyright checker. This checks for a valid copyright
  notice in Python files. If any file was changed and the file is
  lager than 100 chars, it is able to update the copyright year.
- add copyright notice to maintenance/__init__.py because the file
  is larger than 100 chars.
- Update tests

Change-Id: I7d64e87c1fd3162dbc684bf44c64ebb18f16f88a
---
M .pre-commit-config.yaml
M scripts/maintenance/__init__.py
A tests/hooks/__init__.py
A tests/hooks/copyright_fixer.py
M tests/setup_tests.py
5 files changed, 90 insertions(+), 2 deletions(-)

Approvals:
  Xqt: Looks good to me, approved
  jenkins-bot: Verified




diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index b1977c3..f92ce04 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -54,6 +54,13 @@
       - id: rst-directive-colons
       - id: rst-inline-touching-normal
       - id: text-unicode-replacement-char
+  - repo: local
+    hooks:
+      - id: copyright
+        name: check and fix copyright notice
+        entry: tests/hooks/copyright_fixer.py
+        files: .+\.py$
+        language: python
   - repo: https://github.com/astral-sh/ruff-pre-commit
     rev: v0.12.0
     hooks:
diff --git a/scripts/maintenance/__init__.py b/scripts/maintenance/__init__.py
index bc5b99f..f6932d9 100644
--- a/scripts/maintenance/__init__.py
+++ b/scripts/maintenance/__init__.py
@@ -12,3 +12,11 @@
 .. versionremoved:: 9.0
    ``wikimedia_sites`` script was removed (:phab:`T78396`).
 """
+from __future__ import annotations
+
+
+#
+# (C) Pywikibot team, 2014-2025
+#
+# Distributed under the terms of the MIT license.
+#
diff --git a/tests/hooks/__init__.py b/tests/hooks/__init__.py
new file mode 100644
index 0000000..8a22a45
--- /dev/null
+++ b/tests/hooks/__init__.py
@@ -0,0 +1,3 @@
+"""Local pre-commit hooks for CI tests."""
+
+from __future__ import annotations
diff --git a/tests/hooks/copyright_fixer.py b/tests/hooks/copyright_fixer.py
new file mode 100755
index 0000000..93eeb81
--- /dev/null
+++ b/tests/hooks/copyright_fixer.py
@@ -0,0 +1,70 @@
+#!/usr/bin/env python
+"""Pre-commit hook to set the leftmost copyright year."""
+#
+# (C) Pywikibot team, 2025
+#
+# Distributed under the terms of the MIT license.
+#
+from __future__ import annotations
+
+import re
+import subprocess
+import sys
+from collections.abc import Sequence
+from datetime import date
+from pathlib import Path
+
+
+PATTERN = re.compile(
+    r'(?m)^(# \([Cc©]\) Pywikibot [Tt]eam, 20\d{2})(-20\d{2})?$'
+)
+
+
+def get_patched_files():
+    """Return the PatchSet for the latest commit."""
+    out = subprocess.run(['git', 'diff', '--unified=0'],
+                         stdout=subprocess.PIPE,
+                         check=True, encoding='utf-8', text=True).stdout
+    return {Path(path) for path in re.findall(r'(?m)^\+\+\+ b/(.+)$', out)
+            if path.endswith('.py')}
+
+
+def check_file(path: Path, year: int, files: set(Path)) -> bool:
+    """Check for copyright string and fix it if necessary.
+
+    Update copyright string for changed files.
+    """
+    text = path.read_text(encoding='utf-8')
+    if len(text) < 100:
+        return True
+
+    m = PATTERN.search(text)
+    if not m:
+        return False
+
+    if path in files and not m[0].endswith(str(year)):
+        text = PATTERN.sub(f'{m[1]}-{year}', text)
+        path.write_text(text, encoding='utf-8')
+        print(f'Fixing copyright in {path}')  # noqa: T201
+
+    return True
+
+
+def main(argv: Sequence[str] | None = None) -> int:
+    """Test that test filenames contains a valid copyright."""
+    failed = False
+    year = date.today().year
+    files = get_patched_files()
+
+    for filename in sys.argv[1:]:
+        path = Path(filename)
+
+        if not check_file(path, year, files):
+            print(f'Missing or invalid copyright in: {path}')  # noqa: T201
+            failed = True
+
+    return (0, 1)[failed]
+
+
+if __name__ == '__main__':
+    sys.exit(main(sys.argv))
diff --git a/tests/setup_tests.py b/tests/setup_tests.py
index b512af8..8f3557a 100755
--- a/tests/setup_tests.py
+++ b/tests/setup_tests.py
@@ -1,7 +1,7 @@
 #!/usr/bin/env python3
 """Test setup.py."""
 #
-# (C) Pywikibot team, 2024
+# (C) Pywikibot team, 2024-2025
 #
 # Distributed under the terms of the MIT license.
 #
@@ -50,7 +50,7 @@
         packages = setup.get_packages(name)
         self.assertEqual(packages[0], name)
         self.assertIn(name + '.data', packages)
-        self.assertLength(packages, 10)
+        self.assertLength(packages, 11)

     def test_get_scripts_packages(self) -> None:
         """Test :func:`setup.get_packages` function for scripts."""

--
To view, visit 
https://gerrit.wikimedia.org/r/c/pywikibot/core/+/1162628?usp=email
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.wikimedia.org/r/settings?usp=email

Gerrit-MessageType: merged
Gerrit-Project: pywikibot/core
Gerrit-Branch: master
Gerrit-Change-Id: I7d64e87c1fd3162dbc684bf44c64ebb18f16f88a
Gerrit-Change-Number: 1162628
Gerrit-PatchSet: 2
Gerrit-Owner: Xqt <[email protected]>
Gerrit-Reviewer: Xqt <[email protected]>
Gerrit-Reviewer: jenkins-bot
_______________________________________________
Pywikibot-commits mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to