Drop support for legacy Python 2
This commit is contained in:
parent
5fded8398b
commit
07fac0628c
|
@ -15,12 +15,8 @@ env:
|
|||
|
||||
matrix:
|
||||
include:
|
||||
- python: 2.7
|
||||
env: TOXENV=py2lint
|
||||
- python: 2.7
|
||||
env: TOXENV=py27
|
||||
- python: 3.6
|
||||
env: TOXENV=py3lint
|
||||
env: TOXENV=lint
|
||||
- python: 3.7
|
||||
env: TOXENV=py37
|
||||
dist: xenial
|
||||
|
@ -33,13 +29,10 @@ matrix:
|
|||
env: TOXENV=py34
|
||||
- python: pypy3
|
||||
env: TOXENV=pypy3
|
||||
- python: pypy
|
||||
env: TOXENV=pypy
|
||||
- python: 3.8-dev
|
||||
env: TOXENV=py38dev
|
||||
dist: xenial
|
||||
allow_failures:
|
||||
- env: TOXENV=pypy
|
||||
- env: TOXENV=pypy3
|
||||
fast_finish: true
|
||||
|
||||
|
|
|
@ -9,6 +9,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
### Added
|
||||
- This changelog file ([#273])
|
||||
|
||||
### Removed
|
||||
|
||||
* Support for Python 2.7 ([#265])
|
||||
|
||||
## [2.4.0] - 2018-08-08
|
||||
### Deprecated
|
||||
|
|
12
README.md
12
README.md
|
@ -29,12 +29,12 @@ Or from requirements.txt:
|
|||
|
||||
Note:
|
||||
|
||||
* pylast >= 3.0.0 will likely only support Python 3.4+ ([#265](https://github.com/pylast/pylast/issues/265))
|
||||
* pyLast >= 2.2.0 supports Python 2.7.10+, 3.4, 3.5, 3.6, 3.7.
|
||||
* pyLast >= 2.0.0 < 2.2.0 supports Python 2.7.10+, 3.4, 3.5, 3.6.
|
||||
* pyLast >= 1.7.0 < 2.0.0 supports Python 2.7, 3.3, 3.4, 3.5, 3.6.
|
||||
* pyLast >= 1.0.0 < 1.7.0 supports Python 2.7, 3.3, 3.4.
|
||||
* pyLast >= 0.5 < 1.0.0 supports Python 2, 3.
|
||||
* pylast 3.0.0+ supports Python 3.4+ ([#265](https://github.com/pylast/pylast/issues/265))
|
||||
* pyLast 2.2.0 - 2.4.0 supports Python 2.7.10+, 3.4, 3.5, 3.6, 3.7.
|
||||
* pyLast 2.0.0 - 2.1.0 supports Python 2.7.10+, 3.4, 3.5, 3.6.
|
||||
* pyLast 1.7.0 - 1.9.0 supports Python 2.7, 3.3, 3.4, 3.5, 3.6.
|
||||
* pyLast 1.0.0 - 1.6.0 supports Python 2.7, 3.3, 3.4.
|
||||
* pyLast 0.5 supports Python 2, 3.
|
||||
* pyLast < 0.5 supports Python 2.
|
||||
|
||||
Features
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
clonedigger pylast
|
||||
grep -E "Clones detected|lines are duplicates" output.html
|
||||
exit 0
|
|
@ -25,13 +25,13 @@ import collections
|
|||
import hashlib
|
||||
import logging
|
||||
import shelve
|
||||
import six
|
||||
import ssl
|
||||
import sys
|
||||
import tempfile
|
||||
import time
|
||||
import warnings
|
||||
import xml.dom
|
||||
import html.entities
|
||||
from http.client import HTTPSConnection
|
||||
|
||||
from . import version
|
||||
|
||||
|
@ -44,24 +44,33 @@ __email__ = "amr.hassan@gmail.com"
|
|||
__version__ = version.__version__
|
||||
|
||||
if sys.version_info < (3,):
|
||||
warnings.warn(
|
||||
"You are using pylast with Python 2. "
|
||||
"Pylast will soon be Python 3 only. "
|
||||
"More info: https://github.com/pylast/pylast/issues/265",
|
||||
UserWarning,
|
||||
raise ImportError(
|
||||
"""pylast 3.0 and above are no longer compatible with Python 2.
|
||||
|
||||
This is pylast {} and you are using Python {}.
|
||||
Make sure you have pip >= 9.0 and setuptools >= 24.2 and retry:
|
||||
|
||||
$ pip install --upgrade pip setuptools
|
||||
|
||||
Other choices:
|
||||
|
||||
- Upgrade to Python 3.
|
||||
|
||||
- Install an older version of pylast:
|
||||
|
||||
$ pip install 'pylast<3.0'
|
||||
|
||||
For more information:
|
||||
|
||||
https://github.com/pylast/pylast/issues/265
|
||||
""".format(
|
||||
version, ".".join([str(v) for v in sys.version_info[:3]])
|
||||
)
|
||||
)
|
||||
|
||||
if sys.version_info.major == 2:
|
||||
import htmlentitydefs
|
||||
from httplib import HTTPSConnection
|
||||
from urllib import quote_plus as url_quote_plus
|
||||
else:
|
||||
import html.entities as htmlentitydefs
|
||||
from http.client import HTTPSConnection
|
||||
# Keep importable on Python 2 for a while to show ImportError
|
||||
from urllib.parse import quote_plus as url_quote_plus
|
||||
|
||||
unichr = chr
|
||||
|
||||
|
||||
STATUS_INVALID_SERVICE = 2
|
||||
STATUS_INVALID_METHOD = 3
|
||||
|
@ -123,7 +132,7 @@ SCROBBLE_MODE_SKIPPED = "S"
|
|||
# Delay time in seconds from section 4.4 of https://www.last.fm/api/tos
|
||||
DELAY_TIME = 0.2
|
||||
|
||||
# Python >3.4 and >2.7.9 has sane defaults
|
||||
# Python >3.4 has sane defaults
|
||||
SSL_CONTEXT = ssl.create_default_context()
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
@ -1118,10 +1127,10 @@ class _BaseObject(object):
|
|||
|
||||
def __hash__(self):
|
||||
# Convert any ints (or whatever) into strings
|
||||
values = map(six.text_type, self._get_params().values())
|
||||
values = map(str, self._get_params().values())
|
||||
|
||||
return hash(self.network) + hash(
|
||||
six.text_type(type(self))
|
||||
str(type(self))
|
||||
+ "".join(list(self._get_params().keys()) + list(values)).lower()
|
||||
)
|
||||
|
||||
|
@ -1649,7 +1658,7 @@ class Artist(_BaseObject, _Taggable):
|
|||
return "pylast.Artist({}, {})".format(repr(self.get_name()), repr(self.network))
|
||||
|
||||
def __unicode__(self):
|
||||
return six.text_type(self.get_name())
|
||||
return str(self.get_name())
|
||||
|
||||
@_string_output
|
||||
def __str__(self):
|
||||
|
@ -2690,22 +2699,18 @@ def md5(text):
|
|||
|
||||
|
||||
def _unicode(text):
|
||||
if isinstance(text, six.binary_type):
|
||||
return six.text_type(text, "utf-8")
|
||||
elif isinstance(text, six.text_type):
|
||||
if isinstance(text, bytes):
|
||||
return str(text, "utf-8")
|
||||
elif isinstance(text, str):
|
||||
return text
|
||||
else:
|
||||
return six.text_type(text)
|
||||
return str(text)
|
||||
|
||||
|
||||
def _string(string):
|
||||
"""For Python2 routines that can only process str type."""
|
||||
if isinstance(string, str):
|
||||
return string
|
||||
casted = six.text_type(string)
|
||||
if sys.version_info.major == 2:
|
||||
casted = casted.encode("utf-8")
|
||||
return casted
|
||||
return str(string)
|
||||
|
||||
|
||||
def cleanup_nodes(doc):
|
||||
|
@ -2864,9 +2869,9 @@ def _unescape_htmlentity(string):
|
|||
|
||||
# string = _unicode(string)
|
||||
|
||||
mapping = htmlentitydefs.name2codepoint
|
||||
mapping = html.entities.name2codepoint
|
||||
for key in mapping:
|
||||
string = string.replace("&%s;" % key, unichr(mapping[key]))
|
||||
string = string.replace("&%s;" % key, chr(mapping[key]))
|
||||
|
||||
return string
|
||||
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
# Master version for pylast
|
||||
__version__ = "2.5.0.dev0"
|
||||
__version__ = "3.0.0.dev0"
|
||||
|
|
42
setup.py
42
setup.py
|
@ -1,21 +1,50 @@
|
|||
#!/usr/bin/env python
|
||||
from setuptools import find_packages, setup
|
||||
from __future__ import print_function
|
||||
import sys
|
||||
|
||||
with open("README.md") as f:
|
||||
long_description = f.read()
|
||||
from setuptools import find_packages, setup
|
||||
|
||||
version_dict = {}
|
||||
with open("pylast/version.py") as f:
|
||||
exec(f.read(), version_dict)
|
||||
version = version_dict["__version__"]
|
||||
|
||||
|
||||
if sys.version_info < (3, 4):
|
||||
error = """pylast 3.0 and above are no longer compatible with Python 2.
|
||||
|
||||
This is pylast {} and you are using Python {}.
|
||||
Make sure you have pip >= 9.0 and setuptools >= 24.2 and retry:
|
||||
|
||||
$ pip install --upgrade pip setuptools
|
||||
|
||||
Other choices:
|
||||
|
||||
- Upgrade to Python 3.
|
||||
|
||||
- Install an older version of pylast:
|
||||
|
||||
$ pip install 'pylast<3.0'
|
||||
|
||||
For more information:
|
||||
|
||||
https://github.com/pylast/pylast/issues/265
|
||||
""".format(
|
||||
version, ".".join([str(v) for v in sys.version_info[:3]])
|
||||
)
|
||||
print(error, file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
with open("README.md") as f:
|
||||
long_description = f.read()
|
||||
|
||||
|
||||
setup(
|
||||
name="pylast",
|
||||
long_description=long_description,
|
||||
long_description_content_type="text/markdown",
|
||||
version=version,
|
||||
author="Amr Hassan <amr.hassan@gmail.com> and Contributors",
|
||||
install_requires=["six"],
|
||||
tests_require=[
|
||||
"coverage",
|
||||
"flaky",
|
||||
|
@ -34,17 +63,16 @@ setup(
|
|||
"Topic :: Internet",
|
||||
"Topic :: Multimedia :: Sound/Audio",
|
||||
"Topic :: Software Development :: Libraries :: Python Modules",
|
||||
"Programming Language :: Python :: 2",
|
||||
"Programming Language :: Python :: 2.7",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Programming Language :: Python :: 3.4",
|
||||
"Programming Language :: Python :: 3.5",
|
||||
"Programming Language :: Python :: 3.6",
|
||||
"Programming Language :: Python :: 3.7",
|
||||
"Programming Language :: Python :: 3 :: Only",
|
||||
"Programming Language :: Python :: Implementation :: CPython",
|
||||
"Programming Language :: Python :: Implementation :: PyPy",
|
||||
],
|
||||
python_requires=">=2.7.10, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
|
||||
python_requires=">=3.4",
|
||||
keywords=["Last.fm", "music", "scrobble", "scrobbling"],
|
||||
packages=find_packages(exclude=("tests*",)),
|
||||
license="Apache2",
|
||||
|
|
|
@ -67,7 +67,7 @@ class TestPyLastUser(TestPyLastWithLastFm):
|
|||
else:
|
||||
# Old way
|
||||
# Just check date because of timezones
|
||||
self.assertIn(u"2002-11-20 ", registered)
|
||||
self.assertIn("2002-11-20 ", registered)
|
||||
|
||||
def test_get_user_unixtime_registration(self):
|
||||
# Arrange
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import mock
|
||||
import pytest
|
||||
import six
|
||||
|
||||
import pylast
|
||||
|
||||
|
@ -13,9 +12,9 @@ def mock_network():
|
|||
@pytest.mark.parametrize(
|
||||
"artist",
|
||||
[
|
||||
u"\xe9lafdasfdsafdsa",
|
||||
u"ééééééé",
|
||||
pylast.Artist(u"B\xe9l", mock_network()),
|
||||
"\xe9lafdasfdsafdsa",
|
||||
"ééééééé",
|
||||
pylast.Artist("B\xe9l", mock_network()),
|
||||
"fdasfdsafsaf not unicode",
|
||||
],
|
||||
)
|
||||
|
@ -24,7 +23,7 @@ def test_get_cache_key(artist):
|
|||
request._get_cache_key()
|
||||
|
||||
|
||||
@pytest.mark.parametrize("obj", [pylast.Artist(u"B\xe9l", mock_network())])
|
||||
@pytest.mark.parametrize("obj", [pylast.Artist("B\xe9l", mock_network())])
|
||||
def test_cast_and_hash(obj):
|
||||
assert type(six.text_type(obj)) is six.text_type
|
||||
assert type(str(obj)) is str
|
||||
assert isinstance(hash(obj), int)
|
||||
|
|
18
tox.ini
18
tox.ini
|
@ -1,5 +1,5 @@
|
|||
[tox]
|
||||
envlist = py27, py37, py36, py35, py34, pypy, pypy3, py38dev
|
||||
envlist = py37, py36, py35, py34, pypy3, py38dev
|
||||
recreate = False
|
||||
|
||||
[testenv]
|
||||
|
@ -25,21 +25,7 @@ commands = {posargs}
|
|||
deps =
|
||||
flake8
|
||||
pep8-naming
|
||||
commands =
|
||||
flake8 .
|
||||
|
||||
[testenv:py2lint]
|
||||
deps =
|
||||
{[testenv:lint]deps}
|
||||
clonedigger
|
||||
commands =
|
||||
{[testenv:lint]commands}
|
||||
./clonedigger.sh
|
||||
|
||||
[testenv:py3lint]
|
||||
deps =
|
||||
{[testenv:lint]deps}
|
||||
black
|
||||
commands =
|
||||
{[testenv:lint]commands}
|
||||
flake8 .
|
||||
black --check --diff .
|
||||
|
|
Loading…
Reference in a new issue