From cc1a3f10813171037d6d6021442a37c5a76360aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20P=2E=20Santos?= Date: Tue, 12 Dec 2023 10:24:01 -0300 Subject: [PATCH] Migrate HTTP client library to httpx Changes: - Replaced `requests` with `httpx` as the default HTTP client. - Update existing cassette recordings with new data. - Added `pytest-mock` for mocking dependencies in tests. - Remove outdated dependency. - Bumped the version number to 2.1.0. Reason: The switch from the default HTTP client library, `requests`, to `httpx` aims to modernize the project's underlying infrastructure, providing a more up-to-date and flexible foundation. This update also opens the possibility of implementing asynchronous functionalities in the future. It's a significant step to align the project with modern development practices and ensure greater flexibility for future expansions. --- pyradios/__init__.py | 2 +- pyradios/radios.py | 4 +- requirements-dev.txt | 2 +- requirements.txt | 2 +- .../test_request_codecs.yaml | 24 ++++---- .../test_request_codecs_with_filters.yaml | 22 +++---- ...est_request_countrycodes_with_filters.yaml | 22 +++---- .../test_request_languages_with_filters.yaml | 22 +++---- .../test_request_states_with_filters.yaml | 22 +++---- .../test_request_stations_by_votes.yaml | 34 +++++------ .../test_request_tags_with_filters.yaml | 22 +++---- tests/test_radio_browser.py | 59 ++++++++----------- 12 files changed, 113 insertions(+), 124 deletions(-) diff --git a/pyradios/__init__.py b/pyradios/__init__.py index f579729..ffae2b7 100644 --- a/pyradios/__init__.py +++ b/pyradios/__init__.py @@ -4,7 +4,7 @@ from pyradios.facets import RadioFacets # warning: setup.py assumes strict single quotes on the line below -__version__ = '2.0.0' +__version__ = '2.1.0' __all__ = ["RadioBrowser", "RadioFacets"] diff --git a/pyradios/radios.py b/pyradios/radios.py index 0f3925c..35c14e3 100644 --- a/pyradios/radios.py +++ b/pyradios/radios.py @@ -1,4 +1,4 @@ -import requests +import httpx from pyradios.base_url import pick_base_url from pyradios.utils import type_check @@ -16,7 +16,7 @@ def __init__(self, headers=None, session=None): def _init_session(self, session): if session is None: - return requests.Session() + return httpx.Client() return session def get(self, url, **kwargs): diff --git a/requirements-dev.txt b/requirements-dev.txt index 1f3c6eb..af3e5d0 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,6 +1,6 @@ # here we list the requirements needed by developers - tools referenced in the makefile that should get into your venv pytest>=6.2.5 flake8>=4.0.1 -responses>=0.15.0 setuptools pytest-recording +pytest-mock diff --git a/requirements.txt b/requirements.txt index ee88e26..b5e76b3 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1 @@ -requests>=2.26.0 +httpx>=0.25.2 diff --git a/tests/cassettes/test_radio_browser/test_request_codecs.yaml b/tests/cassettes/test_radio_browser/test_request_codecs.yaml index fc6f15d..2c6defb 100644 --- a/tests/cassettes/test_radio_browser/test_request_codecs.yaml +++ b/tests/cassettes/test_radio_browser/test_request_codecs.yaml @@ -1,20 +1,21 @@ interactions: - request: - body: null + body: '' headers: - Accept: + accept: - '*/*' - Accept-Encoding: + accept-encoding: - gzip, deflate - Connection: + connection: - keep-alive - User-Agent: + host: + - nl1.api.radio-browser.info + user-agent: - pyradios/2.0.0 method: GET uri: https://nl1.api.radio-browser.info/json/codecs/ response: - body: - string: '[{"name":"AAC","stationcount":4449},{"name":"AAC+","stationcount":7495},{"name":"AAC+,H.264","stationcount":4},{"name":"AAC,H.264","stationcount":80},{"name":"FLV","stationcount":10},{"name":"MP3","stationcount":27967},{"name":"MP3,H.264","stationcount":14},{"name":"OGG","stationcount":443},{"name":"UNKNOWN","stationcount":1652}]' + content: '[{"name":"AAC","stationcount":4559},{"name":"AAC+","stationcount":7385},{"name":"AAC+,H.264","stationcount":6},{"name":"AAC,H.264","stationcount":87},{"name":"FLV","stationcount":11},{"name":"MP3","stationcount":29173},{"name":"MP3,H.264","stationcount":14},{"name":"OGG","stationcount":464},{"name":"UNKNOWN","stationcount":1681},{"name":"UNKNOWN,H.264","stationcount":1}]' headers: Access-Control-Allow-Headers: - origin, x-requested-with, content-type, User-Agent @@ -25,14 +26,13 @@ interactions: Connection: - keep-alive Content-Length: - - '331' + - '373' Content-Type: - application/json Date: - - Wed, 25 Oct 2023 06:13:07 GMT + - Mon, 11 Dec 2023 18:03:57 GMT Server: - nginx/1.18.0 (Ubuntu) - status: - code: 200 - message: OK + http_version: HTTP/1.1 + status_code: 200 version: 1 diff --git a/tests/cassettes/test_radio_browser/test_request_codecs_with_filters.yaml b/tests/cassettes/test_radio_browser/test_request_codecs_with_filters.yaml index 56f3c49..70c47ed 100644 --- a/tests/cassettes/test_radio_browser/test_request_codecs_with_filters.yaml +++ b/tests/cassettes/test_radio_browser/test_request_codecs_with_filters.yaml @@ -1,20 +1,21 @@ interactions: - request: - body: null + body: '' headers: - Accept: + accept: - '*/*' - Accept-Encoding: + accept-encoding: - gzip, deflate - Connection: + connection: - keep-alive - User-Agent: + host: + - nl1.api.radio-browser.info + user-agent: - pyradios/2.0.0 method: GET uri: https://nl1.api.radio-browser.info/json/codecs/mp3 response: - body: - string: '[{"name":"MP3","stationcount":27967},{"name":"MP3,H.264","stationcount":14}]' + content: '[{"name":"MP3","stationcount":29173},{"name":"MP3,H.264","stationcount":14}]' headers: Access-Control-Allow-Headers: - origin, x-requested-with, content-type, User-Agent @@ -29,10 +30,9 @@ interactions: Content-Type: - application/json Date: - - Wed, 25 Oct 2023 06:13:08 GMT + - Mon, 11 Dec 2023 18:04:09 GMT Server: - nginx/1.18.0 (Ubuntu) - status: - code: 200 - message: OK + http_version: HTTP/1.1 + status_code: 200 version: 1 diff --git a/tests/cassettes/test_radio_browser/test_request_countrycodes_with_filters.yaml b/tests/cassettes/test_radio_browser/test_request_countrycodes_with_filters.yaml index f0626fd..63c5e36 100644 --- a/tests/cassettes/test_radio_browser/test_request_countrycodes_with_filters.yaml +++ b/tests/cassettes/test_radio_browser/test_request_countrycodes_with_filters.yaml @@ -1,20 +1,21 @@ interactions: - request: - body: null + body: '' headers: - Accept: + accept: - '*/*' - Accept-Encoding: + accept-encoding: - gzip, deflate - Connection: + connection: - keep-alive - User-Agent: + host: + - nl1.api.radio-browser.info + user-agent: - pyradios/2.0.0 method: GET uri: https://nl1.api.radio-browser.info/json/countrycodes/BR response: - body: - string: '[{"name":"BR","stationcount":953}]' + content: '[{"name":"BR","stationcount":991}]' headers: Access-Control-Allow-Headers: - origin, x-requested-with, content-type, User-Agent @@ -29,10 +30,9 @@ interactions: Content-Type: - application/json Date: - - Wed, 25 Oct 2023 06:13:07 GMT + - Mon, 11 Dec 2023 18:03:51 GMT Server: - nginx/1.18.0 (Ubuntu) - status: - code: 200 - message: OK + http_version: HTTP/1.1 + status_code: 200 version: 1 diff --git a/tests/cassettes/test_radio_browser/test_request_languages_with_filters.yaml b/tests/cassettes/test_radio_browser/test_request_languages_with_filters.yaml index c116145..5f70be0 100644 --- a/tests/cassettes/test_radio_browser/test_request_languages_with_filters.yaml +++ b/tests/cassettes/test_radio_browser/test_request_languages_with_filters.yaml @@ -1,20 +1,21 @@ interactions: - request: - body: null + body: '' headers: - Accept: + accept: - '*/*' - Accept-Encoding: + accept-encoding: - gzip, deflate - Connection: + connection: - keep-alive - User-Agent: + host: + - nl1.api.radio-browser.info + user-agent: - pyradios/2.0.0 method: GET uri: https://nl1.api.radio-browser.info/json/languages/portuguese response: - body: - string: '[{"name":"brazilian portuguese","iso_639":null,"stationcount":378},{"name":"portuguese","iso_639":"pt","stationcount":562}]' + content: '[{"name":"brazilian portuguese","iso_639":null,"stationcount":381},{"name":"portuguese","iso_639":"pt","stationcount":568}]' headers: Access-Control-Allow-Headers: - origin, x-requested-with, content-type, User-Agent @@ -29,10 +30,9 @@ interactions: Content-Type: - application/json Date: - - Wed, 25 Oct 2023 06:13:09 GMT + - Mon, 11 Dec 2023 18:04:23 GMT Server: - nginx/1.18.0 (Ubuntu) - status: - code: 200 - message: OK + http_version: HTTP/1.1 + status_code: 200 version: 1 diff --git a/tests/cassettes/test_radio_browser/test_request_states_with_filters.yaml b/tests/cassettes/test_radio_browser/test_request_states_with_filters.yaml index 6bebfdb..1428764 100644 --- a/tests/cassettes/test_radio_browser/test_request_states_with_filters.yaml +++ b/tests/cassettes/test_radio_browser/test_request_states_with_filters.yaml @@ -1,20 +1,21 @@ interactions: - request: - body: null + body: '' headers: - Accept: + accept: - '*/*' - Accept-Encoding: + accept-encoding: - gzip, deflate - Connection: + connection: - keep-alive - User-Agent: + host: + - nl1.api.radio-browser.info + user-agent: - pyradios/2.0.0 method: GET uri: https://nl1.api.radio-browser.info/json/states/Brazil/Paran%C3%A1 response: - body: - string: "[{\"name\":\"Cascavel, Parana\",\"country\":\"Brazil\",\"stationcount\":1},{\"name\":\"Parana\",\"country\":\"Brazil\",\"stationcount\":16},{\"name\":\"Paran\xE1(Brazil)\",\"country\":\"Brazil\",\"stationcount\":13}]" + content: "[{\"name\":\"Cascavel, Parana\",\"country\":\"Brazil\",\"stationcount\":1},{\"name\":\"Parana\",\"country\":\"Brazil\",\"stationcount\":15},{\"name\":\"Paran\xE1(Brazil)\",\"country\":\"Brazil\",\"stationcount\":13}]" headers: Access-Control-Allow-Headers: - origin, x-requested-with, content-type, User-Agent @@ -29,10 +30,9 @@ interactions: Content-Type: - application/json Date: - - Wed, 25 Oct 2023 06:13:09 GMT + - Mon, 11 Dec 2023 18:04:15 GMT Server: - nginx/1.18.0 (Ubuntu) - status: - code: 200 - message: OK + http_version: HTTP/1.1 + status_code: 200 version: 1 diff --git a/tests/cassettes/test_radio_browser/test_request_stations_by_votes.yaml b/tests/cassettes/test_radio_browser/test_request_stations_by_votes.yaml index a2fbad0..132a9d1 100644 --- a/tests/cassettes/test_radio_browser/test_request_stations_by_votes.yaml +++ b/tests/cassettes/test_radio_browser/test_request_stations_by_votes.yaml @@ -1,26 +1,27 @@ interactions: - request: - body: null + body: '' headers: - Accept: + accept: - '*/*' - Accept-Encoding: + accept-encoding: - gzip, deflate - Connection: + connection: - keep-alive - User-Agent: + host: + - nl1.api.radio-browser.info + user-agent: - pyradios/2.0.0 method: GET uri: https://nl1.api.radio-browser.info/json/stations/topvote/1 response: - body: - string: '[{"changeuuid":"8b62de9b-db82-43dd-9f8a-832a4346448e","stationuuid":"78012206-1aa1-11e9-a80b-52543be04c81","serveruuid":null,"name":"MANGORADIO","url":"http://stream.mangoradio.de/","url_resolved":"https://mangoradio.stream.laut.fm/mangoradio?t302=2023-10-25_06-42-39&uuid=f992e1d3-d33e-45de-978c-e56eb288f9ef","homepage":"https://mangoradio.de/","favicon":"","tags":"mango,mangoradio,mongo,mongoradio,public - radio,webradio","country":"Germany","countrycode":"DE","iso_3166_2":null,"state":"","language":"german","languagecodes":"de","votes":646087,"lastchangetime":"2022-10-02 - 08:26:04","lastchangetime_iso8601":"2022-10-02T08:26:04Z","codec":"MP3","bitrate":128,"hls":0,"lastcheckok":1,"lastchecktime":"2023-10-25 - 04:46:00","lastchecktime_iso8601":"2023-10-25T04:46:00Z","lastcheckoktime":"2023-10-25 - 04:46:00","lastcheckoktime_iso8601":"2023-10-25T04:46:00Z","lastlocalchecktime":"2023-10-25 - 03:44:01","lastlocalchecktime_iso8601":"2023-10-25T03:44:01Z","clicktimestamp":"2023-10-25 - 06:05:42","clicktimestamp_iso8601":"2023-10-25T06:05:42Z","clickcount":10851,"clicktrend":151,"ssl_error":0,"geo_lat":null,"geo_long":null,"has_extended_info":false}]' + content: '[{"changeuuid":"599cf698-a707-4d50-8383-e5f342fb9c08","stationuuid":"78012206-1aa1-11e9-a80b-52543be04c81","serveruuid":null,"name":"MANGORADIO","url":"http://stream.mangoradio.de/","url_resolved":"https://mangoradio.stream.laut.fm/mangoradio?t302=2023-12-11_08-56-28&uuid=8b1ac60c-8b49-4740-8622-3e8920aeedc5","homepage":"https://mangoradio.de/","favicon":"","tags":"mango,mangoradio,mongo,mongoradio,public + radio,webradio","country":"Germany","countrycode":"DE","iso_3166_2":null,"state":"","language":"german","languagecodes":"de","votes":659857,"lastchangetime":"2023-11-04 + 17:05:55","lastchangetime_iso8601":"2023-11-04T17:05:55Z","codec":"MP3","bitrate":128,"hls":0,"lastcheckok":1,"lastchecktime":"2023-12-11 + 08:04:26","lastchecktime_iso8601":"2023-12-11T08:04:26Z","lastcheckoktime":"2023-12-11 + 08:04:26","lastcheckoktime_iso8601":"2023-12-11T08:04:26Z","lastlocalchecktime":"2023-12-10 + 21:14:51","lastlocalchecktime_iso8601":"2023-12-10T21:14:51Z","clicktimestamp":"2023-12-11 + 17:56:12","clicktimestamp_iso8601":"2023-12-11T17:56:12Z","clickcount":4976,"clicktrend":-120,"ssl_error":0,"geo_lat":null,"geo_long":null,"has_extended_info":false}]' headers: Access-Control-Allow-Headers: - origin, x-requested-with, content-type, User-Agent @@ -35,10 +36,9 @@ interactions: Content-Type: - application/json Date: - - Wed, 25 Oct 2023 06:13:11 GMT + - Mon, 11 Dec 2023 18:04:40 GMT Server: - nginx/1.18.0 (Ubuntu) - status: - code: 200 - message: OK + http_version: HTTP/1.1 + status_code: 200 version: 1 diff --git a/tests/cassettes/test_radio_browser/test_request_tags_with_filters.yaml b/tests/cassettes/test_radio_browser/test_request_tags_with_filters.yaml index 84bdd81..6c036b9 100644 --- a/tests/cassettes/test_radio_browser/test_request_tags_with_filters.yaml +++ b/tests/cassettes/test_radio_browser/test_request_tags_with_filters.yaml @@ -1,20 +1,21 @@ interactions: - request: - body: null + body: '' headers: - Accept: + accept: - '*/*' - Accept-Encoding: + accept-encoding: - gzip, deflate - Connection: + connection: - keep-alive - User-Agent: + host: + - nl1.api.radio-browser.info + user-agent: - pyradios/2.0.0 method: GET uri: https://nl1.api.radio-browser.info/json/tags/drum%20and%20bass response: - body: - string: '[{"name":"drum and bass","stationcount":71}]' + content: '[{"name":"drum and bass","stationcount":76}]' headers: Access-Control-Allow-Headers: - origin, x-requested-with, content-type, User-Agent @@ -29,10 +30,9 @@ interactions: Content-Type: - application/json Date: - - Wed, 25 Oct 2023 06:13:10 GMT + - Mon, 11 Dec 2023 18:04:30 GMT Server: - nginx/1.18.0 (Ubuntu) - status: - code: 200 - message: OK + http_version: HTTP/1.1 + status_code: 200 version: 1 diff --git a/tests/test_radio_browser.py b/tests/test_radio_browser.py index e16ca01..dd69c93 100644 --- a/tests/test_radio_browser.py +++ b/tests/test_radio_browser.py @@ -1,8 +1,8 @@ import re +import httpx import pytest import random -import responses from pyradios import RadioBrowser from pyradios.radios import version @@ -17,7 +17,7 @@ def pick_random_station(rb, **params): def test_version(): - assert version == '2.0.0' + assert version == '2.1.0' @pytest.fixture @@ -27,8 +27,7 @@ def rb(): return _rb -@responses.activate -def test_request_station_click_counter(rb): +def test_request_station_click_counter(rb, mocker): expected = { "ok": True, "message": "retrieved station url", @@ -36,39 +35,29 @@ def test_request_station_click_counter(rb): "name": "BBC Radio 1", "url": "https://stream.live.vc.bbcmedia.co.uk/bbc_radio_one", } - # mock responses - responses.add( - responses.GET, - BASE_URL + "json/url/a726a172-4cc2-4076-b283-a950218ed0c2", - json=expected, - status=200, - ) - - resp = rb.click_counter("a726a172-4cc2-4076-b283-a950218ed0c2") - - assert "ok" in resp - assert "message" in resp - assert "stationuuid" in resp - assert "name" in resp - assert "url" in resp - assert resp == expected - - -@responses.activate -def test_request_countrycodes(rb): + + with mocker.patch.object(rb.client, 'get', return_value=expected): + + resp = rb.click_counter("a726a172-4cc2-4076-b283-a950218ed0c2") + + assert "ok" in resp + assert "message" in resp + assert "stationuuid" in resp + assert "name" in resp + assert "url" in resp + assert resp == expected + + +def test_request_countrycodes(rb, mocker): expected = [{"name": "AD", "stationcount": 5}] - responses.add( - responses.GET, - BASE_URL + "json/countrycodes/", - json=expected, - status=200, - ) - resp = rb.countrycodes() - assert len(resp) > 0, "at least one country should be in the response" - assert "name" in resp[0] - assert "stationcount" in resp[0] - assert resp == expected + with mocker.patch.object(rb.client, 'get', return_value=expected): + resp = rb.countrycodes() + + assert len(resp) > 0, "at least one country should be in the response" + assert "name" in resp[0] + assert "stationcount" in resp[0] + assert resp == expected @pytest.mark.vcr()