Merge pull request #430 from pylast/rm-3.7

This commit is contained in:
Hugo van Kemenade 2023-06-06 19:15:22 +03:00 committed by GitHub
commit 5f302e0813
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 64 additions and 72 deletions

View file

@ -11,7 +11,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: ["pypy3.9", "3.7", "3.8", "3.9", "3.10", "3.11", "3.12-dev"]
python-version: ["pypy3.9", "3.8", "3.9", "3.10", "3.11", "3.12"]
os: [ubuntu-latest]
steps:
@ -21,6 +21,7 @@ jobs:
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
allow-prereleases: true
cache: pip
cache-dependency-path: pyproject.toml

View file

@ -1,9 +1,9 @@
repos:
- repo: https://github.com/asottile/pyupgrade
rev: v3.3.1
rev: v3.4.0
hooks:
- id: pyupgrade
args: [--py37-plus]
args: [--py38-plus]
- repo: https://github.com/psf/black
rev: 23.3.0
@ -14,7 +14,7 @@ repos:
rev: 1.13.0
hooks:
- id: blacken-docs
args: [--target-version=py37]
args: [--target-version=py38]
additional_dependencies: [black==23.3.0]
- repo: https://github.com/PyCQA/isort
@ -46,12 +46,12 @@ repos:
- id: requirements-txt-fixer
- repo: https://github.com/tox-dev/pyproject-fmt
rev: 0.9.2
rev: 0.10.0
hooks:
- id: pyproject-fmt
- repo: https://github.com/abravalheri/validate-pyproject
rev: v0.12.2
rev: v0.13
hooks:
- id: validate-pyproject

View file

@ -35,7 +35,7 @@ Or from requirements.txt:
Note:
* pyLast 5.2+ supports Python 3.7-3.12.
* pyLast 5.2+ supports Python 3.8-3.12.
* pyLast 5.1 supports Python 3.7-3.11.
* pyLast 5.0 supports Python 3.7-3.10.
* pyLast 4.3 - 4.5 supports Python 3.6-3.10.

View file

