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

Change subject: tests: enable TypeChecking linter and update affected codes
......................................................................

tests: enable TypeChecking linter and update affected codes

Checks for unquoted type expressions in typing.cast() calls:
This rule enforces consistent quoting of type expressions passed to
cast(). Quoting is often necessary for forward references or symbols
imported only in typing.TYPE_CHECKING blocks. It also avoids repeated
evaluation of complex type expressions at runtime, which can be
beneficial in hot loops.

Checks for imports that are only used for type annotations:
Imports used only for type annotations can add runtime overhead and
contribute to import cycles. Use if TYPE_CHECKING: to avoid importing
them at runtime.

Change-Id: Ie8dd6f071f2b06c983765dc3c183782461d6d803
---
M pyproject.toml
M pywikibot/__init__.py
M pywikibot/_wbtypes.py
M pywikibot/backports.py
M pywikibot/bot_choice.py
M pywikibot/comms/eventstreams.py
M pywikibot/config.py
M pywikibot/cosmetic_changes.py
M pywikibot/data/api/_generators.py
M pywikibot/data/api/_optionset.py
M pywikibot/data/citoid.py
M pywikibot/data/sparql.py
M pywikibot/date.py
M pywikibot/diff.py
M pywikibot/editor.py
M pywikibot/family.py
M pywikibot/logentries.py
M pywikibot/logging.py
M pywikibot/login.py
M pywikibot/page/_basepage.py
M pywikibot/page/_category.py
M pywikibot/page/_filepage.py
M pywikibot/page/_user.py
M pywikibot/pagegenerators/__init__.py
M pywikibot/pagegenerators/_factory.py
M pywikibot/pagegenerators/_filters.py
M pywikibot/pagegenerators/_generators.py
M pywikibot/proofreadpage.py
M pywikibot/scripts/generate_user_files.py
M pywikibot/site/_apisite.py
M pywikibot/site/_datasite.py
M pywikibot/site/_extensions.py
M pywikibot/site/_generators.py
M pywikibot/site/_siteinfo.py
M pywikibot/specialbots/_upload.py
M pywikibot/tools/__init__.py
M pywikibot/tools/chars.py
M pywikibot/tools/djvu.py
M pywikibot/tools/itertools.py
M pywikibot/userinterfaces/buffer_interface.py
M pywikibot/userinterfaces/terminal_interface_base.py
M pywikibot/xmlreader.py
M scripts/add_text.py
M scripts/category.py
M scripts/checkimages.py
M scripts/harvest_template.py
M scripts/interwiki.py
M scripts/misspelling.py
M scripts/pagefromfile.py
M scripts/patrol.py
M scripts/redirect.py
M scripts/revertbot.py
M scripts/solve_disambiguation.py
M scripts/templatecount.py
M scripts/welcome.py
M tests/hooks/copyright_fixer.py
M tests/script_tests.py
M tests/utils.py
58 files changed, 252 insertions(+), 97 deletions(-)

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




diff --git a/pyproject.toml b/pyproject.toml
index 9f78143..7ea8932 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -201,7 +201,7 @@


 [tool.ruff.lint]
-select = ["C4", "COM818", "COM819", "D", "Q", "RSE"]
+select = ["C4", "COM818", "COM819", "D", "Q", "RSE", "TC"]
 ignore = ["D105", "D211", "D213", "D214", "D301", "D401", "D404", "D406", 
"D407", "D412", "D413", "D416", "D417"]

 [tool.ruff.lint.per-file-ignores]
diff --git a/pywikibot/__init__.py b/pywikibot/__init__.py
index 67f083a..faa2796 100644
--- a/pywikibot/__init__.py
+++ b/pywikibot/__init__.py
@@ -12,7 +12,6 @@
 import sys
 import threading
 import warnings
-from collections.abc import Callable
 from contextlib import suppress
 from functools import cache
 from queue import Queue
@@ -70,6 +69,8 @@


 if TYPE_CHECKING:
+    from collections.abc import Callable
+
     from pywikibot.site import APISite

 if PYTHON_VERSION >= (3, 13):
@@ -244,7 +245,7 @@
     if not isinstance(fam, Family):
         fam = Family.load(fam)

-    fam = cast(Family, fam)
+    fam = cast('Family', fam)
     interface = interface or fam.interface(code)

     # config.usernames is initialised with a defaultdict for each family name
@@ -261,7 +262,7 @@

     if not isinstance(interface, type):
         # If it isn't a class, assume it is a string
-        interface = cast(str, interface)
+        interface = cast('str', interface)
         try:
             tmp = __import__('pywikibot.site', fromlist=[interface])
         except ImportError:
diff --git a/pywikibot/_wbtypes.py b/pywikibot/_wbtypes.py
index 9efd083..818748f 100644
--- a/pywikibot/_wbtypes.py
+++ b/pywikibot/_wbtypes.py
@@ -534,7 +534,7 @@
                     and precision in self.PRECISION.values()):
                 prec = precision
             elif isinstance(precision, str) and precision in self.PRECISION:
-                prec = self.PRECISION[cast(str, precision)]
+                prec = self.PRECISION[cast('str', precision)]
             else:
                 raise ValueError(f'Invalid precision: "{precision}"')

diff --git a/pywikibot/backports.py b/pywikibot/backports.py
index 91a708d..bbbeb96 100644
--- a/pywikibot/backports.py
+++ b/pywikibot/backports.py
@@ -313,4 +313,6 @@
                 return Union[other, self]

 else:
-    from builtins import sentinel  # type: ignore[no-redef, attr-defined]
+    from builtins import (  # type: ignore[no-redef, attr-defined] # noqa: 
TC003, E501
+        sentinel,
+    )
diff --git a/pywikibot/bot_choice.py b/pywikibot/bot_choice.py
index 46ca97b..463ad1e 100644
--- a/pywikibot/bot_choice.py
+++ b/pywikibot/bot_choice.py
@@ -8,7 +8,6 @@

 import re
 from abc import ABC, abstractmethod
