jenkins-bot has submitted this change and it was merged. ( https://gerrit.wikimedia.org/r/263372 )
Change subject: Abandon support for python 2.6 ......................................................................
Abandon support for python 2.6
- remove 2.6 tests from appreyor and travis - update HISTORY.rst and docs - update requirements - update docs - remove backports from doc - cleanup backports.py (to be deleted later) - cleanup tools - update library parts and tests
Bug: T154771 Change-Id: Ied97711c81adebe9c260c8e7c2647b6cc71846fa --- M .appveyor.yml M .travis.yml M HISTORY.rst M dev-requirements.txt M docs/api_ref/pywikibot.rst M docs/index.rst M pwb.py M pywikibot/CONTENT.rst M pywikibot/README.rst M pywikibot/__init__.py M pywikibot/backports.py M pywikibot/bot.py M pywikibot/diff.py M pywikibot/family.py M pywikibot/interwiki_graph.py M pywikibot/page.py M pywikibot/site_detect.py M pywikibot/textlib.py M pywikibot/tools/__init__.py M pywikibot/tools/djvu.py M requests-requirements.txt M requirements.txt M setup.py M tests/__init__.py M tests/link_tests.py M tests/python_tests.py M tests/script_tests.py M tests/textlib_tests.py M tests/tools_tests.py M tests/utils.py M tox.ini 31 files changed, 89 insertions(+), 413 deletions(-)
Approvals: Dalba: Looks good to me, approved jenkins-bot: Verified
diff --git a/.appveyor.yml b/.appveyor.yml index 87a3ef6..85ccee8 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -17,15 +17,6 @@
# Test the lowest supported release of each major Python version.
- # Pywikibot support matrix suggests 'should run' on Python 2.6.5+ - # Only Python 2.6.6 is able to be set up on Appveyor. - # https://github.com/ogrisel/python-appveyor-demo/issues/10 - # fwiw, Redhat Enterprise Linux ships with 2.6.6. - - - PYTHON: "C:\Python266-x64" - PYTHON_VERSION: "2.6.6" - PYTHON_ARCH: "64" - - PYTHON: "C:\Python272" PYTHON_VERSION: "2.7.2" PYTHON_ARCH: "32" @@ -92,10 +83,6 @@ - pip install virtualenv - virtualenv env - env\Scripts\activate.bat - # wheel version 0.29.0 is enforced because version 0.30.0 doesn't support - # Python 2.6 and 3.3 anymore. Once we drop support for those versions we - # can use the latest version of wheel. - - pip install wheel==0.29.0 - pip install -r dev-requirements.txt - pip install -r requests-requirements.txt
diff --git a/.travis.yml b/.travis.yml index 044670e..cdd20c0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,6 @@ sudo: false
python: - - '2.6' - '2.7' - '3.4' - '3.5' @@ -160,7 +159,7 @@ env: LANGUAGE=test FAMILY=wikidata SITE_ONLY=1 - python: '3.4' env: LANGUAGE=ar FAMILY=wiktionary PYWIKIBOT2_TEST_NO_RC=1 - - python: '2.6' + - python: '3.6' env: LANGUAGE=wikidata FAMILY=wikidata SITE_ONLY=1
notifications: diff --git a/HISTORY.rst b/HISTORY.rst index d989c25..3c7d1e2 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -4,6 +4,7 @@ Current release ---------------
+* Dropped support for Python 2.6 (T154771) * Dropped support for Python 3.3 (T184508) * Bugfixes and improvements * Localisation updates diff --git a/dev-requirements.txt b/dev-requirements.txt index 5084cdf..d3eb990 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -1,6 +1,6 @@ # This is a PIP 6+ requirements file for development dependencies # -unittest2==0.8.0 ; python_full_version < '2.7.3' +unittest2==0.8.0 ; python_full_version == '2.7.2'
pytest>=2.8.0 pytest-timeout @@ -8,7 +8,7 @@ pytest-cov pytest-attrib pytest-httpbin -httpbin<0.6.0 ; os_name != 'posix' or python_version < '2.7' +httpbin<0.6.0 ; os_name != 'posix'
six
@@ -35,5 +35,3 @@ # are not useful on the Appveyor Win32 builds since the relevant UI tests # also require accessing the menu of the console window, which doesnt exist # in the Appveyor environment. - -setuptools_scm ; python_version == '2.6' diff --git a/docs/api_ref/pywikibot.rst b/docs/api_ref/pywikibot.rst index 21c21b3..d683df6 100644 --- a/docs/api_ref/pywikibot.rst +++ b/docs/api_ref/pywikibot.rst @@ -21,14 +21,6 @@ Submodules ----------
-pywikibot.backports module --------------------------- - -.. automodule:: pywikibot.backports - :members: - :undoc-members: - :show-inheritance: - pywikibot.bot module --------------------
diff --git a/docs/index.rst b/docs/index.rst index 91c773c..8a6cea7 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -13,7 +13,7 @@
Pywikibot is a Python library and collection of scripts that automate work on `MediaWiki https://mediawiki.org`_ sites.
-Pywikibot supports Python 2.6.5+, 2.7.2+ and 3.4+. +Pywikibot supports Python 2.7.2+ and 3.4+.
Pywikibot and this documentation are licensed under the :ref:`MIT license <licenses-MIT>`; manual pages on mediawiki.org are licensed under the `CC-BY-SA 3.0`_ license. diff --git a/pwb.py b/pwb.py index aed8514..afd2607 100755 --- a/pwb.py +++ b/pwb.py @@ -30,22 +30,19 @@
PYTHON_VERSION = sys.version_info[:3] PY2 = (PYTHON_VERSION[0] == 2) -PY26 = (PYTHON_VERSION < (2, 7))
versions_required_message = """ Pywikibot is not available on: {version}
-This version of Pywikibot only supports Python 2.6.5+, 2.7.2+ or 3.4+. +This version of Pywikibot only supports Python 2.7.2+ or 3.4+. """
def python_is_supported(): """Check that Python is supported.""" # Any change to this must be copied to setup.py - return (PYTHON_VERSION >= (3, 4, 0) or - (PY2 and PYTHON_VERSION >= (2, 7, 2)) or - (PY26 and PYTHON_VERSION >= (2, 6, 5))) + return PYTHON_VERSION >= (3, 4, 0) or PY2 and PYTHON_VERSION >= (2, 7, 2)
if not python_is_supported(): diff --git a/pywikibot/CONTENT.rst b/pywikibot/CONTENT.rst index 180c4e4..cd486e8 100644 --- a/pywikibot/CONTENT.rst +++ b/pywikibot/CONTENT.rst @@ -9,8 +9,8 @@ +---------------------------+-------------------------------------------------------+ | _wbtypes.py | Wikibase data type classes | +---------------------------+-------------------------------------------------------+ - | backports.py | Module contains backports to support older Python | - | | versions | + | backports.py | Deprecated module that contained backports to support | + | | older Python versions (could be dropped soon) | +---------------------------+-------------------------------------------------------+ | bot.py | User-interface related functions for building bots | +---------------------------+-------------------------------------------------------+ diff --git a/pywikibot/README.rst b/pywikibot/README.rst index a9dd281..a817648 100644 --- a/pywikibot/README.rst +++ b/pywikibot/README.rst @@ -30,7 +30,7 @@ * python-tkinter (optional, used by some experimental GUI stuff)
-You need to have at least python version `2.6.5 http://www.python.org/download/`_ +You need to have at least python version `2.7.2 http://www.python.org/download/`_ or newer installed on your computer to be able to run any of the code in this package, but not 3.0-3.3. It works fine with 3.4+ versions of python installed. Support for older versions of python is not planned. Some scripts could run with diff --git a/pywikibot/__init__.py b/pywikibot/__init__.py index 1264b64..cd3e18c 100644 --- a/pywikibot/__init__.py +++ b/pywikibot/__init__.py @@ -135,13 +135,6 @@ deprecate_arg = redirect_func(_deprecate_arg)
-if sys.version_info[:2] == (2, 6): - warn( - 'Pywikibot will soon drop support for Python 2.6', - DeprecationWarning, - ) - - class Timestamp(datetime.datetime):
"""Class for handling MediaWiki timestamps. diff --git a/pywikibot/backports.py b/pywikibot/backports.py index 86c8de7..52a711e 100644 --- a/pywikibot/backports.py +++ b/pywikibot/backports.py @@ -1,169 +1,48 @@ # -*- coding: utf-8 -*- """ -This module contains backports to support older Python versions. +This module contained backports to support older Python versions.
-They contain the backported code originally developed for Python. It is -therefore distributed under the PSF license. +Their usage is deprecated and this module could be dropped soon. """ # -# (C) Python Software Foundation, 2001-2014 -# (C) with modifications from Pywikibot team, 2015 +# (C) Pywikibot team, 2015-2018 # -# Distributed under the terms of the PSF license. +# Distributed under the terms of the MIT license. #
from __future__ import absolute_import, unicode_literals
-__license__ = """ -PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2 --------------------------------------------- -1. This LICENSE AGREEMENT is between the Python Software Foundation -("PSF"), and the Individual or Organization ("Licensee") accessing and -otherwise using this software ("Python") in source or binary form and -its associated documentation. - -2. Subject to the terms and conditions of this License Agreement, PSF hereby -grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, -analyze, test, perform and/or display publicly, prepare derivative works, -distribute, and otherwise use Python alone or in any derivative version, -provided, however, that PSF's License Agreement and PSF's notice of copyright, -i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, -2011, 2012, 2013, 2014 Python Software Foundation; All Rights Reserved" are -retained in Python alone or in any derivative version prepared by Licensee. - -3. In the event Licensee prepares a derivative work that is based on -or incorporates Python or any part thereof, and wants to make -the derivative work available to others as provided herein, then -Licensee hereby agrees to include in any such work a brief summary of -the changes made to Python. - -4. PSF is making Python available to Licensee on an "AS IS" -basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR -IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND -DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS -FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT -INFRINGE ANY THIRD PARTY RIGHTS. - -5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON -FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS -A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON, -OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. - -6. This License Agreement will automatically terminate upon a material -breach of its terms and conditions. - -7. Nothing in this License Agreement shall be deemed to create any -relationship of agency, partnership, or joint venture between PSF and -Licensee. This License Agreement does not grant permission to use PSF -trademarks or trade name in a trademark sense to endorse or promote -products or services of Licensee, or any third party. - -8. By copying, installing or otherwise using Python, Licensee -agrees to be bound by the terms and conditions of this License -Agreement. -""" - +from difflib import _format_range_unified import logging -import warnings + +from pywikibot.tools import deprecated
+@deprecated('difflib._format_range_unified') def format_range_unified(start, stop): """ Convert range to the "ed" format.
- Copied from C{difflib._format_range_unified()} which was introduced in - Python 2.7.2. - - @see: https://hg.python.org/cpython/file/8527427914a2/Lib/difflib.py#l1147 + DEPRECATED (Python 2.6 backport). + Use difflib._format_range_unified instead. """ - # Per the diff spec at http://www.unix.org/single_unix_specification/ - beginning = start + 1 # lines start numbering with one - length = stop - start - if length == 1: - return '{0}'.format(beginning) - if not length: - beginning -= 1 # empty ranges begin at line just before the range - return '{0},{1}'.format(beginning, length) + return _format_range_unified(start, stop)
-# Logging/Warnings integration +@deprecated('logging.NullHandler') +class NullHandler(logging.NullHandler):
-_warnings_showwarning = None + """This handler does nothing.""" + + pass
-class NullHandler(logging.Handler): - - """ - This handler does nothing. - - It's intended to be used to avoid the "No handlers could be found for - logger XXX" one-off warning. This is important for library code, which - may contain code to log events. If a user of the library does not configure - logging, the one-off warning might be produced; to avoid this, the library - developer simply needs to instantiate a NullHandler and add it to the - top-level logger of the library module or package. - - Copied from C{logging.NullHandler} which was introduced in Python 2.7. - - @see: http://bugs.python.org/issue4384 - """ - - def handle(self, record): - """Dummy handling.""" - pass - - def emit(self, record): - """Dummy handling.""" - pass - - def createLock(self): - """Dummy handling.""" - self.lock = None - - -def _showwarning(message, category, filename, lineno, file=None, line=None): - """ - Implementation of showwarnings which redirects to logging. - - It will first check to see if the file parameter is None. If a file is - specified, it will delegate to the original warnings implementation of - showwarning. Otherwise, it will call warnings.formatwarning and will log - the resulting string to a warnings logger named "py.warnings" with level - logging.WARNING. - - Copied from C{logging._showwarning} which was introduced in Python 2.7. - - @see: http://bugs.python.org/issue4384 - """ - if file is not None: - if _warnings_showwarning is not None: - _warnings_showwarning(message, category, filename, lineno, file, line) - else: - s = warnings.formatwarning(message, category, filename, lineno, line) - logger = logging.getLogger("py.warnings") - if not logger.handlers: - logger.addHandler(NullHandler()) - logger.warning("%s", s) - - +@deprecated('logging.captureWarnings') def captureWarnings(capture): """ Capture warnings into logging.
- If capture is true, redirect all warnings to the logging package. - If capture is False, ensure that warnings are not redirected to logging - but to their original destinations. - - Copied from C{logging.captureWarnings} which was introduced in Python 2.7. - - @see: http://bugs.python.org/issue4384 + DEPRECATED (Python 2.6 backport). + Use logging.captureWarnings instead. """ - global _warnings_showwarning - if capture: - if _warnings_showwarning is None: - _warnings_showwarning = warnings.showwarning - warnings.showwarning = _showwarning - else: - if _warnings_showwarning is not None: - warnings.showwarning = _warnings_showwarning - _warnings_showwarning = None + logging.captureWarnings(capture) diff --git a/pywikibot/bot.py b/pywikibot/bot.py index 2c8f041..ceb9459 100644 --- a/pywikibot/bot.py +++ b/pywikibot/bot.py @@ -77,7 +77,6 @@
import pywikibot
-from pywikibot import backports from pywikibot import config from pywikibot import daemonize from pywikibot import i18n @@ -250,10 +249,7 @@
# If there are command line warnings options, do not override them if not sys.warnoptions: - if hasattr(logging, 'captureWarnings'): - logging.captureWarnings(True) # introduced in Python >= 2.7 - else: - backports.captureWarnings(True) + logging.captureWarnings(True)
if config.debug_log or 'deprecation' in config.log: warnings.filterwarnings("always") diff --git a/pywikibot/diff.py b/pywikibot/diff.py index 636be64..95669e9 100644 --- a/pywikibot/diff.py +++ b/pywikibot/diff.py @@ -12,6 +12,7 @@ import sys
from collections import Sequence +from difflib import _format_range_unified as format_range_unified if sys.version_info[0] > 2: from itertools import zip_longest else: @@ -20,7 +21,6 @@ import pywikibot from pywikibot.tools import chars
-from pywikibot.backports import format_range_unified # introduced in 2.7.2 from pywikibot.tools import deprecated_args from pywikibot.tools.formatter import color_format
diff --git a/pywikibot/family.py b/pywikibot/family.py index d6524c7..632aff5 100644 --- a/pywikibot/family.py +++ b/pywikibot/family.py @@ -16,13 +16,12 @@
PY3 = sys.version_info[0] > 2 if PY3: - from os.path import basename, dirname, splitext - from importlib import import_module import urllib.parse as urlparse else: - import imp import urlparse
+from os.path import basename, dirname, splitext +from importlib import import_module from warnings import warn
import pywikibot @@ -959,12 +958,8 @@ # RuntimeWarning's while loading. with warnings.catch_warnings(): warnings.simplefilter("ignore", RuntimeWarning) - if PY3: - sys.path.append(dirname(family_file)) - mod = import_module(splitext(basename(family_file))[0]) - else: - # Python 2.6 has no importlib.import_module - mod = imp.load_source(fam, family_file) + sys.path.append(dirname(family_file)) + mod = import_module(splitext(basename(family_file))[0]) except ImportError: raise UnknownFamily(u'Family %s does not exist' % fam) cls = mod.Family() diff --git a/pywikibot/interwiki_graph.py b/pywikibot/interwiki_graph.py index bdad631..e14797b 100644 --- a/pywikibot/interwiki_graph.py +++ b/pywikibot/interwiki_graph.py @@ -1,12 +1,13 @@ # -*- coding: utf-8 -*- """Module with the Graphviz drawing calls.""" # -# (C) Pywikibot team, 2006-2016 +# (C) Pywikibot team, 2006-2018 # # Distributed under the terms of the MIT license. # from __future__ import absolute_import, unicode_literals
+from collections import Counter import itertools import threading
@@ -18,7 +19,6 @@ import pywikibot
from pywikibot import config2 as config -from pywikibot.tools import Counter
# deprecated value pydotfound = not isinstance(pydot, ImportError) diff --git a/pywikibot/page.py b/pywikibot/page.py index bf836c2..fa29cf4 100644 --- a/pywikibot/page.py +++ b/pywikibot/page.py @@ -29,7 +29,7 @@ except ImportError: import unicodedata
-from collections import defaultdict, namedtuple +from collections import Counter, defaultdict, namedtuple, OrderedDict from warnings import warn
from pywikibot.tools import PY2 @@ -65,13 +65,11 @@ from pywikibot.site import DataSite, Namespace, need_version from pywikibot.tools import ( compute_file_hash, - PYTHON_VERSION, MediaWikiVersion, UnicodeMixin, ComparableMixin, DotReadableDict, deprecated, deprecate_arg, deprecated_args, issue_deprecation_warning, add_full_name, manage_wrapping, ModuleDeprecationWrapper as _ModuleDeprecationWrapper, first_upper, redirect_func, remove_last_args, _NotImplementedWarning, - OrderedDict, Counter, ) from pywikibot.tools.ip import ip_regexp from pywikibot.tools.ip import is_IP @@ -5421,9 +5419,6 @@ @type defaultNamespace: int
@raises UnicodeError: text could not be converted to unicode. - On Python 2.6.6 without unicodedata2, this could also be raised - if the text contains combining characters. - See https://phabricator.wikimedia.org/T102461 """ source_is_page = isinstance(source, BasePage)
@@ -5460,16 +5455,6 @@
# Normalize unicode string to a NFC (composed) format to allow # proper string comparisons to strings output from MediaWiki API. - # Due to Python issue 10254, this is not possible on Python 2.6.6 - # if the string contains combining characters. See T102461. - if (PYTHON_VERSION == (2, 6, 6) and - unicodedata.__name__ != 'unicodedata2' and - any(unicodedata.combining(c) for c in t)): - raise UnicodeError( - 'Link(%r, %s): combining characters detected, which are ' - 'not supported by Pywikibot on Python 2.6.6. See ' - 'https://phabricator.wikimedia.org/T102461' - % (t, self._source)) t = unicodedata.normalize('NFC', t)
# This code was adapted from Title.php : secureAndSplit() diff --git a/pywikibot/site_detect.py b/pywikibot/site_detect.py index 56c9b62..534c813 100644 --- a/pywikibot/site_detect.py +++ b/pywikibot/site_detect.py @@ -23,9 +23,9 @@ from html.parser import HTMLParser from urllib.parse import urljoin, urlparse else: - try: - from future.backports.html.parser import HTMLParser - except ImportError: + if PYTHON_VERSION == (2, 7, 2): + from future.backports.html.parser import HTMLParser # T175873 + else: from HTMLParser import HTMLParser from urlparse import urljoin, urlparse
diff --git a/pywikibot/textlib.py b/pywikibot/textlib.py index 2c2b26c..f959673 100644 --- a/pywikibot/textlib.py +++ b/pywikibot/textlib.py @@ -13,7 +13,7 @@ # from __future__ import absolute_import, unicode_literals
-import collections +from collections import OrderedDict, Sequence import datetime import re import sys @@ -39,7 +39,6 @@ deprecate_arg, deprecated, DeprecatedRegex, - OrderedDict, StringTypes, UnicodeType, issue_deprecation_warning @@ -645,7 +644,7 @@ title += '#' + l.section return title
- if isinstance(replace, collections.Sequence): + if isinstance(replace, Sequence): if len(replace) != 2: raise ValueError('When used as a sequence, the "replace" ' 'argument must contain exactly 2 items.') diff --git a/pywikibot/tools/__init__.py b/pywikibot/tools/__init__.py index 611a957..7438303 100644 --- a/pywikibot/tools/__init__.py +++ b/pywikibot/tools/__init__.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- """Miscellaneous helper functions (not wiki-dependent).""" # -# (C) Pywikibot team, 2008-2017 +# (C) Pywikibot team, 2008-2018 # # Distributed under the terms of the MIT license. # @@ -100,59 +100,6 @@ """Constructor.""" raise NotImplementedError( '%s: %s' % (self.__class__.__name__, self.__doc__)) - - -if PYTHON_VERSION < (2, 7): - try: - import future.backports.misc - except ImportError: - warn(""" -pywikibot support of Python 2.6 relies on package future for many features. -Please upgrade to Python 2.7+ or Python 3.4+, or run: - "pip install future>=0.15.0" -""", RuntimeWarning) - try: - from ordereddict import OrderedDict - except ImportError: - class OrderedDict(NotImplementedClass): - - """OrderedDict not found.""" - - pass - - try: - from counter import Counter - except ImportError: - class Counter(NotImplementedClass): - - """Counter not found.""" - - pass - count = None - else: - Counter = future.backports.misc.Counter - OrderedDict = future.backports.misc.OrderedDict - - try: - count = future.backports.misc.count - except AttributeError: - warn('Please update the "future" package to at least version ' - '0.15.0 to use its count.', RuntimeWarning, 2) - count = None - del future - - if count is None: - def count(start=0, step=1): - """Backported C{count} to support keyword arguments and step.""" - while True: - yield start - start += step - - -else: - Counter = collections.Counter - OrderedDict = collections.OrderedDict - count = itertools.count
def has_module(module): @@ -1536,7 +1483,7 @@ if wrapper.__signature__: # Build a new signature with deprecated args added. # __signature__ is only available in Python 3 which has OrderedDict - params = OrderedDict() + params = collections.OrderedDict() for param in wrapper.__signature__.parameters.values(): params[param.name] = param.replace() for old_arg, new_arg in arg_pairs.items(): @@ -1837,3 +1784,9 @@ bytes_to_read -= len(read_bytes) sha.update(read_bytes) return sha.hexdigest() + + +wrapper = ModuleDeprecationWrapper(__name__) +wrapper._add_deprecated_attr('Counter', collections.Counter) +wrapper._add_deprecated_attr('OrderedDict', collections.OrderedDict) +wrapper._add_deprecated_attr('count', itertools.count) diff --git a/pywikibot/tools/djvu.py b/pywikibot/tools/djvu.py index 4e919fe..c386410 100644 --- a/pywikibot/tools/djvu.py +++ b/pywikibot/tools/djvu.py @@ -2,12 +2,13 @@ # -*- coding: utf-8 -*- """Wrapper around djvulibre to access djvu files properties and content.""" # -# (C) Pywikibot team, 2015-2017 +# (C) Pywikibot team, 2015-2018 # # Distributed under the terms of the MIT license. # from __future__ import absolute_import, unicode_literals
+from collections import Counter import os import re import subprocess @@ -15,7 +16,6 @@ import pywikibot
from pywikibot.tools import ( - Counter, deprecated, deprecated_args, StringTypes, UnicodeType, diff --git a/requests-requirements.txt b/requests-requirements.txt index 651eabf..cf986cd 100644 --- a/requests-requirements.txt +++ b/requests-requirements.txt @@ -2,11 +2,8 @@
# requests security extra # Bug T105767 on Python 2.7 release 9+ -cryptography>=1.3.4 ; python_version != '2.6' and (python_full_version < '2.7.9' or python_version > '3.3') -cryptography>=1.3.4,<=2.0.3 ; python_version == '2.6' and platform_system == 'Windows' -cryptography>=1.3.4,<2.2 ; python_version == '2.6' and platform_system != 'Windows' -pyOpenSSL>=0.14,!=17.2.0 ; python_full_version < '2.7.9' and python_version != '2.6' -PyOpenSSL<17.5.0 ; python_version == '2.6' +cryptography>=1.3.4 ; python_full_version < '2.7.9' or python_version > '3.3' +pyOpenSSL>=0.14,!=17.2.0 ; python_full_version < '2.7.9' idna>=2.0.0 ; python_full_version < '2.7.9' or python_version >= '3' # https://github.com/eliben/pycparser/issues/147 pycparser != 2.14 diff --git a/requirements.txt b/requirements.txt index f3c051f..ffd1dba 100644 --- a/requirements.txt +++ b/requirements.txt @@ -22,11 +22,9 @@ requests>=2.9,!=2.18.2
# requests security extra -cryptography>=1.3.4 ; python_version != '2.6' and python_full_version < '2.7.9' -cryptography>=1.3.4,<=2.0.3 ; python_version == '2.6' and platform_system == 'Windows' -cryptography>=1.3.4,<2.2 ; python_version == '2.6' and platform_system != 'Windows' -pyOpenSSL>=0.14,!=17.2.0 ; python_full_version < '2.7.9' and python_version != '2.6' -PyOpenSSL<17.5.0 ; python_version == '2.6' +cryptography>=1.3.4 ; python_full_version < '2.7.9' +pyOpenSSL>=0.14,!=17.2.0 ; python_full_version < '2.7.9' + idna>=2.0.0 ; python_full_version < '2.7.9' # https://github.com/eliben/pycparser/issues/147 pycparser != 2.14 @@ -46,15 +44,13 @@ git+https://github.com/nlhepler/pydot#egg=pydot-1.0.29
# wikistats.py and scripts -unicodecsv!=0.14.0 ; python_version < '2.7' -unicodecsv ; python_version < '3' and python_version >= '2.7' +unicodecsv ; python_version < '3'
# cosmetic_changes and scripts/isbn python-stdnum
# GUI -Pillow<4.0.0 ; python_version == '2.6' -Pillow ; python_version == '2.7' or python_version >= '3.4' +Pillow
# core pagegenerators google >= 1.7 @@ -63,21 +59,11 @@ # scripts/script_wui.py: crontab
-# scipts/replicate_wiki.py and scripts/editarticle.py -argparse ; python_version < '2.7' - # scripts/flickrripper.py -# On Python 2, flickrapi 1.4.x or 2.x may be used. Only 2.x works on Python 3. -# The following automatically selects 2.x on all Python versions, which depends -# on requests 2.x, which may cause pip to report an error like the following: -# pkg_resources.VersionConflict: (requests 1.2.3 (/usr/lib/python2.7/site-packages), Requirement.parse('requests>=2.2.1')) -# If you see that on Python 2, change this to flickrapi==1.4.5 -# On Python 3, force pip to install requests 2.2.1, or remove flickrapi below. -flickrapi>=1.4.5,<2 ; python_version < '2.7' -flickrapi ; python_version >= '2.7' +flickrapi
# incomplete core component botirc -irc ; python_version > '2.6' +irc
# textlib.py and patrol.py mwparserfromhell>=0.3.3 diff --git a/setup.py b/setup.py index 1b2ccce..90d1649 100644 --- a/setup.py +++ b/setup.py @@ -23,22 +23,19 @@
PYTHON_VERSION = sys.version_info[:3] PY2 = (PYTHON_VERSION[0] == 2) -PY26 = (PYTHON_VERSION < (2, 7))
versions_required_message = """ Pywikibot is not available on: {version}
-This version of Pywikibot only supports Python 2.6.5+, 2.7.2+ or 3.4+. +This version of Pywikibot only supports Python 2.7.2+ or 3.4+. """
def python_is_supported(): """Check that Python is supported.""" # Any change to this must be copied to pwb.py - return (PYTHON_VERSION >= (3, 4, 0) or - (PY2 and PYTHON_VERSION >= (2, 7, 2)) or - (PY26 and PYTHON_VERSION >= (2, 6, 5))) + return PYTHON_VERSION >= (3, 4, 0) or PY2 and PYTHON_VERSION >= (2, 7, 2)
if not python_is_supported(): @@ -48,25 +45,15 @@
dependencies = ['requests>=2.9,!=2.18.2']
-# the irc module has no Python 2.6 support since 10.0 -irc_dep = 'irc==8.9' if sys.version_info < (2, 7) else 'irc' -csv_dep = 'unicodecsv!=0.14.0' if PYTHON_VERSION < (2, 7) else 'unicodecsv' - -# According to https://pillow.readthedocs.io/en/latest/installation.html#notes -if PY26: - pillow = 'Pillow<4.0.0' -else: - pillow = 'Pillow' - extra_deps = { # Core library dependencies 'eventstreams': ['sseclient>=0.0.18'], 'isbn': ['python-stdnum'], 'Graphviz': ['pydot>=1.0.28'], 'Google': ['google>=1.7'], - 'IRC': [irc_dep], + 'IRC': ['irc'], 'mwparserfromhell': ['mwparserfromhell>=0.3.3'], - 'Tkinter': [pillow], + 'Tkinter': ['Pillow'], 'security': ['requests[security]', 'pycparser!=2.14'], 'mwoauth': ['mwoauth>=0.2.4,!=0.3.1'], 'html': ['BeautifulSoup4'], @@ -75,31 +62,21 @@ if PY2: # Additional core library dependencies which are only available on Python 2 extra_deps.update({ - 'csv': [csv_dep], + 'csv': ['unicodecsv'], 'MySQL': ['oursql'], 'unicode7': ['unicodedata2>=7.0.0-2'], })
script_deps = { - 'flickrripper.py': [pillow], + 'flickrripper.py': ['flickrapi', 'Pillow'], 'states_redirect.py': ['pycountry'], 'weblinkchecker.py': ['memento_client>=0.5.1,!=0.6.0'], 'patrol.py': ['mwparserfromhell>=0.3.3'], } -# flickrapi 1.4.4 installs a root logger in verbose mode; 1.4.5 fixes this. -# The problem doesnt exist in flickrapi 2.x. -# pywikibot accepts flickrapi 1.4.5+ on Python 2, as it has been stable for a -# long time, and only depends on python-requests 1.x, whereas flickrapi 2.x -# depends on python-requests 2.x, which is first packaged in Ubuntu 14.04 -# and will be first packaged for Fedora Core 21. -# flickrapi 1.4.x does not run on Python 3, and setuptools can only -# select flickrapi 2.x for Python 3 installs. -script_deps['flickrripper.py'].append( - 'flickrapi>=1.4.5,<2' if PY26 else 'flickrapi')
# lunatic-python is only available for Linux if sys.platform.startswith('linux'): - script_deps['script_wui.py'] = [irc_dep, 'lunatic-python', 'crontab'] + script_deps['script_wui.py'] = ['irc', 'lunatic-python', 'crontab']
# The main pywin32 repository contains a Python 2 only setup.py with a small # wrapper setup3.py for Python 3. @@ -113,7 +90,7 @@ 'git+https://github.com/nlhepler/pydot#egg=pydot-1.0.29', ]
-if PYTHON_VERSION < (2, 7, 3): +if PYTHON_VERSION == (2, 7, 2): # work around distutils hardcoded unittest dependency # work around T106512 import unittest @@ -123,12 +100,6 @@ sys.modules['unittest'] = unittest2
if sys.version_info[0] == 2: - if PY26: - script_deps['replicate_wiki.py'] = ['argparse'] - dependencies.append('future>=0.15.0') # provides collections backports - - dependencies += extra_deps['unicode7'] # T102461 workaround - # tools.ip does not have a hard dependency on an IP address module, # as it falls back to using regexes if one is not available. # The functional backport of py3 ipaddress is acceptable: @@ -139,7 +110,7 @@ # ipaddr 2.1.10+ is distributed with Debian and Fedora. See T105443. dependencies.append('ipaddr>=2.1.10')
- if sys.version_info < (2, 7, 3): + if sys.version_info == (2, 7, 2): dependencies.append('future>=0.15.0') # Bug fixes for HTMLParser
if sys.version_info < (2, 7, 9): @@ -257,7 +228,6 @@ 'License :: OSI Approved :: MIT License', 'Natural Language :: English', 'Operating System :: OS Independent', - 'Programming Language :: Python :: 2.6', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', diff --git a/tests/__init__.py b/tests/__init__.py index f548ec6..75404a3 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- """Package tests.""" # -# (C) Pywikibot team, 2007-2015 +# (C) Pywikibot team, 2007-2018 # # Distributed under the terms of the MIT license. # @@ -16,7 +16,6 @@
# Verify that the unit tests have a base working environment: # - requests is mandatory -# - future is needed as a fallback for python 2.6, # however if unavailable this will fail on use; see pywikibot/tools.py # - unittest2; see below # - mwparserfromhell is optional, so is only imported in textlib_tests @@ -24,9 +23,8 @@
from pywikibot.tools import PYTHON_VERSION
-if PYTHON_VERSION < (2, 7, 3): - # unittest2 is a backport of python 2.7s unittest module to python 2.6 - # Also use unittest2 for python 2.7.2 (T106512) +if PYTHON_VERSION == (2, 7, 2): + # Use unittest2 for python 2.7.2 (T106512) import unittest2 as unittest else: import unittest diff --git a/tests/link_tests.py b/tests/link_tests.py index 5b661b5..0fcfcc3 100644 --- a/tests/link_tests.py +++ b/tests/link_tests.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- """Test Link functionality.""" # -# (C) Pywikibot team, 2014-2017 +# (C) Pywikibot team, 2014-2018 # # Distributed under the terms of the MIT license. # @@ -14,7 +14,6 @@ from pywikibot import config2 as config from pywikibot.page import Link, Page from pywikibot.exceptions import Error, InvalidTitle -from pywikibot.tools import PYTHON_VERSION
from tests.aspects import ( unittest, @@ -240,19 +239,6 @@ title = 'Li̍t-sṳ́' link = Link(title, self.site) self.assertEqual(link.title, 'Li̍t-sṳ́') - - @unittest.skipIf(PYTHON_VERSION != (2, 6, 6), 'Python 2.6.6-only test') - def test_py266_bug_exception(self): - """Test Python issue 10254 causes an exception.""" - pywikibot.page.unicodedata = __import__('unicodedata') - title = 'Li̍t-sṳ́' - with self.assertRaisesRegex( - UnicodeError, - re.escape('Link(%r, %s): combining characters detected, which ' - 'are not supported by Pywikibot on Python 2.6.6. ' - 'See https://phabricator.wikimedia.org/T102461' - % (title, self.site))): - Link(title, self.site)
# ---- The first set of tests are explicit links, starting with a ':'. diff --git a/tests/python_tests.py b/tests/python_tests.py index 0320f8e..6dcbd9f 100755 --- a/tests/python_tests.py +++ b/tests/python_tests.py @@ -2,7 +2,7 @@ # -*- coding: utf-8 -*- """Tests Python features.""" # -# (C) Pywikibot team, 2015 +# (C) Pywikibot team, 2015-2018 # # Distributed under the terms of the MIT license. from __future__ import absolute_import, unicode_literals @@ -13,15 +13,9 @@ except ImportError: unicodedata2 = None
-from pywikibot.tools import PYTHON_VERSION - from tests.aspects import TestCase, unittest -from tests.utils import expected_failure_if
# TODO: -# very old -# http://bugs.python.org/issue2517 -# # unicode # http://sourceforge.net/p/pywikipediabot/bugs/1246/ # http://bugs.python.org/issue10254 @@ -37,7 +31,6 @@ # http://sourceforge.net/p/pywikipediabot/bugs/509/ # https://phabricator.wikimedia.org/T57329 # http://bugs.python.org/issue1528074 -# http://bugs.python.org/issue1678345
class PythonTestCase(TestCase): @@ -46,11 +39,9 @@
net = False
- @expected_failure_if((2, 7, 0) <= PYTHON_VERSION < (2, 7, 2) or - PYTHON_VERSION == (2, 6, 6)) def test_issue_10254(self): """Test Python issue #10254.""" - # Python 2.6.6, 2.7.0 and 2.7.1 have a bug in this routine. + # Python 2.7.0 and 2.7.1 have a bug in this routine. # See T102461 and http://bugs.python.org/issue10254 text = 'Li̍t-sṳ́' self.assertEqual(text, unicodedata.normalize('NFC', text)) diff --git a/tests/script_tests.py b/tests/script_tests.py index 647d31e..d542f92 100644 --- a/tests/script_tests.py +++ b/tests/script_tests.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- """Test that each script can be compiled and executed.""" # -# (C) Pywikibot team, 2014-2017 +# (C) Pywikibot team, 2014-2018 # # Distributed under the terms of the MIT license. # @@ -12,7 +12,6 @@
from pywikibot.tools import ( PY2, - PYTHON_VERSION, StringTypes, )
@@ -39,10 +38,6 @@ 'states_redirect': ['pycountry'], 'patrol': ['mwparserfromhell'], } - -if PYTHON_VERSION < (2, 7): - script_deps['replicate_wiki'] = ['argparse'] - script_deps['editarticle'] = ['argparse']
if PY2: script_deps['data_ingestion'] = ['unicodecsv'] diff --git a/tests/textlib_tests.py b/tests/textlib_tests.py index ca49ada..49855fd 100644 --- a/tests/textlib_tests.py +++ b/tests/textlib_tests.py @@ -8,6 +8,7 @@ from __future__ import absolute_import, unicode_literals
import codecs +from collections import OrderedDict import functools import os import re @@ -18,7 +19,7 @@
from pywikibot import config, UnknownSite from pywikibot.site import _IWEntry -from pywikibot.tools import OrderedDict, suppress_warnings +from pywikibot.tools import suppress_warnings
from tests.aspects import ( unittest, require_modules, TestCase, DefaultDrySiteTestCase, diff --git a/tests/tools_tests.py b/tests/tools_tests.py index 16d8430..0e1aa04 100644 --- a/tests/tools_tests.py +++ b/tests/tools_tests.py @@ -2,7 +2,7 @@ # -*- coding: utf-8 -*- """Test tools package alone which don't fit into other tests.""" # -# (C) Pywikibot team, 2016-2017 +# (C) Pywikibot team, 2016-2018 # # Distributed under the terms of the MIT license. from __future__ import absolute_import, unicode_literals @@ -452,7 +452,7 @@ self.assertEqual(next(deduper), 3)
if key in (hash, passthrough): - if isinstance(deduped, tools.OrderedDict): + if isinstance(deduped, collections.OrderedDict): self.assertEqual(list(deduped.keys()), [1, 3]) elif isinstance(deduped, collections.Mapping): self.assertCountEqual(list(deduped.keys()), [1, 3]) @@ -463,7 +463,7 @@ self.assertEqual(next(deduper), 4)
if key in (hash, passthrough): - if isinstance(deduped, tools.OrderedDict): + if isinstance(deduped, collections.OrderedDict): self.assertEqual(list(deduped.keys()), [1, 3, 2, 4]) elif isinstance(deduped, collections.Mapping): self.assertCountEqual(list(deduped.keys()), [1, 2, 3, 4]) @@ -513,7 +513,7 @@
def test_OrderedDict(self): """Test filter_unique with a OrderedDict.""" - deduped = tools.OrderedDict() + deduped = collections.OrderedDict() deduper = tools.filter_unique(self.ints, container=deduped) self._test_dedup_int(deduped, deduper)
diff --git a/tests/utils.py b/tests/utils.py index 43d883e..4fe6414 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -45,9 +45,6 @@
OSWIN32 = (sys.platform == 'win32')
-PYTHON_26_CRYPTO_WARN = ('Python 2.6 is no longer supported by the Python core ' - 'team, please upgrade your Python.') -
class DrySiteNote(RuntimeWarning):
@@ -638,27 +635,12 @@ """ Execute a command and capture outputs.
- On Python 2.6 it adds an option to ignore the deprecation warning from - the cryptography package after the first entry of the command parameter. - @param command: executable to run and arguments to use @type command: list of unicode """ - if PYTHON_VERSION < (2, 7): - command.insert( - 1, '-W ignore:{0}:DeprecationWarning'.format(PYTHON_26_CRYPTO_WARN)) - if PYTHON_VERSION[:2] == (2, 6): - command.insert(1, '-W ignore:{0}:DeprecationWarning'.format( - 'Pywikibot will soon drop support for Python 2.6')) # Any environment variables added on Windows must be of type # str() on Python 2. env = os.environ.copy() - - # Python issue 6906 - if PYTHON_VERSION < (2, 6, 6): - for var in ('TK_LIBRARY', 'TCL_LIBRARY', 'TIX_LIBRARY'): - if var in env: - env[var] = env[var].encode('mbcs')
# Prevent output by test package; e.g. 'max_retries reduced from x to y' env[str('PYWIKIBOT_TEST_QUIET')] = str('1') diff --git a/tox.ini b/tox.ini index c42d245..c53553a 100644 --- a/tox.ini +++ b/tox.ini @@ -3,12 +3,11 @@ minversion = 1.7.2 skipsdist = True skip_missing_interpreters = True -envlist = diff-checker,commit-message,flake8,pyflakes-{py26,py3,pypy},doctest-{py27,py34},py26,py27,py34 +envlist = diff-checker,commit-message,flake8,pyflakes-{py27,py3,pypy},doctest-{py27,py34},py27,py34
[tox:jenkins] # Override default for WM Jenkins # Others are run in their own individual jobs on WM Jenkins -# Wikimedia Jenkins does not have Python 2.6 envlist = diff-checker,commit-message,flake8,pyflakes-{py3,pypy}
[params] @@ -29,12 +28,9 @@ deps = commit-message-validator commands = commit-message-validator
-[testenv:py26] -deps = unittest2 - -[testenv:pyflakes-py26] +[testenv:pyflakes-py27] commands = findx . -name '*.py' -a '!' -path '*/.*' -a '!' -name 'user-config.py' : pyflakes -basepython = python2.6 +basepython = python2.7 deps = pyflakes findx >= 0.9.9 @@ -170,7 +166,7 @@
ignore = C401,C402,C405,E402,D105,D211,FI10,FI12,FI13,FI15,FI16,FI17,FI5,H101,H236,H301,H404,H405,H903,I100,I101,I202,N802,N803,N806,D401,D413,D103,D412,W503 exclude = .tox,.git,./*.egg,ez_setup.py,build,externals,user-config.py,./scripts/i18n/*,scripts/userscripts/* -min-version = 2.6 +min-version = 2.7 max_line_length = 100 accept-encodings = utf-8 require-code = true