jenkins-bot has submitted this change. ( https://gerrit.wikimedia.org/r/c/pywikibot/core/+/835299 )
Change subject: automatically convert type comments to annotations ......................................................................
automatically convert type comments to annotations
Change-Id: Icf47dbe653f015c4819251501e1c0a11439181c6 --- M pywikibot/__init__.py M pywikibot/bot.py M pywikibot/bot_choice.py M pywikibot/config.py M pywikibot/cosmetic_changes.py M pywikibot/data/api/_requests.py M pywikibot/date.py M pywikibot/diff.py M pywikibot/echo.py M pywikibot/family.py M pywikibot/flow.py M pywikibot/i18n.py M pywikibot/interwiki_graph.py M pywikibot/logentries.py M pywikibot/logging.py M pywikibot/login.py M pywikibot/page/_wikibase.py M pywikibot/pagegenerators/__init__.py M pywikibot/pagegenerators/_factory.py M pywikibot/pagegenerators/_generators.py M pywikibot/plural.py M pywikibot/proofreadpage.py M pywikibot/scripts/generate_user_files.py M pywikibot/site/_apisite.py M scripts/add_text.py M scripts/blockpageschecker.py M scripts/category.py M scripts/redirect.py M scripts/replace.py M scripts/weblinkchecker.py M scripts/welcome.py M tests/__init__.py 32 files changed, 150 insertions(+), 146 deletions(-)
Approvals: JJMC89: Looks good to me, approved jenkins-bot: Verified
diff --git a/pywikibot/__init__.py b/pywikibot/__init__.py index ca3c648..3b5a311 100644 --- a/pywikibot/__init__.py +++ b/pywikibot/__init__.py @@ -92,7 +92,7 @@ # argvu is set by pywikibot.bot when it's imported
if not hasattr(sys.modules[__name__], 'argvu'): - argvu = [] # type: List[str] + argvu: List[str] = []
class Coordinate(_WbRepresentation): @@ -609,7 +609,8 @@ self.upperBound = self.lowerBound = None else: if error is None: - upperError = lowerError = Decimal(0) # type: Optional[Decimal] + upperError: Optional[Decimal] = Decimal(0) + lowerError: Optional[Decimal] = Decimal(0) elif isinstance(error, tuple): upperError = self._todecimal(error[0]) lowerError = self._todecimal(error[1]) @@ -952,7 +953,7 @@ return cls(data)
-_sites = {} # type: Dict[str, APISite] +_sites: Dict[str, APISite] = {}
@cache @@ -1260,9 +1261,9 @@
# queue to hold pending requests -page_put_queue = Queue(_config.max_queue_size) # type: Queue +page_put_queue: Queue = Queue(_config.max_queue_size) # queue to signal that async_manager is working on a request. See T147178. -page_put_queue_busy = Queue(_config.max_queue_size) # type: Queue +page_put_queue_busy: Queue = Queue(_config.max_queue_size) # set up the background thread _putthread = threading.Thread(target=async_manager, name='Put-Thread', # for debugging purposes diff --git a/pywikibot/bot.py b/pywikibot/bot.py index be0d959..dbc4b2d83 100644 --- a/pywikibot/bot.py +++ b/pywikibot/bot.py @@ -269,7 +269,7 @@
"""
-ui = None # type: Optional[pywikibot.userinterfaces._interface_base.ABUIC] +ui: Optional[pywikibot.userinterfaces._interface_base.ABUIC] = None """Holds a user interface object defined in :mod:`pywikibot.userinterfaces` subpackage. """ @@ -706,7 +706,7 @@ Tuple[int, int] ]]
- self._current_match = None # type: current_match_type + self._current_match: current_match_type = None self.context = 30 self.context_delta = 0 self.allow_skip_link = True @@ -716,10 +716,10 @@ self.allow_replace_label = False self.allow_replace_all = False # Use list to preserve order - self._own_choices = [ + self._own_choices: List[Tuple[str, StandardOption]] = [ ('skip_link', StaticChoice('Do not change', 'n', None)), ('unlink', StaticChoice('Unlink', 'u', False)), - ] # type: List[Tuple[str, StandardOption]] + ] if self._new: self._own_choices += [ ('replace', LinkChoice('Change link target', 't', self, @@ -732,7 +732,7 @@ True, True)), ]
- self.additional_choices = [] # type: List[StandardOption] + self.additional_choices: List[StandardOption] = []
def handle_answer(self, choice: str) -> Any: """Return the result for replace_links.""" @@ -899,7 +899,7 @@ module_name = calledModuleName() or 'terminal-interface' non_global_args = [] username = None - do_help_val = None if do_help else False # type: Union[bool, str, None] + do_help_val: Union[bool, str, None] = None if do_help else False assert args is not None for arg in args: option, _, value = arg.partition(':') @@ -1025,7 +1025,7 @@
try: module = import_module(module_name) - help_text = module.__doc__ # type: str # type: ignore[assignment] + help_text: str = module.__doc__ # type: ignore[assignment] if hasattr(module, 'docuReplacements'): for key, value in module.docuReplacements.items(): help_text = help_text.replace(key, value.strip('\n\r')) @@ -1195,7 +1195,7 @@ keyword is a :python:`dict method<library/stdtypes.html#dict.clear>`. """
- available_options = {} # type: Dict[str, Any] + available_options: Dict[str, Any] = {} """ Handler configuration attribute. Only the keys of the dict can be passed as `__init__` options. The values are the default values. Overwrite this in subclasses! @@ -1254,7 +1254,7 @@ A :attr:`counter` instance variable is provided. """
- use_disambigs = None # type: Optional[bool] + use_disambigs: Optional[bool] = None """Attribute to determine whether to use disambiguation pages. Set it to True to use disambigs only, set it to False to skip disambigs. If None both are processed. @@ -1262,7 +1262,7 @@ .. versionadded:: 7.2 """
- use_redirects = None # type: Optional[bool] + use_redirects: Optional[bool] = None """Attribute to determine whether to use redirect pages. Set it to True to use redirects only, set it to False to skip redirects. If None both are processed. For example to create a RedirectBot you may @@ -1283,7 +1283,7 @@ 'always': False, # By default ask for confirmation when putting a page }
- update_options = {} # type: Dict[str, Any] + update_options: Dict[str, Any] = {} """`update_options` can be used to update :attr:`available_options`; do not use it if the bot class is to be derived but use `self.available_options.update(<dict>)` initializer in such case. @@ -1291,7 +1291,7 @@ .. versionadded:: 6.4 """
- _current_page = None # type: Optional[pywikibot.page.BasePage] + _current_page: Optional['pywikibot.page.BasePage'] = None
def __init__(self, **kwargs: Any) -> None: """Initializer. @@ -1306,12 +1306,12 @@ else: #: instance variable to hold the generator processed by #: :meth:`run` method - self.generator = kwargs.pop('generator') # type: Iterable + self.generator: Iterable = kwargs.pop('generator')
self.available_options.update(self.update_options) super().__init__(**kwargs)
- self.counter = Counter() # type: Counter + self.counter: Counter = Counter() """Instance variable which holds counters. The default counters are 'read', 'write' and 'skip'. You can use your own counters like::
@@ -1322,7 +1322,7 @@ Your additional counters are also printed during :meth:`exit` """
- self.generator_completed = False # type: bool + self.generator_completed: bool = False """Instance attribute which is True if the generator is completed.
To check for an empty generator you may use:: @@ -1337,7 +1337,7 @@ """
#: instance variable to hold the default page type - self.treat_page_type = pywikibot.page.BasePage # type: Any + self.treat_page_type: Any = pywikibot.page.BasePage
@property @deprecated("self.counter['read']", since='7.0.0') @@ -1801,7 +1801,7 @@ pywikibot.Site. """ if site is True: - self._site = pywikibot.Site() # type: Optional[BaseSite] + self._site: Optional[BaseSite] = pywikibot.Site() elif site is False: raise ValueError("'site' must be a site, True, or None") else: @@ -1979,7 +1979,7 @@ """
#: Must be defined in subclasses. - summary_key = None # type: Optional[str] + summary_key: Optional[str] = None
@property def summary_parameters(self) -> Dict[str, str]: @@ -2407,7 +2407,7 @@
def treat_page(self) -> None: """Treat a page.""" - page = self.current_page # type: Optional[pywikibot.page.BasePage] + page: Optional[pywikibot.page.BasePage] = self.current_page if self.use_from_page is True: try: item = pywikibot.ItemPage.fromPage(page) diff --git a/pywikibot/bot_choice.py b/pywikibot/bot_choice.py index dbeacac..1cd8638 100644 --- a/pywikibot/bot_choice.py +++ b/pywikibot/bot_choice.py @@ -110,7 +110,7 @@ """
#: Place output before or after the question - before_question = False # type: bool + before_question: bool = False
@property def stop(self) -> bool: @@ -430,7 +430,7 @@
def format(self, default: Optional[str] = None) -> str: """Return a formatted string showing the range.""" - value = None # type: Optional[int] + value: Optional[int] = None
if default is not None and self.test(default): value = self.parse(default) diff --git a/pywikibot/config.py b/pywikibot/config.py index 0862233..0e4c691 100644 --- a/pywikibot/config.py +++ b/pywikibot/config.py @@ -141,8 +141,8 @@ # usernames['wikibooks']['*'] = 'mySingleUsername' # You may use '*' for family name in a similar manner. # -usernames = collections.defaultdict(dict) # type: Dict[str, Dict[str, str]] -disambiguation_comment = collections.defaultdict(dict) # type: _DabComDict +usernames: Dict[str, Dict[str, str]] = collections.defaultdict(dict) +disambiguation_comment: _DabComDict = collections.defaultdict(dict)
# User agent format. # For the meaning and more help in customization see: @@ -167,7 +167,7 @@ # True for enabling, False for disabling, str to hardcode a UA. # Example: {'problematic.site.example': True, # 'prefers.specific.ua.example': 'snakeoil/4.2'} -fake_user_agent_exceptions = {} # type: Dict[str, Union[bool, str]] +fake_user_agent_exceptions: Dict[str, Union[bool, str]] = {}
# The default interface for communicating with the site # currently the only defined interface is 'APISite', so don't change this! @@ -215,7 +215,7 @@ # 'access_key', 'access_secret') # # Note: the target wiki site must install OAuth extension -authenticate = {} # type: Dict[str, Tuple[str, ...]] +authenticate: Dict[str, Tuple[str, ...]] = {}
# By default you are asked for a password on the terminal. # A password file may be used, e.g. password_file = '.passwd' @@ -268,7 +268,7 @@ # # Note that these headers will be sent with all requests, # not just MediaWiki API calls. -extra_headers = {} # type: Mapping[str, str] +extra_headers: Mapping[str, str] = {}
# Set to True to override the {{bots}} exclusion protocol (at your own risk!) ignore_bot_templates = False @@ -517,7 +517,7 @@ # this can be used to pass variables to the UI init function # useful for e.g. # userinterface_init_kwargs = {'default_stream': 'stdout'} -userinterface_init_kwargs = {} # type: Dict[str, str] +userinterface_init_kwargs: Dict[str, str] = {}
# i18n setting for user interface language # default is obtained from locale.getlocale @@ -590,9 +590,9 @@ # log = [] # Per default, no logging is enabled. # This setting can be overridden by the -log or -nolog command-line arguments. -log = [] # type: List[str] +log: List[str] = [] # filename defaults to modulename-bot.log -logfilename = None # type: Optional[str] +logfilename: Optional[str] = None # maximal size of a logfile in kilobytes. If the size reached that limit the # logfile will be renamed (if logfilecount is not 0) and the old file is filled # again. logfilesize must be an integer value @@ -610,7 +610,7 @@ log_pywiki_repo_version = False # if True, include a lot of debugging info in logfile # (overrides log setting above) -debug_log = [] # type: List[str] +debug_log: List[str] = []
# ############# EXTERNAL SCRIPT PATH SETTINGS ############## # Set your own script path to lookup for your script files. @@ -630,7 +630,7 @@ # # sample: # user_script_paths = ['scripts.myscripts'] -user_script_paths = [] # type: List[str] +user_script_paths: List[str] = []
# ############# EXTERNAL FAMILIES SETTINGS ############## # Set your own family path to lookup for your family files. @@ -645,7 +645,7 @@ # samples: # family_files['mywiki'] = 'https://de.wikipedia.org' # user_families_paths = ['data/families'] -user_families_paths = [] # type: List[str] +user_families_paths: List[str] = []
# ############# INTERWIKI SETTINGS ##############
@@ -723,7 +723,7 @@
# Slow down the robot such that it never makes a second page edit within # 'put_throttle' seconds. -put_throttle = 10 # type: Union[int, float] +put_throttle: Union[int, float] = 10
# Sometimes you want to know when a delay is inserted. If a delay is larger # than 'noisysleep' seconds, it is logged on the screen. @@ -810,7 +810,7 @@ # (if cosmetic_changes_mylang_only is set) # Please set your dictionary by adding such lines to your user config file: # cosmetic_changes_enable['wikipedia'] = ('de', 'en', 'fr') -cosmetic_changes_enable = {} # type: Dict[str, Tuple[str, ...]] +cosmetic_changes_enable: Dict[str, Tuple[str, ...]] = {}
# The dictionary cosmetic_changes_disable should contain a tuple of languages # for each site where you wish to disable cosmetic changes. You may use it with @@ -818,7 +818,7 @@ # language. This also overrides the settings in the cosmetic_changes_enable # dictionary. Please set your dict by adding such lines to your user config: # cosmetic_changes_disable['wikipedia'] = ('de', 'en', 'fr') -cosmetic_changes_disable = {} # type: Dict[str, Tuple[str, ...]] +cosmetic_changes_disable: Dict[str, Tuple[str, ...]] = {}
# cosmetic_changes_deny_script is a list of scripts for which cosmetic changes # are disabled. You may add additional scripts by appending script names in @@ -840,7 +840,7 @@ # # to replace all occurrences of 'Hoofdpagina' with 'Veurblaad' when writing to # liwiki. Note that this does not take the origin wiki into account. -replicate_replace = {} # type: Dict[str, Dict[str, str]] +replicate_replace: Dict[str, Dict[str, str]] = {}
# ############# FURTHER SETTINGS ##############
@@ -850,11 +850,11 @@ # on the wiki server. Allows simulation runs of bots to be carried out without # changing any page on the server side. Use this setting to add more actions # into user config file for wikis with extra write actions. -actions_to_block = [] # type: List[str] +actions_to_block: List[str] = []
# Set simulate to True or use -simulate option to block all actions given # above. -simulate = False # type: Union[bool, str] +simulate: Union[bool, str] = False
# How many pages should be put to a queue in asynchronous mode. # If maxsize is <= 0, the queue size is infinite. diff --git a/pywikibot/cosmetic_changes.py b/pywikibot/cosmetic_changes.py index 04e6513..484e784 100644 --- a/pywikibot/cosmetic_changes.py +++ b/pywikibot/cosmetic_changes.py @@ -489,7 +489,7 @@ return '{}|{}]]'.format( split[0], '|'.join(cache.get(x.strip(), x) for x in split[1:]))
- cache = {} # type: Dict[Union[bool, str], Any] + cache: Dict[Union[bool, str], Any] = {} exceptions = ['comment', 'nowiki', 'pre', 'syntaxhighlight'] regex = re.compile( FILE_LINK_REGEX % '|'.join(self.site.namespaces[6]), @@ -956,7 +956,7 @@
def fixTypo(self, text: str) -> str: """Fix units.""" - exceptions = [ + exceptions: List[Union[str, Pattern[str]]] = [ 'comment', 'gallery', 'hyperlink', @@ -967,7 +967,7 @@ 'pre', 'startspace', 'syntaxhighlight', - ] # type: List[Union[str, Pattern[str]]] + ]
# change <number> ccm -> <number> cm³ text = textlib.replaceExcept(text, r'(\d)\s*(?: )?ccm', @@ -990,7 +990,7 @@ if self.site.code not in ['ckb', 'fa']: return text
- exceptions = [ + exceptions: List[Union[str, Pattern[str]]] = [ 'file', 'gallery', 'hyperlink', @@ -1005,7 +1005,7 @@ 'ref', 'startspace', 'syntaxhighlight', - ] # type: List[Union[str, Pattern[str]]] + ]
digits = textlib.NON_LATIN_DIGITS faChrs = 'ءاآأإئؤبپتثجچحخدذرزژسشصضطظعغفقکگلمنوهیةيك' + digits['fa'] diff --git a/pywikibot/data/api/_requests.py b/pywikibot/data/api/_requests.py index f9c37dd..bdfcd74 100644 --- a/pywikibot/data/api/_requests.py +++ b/pywikibot/data/api/_requests.py @@ -225,7 +225,7 @@ raise ValueError("'action' specification missing from Request.") self.action = parameters['action'] self.update(parameters) # also convert all parameter values to lists - self._warning_handler = None # type: Optional[Callable[[str, str], Union[Match[str], bool, None]]] # noqa: E501 + self._warning_handler: Optional[Callable[[str, str], Union[Match[str], bool, None]]] = None # noqa: E501 self.write = self.action in WRITE_ACTIONS # Client side verification that the request is being performed # by a logged in user, and warn if it isn't a config username. diff --git a/pywikibot/date.py b/pywikibot/date.py index 21d2398..5e167f2 100644 --- a/pywikibot/date.py +++ b/pywikibot/date.py @@ -350,7 +350,7 @@
# Each tuple must 3 parts: a list of all possible digits (symbols), encoder # (from int to a str) and decoder (from str to an int) -_digitDecoders = { +_digitDecoders: Dict[str, decoder_type] = { # %% is a % '%': '%', # %d is a decimal @@ -381,7 +381,7 @@ # %T is a year in TH: -- all years are shifted: 2005 => 'พ.ศ. 2548' 'T': (_decimalDigits, lambda v: str(v + 543), lambda v: int(v) - 543), -} # type: Dict[str, decoder_type] +}
# Allows to search for '(%%)|(%d)|(%R)|...", and allows one digit 1-9 to set # the size of zero-padding for numbers @@ -434,7 +434,7 @@ if pattern not in _escPtrnCache2: newPattern = '' # match starts at the beginning of the string strPattern = '' - decoders = [] # type: List[decoder_type] + decoders: List[decoder_type] = [] for s in _reParameters.split(pattern): if s is None: continue @@ -663,7 +663,7 @@ """ self.index = index self.variant, _, self.month = format_key.partition('_') - self.data = {} # type: Dict[str, Callable[[int], str]] + self.data: Dict[str, Callable[[int], str]] = {}
def __getitem__(self, key: str) -> Callable[[int], str]: if key not in self.data: @@ -722,7 +722,7 @@ alwaysTrue)])
-formats = { +formats: Dict[Union[str, int], Mapping[str, Callable[[int], str]]] = { 'MonthName': MonthNames(), 'Number': { 'ar': lambda v: dh_number(v, '%d (عدد)'), @@ -1654,7 +1654,7 @@ 'yo': lambda v: dh_singVal(v, 'Current events'), 'zh': lambda v: dh_singVal(v, '新闻动态'), }, -} # type: Dict[Union[str, int], Mapping[str, Callable[[int], str]]] +}
# # Add auto-generated empty dictionaries for DayOfMonth and MonthOfYear articles diff --git a/pywikibot/diff.py b/pywikibot/diff.py index c8f397f..29ea3d5 100644 --- a/pywikibot/diff.py +++ b/pywikibot/diff.py @@ -114,7 +114,7 @@ """Color diff lines.""" diff = iter(self.diff)
- fmt = '' # type: Optional[str] + fmt: Optional[str] = '' line1, line2 = '', next(diff) for line in diff: fmt, line1, line2 = line1, line2, line @@ -263,8 +263,8 @@ :param replace_invisible: Replace invisible characters like U+200e with the charnumber in brackets (e.g. <200e>). """ - self.a = text_a.splitlines(True) # type: Union[str, List[str]] - self.b = text_b.splitlines(True) # type: Union[str, List[str]] + self.a: Union[str, List[str]] = text_a.splitlines(True) + self.b: Union[str, List[str]] = text_b.splitlines(True) if by_letter and len(self.a) <= 1 and len(self.b) <= 1: self.a = text_a self.b = text_b @@ -338,7 +338,7 @@
if self.context: # Determine if two hunks are connected by self.context - super_hunk = [] # type: List[Hunk] + super_hunk: List[Hunk] = [] super_hunks = [super_hunk] for hunk in hunks: # self.context * 2, because if self.context is 2 the hunks @@ -417,7 +417,7 @@
super_hunks = self._generate_super_hunks( h for h in self.hunks if h.reviewed == Hunk.PENDING) - position = 0 # type: Optional[int] + position: Optional[int] = 0
while any(any(hunk.reviewed == Hunk.PENDING for hunk in super_hunk) for super_hunk in super_hunks): @@ -540,7 +540,7 @@ 'Please review them before proceeding.\n') self.review_hunks()
- l_text = [] # type: List[str] + l_text: List[str] = [] for hunk_idx, (i1, i2), (j1, j2) in self.blocks: # unchanged text. if hunk_idx < 0: @@ -604,8 +604,8 @@ """ from bs4 import BeautifulSoup
- comparands = {'deleted-context': [], - 'added-context': []} # type: Dict[str, List[str]] + comparands: Dict[str, List[str]] = {'deleted-context': [], + 'added-context': []} soup = BeautifulSoup(compare_string, 'html.parser') for change_type, css_class in (('deleted-context', 'diff-deletedline'), ('added-context', 'diff-addedline')): diff --git a/pywikibot/echo.py b/pywikibot/echo.py index 8b0c7b1..18112da 100644 --- a/pywikibot/echo.py +++ b/pywikibot/echo.py @@ -21,13 +21,13 @@ """Initialize an empty Notification object.""" self.site = site
- self.event_id = None # type: Optional[int] + self.event_id: Optional[int] = None self.type = None self.category = None self.timestamp = None self.page = None self.agent = None - self.read = None # type: Optional[bool] + self.read: Optional[bool] = None self.content = None self.revid = None
diff --git a/pywikibot/family.py b/pywikibot/family.py index de40fbe..dff749a 100644 --- a/pywikibot/family.py +++ b/pywikibot/family.py @@ -72,7 +72,7 @@
name = None
- langs = {} # type: Dict[str, str] + langs: Dict[str, str] = {}
# For interwiki sorting order see # https://meta.wikimedia.org/wiki/Interwiki_sorting_order @@ -173,12 +173,12 @@
# A dict of tuples for different sites with names of templates # that indicate an edit should be avoided - edit_restricted_templates = {} # type: Dict[str, Tuple[str, ...]] + edit_restricted_templates: Dict[str, Tuple[str, ...]] = {}
# A dict of tuples for different sites with names of archive # templates that indicate an edit of non-archive bots # should be avoided - archived_page_templates = {} # type: Dict[str, Tuple[str, ...]] + archived_page_templates: Dict[str, Tuple[str, ...]] = {}
# A list of projects that share cross-project sessions. cross_projects = [] @@ -191,34 +191,34 @@ cross_projects_cookie_username = 'centralauth_User'
# A list with the name in the cross-language flag permissions - cross_allowed = [] # type: List[str] + cross_allowed: List[str] = []
# A dict with the name of the category containing disambiguation # pages for the various languages. Only one category per language, # and without the namespace, so add things like: # 'en': "Disambiguation" - disambcatname = {} # type: Dict[str, str] + disambcatname: Dict[str, str] = {}
# attop is a list of languages that prefer to have the interwiki # links at the top of the page. - interwiki_attop = [] # type: List[str] + interwiki_attop: List[str] = [] # on_one_line is a list of languages that want the interwiki links # one-after-another on a single line - interwiki_on_one_line = [] # type: List[str] + interwiki_on_one_line: List[str] = [] # String used as separator between interwiki links and the text interwiki_text_separator = '\n\n'
# Similar for category - category_attop = [] # type: List[str] + category_attop: List[str] = [] # on_one_line is a list of languages that want the category links # one-after-another on a single line - category_on_one_line = [] # type: List[str] + category_on_one_line: List[str] = [] # String used as separator between category links and the text category_text_separator = '\n\n' # When both at the bottom should categories come after interwikilinks? # TODO: T86284 Needed on Wikia sites, as it uses the CategorySelect # extension which puts categories last on all sites. TO BE DEPRECATED! - categories_last = [] # type: List[str] + categories_last: List[str] = []
# Which languages have a special order for putting interlanguage # links, and what order is it? If a language is not in @@ -238,15 +238,15 @@ # Which language codes no longer exist and by which language code # should they be replaced. If for example the language with code xx: # now should get code yy:, add {'xx':'yy'} to obsolete. - interwiki_replacements = {} # type: Dict[str, str] + interwiki_replacements: Dict[str, str] = {}
# Codes that should be removed, usually because the site has been # taken down. - interwiki_removals = [] # type: List[str] + interwiki_removals: List[str] = []
# Language codes of the largest wikis. They should be roughly sorted # by size. - languages_by_size = [] # type: List[str] + languages_by_size: List[str] = []
# Some languages belong to a group where the possibility is high that # equivalent articles have identical titles among the group. @@ -339,7 +339,7 @@
# Some wiki farms have UrlShortener extension enabled only on the main # site. This value can specify this last one with (lang, family) tuple. - shared_urlshortner_wiki = None # type: Optional[Tuple[str, str]] + shared_urlshortner_wiki: Optional[Tuple[str, str]] = None
title_delimiter_and_aliases = ' _' """Titles usually are delimited by a space and the alias is replaced @@ -955,9 +955,9 @@ }
# Not open for edits; stewards can still edit. - closed_wikis = [] # type: List[str] + closed_wikis: List[str] = [] # Completely removed - removed_wikis = [] # type: List[str] + removed_wikis: List[str] = []
# WikimediaFamily uses Wikibase for the category name containing # disambiguation pages for the various languages. We need the diff --git a/pywikibot/flow.py b/pywikibot/flow.py index 3f58475..4e2984e 100644 --- a/pywikibot/flow.py +++ b/pywikibot/flow.py @@ -100,7 +100,7 @@ raise ValueError('Illegal board data (missing required data).') parsed_url = urlparse(rule['url']) params = parse_qs(parsed_url.query) - new_params = {} # type: Dict[str, Any] + new_params: Dict[str, Any] = {} for key, value in params.items(): if key != 'title': key = key.replace('topiclist_', '').replace('-', '_') @@ -326,7 +326,7 @@ self._page = page self._uuid = uuid
- self._content = {} # type: Dict[str, Any] + self._content: Dict[str, Any] = {}
@classmethod def fromJSON(cls, page: 'Topic', post_uuid: str, # noqa: N802 diff --git a/pywikibot/i18n.py b/pywikibot/i18n.py index 418a029..079b67f 100644 --- a/pywikibot/i18n.py +++ b/pywikibot/i18n.py @@ -275,7 +275,7 @@ 'zh-tw': 'zh-classical', 'zh-yue': 'cdo'})
-_GROUP_NAME_TO_FALLBACKS = { +_GROUP_NAME_TO_FALLBACKS: Dict[str, List[str]] = { '': [], 'aa': ['am'], 'ab': ['ru'], @@ -358,7 +358,7 @@ 'zh-classical': ['zh', 'zh-hans', 'zh-tw', 'zh-cn', 'zh-classical', 'lzh'], 'zh-min-nan': [ 'cdo', 'zh', 'zh-hans', 'zh-tw', 'zh-cn', 'zh-classical', 'lzh'] -} # type: Dict[str, List[str]] +}
def set_messages_package(package_name: str) -> None: diff --git a/pywikibot/interwiki_graph.py b/pywikibot/interwiki_graph.py index 209d4f2..d5bc153 100644 --- a/pywikibot/interwiki_graph.py +++ b/pywikibot/interwiki_graph.py @@ -71,7 +71,7 @@ # 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: FoundInType + self.found_in: FoundInType = {} if origin: self.found_in = {origin: []}
@@ -99,7 +99,7 @@ if PYDOT_ERROR: msg = f'pydot is not installed: {PYDOT_ERROR}.' raise ImportError(msg) - self.graph = None # type: Optional[pydot.Dot] + self.graph: Optional[pydot.Dot] = None self.subject = subject
@staticmethod diff --git a/pywikibot/logentries.py b/pywikibot/logentries.py index b295cbc..2eb9ff2 100644 --- a/pywikibot/logentries.py +++ b/pywikibot/logentries.py @@ -30,7 +30,7 @@ # Log type expected. None for every type, or one of the (letype) str : # block/patrol/etc... # Overridden in subclasses. - _expected_type = None # type: Optional[str] + _expected_type: Optional[str] = None
def __init__(self, apidata: Dict[str, Any], site: 'pywikibot.site.BaseSite') -> None: @@ -390,7 +390,7 @@ or use the get_valid_entry_class instance method instead. """ if logtype not in cls._logtypes: - bases = (OtherLogEntry, ) # type: Tuple['LogEntry', ...] + bases: Tuple['LogEntry', ...] = (OtherLogEntry, ) if logtype in ('newusers', 'thanks'): bases = (UserTargetLogEntry, OtherLogEntry)
diff --git a/pywikibot/logging.py b/pywikibot/logging.py index 0955418..9dafa11 100644 --- a/pywikibot/logging.py +++ b/pywikibot/logging.py @@ -46,7 +46,7 @@ .. seealso:: :python:`Python Logging Levels<logging.html#logging-levels>` """
-_init_routines = [] # type: List[Callable[[], Any]] +_init_routines: List[Callable[[], Any]] = [] _inited_routines = set()
diff --git a/pywikibot/login.py b/pywikibot/login.py index 0581b8b..7fc55de 100644 --- a/pywikibot/login.py +++ b/pywikibot/login.py @@ -377,7 +377,7 @@ 'should be removed if OAuth enabled.' .format(login=self)) self._consumer_token = (user, password) - self._access_token = None # type: Optional[Tuple[str, str]] + self._access_token: Optional[Tuple[str, str]] = None
def login(self, retry: bool = False, force: bool = False) -> bool: """ diff --git a/pywikibot/page/_wikibase.py b/pywikibot/page/_wikibase.py index 1e647a9..77ac917 100644 --- a/pywikibot/page/_wikibase.py +++ b/pywikibot/page/_wikibase.py @@ -89,7 +89,7 @@ :type title_pattern: str """
- DATA_ATTRIBUTES = {} # type: Dict[str, Any] + DATA_ATTRIBUTES: Dict[str, Any] = {}
def __init__(self, repo, id_=None) -> None: """ diff --git a/pywikibot/pagegenerators/__init__.py b/pywikibot/pagegenerators/__init__.py index 356f24b..ef08476 100644 --- a/pywikibot/pagegenerators/__init__.py +++ b/pywikibot/pagegenerators/__init__.py @@ -591,7 +591,7 @@ kwargs.pop('start', None) # don't set start time kwargs.pop('end', None) # don't set stop time
- seen = set() # type: Set[Any] + seen: Set[Any] = set() while total is None or len(seen) < total: def filtered_generator() -> Iterable['pywikibot.page.Page']: for item in generator(total=None if seen else 1, **kwargs): @@ -619,7 +619,7 @@ """ # pages may be on more than one site, for example if an interwiki # generator is used, so use a separate preloader for each site - sites = {} # type: PRELOAD_SITE_TYPE + sites: PRELOAD_SITE_TYPE = {} # build a list of pages for each site found in the iterator for page in generator: site = page.site @@ -662,7 +662,7 @@ :param generator: pages to iterate over :param groupsize: how many pages to preload at once """ - sites = {} # type: PRELOAD_SITE_TYPE + sites: PRELOAD_SITE_TYPE = {} for page in generator: site = page.site sites.setdefault(site, []).append(page) diff --git a/pywikibot/pagegenerators/_factory.py b/pywikibot/pagegenerators/_factory.py index a67280a..41d345f 100644 --- a/pywikibot/pagegenerators/_factory.py +++ b/pywikibot/pagegenerators/_factory.py @@ -96,25 +96,25 @@ :param disabled_options: disable these given options and let them be handled by scripts options handler """ - self.gens = [] # type: List[Iterable['pywikibot.page.Page']] - self._namespaces = [] # type: GEN_FACTORY_NAMESPACE_TYPE - self.limit = None # type: Optional[int] - self.qualityfilter_list = [] # type: List[int] - self.articlefilter_list = [] # type: List[str] - self.articlenotfilter_list = [] # type: List[str] - self.titlefilter_list = [] # type: List[str] - self.titlenotfilter_list = [] # type: List[str] - self.claimfilter_list = [] # type: GEN_FACTORY_CLAIM_TYPE - self.catfilter_list = [] # type: List['pywikibot.Category'] + self.gens: List[Iterable['pywikibot.page.Page']] = [] + self._namespaces: GEN_FACTORY_NAMESPACE_TYPE = [] + self.limit: Optional[int] = None + self.qualityfilter_list: List[int] = [] + self.articlefilter_list: List[str] = [] + self.articlenotfilter_list: List[str] = [] + self.titlefilter_list: List[str] = [] + self.titlenotfilter_list: List[str] = [] + self.claimfilter_list: GEN_FACTORY_CLAIM_TYPE = [] + self.catfilter_list: List['pywikibot.Category'] = [] self.intersect = False - self.subpage_max_depth = None # type: Optional[int] + self.subpage_max_depth: Optional[int] = None self._site = site self._positional_arg_name = positional_arg_name - self._sparql = None # type: Optional[str] + self._sparql: Optional[str] = None self.nopreload = False self._validate_options(enabled_options, disabled_options)
- self.is_preloading = None # type: Optional[bool] + self.is_preloading: Optional[bool] = None """Return whether Page objects are preloaded. You may use this instance variable after :meth:`getCombinedGenerator` is called e.g.:: @@ -307,7 +307,7 @@ category = i18n.input('pywikibot-enter-category-name') category = category.replace('#', '|')
- startfrom = None # type: Optional[str] + startfrom: Optional[str] = None category, _, startfrom = category.partition('|')
if not startfrom: @@ -432,7 +432,7 @@ valid_cats = [c for _list in cats.values() for c in _list]
value = value or '' - lint_from = None # type: Optional[str] + lint_from: Optional[str] = None cat, _, lint_from = value.partition('/') lint_from = lint_from or None
@@ -923,7 +923,7 @@ :param arg: Pywikibot argument consisting of -name:value :return: True if the argument supplied was recognised by the factory """ - value = None # type: Optional[str] + value: Optional[str] = None
if not arg.startswith('-') and self._positional_arg_name: value = arg diff --git a/pywikibot/pagegenerators/_generators.py b/pywikibot/pagegenerators/_generators.py index 78996d2..3b60393 100644 --- a/pywikibot/pagegenerators/_generators.py +++ b/pywikibot/pagegenerators/_generators.py @@ -65,7 +65,7 @@ if site is None: site = pywikibot.Site()
- filterredir = None # type: Optional[bool] + filterredir: Optional[bool] = None if not includeredirects: filterredir = False elif includeredirects == 'only': @@ -104,7 +104,7 @@ namespace = prefixlink.namespace title = prefixlink.title
- filterredir = None # type: Optional[bool] + filterredir: Optional[bool] = None if not includeredirects: filterredir = False elif includeredirects == 'only': @@ -930,7 +930,7 @@ self.content = content self.skipping = bool(start)
- self.start = None # type: Optional[str] + self.start: Optional[str] = None if start is not None and self.skipping: self.start = start.replace('_', ' ')
diff --git a/pywikibot/plural.py b/pywikibot/plural.py index 45b015d..d5f6e94 100644 --- a/pywikibot/plural.py +++ b/pywikibot/plural.py @@ -11,7 +11,7 @@
PluralRule = Dict[str, Union[int, Callable[[int], Union[bool, int]]]]
-plural_rules = { +plural_rules: Dict[str, PluralRule] = { '_default': {'nplurals': 2, 'plural': lambda n: (n != 1)}, 'ar': {'nplurals': 6, 'plural': lambda n: 0 if (n == 0) else @@ -83,7 +83,7 @@ 1 if (n % 100 == 2) else 2 if n % 100 in (3, 4) else 3}, -} # type: Dict[str, PluralRule] +}
plural_rules.update( dict.fromkeys( diff --git a/pywikibot/proofreadpage.py b/pywikibot/proofreadpage.py index 8c8432a..350f11a 100644 --- a/pywikibot/proofreadpage.py +++ b/pywikibot/proofreadpage.py @@ -243,7 +243,7 @@ :return: (base, ext, num). """ left, sep, right = self.title(with_ns=False).rpartition('/') - num = None # type: Optional[int] + num: Optional[int] = None
if sep: base = left @@ -279,7 +279,7 @@ set(self.getReferences(namespaces=index_ns))]
if not what_links_here: - self._index = (None, []) # type: _IndexType + self._index: _IndexType = (None, []) elif len(what_links_here) == 1: self._index = (what_links_here.pop(), []) else: @@ -927,11 +927,11 @@ """Associate label and number for each page linked to the index.""" # Clean cache, if any. 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: PagesFromLabelType - self._labels_from_page_number = {} # type: Dict[int, str] - self._labels_from_page = {} # type: Dict[pywikibot.page.Page, str] + self._numbers_from_page: Dict[pywikibot.page.Page, int] = {} + self._page_numbers_from_label: Dict[str, Set[int]] = {} + self._pages_from_label: PagesFromLabelType = {} + self._labels_from_page_number: Dict[int, str] = {} + self._labels_from_page: Dict[pywikibot.page.Page, str] = {} self._soup = _bs4_soup(self.get_parsed_page(True)) # type: ignore # Do not search for "new" here, to avoid to skip purging if links # to non-existing pages are present. diff --git a/pywikibot/scripts/generate_user_files.py b/pywikibot/scripts/generate_user_files.py index d88e229..649a6e7 100755 --- a/pywikibot/scripts/generate_user_files.py +++ b/pywikibot/scripts/generate_user_files.py @@ -176,6 +176,9 @@ # This is an automatically generated file. You can find more # configuration parameters in 'config.py' file or refer # https://doc.wikimedia.org/pywikibot/master/api_ref/pywikibot.config.html +from typing import Optional, Union + +from pywikibot.backports import Dict, List, Tuple
# The family of sites to be working on. # Pywikibot will import families/xxx_family.py so if you want to change diff --git a/pywikibot/site/_apisite.py b/pywikibot/site/_apisite.py index d316b81..7e53bbf 100644 --- a/pywikibot/site/_apisite.py +++ b/pywikibot/site/_apisite.py @@ -78,7 +78,7 @@
__all__ = ('APISite', ) -_mw_msg_cache = defaultdict(dict) # type: DefaultDict[str, Dict[str, str]] +_mw_msg_cache: DefaultDict[str, Dict[str, str]] = defaultdict(dict)
_CompType = Union[int, str, 'pywikibot.page.Page', 'pywikibot.page.Revision'] @@ -115,10 +115,10 @@ ) -> None: """Initializer.""" super().__init__(code, fam, user) - self._globaluserinfo = {} # type: Dict[Union[int, str], Any] + self._globaluserinfo: Dict[Union[int, str], Any] = {} self._interwikimap = _InterwikiMap(self) self._loginstatus = _LoginStatus.NOT_ATTEMPTED - self._msgcache = {} # type: Dict[str, str] + self._msgcache: Dict[str, str] = {} self._paraminfo = api.ParamInfo(self) self._siteinfo = Siteinfo(self) self.tokens = TokenWallet(self) @@ -244,7 +244,7 @@ :raises TypeError: a namespace identifier has an inappropriate type such as NoneType or bool """ - req_args = {'site': self} # type: Dict[str, Any] + req_args: Dict[str, Any] = {'site': self} if 'g_content' in args: req_args['g_content'] = args.pop('g_content') if 'parameters' in args: @@ -535,7 +535,7 @@
:raises TypeError: Inappropriate argument type of 'user' """ - param = {} # type: Dict[str, Union[int, str]] + param: Dict[str, Union[int, str]] = {} if user is None: user = self.username() assert isinstance(user, str) @@ -642,7 +642,7 @@ "API userinfo response lacks 'query' key" assert 'userinfo' in uidata['query'], \ "API userinfo response lacks 'userinfo' key" - self._useroptions = uidata['query']['userinfo']['options'] # type: Dict[str, Any] # noqa: E501 + self._useroptions: Dict[str, Any] = uidata['query']['userinfo']['options'] # noqa: E501 # To determine if user name has changed self._useroptions['_name'] = ( None if 'anon' in uidata['query']['userinfo'] else @@ -881,7 +881,7 @@
months = self.mediawiki_messages(months_long + months_short)
- self._months_names = [] # type: List[Tuple[str, str]] + self._months_names: List[Tuple[str, str]] = [] for m_l, m_s in zip(months_long, months_short): self._months_names.append((months[m_l], months[m_s]))
@@ -1700,7 +1700,7 @@
# Catalog of editpage error codes, for use in generating messages. # The block at the bottom are page related errors. - _ep_errors = { + _ep_errors: Dict[str, Union[str, Type[PageSaveRelatedError]]] = { 'noapiwrite': 'API editing not enabled on {site} wiki', 'writeapidenied': 'User {user} is not authorized to edit on {site} wiki', @@ -1731,7 +1731,7 @@ 'titleblacklist-forbidden': TitleblacklistError, 'spamblacklist': SpamblacklistError, 'abusefilter-disallowed': AbuseFilterDisallowedError, - } # type: Dict[str, Union[str, Type[PageSaveRelatedError]]] + } _ep_text_overrides = {'appendtext', 'prependtext', 'undo'}
@need_right('edit') @@ -2052,7 +2052,7 @@ raise Error('mergehistory: unexpected response')
# catalog of move errors for use in error messages - _mv_errors = { + _mv_errors: Dict[str, Union[str, OnErrorExc]] = { 'noapiwrite': 'API editing not enabled on {site} wiki', 'writeapidenied': 'User {user} is not authorized to edit on {site} wiki', @@ -2081,7 +2081,7 @@ '[[{newtitle}]] file extension does not match content of ' '[[{oldtitle}]]', 'missingtitle': "{oldtitle} doesn't exist", - } # type: Dict[str, Union[str, OnErrorExc]] + }
@need_right('move') def movepage( diff --git a/scripts/add_text.py b/scripts/add_text.py index 77aaa5a..2b270e9 100755 --- a/scripts/add_text.py +++ b/scripts/add_text.py @@ -71,7 +71,7 @@
ARGS_TYPE = Dict[str, Union[bool, str]] -DEFAULT_ARGS = { +DEFAULT_ARGS: ARGS_TYPE = { 'text': '', 'textfile': '', 'summary': '', @@ -83,7 +83,7 @@ 'talk_page': False, 'reorder': True, 'regex_skip_url': '', -} # type: ARGS_TYPE +}
ARG_PROMPT = { '-text': 'What text do you want to add?', diff --git a/scripts/blockpageschecker.py b/scripts/blockpageschecker.py index 36be5d7..6feda12 100755 --- a/scripts/blockpageschecker.py +++ b/scripts/blockpageschecker.py @@ -300,7 +300,7 @@ # keep track of the changes for each step (edit then move) changes = -1
- msg_type = None # type: Optional[str] + msg_type: Optional[str] = None edit_restriction = restrictions.get('edit') if not edit_restriction: # page is not edit-protected diff --git a/scripts/category.py b/scripts/category.py index ea2f008..3a23f8b 100755 --- a/scripts/category.py +++ b/scripts/category.py @@ -279,7 +279,7 @@ self.includeonly = [] return page
- tmpl = [] # type: Sequence + tmpl: Sequence = [] with suppress(KeyError): tmpl, _loc = moved_links[page.site.code]
@@ -620,7 +620,7 @@ self.oldtalk = self.oldcat.toggleTalkPage()
if newcat: - self.newcat = self._makecat(newcat) # type: Optional[pywikibot.Category] # noqa: E501 + self.newcat: Optional[pywikibot.Category] = self._makecat(newcat) # noqa: E501 self.newtalk = self.newcat.toggleTalkPage() else: self.newcat = None diff --git a/scripts/redirect.py b/scripts/redirect.py index 402c719..27123c0 100755 --- a/scripts/redirect.py +++ b/scripts/redirect.py @@ -683,8 +683,8 @@
:param args: command line arguments """ - options = {} # type: Dict[str, Any] - gen_options = {} # type: Dict[str, Any] + options: Dict[str, Any] = {} + gen_options: Dict[str, Any] = {} # what the bot should do (either resolve double redirs, or process broken # redirs) action = None diff --git a/scripts/replace.py b/scripts/replace.py index fd25330..16d938a 100755 --- a/scripts/replace.py +++ b/scripts/replace.py @@ -917,7 +917,7 @@ # if -xml flag is present xmlFilename = None xmlStart = None - sql_query = None # type: Optional[str] + sql_query: Optional[str] = None # Set the default regular expression flags flags = 0 # Request manual replacements even if replacements are already defined diff --git a/scripts/weblinkchecker.py b/scripts/weblinkchecker.py index 8f41b83..c6ed186 100755 --- a/scripts/weblinkchecker.py +++ b/scripts/weblinkchecker.py @@ -249,7 +249,7 @@ """
#: Collecting start time of a thread for any host - hosts = {} # type: Dict[str, float] + hosts: Dict[str, float] = {} lock = threading.Lock()
def __init__(self, page, url, history, http_ignores, day) -> None: diff --git a/scripts/welcome.py b/scripts/welcome.py index 1335a43..36f45f2 100755 --- a/scripts/welcome.py +++ b/scripts/welcome.py @@ -467,9 +467,9 @@ """Initializer.""" super().__init__(**kwargs) self.check_managed_sites() - self.bname = {} # type: Dict[str, str] + self.bname: Dict[str, str] = {}
- self.welcomed_users = [] # type: List[str] + self.welcomed_users: List[str] = [] self.log_name = i18n.translate(self.site, logbook)
if not self.log_name: diff --git a/tests/__init__.py b/tests/__init__.py index 1966c56..87b0452 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -170,7 +170,7 @@ }
# remove "# pragma: no cover" below if this set is not empty -disabled_tests = {} # type: Dict[str, List[str]] +disabled_tests: Dict[str, List[str]] = {}
def _unknown_test_modules():
pywikibot-commits@lists.wikimedia.org