-from collections.abc import Iterable, Mapping, Sequence
 from textwrap import fill
 from typing import TYPE_CHECKING

@@ -39,6 +38,7 @@


 if TYPE_CHECKING:
+    from collections.abc import Iterable, Mapping, Sequence
     from typing import Any, Literal

     from pywikibot.page import BaseLink, Link, Page
diff --git a/pywikibot/comms/eventstreams.py b/pywikibot/comms/eventstreams.py
index 93af5ad..d331896 100644
--- a/pywikibot/comms/eventstreams.py
+++ b/pywikibot/comms/eventstreams.py
@@ -21,18 +21,21 @@
 from datetime import timedelta
 from functools import partial
 from types import NoneType
-from typing import Any
+from typing import TYPE_CHECKING, Any

 from requests.packages.urllib3.exceptions import ProtocolError
 from requests.packages.urllib3.util.response import httplib

 from pywikibot import Site, Timestamp, config, debug, warning
 from pywikibot.comms.http import user_agent
-from pywikibot.site import BaseSite
 from pywikibot.tools import cached, deprecated_args
 from pywikibot.tools.collections import GeneratorWrapper


+if TYPE_CHECKING:
+    from pywikibot.site import BaseSite
+
+
 try:
     from requests_sse import EventSource
 except ModuleNotFoundError as e:
diff --git a/pywikibot/config.py b/pywikibot/config.py
index c5e2f09..7f10d0e 100644
--- a/pywikibot/config.py
+++ b/pywikibot/config.py
@@ -52,7 +52,6 @@
 import stat
 import sys
 import types
-from collections.abc import Mapping
 from locale import getlocale
 from os import environ, getenv
 from pathlib import Path
@@ -66,6 +65,7 @@


 if TYPE_CHECKING:
+    from collections.abc import Mapping
     _DabComDict = collections.defaultdict[str, dict[str, str]]

 _ValueType = TypeVar('_ValueType')
diff --git a/pywikibot/cosmetic_changes.py b/pywikibot/cosmetic_changes.py
index 4242ad0..fb8dc89 100644
--- a/pywikibot/cosmetic_changes.py
+++ b/pywikibot/cosmetic_changes.py
@@ -57,10 +57,9 @@
 from __future__ import annotations

 import re
-from collections.abc import Callable
 from contextlib import suppress
 from enum import IntEnum
-from typing import Any, cast
+from typing import TYPE_CHECKING, Any, cast
 from urllib.parse import urlparse, urlunparse

 import pywikibot
@@ -71,6 +70,10 @@
 from pywikibot.userinterfaces.transliteration import NON_ASCII_DIGITS


+if TYPE_CHECKING:
+    from collections.abc import Callable
+
+
 try:
     import stdnum.isbn as stdnum_isbn
 except ImportError:
@@ -522,7 +525,7 @@
             replaced = '|'.join(cache.get(p.strip(), p) for p in parts)

             # extract namespace