@ -18,30 +18,28 @@ keywords = [
license = {text = "Apache-2.0"}
maintainers = [{name = "Hugo van Kemenade"}]
authors = [{name = "Amr Hassan <amr.hassan@gmail.com> and Contributors", email = "amr.hassan@gmail.com"}]
requires-python = ">=3.7"
requires-python = ">=3.8"
classifiers = [
"Development Status :: 5 - Production/Stable",
"License :: OSI Approved :: Apache Software License",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: Implementation :: PyPy",
"Topic :: Internet",
"Topic :: Multimedia :: Sound/Audio",
"Topic :: Software Development :: Libraries :: Python Modules",
"Development Status :: 5 - Production/Stable",
"License :: OSI Approved :: Apache Software License",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: Implementation :: PyPy",
"Topic :: Internet",
"Topic :: Multimedia :: Sound/Audio",
"Topic :: Software Development :: Libraries :: Python Modules",
]
dynamic = [
"version",
]
dependencies = [
"httpx",
'importlib-metadata; python_version < "3.8"',
]
[project.optional-dependencies]
tests = [

View file

@ -23,6 +23,7 @@ from __future__ import annotations
import collections
import hashlib
import html.entities
import importlib.metadata
import logging
import os
import re
@ -36,18 +37,11 @@ from xml.dom import Node, minidom
import httpx
try:
# Python 3.8+
import importlib.metadata as importlib_metadata
except ImportError:
# Python 3.7 and lower
import importlib_metadata # type: ignore
__author__ = "Amr Hassan, hugovk, Mice Pápai"
__copyright__ = "Copyright (C) 2008-2010 Amr Hassan, 2013-2021 hugovk, 2017 Mice Pápai"
__license__ = "apache2"
__email__ = "amr.hassan@gmail.com"
__version__ = importlib_metadata.version(__name__)
__version__ = importlib.metadata.version(__name__)
# 1 : This error does not exist

View file

@ -94,8 +94,8 @@ class TestPyLastAlbum(TestPyLastWithLastFm):
image = album.get_cover_image()
# Assert
self.assert_startswith(image, "https://")
self.assert_endswith(image, ".gif")
assert image.startswith("https://")
assert image.endswith(".gif") or image.endswith(".png")
def test_mbid(self) -> None:
# Arrange

View file

@ -16,7 +16,7 @@ class TestPyLastLibrary(TestPyLastWithLastFm):
representation = repr(library)
# Assert
self.assert_startswith(representation, "pylast.Library(")
assert representation.startswith("pylast.Library(")
def test_str(self) -> None:
# Arrange
@ -26,7 +26,7 @@ class TestPyLastLibrary(TestPyLastWithLastFm):
string = str(library)
# Assert
self.assert_endswith(string, "'s Library")
assert string.endswith("'s Library")
def test_library_is_hashable(self) -> None:
# Arrange

View file

@ -6,11 +6,11 @@ from flaky import flaky
import pylast
from .test_pylast import PyLastTestCase, load_secrets
from .test_pylast import load_secrets
@flaky(max_runs=3, min_passes=1)
class TestPyLastWithLibreFm(PyLastTestCase):
class TestPyLastWithLibreFm:
"""Own class for Libre.fm because we don't need the Last.fm setUp"""
def test_libre_fm(self) -> None:
@ -38,4 +38,4 @@ class TestPyLastWithLibreFm(PyLastTestCase):
representation = repr(network)
# Assert
self.assert_startswith(representation, "pylast.LibreFMNetwork(")
assert representation.startswith("pylast.LibreFMNetwork(")

View file

@ -330,12 +330,12 @@ class TestPyLastNetwork(TestPyLastWithLastFm):
# Assert
assert len(images) == 4
self.assert_startswith(images[pylast.SIZE_SMALL], "https://")
self.assert_endswith(images[pylast.SIZE_SMALL], ".png")
assert images[pylast.SIZE_SMALL].startswith("https://")
assert images[pylast.SIZE_SMALL].endswith(".png")
assert "/34s/" in images[pylast.SIZE_SMALL]
self.assert_startswith(images[pylast.SIZE_EXTRA_LARGE], "https://")
self.assert_endswith(images[pylast.SIZE_EXTRA_LARGE], ".png")
assert images[pylast.SIZE_EXTRA_LARGE].startswith("https://")
assert images[pylast.SIZE_EXTRA_LARGE].endswith(".png")
assert "/300x300/" in images[pylast.SIZE_EXTRA_LARGE]
def test_artist_search(self) -> None:
@ -362,12 +362,12 @@ class TestPyLastNetwork(TestPyLastWithLastFm):
# Assert
assert len(images) == 5
self.assert_startswith(images[pylast.SIZE_SMALL], "https://")
self.assert_endswith(images[pylast.SIZE_SMALL], ".png")
assert images[pylast.SIZE_SMALL].startswith("https://")
assert images[pylast.SIZE_SMALL].endswith(".png")
assert "/34s/" in images[pylast.SIZE_SMALL]
self.assert_startswith(images[pylast.SIZE_EXTRA_LARGE], "https://")
self.assert_endswith(images[pylast.SIZE_EXTRA_LARGE], ".png")
assert images[pylast.SIZE_EXTRA_LARGE].startswith("https://")
assert images[pylast.SIZE_EXTRA_LARGE].endswith(".png")
assert "/300x300/" in images[pylast.SIZE_EXTRA_LARGE]
def test_track_search(self) -> None:
@ -396,12 +396,12 @@ class TestPyLastNetwork(TestPyLastWithLastFm):
# Assert
assert len(images) == 4
self.assert_startswith(images[pylast.SIZE_SMALL], "https://")
self.assert_endswith(images[pylast.SIZE_SMALL], ".png")
assert images[pylast.SIZE_SMALL].startswith("https://")
assert images[pylast.SIZE_SMALL].endswith(".png")
assert "/34s/" in images[pylast.SIZE_SMALL]
self.assert_startswith(images[pylast.SIZE_EXTRA_LARGE], "https://")
self.assert_endswith(images[pylast.SIZE_EXTRA_LARGE], ".png")
assert images[pylast.SIZE_EXTRA_LARGE].startswith("https://")
assert images[pylast.SIZE_EXTRA_LARGE].endswith(".png")
assert "/300x300/" in images[pylast.SIZE_EXTRA_LARGE]
def test_search_get_total_result_count(self) -> None:

View file

@ -32,24 +32,17 @@ def load_secrets(): # pragma: no cover
return doc
class PyLastTestCase:
def assert_startswith(self, s, prefix, start=None, end=None) -> None:
assert s.startswith(prefix, start, end)
def assert_endswith(self, s, suffix, start=None, end=None) -> None:
assert s.endswith(suffix, start, end)
def _no_xfail_rerun_filter(err, name, test, plugin) -> bool:
for _ in test.iter_markers(name="xfail"):
return False
@flaky(max_runs=3, min_passes=1, rerun_filter=_no_xfail_rerun_filter)
class TestPyLastWithLastFm(PyLastTestCase):
class TestPyLastWithLastFm:
secrets = None
def unix_timestamp(self):
@staticmethod
def unix_timestamp() -> int:
return int(time.time())
@classmethod
@ -70,7 +63,8 @@ class TestPyLastWithLastFm(PyLastTestCase):
password_hash=password_hash,
)
def helper_is_thing_hashable(self, thing) -> None:
@staticmethod
def helper_is_thing_hashable(thing) -> None:
# Arrange
things = set()
@ -81,7 +75,8 @@ class TestPyLastWithLastFm(PyLastTestCase):
assert thing is not None
assert len(things) == 1
def helper_validate_results(self, a, b, c) -> None:
@staticmethod
def helper_validate_results(a, b, c) -> None:
# Assert
assert a is not None
assert b is not None
@ -105,27 +100,31 @@ class TestPyLastWithLastFm(PyLastTestCase):
# Assert
self.helper_validate_results(result1, result2, result3)
def helper_at_least_one_thing_in_top_list(self, things, expected_type) -> None:
@staticmethod
def helper_at_least_one_thing_in_top_list(things, expected_type) -> None:
# Assert
assert len(things) > 1
assert isinstance(things, list)
assert isinstance(things[0], pylast.TopItem)
assert isinstance(things[0].item, expected_type)
def helper_only_one_thing_in_top_list(self, things, expected_type) -> None:
@staticmethod
def helper_only_one_thing_in_top_list(things, expected_type) -> None:
# Assert
assert len(things) == 1
assert isinstance(things, list)
assert isinstance(things[0], pylast.TopItem)
assert isinstance(things[0].item, expected_type)
def helper_only_one_thing_in_list(self, things, expected_type) -> None:
@staticmethod
def helper_only_one_thing_in_list(things, expected_type) -> None:
# Assert
assert len(things) == 1
assert isinstance(things, list)
assert isinstance(things[0], expected_type)
def helper_two_different_things_in_top_list(self, things, expected_type) -> None:
@staticmethod
def helper_two_different_things_in_top_list(things, expected_type) -> None:
# Assert
assert len(things) == 2
thing1 = things[0]

View file

@ -24,7 +24,7 @@ class TestPyLastUser(TestPyLastWithLastFm):
representation = repr(user)
# Assert
self.assert_startswith(representation, "pylast.User('RJ',")
assert representation.startswith("pylast.User('RJ',")
def test_str(self) -> None:
# Arrange
@ -345,7 +345,7 @@ class TestPyLastUser(TestPyLastWithLastFm):
url = user.get_image()
# Assert
self.assert_startswith(url, "https://")
assert url.startswith("https://")
def test_user_get_library(self) -> None:
# Arrange
@ -428,8 +428,8 @@ class TestPyLastUser(TestPyLastWithLastFm):
image = user.get_image()
# Assert
self.assert_startswith(image, "https://")
self.assert_endswith(image, ".png")
assert image.startswith("https://")
assert image.endswith(".png")
def test_get_url(self) -> None:
# Arrange

View file

@ -3,7 +3,7 @@ requires =
tox>=4.2
env_list =
lint
py{py3, 312, 311, 310, 39, 38, 37}
py{py3, 312, 311, 310, 39, 38}
[testenv]
extras =