From 283634605b9622e79dcdc3ab3833fe2788ba880d Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Fri, 10 Apr 2020 16:57:07 +0200 Subject: [PATCH] Drops Python 2 support --- ci/docker/Dockerfile.archlinux.py2 | 43 -------------------------- ci/docker/Dockerfile.bionic.py2 | 40 ------------------------ ci/docker/Dockerfile.fedora28.py2 | 39 ----------------------- ci/docker_build.sh | 29 +++++------------ ci/docker_run.sh | 13 ++------ ci/entrypoint.sh | 7 ++--- ci/win_set_python.bat | 8 +---- ci/win_style.bat | 2 +- examples/compass/buildozer.spec | 2 +- examples/notification/main.py | 4 --- plyer/compat.py | 37 ---------------------- plyer/facades/audio.py | 5 +-- plyer/platforms/win/libs/balloontip.py | 3 -- plyer/platforms/win/libs/wifi_defs.py | 13 +++----- plyer/tests/test_battery.py | 8 ++--- plyer/tests/test_cpu.py | 9 ++---- plyer/tests/test_facade.py | 8 ++--- plyer/tests/test_screenshot.py | 5 --- 18 files changed, 27 insertions(+), 248 deletions(-) delete mode 100644 ci/docker/Dockerfile.archlinux.py2 delete mode 100644 ci/docker/Dockerfile.bionic.py2 delete mode 100644 ci/docker/Dockerfile.fedora28.py2 delete mode 100644 plyer/compat.py diff --git a/ci/docker/Dockerfile.archlinux.py2 b/ci/docker/Dockerfile.archlinux.py2 deleted file mode 100644 index 621924134..000000000 --- a/ci/docker/Dockerfile.archlinux.py2 +++ /dev/null @@ -1,43 +0,0 @@ -FROM base/archlinux - -ENV APP_DIR=/app -RUN mkdir $APP_DIR -WORKDIR $APP_DIR - -# install default packages -RUN pacman -Fy && \ - pacman -Sy && \ - yes |pacman -Sy \ - gcc \ - python2 \ - jdk-openjdk \ - lshw \ - wget \ - apparmor \ - xdg-user-dirs \ - && yes |pacman -Rns $(pacman -Qtdq) ||true \ - && yes |pacman -Sc - -# generate user folder locations (Pictures, Downloads, ...) -RUN xdg-user-dirs-update - -# install PIP -RUN wget https://bootstrap.pypa.io/get-pip.py -O get-pip.py -RUN python2 -V && \ - python2 get-pip.py && \ - rm get-pip.py && \ - python2 -m pip install --upgrade pip - - -# install dev packages -COPY devrequirements.txt . -RUN python2 -m pip install \ - --upgrade \ - --requirement devrequirements.txt -RUN python2 -m pip install pyjnius - -COPY . $APP_DIR -COPY ./ci/entrypoint.sh $APP_DIR -RUN python2 -m pip install . -ENV PYTHON=/usr/bin/python2 -ENTRYPOINT ["/app/entrypoint.sh", "env"] diff --git a/ci/docker/Dockerfile.bionic.py2 b/ci/docker/Dockerfile.bionic.py2 deleted file mode 100644 index 0299ebee7..000000000 --- a/ci/docker/Dockerfile.bionic.py2 +++ /dev/null @@ -1,40 +0,0 @@ -FROM ubuntu:bionic-20180821 - -ENV APP_DIR=/app -RUN mkdir $APP_DIR -WORKDIR $APP_DIR - -# install default packages -RUN apt-get update && \ - apt-get -y --force-yes install \ - build-essential \ - python-setuptools \ - python-dev \ - openjdk-8-jdk \ - lshw \ - wget \ - git \ - && apt-get -y autoremove \ - && apt-get -y clean - -# generate user folder locations (Pictures, Downloads, ...) -RUN xdg-user-dirs-update - -# install PIP -RUN wget https://bootstrap.pypa.io/2.6/get-pip.py -O get-pip2.py -RUN python -V && \ - python get-pip2.py && \ - rm get-pip2.py && \ - python -m pip install --upgrade pip - -# install dev packages -COPY devrequirements.txt . -RUN python -m pip install \ - --upgrade \ - --requirement devrequirements.txt -RUN python -m pip install pyjnius - -COPY . $APP_DIR -COPY ./ci/entrypoint.sh $APP_DIR -RUN python -m pip install . -ENTRYPOINT ["/app/entrypoint.sh", "py2"] diff --git a/ci/docker/Dockerfile.fedora28.py2 b/ci/docker/Dockerfile.fedora28.py2 deleted file mode 100644 index 94b7a50f3..000000000 --- a/ci/docker/Dockerfile.fedora28.py2 +++ /dev/null @@ -1,39 +0,0 @@ -FROM fedora:28 - -ENV APP_DIR=/app -RUN mkdir $APP_DIR -WORKDIR $APP_DIR - -# install default packages -# redhat-rpm-config: https://stackoverflow.com/a/34641068/5994041 -RUN yum -y install \ - gcc \ - python \ - python-devel \ - java-1.8.0-openjdk \ - java-1.8.0-openjdk-devel \ - lshw \ - wget \ - xdg-user-dirs \ - redhat-rpm-config \ - && yum -y autoremove \ - && yum clean all - -# generate user folder locations (Pictures, Downloads, ...) -RUN xdg-user-dirs-update - -# install PIP -RUN python -V && \ - python -m pip install --upgrade pip - -# install dev packages -COPY devrequirements.txt . -RUN python -m pip install \ - --upgrade \ - --requirement devrequirements.txt -RUN python -m pip install pyjnius - -COPY . $APP_DIR -COPY ./ci/entrypoint.sh $APP_DIR -RUN python -m pip install . -ENTRYPOINT ["/app/entrypoint.sh", "py2"] diff --git a/ci/docker_build.sh b/ci/docker_build.sh index e68ffaa92..2fb37e841 100755 --- a/ci/docker_build.sh +++ b/ci/docker_build.sh @@ -3,30 +3,17 @@ # build docker images from Travis matrix if [ "$TRAVIS_OS_NAME" = "linux" ] && [ "$DOCK" = "1" ] then + docker build \ + --tag plyer:py3 \ + --file ci/docker/Dockerfile.$IMAGE.py3 \ + "$(pwd)" - # separate images for Python 2 - if [ "$PY" = "2" ] + # style image that inherits layers from Python 3 image + if [ "$RUN" = "style" ] then docker build \ - --tag plyer:py2 \ - --file ci/docker/Dockerfile.$IMAGE.py2 \ + --tag plyer:style \ + --file ci/docker/Dockerfile.$IMAGE.style \ "$(pwd)" - - # separate images for Python 3 - elif [ "$PY" = "3" ] - then - docker build \ - --tag plyer:py3 \ - --file ci/docker/Dockerfile.$IMAGE.py3 \ - "$(pwd)" - - # style image that inherits layers from Python 3 image - if [ "$RUN" = "style" ] - then - docker build \ - --tag plyer:style \ - --file ci/docker/Dockerfile.$IMAGE.style \ - "$(pwd)" - fi fi fi diff --git a/ci/docker_run.sh b/ci/docker_run.sh index f622f45ae..bb5c9871a 100755 --- a/ci/docker_run.sh +++ b/ci/docker_run.sh @@ -3,16 +3,7 @@ if [ "$TRAVIS_OS_NAME" = "linux" ] && [ "$DOCK" = "1" ] then - # run tests for Plyer in Python 2 - if [ "$PY" = "2" ] && [ "$RUN" = "unit" ] - then - docker run \ - --interactive \ - --tty \ - plyer:py2 - - # run tests for Plyer in Python 3 - elif [ "$PY" = "3" ] && [ "$RUN" = "unit" ] + if [ "$RUN" = "unit" ] then # running coverage report (COVERALLS=1) @@ -41,7 +32,7 @@ then plyer:py3 fi - elif [ "$PY" = "3" ] && [ "$RUN" = "style" ] + elif [ "$RUN" = "style" ] then docker run \ --interactive \ diff --git a/ci/entrypoint.sh b/ci/entrypoint.sh index 9cd1f7cff..10c0c5307 100755 --- a/ci/entrypoint.sh +++ b/ci/entrypoint.sh @@ -1,10 +1,7 @@ #!/bin/sh set -vex -if [ "$1" = "py2" ] -then - PYTHON=$(which python) -elif [ "$1" = "py3" ] || [ "$1" = "pep8" ] +if [ "$1" = "py3" ] || [ "$1" = "pep8" ] then PYTHON=$(which python3.6) elif [ "$1" = "env" ] @@ -20,7 +17,7 @@ $PYTHON -V if [ "$2" = "style" ] then $PYTHON -m pycodestyle "$(pwd)" \ - --exclude=pep8.py,compat.py,utils.py \ + --exclude=pep8.py,utils.py \ --ignore=E402,W503 touch "$(pwd)/__init__.py" $PYTHON -m pylint \ diff --git a/ci/win_set_python.bat b/ci/win_set_python.bat index 52c99ca52..24627fa6f 100644 --- a/ci/win_set_python.bat +++ b/ci/win_set_python.bat @@ -1,11 +1,5 @@ @echo off -:: choose between Python 2 or 3 from matrix -if "%PY%"=="27" ( - set PYTHON=C:\Python27\python.exe -) else ( - set PYTHON=C:\Python36\python.exe -) - +set PYTHON=C:\Python36\python.exe :: cd to Plyer folder and set PYTHONPATH cd C:\projects\app set PYTHONPATH=%PYTHONPATH%;%cd% diff --git a/ci/win_style.bat b/ci/win_style.bat index 819ad8075..b7aec4df6 100644 --- a/ci/win_style.bat +++ b/ci/win_style.bat @@ -1,7 +1,7 @@ @echo off if "%STYLE%"=="1" ( %PYTHON% -m pycodestyle "%cd%" ^ - --exclude=pep8.py,compat.py,utils.py ^ + --exclude=pep8.py,utils.py ^ --ignore=E402,W503 ^ && echo off > "%cd%\__init__.py" && echo on ^ && %PYTHON% -m pylint ^ diff --git a/examples/compass/buildozer.spec b/examples/compass/buildozer.spec index 031691823..f916be2b1 100644 --- a/examples/compass/buildozer.spec +++ b/examples/compass/buildozer.spec @@ -36,7 +36,7 @@ version = 0.1 # (list) Application requirements # comma seperated e.g. requirements = sqlite3,kivy -requirements = kivy,hostpython2 +requirements = kivy,hostpython3 # (str) Custom source folders for requirements # Sets custom source for any requirements with recipes diff --git a/examples/notification/main.py b/examples/notification/main.py index 9e7a379d6..be6e54675 100644 --- a/examples/notification/main.py +++ b/examples/notification/main.py @@ -6,7 +6,6 @@ from plyer import notification from plyer.utils import platform -from plyer.compat import PY2 kivy.require('1.8.0') @@ -17,9 +16,6 @@ def do_notify(self, mode='normal'): title = self.ids.notification_title.text message = self.ids.notification_text.text ticker = self.ids.ticker_text.text - if PY2: - title = title.decode('utf8') - message = message.decode('utf8') kwargs = {'title': title, 'message': message, 'ticker': ticker} if mode == 'fancy': diff --git a/plyer/compat.py b/plyer/compat.py deleted file mode 100644 index 6b024d0fe..000000000 --- a/plyer/compat.py +++ /dev/null @@ -1,37 +0,0 @@ -''' -Compatibility module for Python 2.7 and > 3.3 -============================================= -''' -# pylint: disable=invalid-name - -__all__ = ('PY2', 'string_types', 'queue', 'iterkeys', - 'itervalues', 'iteritems') - -import sys -try: - import queue -except ImportError: - import Queue as queue - -#: True if Python 2 intepreter is used -PY2 = sys.version_info[0] == 2 - -#: String types that can be used for checking if a object is a string -string_types = None -text_type = None -if PY2: - # pylint: disable=undefined-variable - # built-in actually, so it is defined in globals() for py2 - string_types = basestring # noqa F821 undefined name 'basestring' - text_type = unicode # noqa F821 undefined name 'unicode' -else: - string_types = text_type = str - -if PY2: - def iterkeys(d): return d.iterkeys() - def itervalues(d): return d.itervalues() - def iteritems(d): return d.iteritems() -else: - def iterkeys(d): return iter(d.keys()) - def itervalues(d): return iter(d.values()) - def iteritems(d): return iter(d.items()) diff --git a/plyer/facades/audio.py b/plyer/facades/audio.py index 4b40954f5..707e2d6af 100644 --- a/plyer/facades/audio.py +++ b/plyer/facades/audio.py @@ -45,8 +45,6 @@ ''' -from plyer.compat import string_types, text_type - class Audio(object): ''' @@ -90,8 +88,7 @@ def file_path(self, location): ''' Location of the recording. ''' - assert isinstance(location, (string_types, text_type)), \ - 'Location must be string or unicode' + assert isinstance(location, str), 'Location must be string or unicode' self._file_path = location # private diff --git a/plyer/platforms/win/libs/balloontip.py b/plyer/platforms/win/libs/balloontip.py index 4cfab9034..0e92c17c2 100644 --- a/plyer/platforms/win/libs/balloontip.py +++ b/plyer/platforms/win/libs/balloontip.py @@ -11,7 +11,6 @@ import ctypes from threading import RLock -from plyer.compat import PY2 from plyer.platforms.win.libs import win_api_defs @@ -88,8 +87,6 @@ def __init__(self, title, message, app_name, app_icon='', wnd_class_ex = win_api_defs.get_WNDCLASSEXW() class_name = 'PlyerTaskbar' + str(WindowsBalloonTip._get_unique_id()) - if PY2: - class_name = class_name.decode('utf8') wnd_class_ex.lpszClassName = class_name # keep ref to it as long as window is alive diff --git a/plyer/platforms/win/libs/wifi_defs.py b/plyer/platforms/win/libs/wifi_defs.py index 9d58faf84..289982893 100644 --- a/plyer/platforms/win/libs/wifi_defs.py +++ b/plyer/platforms/win/libs/wifi_defs.py @@ -24,7 +24,6 @@ ) from ctypes.wintypes import DWORD, HANDLE, LPCWSTR, ULONG from sys import exit as sys_exit -from plyer.compat import PY2, xrange def customresize(array, new_size): @@ -57,7 +56,7 @@ class GUID(Structure): wlan_interface_state_associating, wlan_interface_state_discovering, wlan_interface_state_authenticating) = map(WLAN_INTERFACE_STATE, - xrange(0, 8)) + range(0, 8)) class WLAN_INTERFACE_INFO(Structure): @@ -92,7 +91,7 @@ class WLAN_INTERFACE_INFO_LIST(Structure): DOT11_BSS_TYPE = c_uint (dot11_BSS_type_infrastructure, dot11_BSS_type_independent, - dot11_BSS_type_any) = map(DOT11_BSS_TYPE, xrange(1, 4)) + dot11_BSS_type_any) = map(DOT11_BSS_TYPE, range(1, 4)) # The DOT11_PHY_TYPE enumeration defines an 802.11 PHY and media type. DOT11_PHY_TYPE = c_uint @@ -153,7 +152,7 @@ class DOT11_SSID(Structure): wlan_connection_mode_discovery_secure, wlan_connection_mode_discovery_unsecure, wlan_connection_mode_auto, - wlan_connection_mode_invalid) = map(WLAN_CONNECTION_MODE, xrange(0, 6)) + wlan_connection_mode_invalid) = map(WLAN_CONNECTION_MODE, range(0, 6)) class NDIS_OBJECT_HEADER(Structure): @@ -510,11 +509,7 @@ def _make_dict(): global _dict _dict = {} for network in available: - # if bytes, dict['name'] throws an error on py3 if not b'name' - if PY2: - _dict[unicode(network.dot11Ssid.SSID)] = network # noqa F821 undefined name 'unicode' - else: - _dict[network.dot11Ssid.SSID.decode('utf-8')] = network + _dict[network.dot11Ssid.SSID.decode('utf-8')] = network def _get_available_wifi(): diff --git a/plyer/tests/test_battery.py b/plyer/tests/test_battery.py index ec1cd3530..2f4288455 100644 --- a/plyer/tests/test_battery.py +++ b/plyer/tests/test_battery.py @@ -10,14 +10,12 @@ ''' from __future__ import unicode_literals -import sys import unittest from io import BytesIO from os.path import join from textwrap import dedent from mock import patch, Mock -from plyer.compat import text_type from plyer.tests.common import PlatformTest, platform_import @@ -132,7 +130,7 @@ class MockedUPower(object): u'History (rate)': u'1530958556 7,474 discharging' } - data = text_type( + data = str( ' native-path: {native-path}\n' ' vendor: {vendor}\n' ' model: {model}\n' @@ -348,9 +346,7 @@ def false(*args, **kwargs): ).instance() stub = Mock(return_value=sysclass.uevent) - py2_target = '__builtin__.open' - py3_target = 'builtins.open' - target = py3_target if sys.version_info.major == 3 else py2_target + target = 'builtins.open' with patch(target=target, new=stub): self.assertEqual( diff --git a/plyer/tests/test_cpu.py b/plyer/tests/test_cpu.py index 0cfc8b8f3..92fee4aa9 100644 --- a/plyer/tests/test_cpu.py +++ b/plyer/tests/test_cpu.py @@ -8,7 +8,6 @@ * Linux - nproc ''' -import sys import unittest from os import environ from os.path import join @@ -196,9 +195,7 @@ def test_cpu_linux_physical(self): ).instance() stub = MockedProcinfo - py2_target = '__builtin__.open' - py3_target = 'builtins.open' - target = py3_target if sys.version_info.major == 3 else py2_target + target = 'builtins.open' with patch(target=target, new=stub): sb = stub() @@ -231,9 +228,7 @@ def test_cpu_linux_cache(self): ).instance() stub = MockedKernelCPU - py2_target = '__builtin__.open' - py3_target = 'builtins.open' - target = py3_target if sys.version_info.major == 3 else py2_target + target = 'builtins.open' sub_target = 'plyer.platforms.linux.cpu.listdir' with patch(target=target, new=stub): diff --git a/plyer/tests/test_facade.py b/plyer/tests/test_facade.py index 035ec32b6..58d529efc 100644 --- a/plyer/tests/test_facade.py +++ b/plyer/tests/test_facade.py @@ -103,9 +103,8 @@ def test_facade_existing_platforms(self): ) proxy_cls = plyer.utils.Proxy - py2_target = '__builtin__.__import__' - py3_target = 'builtins.__import__' - target = py3_target if sys.version_info.major == 3 else py2_target + target = 'builtins.__import__' + with patch(target=target, return_value=stub_mod): dummy = proxy_cls('dummy', stub_mod) @@ -167,8 +166,7 @@ def _ensure_obj(inst): # (has to be checked on the go!) expected_bool = MockedProxy.expected_asserts.pop(0) call_count = sys.stderr.write.call_count - # 4 calls for py2, 6 calls for py3 with traceback.print_exc - assert (call_count in (4, 6)) == expected_bool, call_count + assert (call_count == 6) == expected_bool, call_count # return stderr to the original state sys.stderr = sys.__stderr__ diff --git a/plyer/tests/test_screenshot.py b/plyer/tests/test_screenshot.py index 5124d5cef..385269251 100644 --- a/plyer/tests/test_screenshot.py +++ b/plyer/tests/test_screenshot.py @@ -14,7 +14,6 @@ from os.path import join, expanduser, exists from mock import patch -from plyer.compat import PY2 from plyer.tests.common import PlatformTest, platform_import @@ -88,10 +87,6 @@ def test_screenshot_screencapture(self): ''' Test mocked MacOS screencapture for plyer.screenshot. ''' - if not PY2: - print('Can not run until PyOBJus works on Py3.') - return - scr = platform_import( platform='macosx', module_name='screenshot',