-            m = cast(re.Match[str],
+            m = cast('re.Match[str]',
                      re.match(r'\[\[\s*(?P<namespace>[^:]+)\s*:', linktext))

             return f'[[{m["namespace"]}:{match["filename"]}{replaced}]]'
diff --git a/pywikibot/data/api/_generators.py 
b/pywikibot/data/api/_generators.py
index 4fb0a31..7ff9221 100644
--- a/pywikibot/data/api/_generators.py
+++ b/pywikibot/data/api/_generators.py
@@ -12,9 +12,8 @@
 from __future__ import annotations

 from abc import ABC, abstractmethod
-from collections.abc import Callable, Iterable
 from contextlib import suppress
-from typing import Any, cast
+from typing import TYPE_CHECKING, Any, cast
 from warnings import warn

 import pywikibot
@@ -29,6 +28,10 @@
 from pywikibot.tools.collections import GeneratorWrapper


+if TYPE_CHECKING:
+    from collections.abc import Callable, Iterable
+
+
 __all__ = (
     'APIGenerator',
     'ListGenerator',
@@ -527,7 +530,7 @@
         # mypy cannot infer that support_namespace() guarantees
         # self.limited_module is not None; therefore use cast here.
         param = self.site._paraminfo.parameter(
-            'query+' + cast(str, self.limited_module),
+            'query+' + cast('str', self.limited_module),
             'namespace'
         )
         if isinstance(namespaces, str):
diff --git a/pywikibot/data/api/_optionset.py b/pywikibot/data/api/_optionset.py
index 600638a..ccf53cc 100644
--- a/pywikibot/data/api/_optionset.py
+++ b/pywikibot/data/api/_optionset.py
@@ -7,8 +7,11 @@
 from __future__ import annotations

 from collections.abc import MutableMapping
+from typing import TYPE_CHECKING

-import pywikibot
+
+if TYPE_CHECKING:
+    import pywikibot


 __all__ = ['OptionSet']
diff --git a/pywikibot/data/citoid.py b/pywikibot/data/citoid.py
index 99afefc..3602924 100644
--- a/pywikibot/data/citoid.py
+++ b/pywikibot/data/citoid.py
@@ -11,11 +11,14 @@

 import urllib.parse
 from dataclasses import dataclass
-from typing import Any
+from typing import TYPE_CHECKING, Any

 from pywikibot.comms import http
 from pywikibot.exceptions import ApiNotAvailableError, CitoidError
-from pywikibot.site import BaseSite
+
+
+if TYPE_CHECKING:
+    from pywikibot.site import BaseSite


 VALID_FORMAT = [
diff --git a/pywikibot/data/sparql.py b/pywikibot/data/sparql.py
index 1f8a494..1137daf 100644
--- a/pywikibot/data/sparql.py
+++ b/pywikibot/data/sparql.py
@@ -156,7 +156,7 @@
         url = endpoint._replace(query=query_string).geturl()
         while True:
             try:
-                self.last_response = cast(Response,
+                self.last_response = cast('Response',
                                           http.fetch(url, headers=headers))
             except Timeout:
                 pass
diff --git a/pywikibot/date.py b/pywikibot/date.py
index b974576..46693f0 100644
--- a/pywikibot/date.py
+++ b/pywikibot/date.py
@@ -17,13 +17,14 @@
 from typing import TYPE_CHECKING, Any

 from pywikibot import Site
-from pywikibot.site import BaseSite
 from pywikibot.tools import first_lower, first_upper
 from pywikibot.userinterfaces.transliteration import NON_ASCII_DIGITS


 if TYPE_CHECKING:
     from typing import Union
+
+    from pywikibot.site import BaseSite
     tuplst_type = list[tuple[Callable[[Union[int, str]], Any],
                              Callable[[Union[int, str]], bool]]]
     encf_type = Callable[[int], Union[int, Sequence[int]]]
diff --git a/pywikibot/diff.py b/pywikibot/diff.py
index ede0860..0bc5edd 100644
--- a/pywikibot/diff.py
+++ b/pywikibot/diff.py
@@ -9,16 +9,20 @@
 import difflib
 import math
 from collections import abc
-from collections.abc import Iterable, Sequence
 from difflib import SequenceMatcher
 from difflib import _format_range_unified  # type: ignore[attr-defined]
 from heapq import nlargest
 from itertools import zip_longest
+from typing import TYPE_CHECKING

 import pywikibot
 from pywikibot.tools import chars, deprecated_signature


+if TYPE_CHECKING:
+    from collections.abc import Iterable, Sequence
+
+
 __all__ = [
     'Hunk',
     'PatchManager', 'cherry_pick',
diff --git a/pywikibot/editor.py b/pywikibot/editor.py
index fe656e2..75d5feb 100644
--- a/pywikibot/editor.py
+++ b/pywikibot/editor.py
@@ -15,16 +15,19 @@
 import subprocess
 import sys
 import tempfile
-from collections.abc import Sequence
 from pathlib import Path
 from sys import platform
 from textwrap import fill
-from typing import Protocol, cast, no_type_check
+from typing import TYPE_CHECKING, Protocol, cast, no_type_check

 import pywikibot
 from pywikibot import config


+if TYPE_CHECKING:
+    from collections.abc import Sequence
+
+
 try:
     from pywikibot.userinterfaces import gui  # noqa: F401
     GUI_ERROR = None
@@ -157,7 +160,7 @@
                 ' separately on your platform.') + '\n')

         assert pywikibot.ui is not None
-        return cast(EditableUI, pywikibot.ui).editText(
+        return cast('EditableUI', pywikibot.ui).editText(
             text, jumpIndex=jumpIndex, highlight=highlight)

     @staticmethod
diff --git a/pywikibot/family.py b/pywikibot/family.py
index b5613ae..74e2f47 100644
--- a/pywikibot/family.py
+++ b/pywikibot/family.py
@@ -14,7 +14,6 @@
 import types
 import urllib.parse as urlparse
 import warnings
-from collections.abc import Mapping, Sequence
 from importlib import import_module
 from itertools import chain
 from os.path import basename, dirname, splitext
@@ -31,6 +30,7 @@
 logger = logging.getLogger('pywiki.wiki.family')

 if TYPE_CHECKING:
+    from collections.abc import Mapping, Sequence
     CrossnamespaceType = collections.defaultdict[str, dict[str, list[int]]]

 # Legal characters for Family.name and Family.langs keys
diff --git a/pywikibot/logentries.py b/pywikibot/logentries.py
index 9a4c230..c83b264 100644
--- a/pywikibot/logentries.py
+++ b/pywikibot/logentries.py
@@ -6,15 +6,18 @@
 """Objects representing MediaWiki log entries."""
 from __future__ import annotations

-import datetime
 from collections import UserDict
-from typing import Any
+from typing import TYPE_CHECKING, Any

 import pywikibot
 from pywikibot.exceptions import Error, HiddenKeyError
 from pywikibot.tools import cached


+if TYPE_CHECKING:
+    import datetime
+
+
 class LogEntry(UserDict):

     """Generic log entry.
diff --git a/pywikibot/logging.py b/pywikibot/logging.py
index 17ceb80..bcc4798 100644
--- a/pywikibot/logging.py
+++ b/pywikibot/logging.py
@@ -42,11 +42,14 @@
 import logging
 import os
 import sys
-from collections.abc import Callable

 # logging levels
 from logging import CRITICAL, DEBUG, ERROR, INFO, WARNING
-from typing import Any
+from typing import TYPE_CHECKING, Any
+
+
+if TYPE_CHECKING:
+    from collections.abc import Callable


 STDOUT = 16  #:
diff --git a/pywikibot/login.py b/pywikibot/login.py
index 6ae3747..5e58ffa 100644
--- a/pywikibot/login.py
+++ b/pywikibot/login.py
@@ -98,7 +98,7 @@
         :raises pywikibot.exceptions.NoUsernameError: No username is
             configured for the requested site.
         """
-        site = cast(pywikibot.site.APISite, site or pywikibot.Site())
+        site = cast('pywikibot.site.APISite', site or pywikibot.Site())

         if not user:
             config_names = config.usernames
diff --git a/pywikibot/page/_basepage.py b/pywikibot/page/_basepage.py
index 0078684..ba160cd 100644
--- a/pywikibot/page/_basepage.py
+++ b/pywikibot/page/_basepage.py
@@ -9,7 +9,6 @@
 import itertools
 import re
 from collections import Counter
-from collections.abc import Generator, Iterable
 from contextlib import suppress
 from itertools import islice
 from textwrap import shorten, wrap
@@ -48,6 +47,7 @@


 if TYPE_CHECKING:
+    from collections.abc import Generator, Iterable
     from typing import Any, Literal, NoReturn

     from pywikibot.page import Revision
diff --git a/pywikibot/page/_category.py b/pywikibot/page/_category.py
index 8422500..b43a114 100644
--- a/pywikibot/page/_category.py
+++ b/pywikibot/page/_category.py
@@ -7,13 +7,16 @@
 from __future__ import annotations

 from collections import defaultdict
-from collections.abc import Generator
-from typing import Any
+from typing import TYPE_CHECKING, Any

 import pywikibot
 from pywikibot.page._page import Page


+if TYPE_CHECKING:
+    from collections.abc import Generator
+
+
 __all__ = ('Category', )


diff --git a/pywikibot/page/_filepage.py b/pywikibot/page/_filepage.py
index 5dfd7b5b..94e2155 100644
--- a/pywikibot/page/_filepage.py
+++ b/pywikibot/page/_filepage.py
@@ -12,10 +12,10 @@
 """
 from __future__ import annotations

-from collections.abc import Iterable
 from http import HTTPStatus
 from os import PathLike
 from pathlib import Path
+from typing import TYPE_CHECKING
 from urllib.parse import urlparse

 import pywikibot
@@ -25,6 +25,10 @@
 from pywikibot.tools import compute_file_hash


+if TYPE_CHECKING:
+    from collections.abc import Iterable
+
+
 __all__ = (
     'FileInfo',
     'FilePage',
diff --git a/pywikibot/page/_user.py b/pywikibot/page/_user.py
index 3d838e0..cef46ed 100644
--- a/pywikibot/page/_user.py
+++ b/pywikibot/page/_user.py
@@ -6,8 +6,7 @@
 """Object representing a Wiki user."""
 from __future__ import annotations

-from collections.abc import Generator, Iterable
-from typing import Any
+from typing import TYPE_CHECKING, Any

 import pywikibot
 from pywikibot.exceptions import (
@@ -26,6 +25,10 @@
 from pywikibot.tools.collections import DataRecord


+if TYPE_CHECKING:
+    from collections.abc import Generator, Iterable
+
+
 __all__ = ('Contribution', 'User')


diff --git a/pywikibot/pagegenerators/__init__.py 
b/pywikibot/pagegenerators/__init__.py
index dcc9d4d..def7264 100644
--- a/pywikibot/pagegenerators/__init__.py
+++ b/pywikibot/pagegenerators/__init__.py
@@ -19,7 +19,6 @@
 """
 from __future__ import annotations

-from collections.abc import Callable, Generator, Iterable
 from typing import TYPE_CHECKING, Any

 import pywikibot
@@ -595,6 +594,7 @@
 docuReplacements = {'&params;': parameterHelp}  # noqa: N816

 if TYPE_CHECKING:
+    from collections.abc import Callable, Generator, Iterable
     PRELOAD_SITE_TYPE = dict[pywikibot.site.BaseSite,
                              list[pywikibot.page.Page]]

diff --git a/pywikibot/pagegenerators/_factory.py 
b/pywikibot/pagegenerators/_factory.py
index 0ea0450..1920bc1 100644
--- a/pywikibot/pagegenerators/_factory.py
+++ b/pywikibot/pagegenerators/_factory.py
@@ -9,7 +9,6 @@
 import itertools
 import re
 import sys
-from collections.abc import Callable, Iterable, Sequence
 from datetime import timedelta
 from functools import partial
 from itertools import zip_longest
@@ -59,6 +58,7 @@


 if TYPE_CHECKING:
+    from collections.abc import Callable, Iterable, Sequence
     from typing import Any, Literal, Optional

     from pywikibot.site import BaseSite, Namespace
diff --git a/pywikibot/pagegenerators/_filters.py 
b/pywikibot/pagegenerators/_filters.py
index 87aa4b6..dcab8ab 100644
--- a/pywikibot/pagegenerators/_filters.py
+++ b/pywikibot/pagegenerators/_filters.py
@@ -8,7 +8,6 @@

 import datetime
 import re
-from collections.abc import Generator, Iterable, Sequence
 from functools import partial
 from typing import TYPE_CHECKING, NamedTuple

@@ -21,6 +20,7 @@


 if TYPE_CHECKING:
+    from collections.abc import Generator, Iterable, Sequence
     from typing import Union
 
     from pywikibot.site import BaseSite, Namespace
diff --git a/pywikibot/pagegenerators/_generators.py 
b/pywikibot/pagegenerators/_generators.py
index 3a0338b..3eca383 100644
--- a/pywikibot/pagegenerators/_generators.py
+++ b/pywikibot/pagegenerators/_generators.py
@@ -11,7 +11,6 @@
 import re
 import typing
 from collections import abc
-from collections.abc import Callable, Generator, Iterable, Iterator, Sequence
 from functools import partial
 from http import HTTPStatus
 from typing import TYPE_CHECKING, Any
@@ -31,6 +30,14 @@


 if TYPE_CHECKING:
+    from collections.abc import (
+        Callable,
+        Generator,
+        Iterable,
+        Iterator,
+        Sequence,
+    )
+
     from pywikibot.site import BaseSite, NamespaceArgType
     from pywikibot.site._namespace import SingleNamespaceType
     from pywikibot.time import Timestamp
diff --git a/pywikibot/proofreadpage.py b/pywikibot/proofreadpage.py
index 80aa945..741dca4 100644
--- a/pywikibot/proofreadpage.py
+++ b/pywikibot/proofreadpage.py
@@ -20,11 +20,10 @@
 import json
 import re
 import time
-from collections.abc import Callable, Iterable, Sequence
 from functools import partial
 from http import HTTPStatus
 from itertools import pairwise
-from typing import Any
+from typing import TYPE_CHECKING, Any
 from urllib.parse import unquote
 from weakref import WeakKeyDictionary

@@ -35,10 +34,15 @@
 from pywikibot.comms import http
 from pywikibot.data.api import ListGenerator, Request
 from pywikibot.exceptions import Error, InvalidTitleError, OtherPageSaveError
-from pywikibot.page import PageSourceType
 from pywikibot.tools import MediaWikiVersion, cached


+if TYPE_CHECKING:
+    from collections.abc import Callable, Iterable, Sequence
+
+    from pywikibot.page import PageSourceType
+
+
 try:
     from bs4 import BeautifulSoup
 except ImportError as e:
diff --git a/pywikibot/scripts/generate_user_files.py 
b/pywikibot/scripts/generate_user_files.py
index 395127a..c03dd1e 100755
--- a/pywikibot/scripts/generate_user_files.py
+++ b/pywikibot/scripts/generate_user_files.py
@@ -22,14 +22,17 @@

 import os
 import re
-from collections.abc import Callable
 from pathlib import Path
 from textwrap import fill
-from typing import NamedTuple
+from typing import TYPE_CHECKING, NamedTuple

 from pywikibot.scripts import _import_with_no_user_config


+if TYPE_CHECKING:
+    from collections.abc import Callable
+
+
 # DISABLED_SECTIONS cannot be copied; variables must be set manually
 DISABLED_SECTIONS = {
     'USER INTERFACE SETTINGS',  # uses sys
diff --git a/pywikibot/site/_apisite.py b/pywikibot/site/_apisite.py
index 3667887..ed772d2 100644
--- a/pywikibot/site/_apisite.py
+++ b/pywikibot/site/_apisite.py
@@ -11,7 +11,6 @@
 import time
 import webbrowser
 from collections import defaultdict
-from collections.abc import Iterable
 from contextlib import suppress
 from textwrap import fill
 from typing import TYPE_CHECKING, Any, Literal, NamedTuple, TypeVar
@@ -84,6 +83,8 @@


 if TYPE_CHECKING:
+    from collections.abc import Iterable
+
     from pywikibot.page import BasePage

     _CompType = int | str | pywikibot.page.Page | pywikibot.page.Revision
diff --git a/pywikibot/site/_datasite.py b/pywikibot/site/_datasite.py
index c48fdf6..36a907c 100644
--- a/pywikibot/site/_datasite.py
+++ b/pywikibot/site/_datasite.py
@@ -9,9 +9,8 @@
 import datetime
 import json
 import uuid
-from collections.abc import Generator, Iterable
 from contextlib import suppress
-from typing import Any
+from typing import TYPE_CHECKING, Any
 from warnings import warn

 import pywikibot
@@ -29,6 +28,10 @@
 from pywikibot.tools import merge_unique_dicts


+if TYPE_CHECKING:
+    from collections.abc import Generator, Iterable
+
+
 __all__ = ('DataSite', )


diff --git a/pywikibot/site/_extensions.py b/pywikibot/site/_extensions.py
index e2f9dbd..7dd69df 100644
--- a/pywikibot/site/_extensions.py
+++ b/pywikibot/site/_extensions.py
@@ -7,7 +7,6 @@
 from __future__ import annotations

 import re
-from collections.abc import Generator, Iterable
 from ipaddress import ip_network
 from typing import TYPE_CHECKING, Any, Protocol

@@ -23,12 +22,14 @@
     UnexpectedAPIDataError,
 )
 from pywikibot.site._decorators import need_extension, need_right
-from pywikibot.site._namespace import NamespaceArgType
 from pywikibot.tools import merge_unique_dicts


 if TYPE_CHECKING:
+    from collections.abc import Generator, Iterable
+
     from pywikibot.site import NamespacesDict
+    from pywikibot.site._namespace import NamespaceArgType


 class BaseSiteProtocol(Protocol):
diff --git a/pywikibot/site/_generators.py b/pywikibot/site/_generators.py
index fda0abc..33c0b61 100644
--- a/pywikibot/site/_generators.py
+++ b/pywikibot/site/_generators.py
@@ -9,7 +9,6 @@
 import heapq
 import itertools
 import typing
-from collections.abc import Callable, Generator, Iterable
 from contextlib import suppress
 from itertools import zip_longest
 from typing import Any
@@ -27,7 +26,6 @@
     UserRightsError,
 )
 from pywikibot.site._decorators import need_right
-from pywikibot.site._namespace import NamespaceArgType
 from pywikibot.tools import (
     deprecated_args,
     deprecated_signature,
@@ -38,10 +36,15 @@


 if typing.TYPE_CHECKING:
+    from collections.abc import Callable, Generator, Iterable
     from datetime import datetime

     from pywikibot.data.api import ParamInfo, Request
-    from pywikibot.site._namespace import NamespacesDict, SingleNamespaceType
+    from pywikibot.site._namespace import (
+        NamespaceArgType,
+        NamespacesDict,
+        SingleNamespaceType,
+    )
     from pywikibot.site._tokenwallet import TokenWallet
     from pywikibot.tools import MediaWikiVersion

diff --git a/pywikibot/site/_siteinfo.py b/pywikibot/site/_siteinfo.py
index 1d085bd..4f3dadf 100644
--- a/pywikibot/site/_siteinfo.py
+++ b/pywikibot/site/_siteinfo.py
@@ -95,22 +95,22 @@
         # query this method to actually get the version number

         if prop == 'general':
-            data = cast(dict[str, Any], data)
+            data = cast('dict[str, Any]', data)
             for key in 'thumblimits', 'imagelimits':
                 data[key] = list(data[key].values())
             data['magiclinks'] = [k for k, v in data['magiclinks'].items()
                                   if v]
         elif prop == 'namespaces':
-            data = cast(dict[str, Any], data)
+            data = cast('dict[str, Any]', data)
             for ns_info in data.values():
                 ns_info['*'] = ns_info['name']
         elif prop in ('languages', 'namespacealiases'):
-            data = cast(list[dict[str, Any]], data)
+            data = cast('list[dict[str, Any]]', data)
             for ns_info in data:
                 key = 'name' if 'name' in ns_info else 'alias'
                 ns_info['*'] = ns_info[key]
         elif prop == 'skins':
-            data = cast(list[dict[str, Any]], data)
+            data = cast('list[dict[str, Any]]', data)
             for ns_info in data:
                 ns_info['*'] = ns_info['name']
                 for key in 'default', 'unusable':
diff --git a/pywikibot/specialbots/_upload.py b/pywikibot/specialbots/_upload.py
index 7dc3735..370ff3d 100644
--- a/pywikibot/specialbots/_upload.py
+++ b/pywikibot/specialbots/_upload.py
@@ -11,10 +11,10 @@

 import os
 import tempfile
-from collections.abc import Callable
 from contextlib import suppress
 from http import HTTPStatus
 from pathlib import Path
+from typing import TYPE_CHECKING
 from urllib.parse import urlparse

 import requests
@@ -26,6 +26,10 @@
 from pywikibot.exceptions import APIError, FatalServerError, NoPageError


+if TYPE_CHECKING:
+    from collections.abc import Callable
+
+
 class UploadRobot(BaseBot):
 
     """Upload bot."""
diff --git a/pywikibot/tools/__init__.py b/pywikibot/tools/__init__.py
index dcf271c..ee8cf87 100644
--- a/pywikibot/tools/__init__.py
+++ b/pywikibot/tools/__init__.py
@@ -17,12 +17,10 @@
 import stat
 import subprocess
 import sys
-from collections.abc import Callable
 from contextlib import suppress
 from functools import total_ordering, wraps
 from pathlib import Path
-from types import TracebackType
-from typing import IO, Any, Literal
+from typing import IO, TYPE_CHECKING, Any, Literal
 from warnings import catch_warnings, showwarning, warn

 import packaging.version
@@ -45,6 +43,11 @@
 from pywikibot.tools._unidata import _first_upper_exception


+if TYPE_CHECKING:
+    from collections.abc import Callable
+    from types import TracebackType
+
+
 try:  # Python 3.14+
     from compression import bz2, gzip, lzma
 except ModuleNotFoundError:
diff --git a/pywikibot/tools/chars.py b/pywikibot/tools/chars.py
index c49d8a4..6a4be54 100644
--- a/pywikibot/tools/chars.py
+++ b/pywikibot/tools/chars.py
@@ -7,14 +7,17 @@
 from __future__ import annotations

 import re
-from collections.abc import Iterable
 from contextlib import suppress
-from typing import cast
+from typing import TYPE_CHECKING, cast
 from urllib.parse import unquote

 from pywikibot.tools._unidata import _category_cf


+if TYPE_CHECKING:
+    from collections.abc import Iterable
+
+
 # This is a set of all invisible characters
 # At the moment we've only added the characters from the Cf category
 _invisible_chars = _category_cf
@@ -135,4 +138,4 @@
                 first_exception = e

     # Couldn't convert, raise the first exception
-    raise cast(BaseException, first_exception)
+    raise cast('BaseException', first_exception)
diff --git a/pywikibot/tools/djvu.py b/pywikibot/tools/djvu.py
index f9cfd73..d7672b4 100644
--- a/pywikibot/tools/djvu.py
+++ b/pywikibot/tools/djvu.py
@@ -10,11 +10,15 @@
 import re
 import subprocess
 from collections import Counter
-from collections.abc import Sequence
+from typing import TYPE_CHECKING

 import pywikibot


+if TYPE_CHECKING:
+    from collections.abc import Sequence
+
+
 def _call_cmd(args: str | Sequence[str],
               lib: str = 'djvulibre') -> tuple[bool, str]:
     """Tiny wrapper around subprocess.Popen().
diff --git a/pywikibot/tools/itertools.py b/pywikibot/tools/itertools.py
index 1270bff..25d02be 100644
--- a/pywikibot/tools/itertools.py
+++ b/pywikibot/tools/itertools.py
@@ -9,13 +9,22 @@
 import collections
 import heapq
 import itertools
-from collections.abc import Callable, Generator, Hashable, Iterable, Iterator
 from contextlib import suppress
-from typing import Any
+from typing import TYPE_CHECKING, Any

 from pywikibot.logging import debug


+if TYPE_CHECKING:
+    from collections.abc import (
+        Callable,
+        Generator,
+        Hashable,
+        Iterable,
+        Iterator,
+    )
+
+
 __all__ = (
     'filter_unique',
     'intersect_generators',
diff --git a/pywikibot/userinterfaces/buffer_interface.py 
b/pywikibot/userinterfaces/buffer_interface.py
index 3de6098..af7285f 100644
--- a/pywikibot/userinterfaces/buffer_interface.py
+++ b/pywikibot/userinterfaces/buffer_interface.py
@@ -11,14 +11,17 @@

 import logging
 import queue
-from collections.abc import Sequence
-from typing import Any
+from typing import TYPE_CHECKING, Any

 from pywikibot import config
 from pywikibot.logging import INFO, VERBOSE
 from pywikibot.userinterfaces._interface_base import ABUIC


+if TYPE_CHECKING:
+    from collections.abc import Sequence
+
+
 class UI(ABUIC):

     """Collects output into an unseen buffer.
diff --git a/pywikibot/userinterfaces/terminal_interface_base.py 
b/pywikibot/userinterfaces/terminal_interface_base.py
index 28a8ba6..d1e0f16 100644
--- a/pywikibot/userinterfaces/terminal_interface_base.py
+++ b/pywikibot/userinterfaces/terminal_interface_base.py
@@ -11,8 +11,7 @@
 import re
 import sys
 import threading
-from collections.abc import Iterable, Sequence
-from typing import Any, Literal, NoReturn, TextIO
+from typing import TYPE_CHECKING, Any, Literal, NoReturn, TextIO

 import pywikibot
 from pywikibot import config
@@ -29,6 +28,10 @@
 from pywikibot.userinterfaces._interface_base import ABUIC


+if TYPE_CHECKING:
+    from collections.abc import Iterable, Sequence
+
+
 transliterator = transliteration.Transliterator(config.console_encoding)

 #: Colors supported by Pywikibot
diff --git a/pywikibot/xmlreader.py b/pywikibot/xmlreader.py
index fbef835..69a5a11 100644
--- a/pywikibot/xmlreader.py
+++ b/pywikibot/xmlreader.py
@@ -19,7 +19,7 @@

 import re
 from dataclasses import dataclass
-from typing import NamedTuple
+from typing import TYPE_CHECKING, NamedTuple
 from xml.etree.ElementTree import Element


@@ -28,11 +28,13 @@
 except ImportError:
     from xml.etree.ElementTree import ParseError, iterparse

-from collections.abc import Callable, Iterator
-
 from pywikibot.tools import open_archive


+if TYPE_CHECKING:
+    from collections.abc import Callable, Iterator
+
+
 @dataclass
 class XmlEntry:

diff --git a/scripts/add_text.py b/scripts/add_text.py
index add8687..6fe0889 100755
--- a/scripts/add_text.py
+++ b/scripts/add_text.py
@@ -69,14 +69,18 @@
 from __future__ import annotations

 import re
-from collections.abc import Sequence
 from pathlib import Path
+from typing import TYPE_CHECKING

 import pywikibot
 from pywikibot import pagegenerators, textlib
 from pywikibot.bot import AutomaticTWSummaryBot, ExistingPageBot


+if TYPE_CHECKING:
+    from collections.abc import Sequence
+
+
 DEFAULT_ARGS: dict[str, bool | str] = {
     'text': '',
     'textfile': '',
diff --git a/scripts/category.py b/scripts/category.py
index ac9d451..8ab7bdc 100755
--- a/scripts/category.py
+++ b/scripts/category.py
@@ -163,13 +163,12 @@
 import os
 import pickle
 import re
-from collections.abc import Sequence
 from contextlib import suppress
 from dataclasses import dataclass, field
 from itertools import chain
 from operator import methodcaller
 from textwrap import fill
-from typing import Union
+from typing import TYPE_CHECKING, Union

 import pywikibot
 from pywikibot import config, i18n, pagegenerators, textlib
@@ -192,6 +191,10 @@
 from pywikibot.tools.itertools import intersect_generators


+if TYPE_CHECKING:
+    from collections.abc import Sequence
+
+
 # This is required for the text that is shown when you run this script
 # with the parameter -help.
 docuReplacements = {'&params;': pagegenerators.parameterHelp}  # noqa: N816
diff --git a/scripts/checkimages.py b/scripts/checkimages.py
index c585210..5977188 100755
--- a/scripts/checkimages.py
+++ b/scripts/checkimages.py
@@ -84,8 +84,8 @@
 import collections
 import re
 import time
-from collections.abc import Generator
 from itertools import zip_longest
+from typing import TYPE_CHECKING

 import pywikibot
 from pywikibot import config, i18n
@@ -107,6 +107,10 @@
 from pywikibot.site import Namespace


+if TYPE_CHECKING:
+    from collections.abc import Generator
+
+
 try:
     from scripts.welcome import get_welcome_text
 except ModuleNotFoundError:
diff --git a/scripts/harvest_template.py b/scripts/harvest_template.py
index b8a77e3..d099176 100755
--- a/scripts/harvest_template.py
+++ b/scripts/harvest_template.py
@@ -117,8 +117,7 @@
 import re
 import signal
 import sys
-from collections.abc import Generator
-from typing import Any
+from typing import TYPE_CHECKING, Any

 import pywikibot
 from pywikibot import WbTime, textlib
@@ -132,6 +131,10 @@
 )


+if TYPE_CHECKING:
+    from collections.abc import Generator
+
+
 willstop = False


diff --git a/scripts/interwiki.py b/scripts/interwiki.py
index bc75034..090d1cd 100755
--- a/scripts/interwiki.py
+++ b/scripts/interwiki.py
@@ -359,10 +359,10 @@
 import re
 import sys
 from collections import Counter, defaultdict
-from collections.abc import Iterable
 from contextlib import suppress
 from pathlib import Path
 from textwrap import fill
+from typing import TYPE_CHECKING

 import pywikibot
 from pywikibot import (
@@ -401,6 +401,10 @@
 from pywikibot.tools.collections import SizedKeyCollection


+if TYPE_CHECKING:
+    from collections.abc import Iterable
+
+
 docuReplacements = {
     '&params;': pagegenerators.parameterHelp
 }
diff --git a/scripts/misspelling.py b/scripts/misspelling.py
index 999c141..d99d9ee 100755
--- a/scripts/misspelling.py
+++ b/scripts/misspelling.py
@@ -26,13 +26,17 @@
 """
 from __future__ import annotations

-from collections.abc import Generator
 from itertools import chain
+from typing import TYPE_CHECKING

 import pywikibot
 from pywikibot import i18n, pagegenerators


+if TYPE_CHECKING:
+    from collections.abc import Generator
+
+
 try:
     from scripts.solve_disambiguation import (
         DisambiguationRobot as BaseDisambigBot,
diff --git a/scripts/pagefromfile.py b/scripts/pagefromfile.py
index 472c484..ce7a28e 100755
--- a/scripts/pagefromfile.py
+++ b/scripts/pagefromfile.py
@@ -79,8 +79,8 @@

 import os
 import re
-from collections.abc import Generator
 from pathlib import Path
+from typing import TYPE_CHECKING

 import pywikibot
 from pywikibot import config, i18n
@@ -89,6 +89,10 @@
 from pywikibot.tools.collections import GeneratorWrapper


+if TYPE_CHECKING:
+    from collections.abc import Generator
+
+
 CTX_ATTR = '_content_ctx'


diff --git a/scripts/patrol.py b/scripts/patrol.py
index ced9a77..9939154 100755
--- a/scripts/patrol.py
+++ b/scripts/patrol.py
@@ -48,8 +48,8 @@

 import time
 from collections import defaultdict
-from collections.abc import Container
 from contextlib import suppress
+from typing import TYPE_CHECKING

 import mwparserfromhell

@@ -59,6 +59,10 @@
 from pywikibot.site import Namespace


+if TYPE_CHECKING:
+    from collections.abc import Container
+
+
 def verbose_output(string) -> None:
     """Verbose output."""
     if pywikibot.config.verbose_output:
diff --git a/scripts/redirect.py b/scripts/redirect.py
index 4cf812e..507b4c0 100755
--- a/scripts/redirect.py
+++ b/scripts/redirect.py
@@ -80,11 +80,10 @@
 from __future__ import annotations

 import datetime
-from collections.abc import Generator
 from contextlib import suppress
 from itertools import islice
 from textwrap import fill
-from typing import Any
+from typing import TYPE_CHECKING, Any

 import pywikibot
 import pywikibot.data
@@ -106,6 +105,10 @@
 from pywikibot.textlib import extract_templates_and_params_regex_simple

 
+if TYPE_CHECKING:
+    from collections.abc import Generator
+
+
 BROKEN_REDIRECT_TEMPLATE = 'Q11838699', 'Q4847311', 'Q21528265'
 docuReplacements = {'&params;': pagegenerators.parameterHelp}  # noqa: N816

diff --git a/scripts/revertbot.py b/scripts/revertbot.py
index d919f7a..e8abe4f 100755
--- a/scripts/revertbot.py
+++ b/scripts/revertbot.py
@@ -48,19 +48,23 @@
 from __future__ import annotations

 import abc
-from collections.abc import Mapping
 from textwrap import fill
-from typing import Any
+from typing import TYPE_CHECKING, Any

 import pywikibot
 from pywikibot import i18n
 from pywikibot.bot import OptionHandler
 from pywikibot.date import format_date, formatYear
 from pywikibot.exceptions import APIError, Error
-from pywikibot.page import Contribution
 from pywikibot.tools import deprecated


+if TYPE_CHECKING:
+    from collections.abc import Mapping
+
+    from pywikibot.page import Contribution
+
+
 class AbstractRevertBot(OptionHandler, abc.ABC):

     """Abstract RevertBot class.
diff --git a/scripts/solve_disambiguation.py b/scripts/solve_disambiguation.py
index f484a8b..685b4ba 100755
--- a/scripts/solve_disambiguation.py
+++ b/scripts/solve_disambiguation.py
@@ -80,10 +80,10 @@
 from __future__ import annotations

 import re
-from collections.abc import Generator
 from contextlib import suppress
 from itertools import chain, islice
 from pathlib import Path
+from typing import TYPE_CHECKING
 
 import pywikibot
 from pywikibot import config, i18n, pagegenerators
@@ -108,6 +108,10 @@
 from pywikibot.tools.formatter import SequenceOutputter


+if TYPE_CHECKING:
+    from collections.abc import Generator
+
+
 # Disambiguation Needed template
 dn_template = {
     'ar': '{{بحاجة لتوضيح}}',
diff --git a/scripts/templatecount.py b/scripts/templatecount.py
index 34973c1..26721ce 100755
--- a/scripts/templatecount.py
+++ b/scripts/templatecount.py
@@ -38,11 +38,15 @@
 """
 from __future__ import annotations

-from collections.abc import Generator
+from typing import TYPE_CHECKING

 import pywikibot


+if TYPE_CHECKING:
+    from collections.abc import Generator
+
+
 class TemplateCountRobot:

     """Template count bot."""
diff --git a/scripts/welcome.py b/scripts/welcome.py
index 52efe16..601ad93 100755
--- a/scripts/welcome.py
+++ b/scripts/welcome.py
@@ -182,12 +182,12 @@
 import pickle
 import re
 import time
-from collections.abc import Generator
 from contextlib import suppress
 from datetime import timedelta
 from enum import Enum
 from random import choice
 from textwrap import fill
+from typing import TYPE_CHECKING

 import pywikibot
 from pywikibot import config, i18n
@@ -201,6 +201,10 @@
 from pywikibot.tools import cached


+if TYPE_CHECKING:
+    from collections.abc import Generator
+
+
 locale.setlocale(locale.LC_ALL, '')

 # Script uses the method i18n.translate() to find the right
diff --git a/tests/hooks/copyright_fixer.py b/tests/hooks/copyright_fixer.py
index 02c4444..043fa6d 100755
--- a/tests/hooks/copyright_fixer.py
+++ b/tests/hooks/copyright_fixer.py
@@ -13,9 +13,13 @@
 import re
 import subprocess
 import sys
-from collections.abc import Sequence
 from datetime import date
 from pathlib import Path
+from typing import TYPE_CHECKING
+
+
+if TYPE_CHECKING:
+    from collections.abc import Sequence


 PATTERN = re.compile(
diff --git a/tests/script_tests.py b/tests/script_tests.py
index edd27e3..7e514e3 100755
--- a/tests/script_tests.py
+++ b/tests/script_tests.py
@@ -9,9 +9,9 @@

 import sys
 import unittest
-from collections.abc import Iterator
 from contextlib import suppress
 from pathlib import Path
+from typing import TYPE_CHECKING

 from pywikibot.bot import global_args as pwb_args
 from pywikibot.tools import has_module
@@ -20,6 +20,10 @@
 from tests.utils import execute_pwb


+if TYPE_CHECKING:
+    from collections.abc import Iterator
+
+
 scripts_path = join_root_path('scripts')

 # login script should be the first to test
diff --git a/tests/utils.py b/tests/utils.py
index 09bf200..0337c85 100644
--- a/tests/utils.py
+++ b/tests/utils.py
@@ -12,12 +12,11 @@
 import tempfile
 import unittest
 import warnings
-from collections.abc import Sequence
 from contextlib import contextmanager, suppress
 from pathlib import Path
 from platform import python_implementation
 from subprocess import PIPE, Popen, TimeoutExpired
-from typing import NoReturn, TypedDict
+from typing import TYPE_CHECKING, NoReturn, TypedDict

 import pywikibot
 from pywikibot import config
@@ -30,6 +29,10 @@
 from tests import _pwb_py


+if TYPE_CHECKING:
+    from collections.abc import Sequence
+
+
 OSWIN32 = (sys.platform == 'win32')



--
To view, visit 
https://gerrit.wikimedia.org/r/c/pywikibot/core/+/1361157?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: Ie8dd6f071f2b06c983765dc3c183782461d6d803
Gerrit-Change-Number: 1361157
Gerrit-PatchSet: 4
Gerrit-Owner: Xqt <[email protected]>
Gerrit-Reviewer: Mahveotm <[email protected]>
Gerrit-Reviewer: jenkins-bot
_______________________________________________
Pywikibot-commits mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to