jenkins-bot has submitted this change. ( https://gerrit.wikimedia.org/r/c/pywikibot/core/+/634769 )
Change subject: [4.0] Remove remaining Python 2 code parts ......................................................................
[4.0] Remove remaining Python 2 code parts
Change-Id: Ide02a21d20a0d060e66ee9596aa8f8b2b010389b --- M .appveyor.yml M .coveragerc M docs/requirements-py3.txt M pwb.py M pywikibot/bot.py M pywikibot/family.py M pywikibot/logging.py M pywikibot/page/__init__.py M pywikibot/textlib.py M pywikibot/tools/__init__.py M setup.py M tests/textlib_tests.py 12 files changed, 32 insertions(+), 37 deletions(-)
Approvals: Mpaa: Looks good to me, approved jenkins-bot: Verified
diff --git a/.appveyor.yml b/.appveyor.yml index c5f21b9..caf0905 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -92,7 +92,6 @@ test_script: - chcp 65001 - set PYTHONIOENCODING=utf8 - - set PYTHONWARNINGS=ignore:::pkg_resources.py2_warn
- "mkdir %PYWIKIBOT_DIR%" - "python -Werror::UserWarning -m generate_user_files -dir:%PYWIKIBOT_DIR% -family:wikipedia -lang:en -v -debug -user:%PYWIKIBOT_USERNAME%" diff --git a/.coveragerc b/.coveragerc index cf272bf..8d0e536 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1,7 +1,5 @@ [report] exclude_lines = - if __debug__ and not PY2: # pyflakes workaround - # Have to re-enable the standard pragma pragma: no cover
diff --git a/docs/requirements-py3.txt b/docs/requirements-py3.txt index 986aee3..3799161 100644 --- a/docs/requirements-py3.txt +++ b/docs/requirements-py3.txt @@ -1,5 +1,4 @@ # This is a PIP requirements file for building Sphinx documentation of pywikibot -# using sphinx on python3.4. # requirements.txt is also needed
sphinx >= 1.8, != 3.1.0 diff --git a/pwb.py b/pwb.py index 70842a6..80bbc7e 100755 --- a/pwb.py +++ b/pwb.py @@ -18,6 +18,7 @@ # # Distributed under the terms of the MIT license. # +# ## KEEP PYTHON 2 SUPPORT FOR THIS SCRIPT ## # from __future__ import print_function
import os @@ -33,7 +34,7 @@ pwb = None
# The following snippet was developed by Ned Batchelder (and others) -# for coverage [1], with python 3 support [2] added later, +# for coverage [1], with Python 3 support [2] added later, # and is available under the BSD license (see [3]) # [1] # https://bitbucket.org/ned/coveragepy/src/b5abcee50dbe/coverage/execfile.py diff --git a/pywikibot/bot.py b/pywikibot/bot.py index dcd8f50..2abb868 100644 --- a/pywikibot/bot.py +++ b/pywikibot/bot.py @@ -1411,10 +1411,7 @@ # exc_info contains exception from self.run() while terminating exc_info = sys.exc_info() pywikibot.output('Script terminated ', newline=False) - # Python 2 also needs QuitKeyboardInterrupt - # to be compared with exc_info[0] (T195687) - if exc_info[0] is None or exc_info[0] in (KeyboardInterrupt, - QuitKeyboardInterrupt): + if exc_info[0] is None or exc_info[0] is KeyboardInterrupt: pywikibot.output('successfully.') else: pywikibot.output('by exception:\n') diff --git a/pywikibot/family.py b/pywikibot/family.py index 2b1412d..4005b6c 100644 --- a/pywikibot/family.py +++ b/pywikibot/family.py @@ -1427,8 +1427,7 @@ # AutoFamily refers to the variable set below, not the function return super().scriptpath(code)
- # str() used because py2 can't accept a unicode as the name of a class - AutoFamily = type(str('AutoFamily'), (SingleSiteFamily,), locals()) + AutoFamily = type('AutoFamily', (SingleSiteFamily,), locals()) return AutoFamily()
diff --git a/pywikibot/logging.py b/pywikibot/logging.py index 6951f62..22ba07f 100644 --- a/pywikibot/logging.py +++ b/pywikibot/logging.py @@ -10,7 +10,7 @@ import sys
# logging levels -from logging import DEBUG, INFO, WARNING, ERROR, CRITICAL, StreamHandler +from logging import DEBUG, INFO, WARNING, ERROR, CRITICAL
STDOUT = 16 VERBOSE = 18 @@ -70,9 +70,6 @@ else: logger = logging.getLogger('pywiki')
- if not logger.handlers: # lastResort for Python 2 (T188417) - logger.handlers.append(StreamHandler()) - # invoke any init routines if _init_routines: _init() diff --git a/pywikibot/page/__init__.py b/pywikibot/page/__init__.py index 55c9a23..82e0059 100644 --- a/pywikibot/page/__init__.py +++ b/pywikibot/page/__init__.py @@ -20,7 +20,6 @@ import logging import os.path import re -import sys import unicodedata
from collections import Counter, defaultdict, OrderedDict @@ -3820,8 +3819,7 @@ if not hasattr(cls, 'title_pattern'): return True
- # todo: use re.fullmatch when Python 3.4+ required - return bool(re.match(cls.title_pattern + '$', entity_id)) + return bool(re.fullmatch(cls.title_pattern, entity_id))
def __getattr__(self, name): if name in self.DATA_ATTRIBUTES: @@ -6458,6 +6456,7 @@ # match.string stores original text so we do not need # to pass it to handle_entity, ♥ Python return match.group(0) + if match.group('decimal'): unicode_codepoint = int(match.group('decimal')) elif match.group('hex'): @@ -6470,14 +6469,11 @@ unicode_codepoint, unicode_codepoint)
if unicode_codepoint and unicode_codepoint not in ignore: - if unicode_codepoint > sys.maxunicode: - # solve narrow Python 2 build exception (UTF-16) - return eval("'\U{0:08x}'".format(unicode_codepoint)) - else: - return chr(unicode_codepoint) - else: - # Leave the entity unchanged - return match.group(0) + return chr(unicode_codepoint) + + # Leave the entity unchanged + return match.group(0) + return _ENTITY_SUB(handle_entity, text)
diff --git a/pywikibot/textlib.py b/pywikibot/textlib.py index 481608a..e495ca2 100644 --- a/pywikibot/textlib.py +++ b/pywikibot/textlib.py @@ -681,15 +681,18 @@ m = link_pattern.search(text, pos=curpos) if not m: break + # Ignore links to sections of the same page if not m.group('title').strip(): curpos = m.end() continue + # Ignore interwiki links if (site.isInterwikiLink(m.group('title').strip()) and not m.group('title').strip().startswith(':')): curpos = m.end() continue + groups = m.groupdict() if groups['label'] and '[[' in groups['label']: # TODO: Work on the link within the label too @@ -704,10 +707,12 @@ end = extended_match.end() else: end = m.end() + start = m.start() # Since this point the m variable shouldn't be used as it may not # contain all contents del m + try: link = pywikibot.Link.create_separated( groups['title'], site, section=groups['section'], @@ -735,15 +740,16 @@ # remove preleading ":" from the link text if new_label[0] == ':': new_label = new_label[1:] + new_linktrail = groups['linktrail'] if new_linktrail: new_label += new_linktrail
if new_link is False: # unlink - we remove the section if there's any - assert isinstance(new_label, str), \ - 'link text must be str.' + assert isinstance(new_label, str), 'link text must be str.' new_link = new_label + if isinstance(new_link, str): # Nothing good can come out of the fact that bytes is returned so # force unicode @@ -751,9 +757,9 @@ # Make sure that next time around we will not find this same hit. curpos = start + len(new_link) continue - elif isinstance(new_link, bytes): - raise ValueError('The result must be unicode (str in Python 3) ' - 'and not bytes (str in Python 2).') + + if isinstance(new_link, bytes): + raise ValueError('The result must be str and not bytes.')
# Verify that it's either Link, Page or str check_classes(new_link) @@ -780,6 +786,7 @@
if new_section: new_title += '#' + new_section + if new_label is None: new_label = new_title
@@ -806,6 +813,7 @@ else: new_text = '[[{0}]]{1}'.format(new_label[:len(new_title)], new_label[len(new_title):]) + text = text[:start] + new_text + text[end:] # Make sure that next time around we will not find this same hit. curpos = start + len(new_text) diff --git a/pywikibot/tools/__init__.py b/pywikibot/tools/__init__.py index b44f246..0a71018 100644 --- a/pywikibot/tools/__init__.py +++ b/pywikibot/tools/__init__.py @@ -932,7 +932,7 @@ """A generator that allows items to be added during generating."""
def __next__(self): - """Python 3 iterator method.""" + """Iterator method.""" if len(self): return self.popleft() else: @@ -964,8 +964,7 @@ @raises ValueError: When 7za is not available or the opening mode is unknown or it tries to write a 7z archive. @raises FileNotFoundError: When the filename doesn't exist and it tries - to read from it or it tries to determine the compression algorithm (or - IOError on Python 2). + to read from it or it tries to determine the compression algorithm. @raises OSError: When it's not a 7z archive but the file extension is 7z. It is also raised by bz2 when its content is invalid. gzip does not immediately raise that error but only on reading it. diff --git a/setup.py b/setup.py index 35af98d..e52b33c 100644 --- a/setup.py +++ b/setup.py @@ -28,6 +28,7 @@ # # Distributed under the terms of the MIT license. # +# ## KEEP PYTHON 2 SUPPORT FOR THIS SCRIPT ## # import os import sys
diff --git a/tests/textlib_tests.py b/tests/textlib_tests.py index 10e7020..0df9bc9 100644 --- a/tests/textlib_tests.py +++ b/tests/textlib_tests.py @@ -1008,9 +1008,10 @@ if link.title == 'World': # This must be a bytes instance not unicode return b'homeworlder' - self.assertRaisesRegex( - ValueError, r'unicode (str.*bytes (str', - textlib.replace_links, self.text, callback, self.wp_site) + + with self.assertRaisesRegex(ValueError, + r'The result must be str and not bytes.'): + textlib.replace_links(self.text, callback, self.wp_site)
def test_replace_interwiki_links(self): """Make sure interwiki links can not be replaced."""