jenkins-bot submitted this change.
cleanup typing now that python 3.5.3+ is required
Change-Id: If21e4267e8b661ac56728fe43a905c52b3c11f32
---
M mypy.ini
M pywikibot/__init__.py
M pywikibot/_wbtypes.py
M pywikibot/bot.py
M pywikibot/bot_choice.py
M pywikibot/exceptions.py
M pywikibot/flow.py
M pywikibot/interwiki_graph.py
M pywikibot/logentries.py
M pywikibot/logging.py
M pywikibot/login.py
M pywikibot/page/__init__.py
M pywikibot/proofreadpage.py
13 files changed, 158 insertions(+), 193 deletions(-)
diff --git a/mypy.ini b/mypy.ini
index 228fda5..34102e5 100644
--- a/mypy.ini
+++ b/mypy.ini
@@ -1,4 +1,5 @@
[mypy]
+python_version = 3.5
check_untyped_defs = true
disallow_any_generics = true
disallow_incomplete_defs = true
diff --git a/pywikibot/__init__.py b/pywikibot/__init__.py
index 53e4c7f..04799fd 100644
--- a/pywikibot/__init__.py
+++ b/pywikibot/__init__.py
@@ -1,6 +1,6 @@
"""The initialization file for the Pywikibot framework."""
#
-# (C) Pywikibot team, 2008-2021
+# (C) Pywikibot team, 2008-2022
#
# Distributed under the terms of the MIT license.
#
@@ -15,7 +15,7 @@
from contextlib import suppress
from decimal import Decimal
from queue import Queue
-from typing import Any, Optional, Union
+from typing import Any, Optional, Type, Union
from urllib.parse import urlparse
from warnings import warn
@@ -71,24 +71,9 @@
from pywikibot.tools import normalize_username
from pywikibot.tools.formatter import color_format
-TO_DECIMAL_TYPE = Union[int, float, str, 'Decimal', None]
-# TODO: replace these after T286867
-
-STR_OR_TIMESTAMP = Any # Union[str, 'Timestamp']
-OPT_STR_OR_SITE = Any # Union[str, 'pywikibot.site.BaseSite', None]
-OPT_STR_OR_ITEM_PAGE = Any # Union[str, 'pywikibot.page.ItemPage', None]
-OPT_STR_OR_FAMILY = Any # Union[str, 'pywikibot.family.Family', None]
-
-TIMESTAMP_CLASS = Any # Type['Timestamp']
-COORDINATE_CLASS = Any # Type['Coordinate']
-WB_TIME_CLASS = Any # Type['WbTime']
-WB_QUANTITY_CLASS = Any # Type['WbQuantity']
-WB_MONOLINGUAL_TEXT_CLASS = Any # Type['WbMonolingualText']
-WB_DATA_PAGE_CLASS = Any # Type['_WbDataPage']
-WB_GEO_SHAPE_CLASS = Any # Type['WbGeoShape']
-WB_TABULAR_DATA_CLASS = Any # Type['WbTabularData']
-WB_UNKNOWN_CLASS = Any # Type['WbUnknown']
+ItemPageStrNoneType = Union[str, 'ItemPage', None]
+ToDecimalType = Union[int, float, str, 'Decimal', None]
__all__ = (
'__copyright__', '__description__', '__download_url__', '__license__',
@@ -138,12 +123,12 @@
return self.replace(microsecond=self.microsecond)
@classproperty
- def ISO8601Format(cls: TIMESTAMP_CLASS) -> str:
+ def ISO8601Format(cls: Type['Timestamp']) -> str:
"""ISO8601 format string class property for compatibility purpose."""
return cls._ISO8601Format()
@classmethod
- def _ISO8601Format(cls: TIMESTAMP_CLASS, sep: str = 'T') -> str:
+ def _ISO8601Format(cls: Type['Timestamp'], sep: str = 'T') -> str:
"""ISO8601 format string.
:param sep: one-character separator, placed between the date and time
@@ -153,7 +138,7 @@
return '%Y-%m-%d{}%H:%M:%SZ'.format(sep)
@classmethod
- def fromISOformat(cls: TIMESTAMP_CLASS, ts: STR_OR_TIMESTAMP,
+ def fromISOformat(cls: Type['Timestamp'], ts: Union[str, 'Timestamp'],
sep: str = 'T') -> 'Timestamp':
"""Convert an ISO 8601 timestamp to a Timestamp object.
@@ -168,7 +153,7 @@
return cls.strptime(ts, cls._ISO8601Format(sep))
@classmethod
- def fromtimestampformat(cls: TIMESTAMP_CLASS, ts: STR_OR_TIMESTAMP
+ def fromtimestampformat(cls: Type['Timestamp'], ts: Union[str, 'Timestamp']
) -> 'Timestamp':
"""Convert a MediaWiki internal timestamp to a Timestamp object."""
# If inadvertently passed a Timestamp object, use replace()
@@ -228,7 +213,7 @@
globe: Optional[str] = None, typ: str = '',
name: str = '', dim: Optional[int] = None,
site: Optional[DataSite] = None,
- globe_item: OPT_STR_OR_ITEM_PAGE = None,
+ globe_item: ItemPageStrNoneType = None,
primary: bool = False) -> None:
"""
Represent a geo coordinate.
@@ -295,7 +280,7 @@
}
@classmethod
- def fromWikibase(cls: COORDINATE_CLASS, data: Dict[str, Any],
+ def fromWikibase(cls: Type['Coordinate'], data: Dict[str, Any],
site: Optional[DataSite] = None) -> 'Coordinate':
"""
Constructor to create an object from Wikibase's JSON output.
@@ -537,7 +522,7 @@
raise ValueError('Invalid precision: "{}"'.format(precision))
@classmethod
- def fromTimestr(cls: WB_TIME_CLASS,
+ def fromTimestr(cls: Type['WbTime'],
datetimestr: str,
precision: Union[int, str] = 14,
before: int = 0,
@@ -575,7 +560,7 @@
precision, before, after, timezone, calendarmodel, site)
@classmethod
- def fromTimestamp(cls: WB_TIME_CLASS, timestamp: 'Timestamp',
+ def fromTimestamp(cls: Type['WbTime'], timestamp: 'Timestamp',
precision: Union[int, str] = 14,
before: int = 0, after: int = 0,
timezone: int = 0, calendarmodel: Optional[str] = None,
@@ -643,7 +628,7 @@
return json
@classmethod
- def fromWikibase(cls: WB_TIME_CLASS, data: Dict[str, Any],
+ def fromWikibase(cls: Type['WbTime'], data: Dict[str, Any],
site: Optional[DataSite] = None) -> 'WbTime':
"""
Create a WbTime from the JSON data given by the Wikibase API.
@@ -679,7 +664,7 @@
return site.mw_version < '1.29.0-wmf.2'
@staticmethod
- def _todecimal(value: TO_DECIMAL_TYPE) -> Optional[Decimal]:
+ def _todecimal(value: ToDecimalType) -> Optional[Decimal]:
"""
Convert a string to a Decimal for use in WbQuantity.
@@ -704,10 +689,10 @@
"""
return format(value, '+g') if value is not None else None
- def __init__(self, amount: TO_DECIMAL_TYPE,
- unit: OPT_STR_OR_ITEM_PAGE = None,
- error: Union[TO_DECIMAL_TYPE,
- Tuple[TO_DECIMAL_TYPE, TO_DECIMAL_TYPE]] = None,
+ def __init__(self, amount: ToDecimalType,
+ unit: ItemPageStrNoneType = None,
+ error: Union[ToDecimalType,
+ Tuple[ToDecimalType, ToDecimalType]] = None,
site: Optional[DataSite] = None) -> None:
"""
Create a new WbQuantity object.
@@ -791,7 +776,7 @@
return json
@classmethod
- def fromWikibase(cls: WB_QUANTITY_CLASS, data: Dict[str, Any],
+ def fromWikibase(cls: Type['WbQuantity'], data: Dict[str, Any],
site: Optional[DataSite] = None) -> 'WbQuantity':
"""
Create a WbQuantity from the JSON data given by the Wikibase API.
@@ -842,7 +827,7 @@
return json
@classmethod
- def fromWikibase(cls: WB_MONOLINGUAL_TEXT_CLASS, data: Dict[str, Any],
+ def fromWikibase(cls: Type['WbMonolingualText'], data: Dict[str, Any],
site: Optional[DataSite] = None) -> 'WbMonolingualText':
"""
Create a WbMonolingualText from the JSON data given by Wikibase API.
@@ -865,7 +850,7 @@
_items = ('page', )
@classmethod
- def _get_data_site(cls: WB_DATA_PAGE_CLASS, repo_site: DataSite
+ def _get_data_site(cls: Type['_WbDataPage'], repo_site: DataSite
) -> APISite:
"""
Return the site serving as a repository for a given data type.
@@ -877,7 +862,7 @@
raise NotImplementedError
@classmethod
- def _get_type_specifics(cls: WB_DATA_PAGE_CLASS, site: DataSite
+ def _get_type_specifics(cls: Type['_WbDataPage'], site: DataSite
) -> Dict[str, Any]:
"""
Return the specifics for a given data type.
@@ -962,7 +947,7 @@
return self.page.title()
@classmethod
- def fromWikibase(cls: WB_DATA_PAGE_CLASS, page_name: str,
+ def fromWikibase(cls: Type['_WbDataPage'], page_name: str,
site: Optional[DataSite]) -> '_WbDataPage':
"""
Create a _WbDataPage from the JSON data given by the Wikibase API.
@@ -983,7 +968,7 @@
"""A Wikibase geo-shape representation."""
@classmethod
- def _get_data_site(cls: WB_GEO_SHAPE_CLASS, site: DataSite) -> APISite:
+ def _get_data_site(cls: Type['WbGeoShape'], site: DataSite) -> APISite:
"""
Return the site serving as a geo-shape repository.
@@ -992,7 +977,7 @@
return site.geo_shape_repository()
@classmethod
- def _get_type_specifics(cls: WB_GEO_SHAPE_CLASS, site: DataSite
+ def _get_type_specifics(cls: Type['WbGeoShape'], site: DataSite
) -> Dict[str, Any]:
"""
Return the specifics for WbGeoShape.
@@ -1011,7 +996,7 @@
"""A Wikibase tabular-data representation."""
@classmethod
- def _get_data_site(cls: WB_TABULAR_DATA_CLASS, site: DataSite) -> APISite:
+ def _get_data_site(cls: Type['WbTabularData'], site: DataSite) -> APISite:
"""
Return the site serving as a tabular-data repository.
@@ -1020,7 +1005,7 @@
return site.tabular_data_repository()
@classmethod
- def _get_type_specifics(cls: WB_TABULAR_DATA_CLASS, site: DataSite
+ def _get_type_specifics(cls: Type['WbTabularData'], site: DataSite
) -> Dict[str, Any]:
"""
Return the specifics for WbTabularData.
@@ -1066,7 +1051,7 @@
return self.json
@classmethod
- def fromWikibase(cls: WB_UNKNOWN_CLASS, data: Dict[str, Any],
+ def fromWikibase(cls: Type['WbUnknown'], data: Dict[str, Any],
site: Optional[DataSite] = None) -> 'WbUnknown':
"""
Create a WbUnknown from the JSON data given by the Wikibase API.
@@ -1112,9 +1097,9 @@
def Site(code: Optional[str] = None,
- fam: OPT_STR_OR_FAMILY = None,
+ fam: Union[str, 'Family', None] = None,
user: Optional[str] = None, *,
- interface: OPT_STR_OR_SITE = None,
+ interface: Union[str, 'BaseSite', None] = None,
url: Optional[str] = None) -> BaseSite:
"""A factory method to obtain a Site object.
diff --git a/pywikibot/_wbtypes.py b/pywikibot/_wbtypes.py
index 641484f..863fad8 100644
--- a/pywikibot/_wbtypes.py
+++ b/pywikibot/_wbtypes.py
@@ -1,18 +1,17 @@
"""Wikibase data type classes."""
#
-# (C) Pywikibot team, 2013-2020
+# (C) Pywikibot team, 2013-2022
#
# Distributed under the terms of the MIT license.
#
import abc
import json
-from typing import Any
+from typing import Any, Optional
from pywikibot.backports import Dict
-# TODO: replace these after T286867
-
-OPT_SITE = Any # Optional['pywikibot.site.DataSite']
+if False: # typing.TYPE_CHECKING
+ from pywikibot.site import DataSite
class WbRepresentation(abc.ABC):
@@ -20,27 +19,30 @@
"""Abstract class for Wikibase representations."""
@abc.abstractmethod
- def __init__(self):
+ def __init__(self) -> None:
"""Constructor."""
raise NotImplementedError
@abc.abstractmethod
- def toWikibase(self):
+ def toWikibase(self) -> Any:
"""Convert representation to JSON for the Wikibase API."""
raise NotImplementedError
@classmethod
@abc.abstractmethod
- def fromWikibase(cls, data: Dict[str, Any], site: OPT_SITE = None
- ) -> 'WbRepresentation':
+ def fromWikibase(
+ cls,
+ data: Dict[str, Any],
+ site: Optional['DataSite'] = None
+ ) -> 'WbRepresentation':
"""Create a representation object based on JSON from Wikibase API."""
raise NotImplementedError
- def __str__(self):
+ def __str__(self) -> str:
return json.dumps(self.toWikibase(), indent=4, sort_keys=True,
separators=(',', ': '))
- def __repr__(self):
+ def __repr__(self) -> str:
assert isinstance(self._items, tuple)
assert all(isinstance(item, str) for item in self._items)
@@ -49,13 +51,13 @@
for attr, value in values)
return '{}({})'.format(self.__class__.__name__, attrs)
- def __eq__(self, other):
+ def __eq__(self, other: object) -> bool:
if isinstance(other, self.__class__):
return self.toWikibase() == other.toWikibase()
return NotImplemented
- def __hash__(self):
+ def __hash__(self) -> int:
return hash(frozenset(self.toWikibase().items()))
- def __ne__(self, other):
+ def __ne__(self, other: object) -> bool:
return not self.__eq__(other)
diff --git a/pywikibot/bot.py b/pywikibot/bot.py
index a3026d6..7181014 100644
--- a/pywikibot/bot.py
+++ b/pywikibot/bot.py
@@ -57,7 +57,7 @@
``put_current`` is used.
"""
#
-# (C) Pywikibot team, 2008-2021
+# (C) Pywikibot team, 2008-2022
#
# Distributed under the terms of the MIT license.
#
@@ -181,18 +181,14 @@
from pywikibot.tools._logging import LoggingFormatter
from pywikibot.tools.formatter import color_format
-ANSWER = Union[
- Tuple[str, str],
- 'pywikibot.bot_choice.Option']
+if False: # typing.TYPE_CHECKING
+ from pywikibot.site import BaseSite
-ANSWER_TYPE = Union[Iterable[ANSWER], 'pywikibot.bot_choice.Option']
-
-# TODO: We should change this to the following after T286867...
-
-PAGE_OR_LINK_TYPE = Any # Union['pywikibot.page.Link', 'pywikibot.page.Page']
-OPT_SITE_TYPE = Any # Optional['pywikibot.site.BaseSite']
-OPT_CLAIM_TYPE = Any # Optional['pywikibot.page.Claim']
-OPT_ITEM_PAGE_TYPE = Any # Optional['pywikibot.page.ItemPage']
+AnswerType = Union[
+ Iterable[Union[Tuple[str, str], 'pywikibot.bot_choice.Option']],
+ 'pywikibot.bot_choice.Option',
+]
+PageLinkType = Union['pywikibot.page.Link', 'pywikibot.page.Page']
# Note: all output goes through python std library "logging" module
_logger = 'bot'
@@ -573,7 +569,7 @@
@initialize_handlers
def input_choice(question: str,
- answers: ANSWER_TYPE,
+ answers: AnswerType,
default: Optional[str] = None,
return_shortcut: bool = True,
automatic_quit: bool = True,
@@ -634,7 +630,7 @@
@initialize_handlers
def input_list_choice(question: str,
- answers: ANSWER_TYPE,
+ answers: AnswerType,
default: Union[int, str, None] = None,
force: bool = False) -> str:
"""
@@ -678,8 +674,8 @@
"""
def __init__(self,
- old_link: PAGE_OR_LINK_TYPE,
- new_link: Union[PAGE_OR_LINK_TYPE, bool],
+ old_link: PageLinkType,
+ new_link: Union[PageLinkType, bool],
default: Optional[str] = None,
automatic_quit: bool = True) -> None:
"""
@@ -707,7 +703,7 @@
self._quit = automatic_quit
current_match_type = Optional[Tuple[
- PAGE_OR_LINK_TYPE,
+ PageLinkType,
str,
Mapping[str, str],
Tuple[int, int]
@@ -749,7 +745,7 @@
raise ValueError('Invalid choice "{}"'.format(choice))
- def __call__(self, link: PAGE_OR_LINK_TYPE,
+ def __call__(self, link: PageLinkType,
text: str, groups: Mapping[str, str],
rng: Tuple[int, int]) -> Any:
"""Ask user how the selected link should be replaced."""
@@ -815,7 +811,7 @@
return self.handle_answer(choice)
@property
- def current_link(self) -> PAGE_OR_LINK_TYPE:
+ def current_link(self) -> PageLinkType:
"""Get the current link when it's handling one currently."""
if self._current_match is None:
raise ValueError('No current link')
@@ -1011,7 +1007,7 @@
module = import_module(module_name) # type: ignore
help_text = module.__doc__ # type: str # type: ignore[assignment]
if hasattr(module, 'docuReplacements'):
- for key, value in module.docuReplacements.items(): # type: ignore
+ for key, value in module.docuReplacements.items():
help_text = help_text.replace(key, value.strip('\n\r'))
except Exception:
if module_name:
@@ -1113,7 +1109,7 @@
i18n.input('pywikibot-enter-finished-browser')
-class _OptionDict(dict):
+class _OptionDict(Dict[str, Any]):
"""The option dict which holds the options of OptionHandler.
@@ -1621,7 +1617,7 @@
instead which specifically handle multiple or single sites.
"""
- def __init__(self, site: OPT_SITE_TYPE = None,
+ def __init__(self, site: Optional['BaseSite'] = None,
**kwargs: Any) -> None:
"""Create a Bot instance and initialize cached sites."""
# TODO: add warning if site is specified and generator
@@ -1632,7 +1628,7 @@
super().__init__(**kwargs)
@property
- def site(self) -> 'pywikibot.site.BaseSite':
+ def site(self) -> Optional['BaseSite']:
"""Get the current site."""
if not self._site:
warning('Bot.site was not set before being retrieved.')
@@ -1642,7 +1638,7 @@
return self._site
@site.setter
- def site(self, site: OPT_SITE_TYPE) -> None:
+ def site(self, site: Optional['BaseSite']) -> None:
"""
Set the Site that the bot is using.
@@ -1704,7 +1700,7 @@
"""
def __init__(self,
- site: Union[OPT_SITE_TYPE, bool] = True,
+ site: Union['BaseSite', bool, None] = True,
**kwargs: Any) -> None:
"""
Create a SingleSiteBot instance.
@@ -1713,7 +1709,7 @@
pywikibot.Site.
"""
if site is True:
- self._site = pywikibot.Site()
+ self._site = pywikibot.Site() # type: Optional[BaseSite]
elif site is False:
raise ValueError("'site' must be a site, True, or None")
else:
@@ -1721,14 +1717,14 @@
super().__init__(**kwargs)
@property
- def site(self) -> OPT_SITE_TYPE:
+ def site(self) -> 'BaseSite':
"""Site that the bot is using."""
if not self._site:
raise ValueError('The site has not been defined yet.')
return self._site
@site.setter
- def site(self, value: OPT_SITE_TYPE) -> None:
+ def site(self, value: Optional['BaseSite']) -> None:
"""Set the current site but warns if different."""
if self._site:
# Warn in any case where the site is (probably) changed after
@@ -2108,7 +2104,7 @@
def user_add_claim(self, item: 'pywikibot.page.ItemPage',
claim: 'pywikibot.page.Claim',
- source: OPT_SITE_TYPE = None,
+ source: Optional['BaseSite'] = None,
bot: bool = True, **kwargs: Any) -> bool:
"""
Add a claim to an item, with user confirmation as required.
@@ -2134,8 +2130,7 @@
claim.getTarget()))
return self._save_page(item, item.addClaim, claim, bot=bot, **kwargs)
- def getSource(self, site: 'pywikibot.site.BaseSite'
- ) -> OPT_CLAIM_TYPE:
+ def getSource(self, site: 'BaseSite') -> Optional['pywikibot.page.Claim']:
"""
Create a Claim usable as a source for Wikibase statements.
@@ -2154,7 +2149,7 @@
self, item: 'pywikibot.page.ItemPage',
claim: 'pywikibot.page.Claim',
exists_arg: str = '',
- source: OPT_SITE_TYPE = None,
+ source: Optional['BaseSite'] = None,
logger_callback: Callable[[str], Any] = log,
**kwargs: Any) -> bool:
"""
@@ -2227,7 +2222,7 @@
data: Optional[Dict[str, Any]] = None,
summary: Optional[str] = None,
**kwargs: Any
- ) -> OPT_ITEM_PAGE_TYPE:
+ ) -> Optional['pywikibot.page.ItemPage']:
"""
Create an ItemPage with the provided page as the sitelink.
diff --git a/pywikibot/bot_choice.py b/pywikibot/bot_choice.py
index 822fe9d..9fb1660 100755
--- a/pywikibot/bot_choice.py
+++ b/pywikibot/bot_choice.py
@@ -1,6 +1,6 @@
"""Options and Choices for :py:meth:`pywikibot.input_choice`."""
#
-# (C) Pywikibot team, 2015-2021
+# (C) Pywikibot team, 2015-2022
#
# Distributed under the terms of the MIT license.
#
@@ -16,10 +16,6 @@
from pywikibot.tools import deprecated, issue_deprecation_warning
-# TODO: replace these after T286867
-
-OPT_REPLACE_TYPE = Any # Optional['pywikibot.bot.InteractiveReplace']
-
class Option(ABC):
@@ -281,14 +277,18 @@
"""A simple choice consisting of an option, shortcut and handler."""
- def __init__(self, option: str, shortcut: str,
- replacer: OPT_REPLACE_TYPE) -> None:
+ def __init__(
+ self,
+ option: str,
+ shortcut: str,
+ replacer: Optional['pywikibot.bot.InteractiveReplace']
+ ) -> None:
"""Initializer."""
super().__init__(option, shortcut)
self._replacer = replacer
@property
- def replacer(self) -> OPT_REPLACE_TYPE:
+ def replacer(self) -> Optional['pywikibot.bot.InteractiveReplace']:
"""The replacer."""
return self._replacer
@@ -320,8 +320,14 @@
"""A choice returning a mix of the link new and current link."""
- def __init__(self, option: str, shortcut: str, replacer: OPT_REPLACE_TYPE,
- replace_section: bool, replace_label: bool) -> None:
+ def __init__(
+ self,
+ option: str,
+ shortcut: str,
+ replacer: Optional['pywikibot.bot.InteractiveReplace'],
+ replace_section: bool,
+ replace_label: bool
+ ) -> None:
"""Initializer."""
super().__init__(option, shortcut, replacer)
self._section = replace_section
@@ -361,7 +367,7 @@
"""Add an option to always apply the default."""
- def __init__(self, replacer: OPT_REPLACE_TYPE,
+ def __init__(self, replacer: Optional['pywikibot.bot.InteractiveReplace'],
option: str = 'always', shortcut: str = 'a') -> None:
"""Initializer."""
super().__init__(option, shortcut, replacer)
diff --git a/pywikibot/exceptions.py b/pywikibot/exceptions.py
index ce08846..211c6c1 100644
--- a/pywikibot/exceptions.py
+++ b/pywikibot/exceptions.py
@@ -281,7 +281,7 @@
# Override this in subclasses.
message = ''
- def __init__(self, page: 'pywikibot.page.Page',
+ def __init__(self, page: 'pywikibot.page.BasePage',
message: Optional[str] = None) -> None:
"""
Initializer.
diff --git a/pywikibot/flow.py b/pywikibot/flow.py
index 855a45e..88f7082 100644
--- a/pywikibot/flow.py
+++ b/pywikibot/flow.py
@@ -1,13 +1,13 @@
"""Objects representing Flow entities, like boards, topics, and posts."""
#
-# (C) Pywikibot team, 2015-2021
+# (C) Pywikibot team, 2015-2022
#
# Distributed under the terms of the MIT license.
#
import abc
import datetime
import logging
-from typing import Any, Union
+from typing import Any, Type, Union
from urllib.parse import parse_qs, urlparse
import pywikibot
@@ -17,20 +17,11 @@
NoPageError,
UnknownExtensionError,
)
-from pywikibot.page import BasePage, User
+from pywikibot.page import BasePage, PageSourceType, User
logger = logging.getLogger('pywiki.wiki.flow')
-# TODO: replace these after T286867
-
-TOPIC_CLASS_TYPE = Any # Type['Topic']
-
-# Union['pywikibot.site.BaseSite', 'pywikibot.page.Link',
-# 'pywikibot.page.Page']
-
-SOURCE_TYPE = Any
-
# Flow page-like objects (boards and topics)
class FlowPage(BasePage, abc.ABC):
@@ -40,7 +31,7 @@
It cannot be instantiated directly.
"""
- def __init__(self, source: SOURCE_TYPE, title: str = '') -> None:
+ def __init__(self, source: PageSourceType, title: str = '') -> None:
"""Initializer.
:param source: A Flow-enabled site or a Link or Page on such a site
@@ -178,7 +169,7 @@
self.root._load(load_from_topic=True)
@classmethod
- def create_topic(cls: TOPIC_CLASS_TYPE, board: 'Board', title: str,
+ def create_topic(cls: Type['Topic'], board: 'Board', title: str,
content: str, content_format: str = 'wikitext'
) -> 'Topic':
"""Create and return a Topic object for a new topic on a Board.
@@ -195,7 +186,7 @@
return cls(board.site, data['topic-page'])
@classmethod
- def from_topiclist_data(cls: TOPIC_CLASS_TYPE, board: 'Board',
+ def from_topiclist_data(cls: Type['Topic'], board: 'Board',
root_uuid: str,
topiclist_data: Dict[str, Any]) -> 'Topic':
"""Create a Topic object from API data.
@@ -422,7 +413,7 @@
return self._current_revision['isModerated']
@property
- def creator(self) -> str:
+ def creator(self) -> User:
"""The creator of this post."""
if not hasattr(self, '_current_revision'):
self._load()
diff --git a/pywikibot/interwiki_graph.py b/pywikibot/interwiki_graph.py
index 8d8e50d..e9ca5c6 100644
--- a/pywikibot/interwiki_graph.py
+++ b/pywikibot/interwiki_graph.py
@@ -1,24 +1,18 @@
"""Module with the Graphviz drawing calls."""
#
-# (C) Pywikibot team, 2006-2021
+# (C) Pywikibot team, 2006-2022
#
# Distributed under the terms of the MIT license.
#
import itertools
import threading
from collections import Counter
-from typing import Any, Optional
+from typing import Optional
import pywikibot
from pywikibot import config
from pywikibot.backports import Dict, List, Set
-FOUND_IN_TYPE = Dict['pywikibot.page.Page', List['pywikibot.page.Page']]
-
-# TODO: replace these after T286867
-
-OPT_PAGE_TYPE = Any # Optional['pywikibot.page.Page']
-
try:
import pydot
PYDOT_ERROR = None
@@ -26,6 +20,9 @@
PYDOT_ERROR = e
+FoundInType = Dict['pywikibot.page.Page', List['pywikibot.page.Page']]
+
+
class GraphSavingThread(threading.Thread):
"""
@@ -61,7 +58,7 @@
"""Data about a page with translations on multiple wikis."""
- def __init__(self, origin: OPT_PAGE_TYPE = None) -> None:
+ def __init__(self, origin: Optional['pywikibot.page.Page'] = None) -> None:
"""Initializer.
:param origin: the page on the 'origin' wiki
@@ -73,17 +70,17 @@
# pages are values. It stores where we found each page.
# As we haven't yet found a page that links to the origin page, we
# start with an empty list for it.
- self.found_in = {} # type: FOUND_IN_TYPE
+ self.found_in = {} # type: FoundInType
if origin:
self.found_in = {origin: []}
@property
- def origin(self) -> OPT_PAGE_TYPE:
+ def origin(self) -> Optional['pywikibot.page.Page']:
"""Page on the origin wiki."""
return self._origin
@origin.setter
- def origin(self, value: OPT_PAGE_TYPE) -> None:
+ def origin(self, value: Optional['pywikibot.page.Page']) -> None:
self._origin = value
diff --git a/pywikibot/logentries.py b/pywikibot/logentries.py
index f2c356d..3df2838 100644
--- a/pywikibot/logentries.py
+++ b/pywikibot/logentries.py
@@ -1,13 +1,13 @@
"""Objects representing Mediawiki log entries."""
#
-# (C) Pywikibot team, 2007-2021
+# (C) Pywikibot team, 2007-2022
#
# Distributed under the terms of the MIT license.
#
from collections import UserDict
from contextlib import suppress
import datetime
-from typing import Any, Optional
+from typing import Any, Optional, Type, Union
import pywikibot
from pywikibot.backports import Dict, List, Tuple
@@ -16,14 +16,6 @@
_logger = 'wiki'
-# TODO: replace these after T286867
-
-PAGE_OR_INT_TYPE = Any # Union[int, 'pywikibot.page.Page']
-OPT_TIMESTAMP_TYPE = Any # Optional['pywikibot.Timestamp']
-
-LOG_ENTRY_CLASS = Any # Type['LogEntry']
-LOG_ENTRY_FACTORY_CLASS = Any # Type['LogEntryFactory']
-
class LogEntry(UserDict):
@@ -107,7 +99,7 @@
return self[self._expected_type]
- def page(self) -> PAGE_OR_INT_TYPE:
+ def page(self) -> Union[int, 'pywikibot.page.Page']:
"""
Page on which action was performed.
@@ -169,7 +161,7 @@
if self.isAutoblockRemoval:
self._blockid = int(self['title'][pos + 1:])
- def page(self) -> PAGE_OR_INT_TYPE:
+ def page(self) -> Union[int, 'pywikibot.page.Page']:
"""
Return the blocked account or IP.
@@ -217,7 +209,7 @@
self._duration = self.expiry() - self.timestamp()
return self._duration
- def expiry(self) -> OPT_TIMESTAMP_TYPE:
+ def expiry(self) -> Optional['pywikibot.Timestamp']:
"""Return a Timestamp representing the block expiry date."""
if not hasattr(self, '_expiry'):
details = self._params.get('expiry')
@@ -374,7 +366,7 @@
"""
return self._creator(logdata)
- def get_valid_entry_class(self, logtype: str) -> LOG_ENTRY_CLASS:
+ def get_valid_entry_class(self, logtype: str) -> 'LogEntry':
"""
Return the class corresponding to the @logtype string parameter.
@@ -387,8 +379,8 @@
return LogEntryFactory.get_entry_class(logtype)
@classmethod
- def get_entry_class(cls: LOG_ENTRY_FACTORY_CLASS,
- logtype: str) -> LOG_ENTRY_CLASS:
+ def get_entry_class(cls: Type['LogEntryFactory'],
+ logtype: str) -> 'LogEntry':
"""
Return the class corresponding to the @logtype string parameter.
@@ -398,7 +390,7 @@
or use the get_valid_entry_class instance method instead.
"""
if logtype not in cls._logtypes:
- bases = (OtherLogEntry, ) # type: Tuple[LOG_ENTRY_CLASS, ...]
+ bases = (OtherLogEntry, ) # type: Tuple['LogEntry', ...]
if logtype in ('newusers', 'thanks'):
bases = (UserTargetLogEntry, OtherLogEntry)
diff --git a/pywikibot/logging.py b/pywikibot/logging.py
index 31a8726..7c2edab 100644
--- a/pywikibot/logging.py
+++ b/pywikibot/logging.py
@@ -11,7 +11,7 @@
# logging levels
from logging import CRITICAL, DEBUG, ERROR, INFO, WARNING
-from typing import AnyStr, Optional
+from typing import Optional
from pywikibot.backports import Callable, List
@@ -62,7 +62,7 @@
# string indicating the debugging layer.
-def logoutput(text: Any, decoder: Optional[str] = None,
+def logoutput(text: object, decoder: Optional[str] = None,
newline: bool = True, _level: int = INFO, _logger: str = '',
**kwargs: Any) -> None:
"""Format output and send to the logging module.
@@ -108,7 +108,7 @@
logger.log(_level, decoded_text, extra=context, **kwargs)
-def output(text: AnyStr, decoder: Optional[str] = None, newline: bool = True,
+def output(text: object, decoder: Optional[str] = None, newline: bool = True,
**kwargs: Any) -> None:
r"""Output a message to the user via the userinterface.
@@ -133,7 +133,7 @@
logoutput(text, decoder, newline, INFO, **kwargs)
-def stdout(text: AnyStr, decoder: Optional[str] = None, newline: bool = True,
+def stdout(text: object, decoder: Optional[str] = None, newline: bool = True,
**kwargs: Any) -> None:
"""Output script results to the user via the userinterface.
@@ -151,7 +151,7 @@
logoutput(text, decoder, newline, STDOUT, **kwargs)
-def warning(text: AnyStr, decoder: Optional[str] = None,
+def warning(text: object, decoder: Optional[str] = None,
newline: bool = True, **kwargs: Any) -> None:
"""Output a warning message to the user via the userinterface.
@@ -165,7 +165,7 @@
logoutput(text, decoder, newline, WARNING, **kwargs)
-def error(text: AnyStr, decoder: Optional[str] = None, newline: bool = True,
+def error(text: object, decoder: Optional[str] = None, newline: bool = True,
**kwargs: Any) -> None:
"""Output an error message to the user via the userinterface.
@@ -179,7 +179,7 @@
logoutput(text, decoder, newline, ERROR, **kwargs)
-def log(text: AnyStr, decoder: Optional[str] = None, newline: bool = True,
+def log(text: object, decoder: Optional[str] = None, newline: bool = True,
**kwargs: Any) -> None:
"""Output a record to the log file.
@@ -193,7 +193,7 @@
logoutput(text, decoder, newline, VERBOSE, **kwargs)
-def critical(text: AnyStr, decoder: Optional[str] = None, newline: bool = True,
+def critical(text: object, decoder: Optional[str] = None, newline: bool = True,
**kwargs: Any) -> None:
"""Output a critical record to the user via the userinterface.
@@ -207,7 +207,7 @@
logoutput(text, decoder, newline, CRITICAL, **kwargs)
-def debug(text: AnyStr, layer: str, decoder: Optional[str] = None,
+def debug(text: object, layer: str, decoder: Optional[str] = None,
newline: bool = True, **kwargs: Any) -> None:
"""Output a debug record to the log file.
diff --git a/pywikibot/login.py b/pywikibot/login.py
index 5be39a1..c52568f 100644
--- a/pywikibot/login.py
+++ b/pywikibot/login.py
@@ -28,10 +28,6 @@
except ImportError as e:
mwoauth = e
-# TODO: replace these after T286867
-
-OPT_SITE_TYPE = Any # Optional['pywikibot.site.BaseSite']
-
class _PasswordFileWarning(UserWarning):
@@ -86,7 +82,7 @@
"""Site login manager."""
def __init__(self, password: Optional[str] = None,
- site: OPT_SITE_TYPE = None,
+ site: Optional['pywikibot.site.BaseSite'] = None,
user: Optional[str] = None) -> None:
"""
Initializer.
@@ -364,7 +360,7 @@
# authentication process
def __init__(self, password: Optional[str] = None,
- site: OPT_SITE_TYPE = None,
+ site: Optional['pywikibot.site.BaseSite'] = None,
user: Optional[str] = None) -> None:
"""
Initializer.
diff --git a/pywikibot/page/__init__.py b/pywikibot/page/__init__.py
index eeb2d6f..69df5ea 100644
--- a/pywikibot/page/__init__.py
+++ b/pywikibot/page/__init__.py
@@ -11,7 +11,7 @@
"""
#
-# (C) Pywikibot team, 2008-2021
+# (C) Pywikibot team, 2008-2022
#
# Distributed under the terms of the MIT license.
#
@@ -101,6 +101,12 @@
'url2unicode',
)
+PageSourceType = Union[
+ 'pywikibot.site.BaseLink',
+ 'pywikibot.page.BaseSite',
+ 'pywikibot.page.Page',
+]
+
logger = logging.getLogger('pywiki.wiki.page')
diff --git a/pywikibot/proofreadpage.py b/pywikibot/proofreadpage.py
index 7c1eed4..7096f32 100644
--- a/pywikibot/proofreadpage.py
+++ b/pywikibot/proofreadpage.py
@@ -33,7 +33,7 @@
from http import HTTPStatus
from typing import Any, Optional, Union
-from requests.exceptions import ReadTimeout # type: ignore[import]
+from requests.exceptions import ReadTimeout
import pywikibot
from pywikibot import textlib
@@ -49,16 +49,7 @@
from pywikibot.comms import http
from pywikibot.data.api import Request
from pywikibot.exceptions import Error, OtherPageSaveError
-
-PAGES_FROM_LABEL_TYPE = Dict[str, Set['pywikibot.page.Page']]
-
-# TODO: replace these after T286867
-
-OPT_INDEX_PAGE_TYPE = Any # Optional['IndexPage']
-OPT_INDEX_PAGE_LIST_TYPE = Any # Optional[List['IndexPage']]
-
-INDEX_TYPE = Optional[Tuple[OPT_INDEX_PAGE_TYPE,
- OPT_INDEX_PAGE_LIST_TYPE]]
+from pywikibot.page import PageSourceType
try:
from bs4 import BeautifulSoup
@@ -81,6 +72,10 @@
_logger = 'proofreadpage'
+PagesFromLabelType = Dict[str, Set['pywikibot.page.Page']]
+_IndexType = Tuple[Optional['IndexPage'], List['IndexPage']]
+
+
def decompose(fn: Callable) -> Callable: # type: ignore # noqa: N805
"""Decorator for ProofreadPage.
@@ -198,7 +193,7 @@
}
_OCR_METHODS = list(_OCR_CMDS.keys())
- def __init__(self, source, title: str = '') -> None:
+ def __init__(self, source: PageSourceType, title: str = '') -> None:
"""Instantiate a ProofreadPage object.
:raise UnknownExtensionError: source Site has no ProofreadPage
@@ -263,7 +258,7 @@
return base, ext, num
@property
- def index(self) -> OPT_INDEX_PAGE_TYPE:
+ def index(self) -> Optional['IndexPage']:
"""Get the Index page which contains ProofreadPage.
If there are many Index pages link to this ProofreadPage, and
@@ -281,7 +276,7 @@
set(self.getReferences(namespaces=index_ns))]
if not what_links_here:
- self._index = (None, [])
+ self._index = (None, []) # type: _IndexType
elif len(what_links_here) == 1:
self._index = (what_links_here.pop(), [])
else:
@@ -294,28 +289,28 @@
self._index = (page, what_links_here)
break
- page, others = self._index
+ index_page, others = self._index
if others:
pywikibot.warning('{} linked to several Index pages.'.format(self))
- pywikibot.output('{}{!s}'.format(' ' * 9, [page] + others))
+ pywikibot.output('{}{!s}'.format(' ' * 9, [index_page] + others))
- if page:
+ if index_page:
pywikibot.output(
- '{}Selected Index: {}'.format(' ' * 9, page))
+ '{}Selected Index: {}'.format(' ' * 9, index_page))
pywikibot.output('{}remaining: {!s}'.format(' ' * 9, others))
- if not page:
+ if not index_page:
pywikibot.warning('Page {} is not linked to any Index page.'
.format(self))
- return page
+ return index_page
@index.setter
def index(self, value: 'IndexPage') -> None:
if not isinstance(value, IndexPage):
raise TypeError('value {} must be an IndexPage object.'
.format(value))
- self._index = (value, None)
+ self._index = (value, [])
@index.deleter
def index(self) -> None:
@@ -453,7 +448,7 @@
"""
# Text is already cached.
if getattr(self, '_text', None) is not None:
- return self._text
+ return self._text # type: ignore[return-value]
if self.exists():
# If page exists, load it.
@@ -547,13 +542,12 @@
def save(self, *args: Any, **kwargs: Any) -> None: # See Page.save().
"""Save page content after recomposing the page."""
- summary = kwargs.pop('summary', '')
- summary = self.pre_summary + summary
+ kwargs['summary'] = self.pre_summary + kwargs.get('summary', '')
# Save using contentformat='application/json'.
kwargs['contentformat'] = 'application/json'
kwargs['contentmodel'] = 'proofread-page'
text = self._page_to_json()
- super().save(*args, text=text, summary=summary, **kwargs)
+ super().save(*args, text=text, **kwargs)
@property
def pre_summary(self) -> str:
@@ -649,7 +643,7 @@
pywikibot.warning('retrying in {} seconds ...'.format(retry))
time.sleep(retry)
else:
- return True, ReadTimeout
+ return True, ReadTimeout('ReadTimeout: Could not perform OCR')
if HTTPStatus.BAD_REQUEST <= response.status_code < 600:
return True, 'Http response status {}'.format(response.status_code)
@@ -797,7 +791,7 @@
INDEX_TEMPLATE = ':MediaWiki:Proofreadpage_index_template'
- def __init__(self, source, title: str = '') -> None:
+ def __init__(self, source: PageSourceType, title: str = '') -> None:
"""Instantiate an IndexPage object.
In this class:
@@ -900,7 +894,7 @@
self._page_from_numbers = {}
self._numbers_from_page = {} # type: Dict[pywikibot.page.Page, int]
self._page_numbers_from_label = {} # type: Dict[str, Set[int]]
- self._pages_from_label = {} # type: PAGES_FROM_LABEL_TYPE
+ self._pages_from_label = {} # type: PagesFromLabelType
self._labels_from_page_number = {} # type: Dict[int, str]
self._labels_from_page = {} # type: Dict[pywikibot.page.Page, str]
if hasattr(self, '_parsed_text'):
To view, visit change 752359. To unsubscribe, or for help writing mail filters, visit settings.