From 85c8b7d11c9713252e27500bb2b61c21c1ced53a Mon Sep 17 00:00:00 2001 From: imperosol Date: Mon, 20 Jan 2025 19:20:13 +0100 Subject: [PATCH] Use requests for external requests L'API de requests est beaucoup plus claire que celle d'urllib et urllib3. --- com/calendar.py | 11 +++++------ com/tests/test_api.py | 15 ++++++--------- pedagogy/utbm_api.py | 15 +++++++-------- pyproject.toml | 1 + uv.lock | 6 ++++-- 5 files changed, 23 insertions(+), 25 deletions(-) diff --git a/com/calendar.py b/com/calendar.py index 9003d6de..f3c612e1 100644 --- a/com/calendar.py +++ b/com/calendar.py @@ -2,7 +2,7 @@ from datetime import datetime, timedelta from pathlib import Path from typing import final -import urllib3 +import requests from dateutil.relativedelta import relativedelta from django.conf import settings from django.urls import reverse @@ -35,16 +35,15 @@ class IcsCalendar: @classmethod def make_external(cls) -> Path | None: - calendar = urllib3.request( - "GET", - "https://calendar.google.com/calendar/ical/ae.utbm%40gmail.com/public/basic.ics", + calendar = requests.get( + "https://calendar.google.com/calendar/ical/ae.utbm%40gmail.com/public/basic.ics" ) - if calendar.status != 200: + if not calendar.ok: return None cls._CACHE_FOLDER.mkdir(parents=True, exist_ok=True) with open(cls._EXTERNAL_CALENDAR, "wb") as f: - _ = f.write(calendar.data) + _ = f.write(calendar.content) return cls._EXTERNAL_CALENDAR @classmethod diff --git a/com/tests/test_api.py b/com/tests/test_api.py index f131052e..c84d8448 100644 --- a/com/tests/test_api.py +++ b/com/tests/test_api.py @@ -16,11 +16,11 @@ from com.calendar import IcsCalendar @dataclass class MockResponse: - status: int + ok: bool value: str @property - def data(self): + def content(self): return self.value.encode("utf8") @@ -38,7 +38,7 @@ class TestExternalCalendar: @pytest.fixture def mock_request(self): mock = MagicMock() - with patch("urllib3.request", mock): + with patch("requests.get", mock): yield mock @pytest.fixture @@ -52,15 +52,12 @@ class TestExternalCalendar: def clear_cache(self): IcsCalendar._EXTERNAL_CALENDAR.unlink(missing_ok=True) - @pytest.mark.parametrize("error_code", [403, 404, 500]) - def test_fetch_error( - self, client: Client, mock_request: MagicMock, error_code: int - ): - mock_request.return_value = MockResponse(error_code, "not allowed") + def test_fetch_error(self, client: Client, mock_request: MagicMock): + mock_request.return_value = MockResponse(ok=False, value="not allowed") assert client.get(reverse("api:calendar_external")).status_code == 404 def test_fetch_success(self, client: Client, mock_request: MagicMock): - external_response = MockResponse(200, "Definitely an ICS") + external_response = MockResponse(ok=True, value="Definitely an ICS") mock_request.return_value = external_response response = client.get(reverse("api:calendar_external")) assert response.status_code == 200 diff --git a/pedagogy/utbm_api.py b/pedagogy/utbm_api.py index fdd6d1fb..700c22f3 100644 --- a/pedagogy/utbm_api.py +++ b/pedagogy/utbm_api.py @@ -1,7 +1,6 @@ """Set of functions to interact with the UTBM UV api.""" -import urllib - +import requests from django.conf import settings from pedagogy.schemas import ShortUvList, UtbmFullUvSchema, UtbmShortUvSchema, UvSchema @@ -12,8 +11,8 @@ def find_uv(lang, year, code) -> UvSchema | None: # query the UV list base_url = settings.SITH_PEDAGOGY_UTBM_API uvs_url = f"{base_url}/uvs/{lang}/{year}" - response = urllib.request.urlopen(uvs_url) - uvs: list[UtbmShortUvSchema] = ShortUvList.validate_json(response.read()) + response = requests.get(uvs_url) + uvs: list[UtbmShortUvSchema] = ShortUvList.validate_json(response.content) short_uv = next((uv for uv in uvs if uv.code == code), None) if short_uv is None: @@ -21,12 +20,12 @@ def find_uv(lang, year, code) -> UvSchema | None: # get detailed information about the UV uv_url = f"{base_url}/uv/{lang}/{year}/{code}/{short_uv.code_formation}" - response = urllib.request.urlopen(uv_url) - full_uv = UtbmFullUvSchema.model_validate_json(response.read()) - return _make_clean_uv(short_uv, full_uv) + response = requests.get(uv_url) + full_uv = UtbmFullUvSchema.model_validate_json(response.content) + return make_clean_uv(short_uv, full_uv) -def _make_clean_uv(short_uv: UtbmShortUvSchema, full_uv: UtbmFullUvSchema) -> UvSchema: +def make_clean_uv(short_uv: UtbmShortUvSchema, full_uv: UtbmFullUvSchema) -> UvSchema: """Cleans the data up so that it corresponds to our data representation. Some of the needed information are in the short uv schema, some diff --git a/pyproject.toml b/pyproject.toml index 3e2cdf0f..b3db97cb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -44,6 +44,7 @@ dependencies = [ "django-honeypot<2.0.0,>=1.2.1", "pydantic-extra-types<3.0.0,>=2.10.1", "ical<9.0.0,>=8.3.0", + "requests>=2.32.3", ] [project.urls] diff --git a/uv.lock b/uv.lock index 2ea5e370..abf0fb98 100644 --- a/uv.lock +++ b/uv.lock @@ -155,7 +155,7 @@ name = "click" version = "8.1.8" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "colorama", marker = "platform_system == 'Windows'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/b9/2e/0090cbf739cee7d23781ad4b89a9894a41538e4fcf4c31dcdd705b78eb8b/click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a", size = 226593 } wheels = [ @@ -744,7 +744,7 @@ version = "1.6.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "click" }, - { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "colorama", marker = "platform_system == 'Windows'" }, { name = "ghp-import" }, { name = "jinja2" }, { name = "markdown" }, @@ -1437,6 +1437,7 @@ dependencies = [ { name = "pydantic-extra-types" }, { name = "python-dateutil" }, { name = "reportlab" }, + { name = "requests" }, { name = "sentry-sdk" }, { name = "sphinx" }, { name = "tomli" }, @@ -1495,6 +1496,7 @@ requires-dist = [ { name = "pydantic-extra-types", specifier = ">=2.10.1,<3.0.0" }, { name = "python-dateutil", specifier = ">=2.9.0.post0,<3.0.0.0" }, { name = "reportlab", specifier = ">=4.2.5,<5.0.0" }, + { name = "requests", specifier = ">=2.32.3" }, { name = "sentry-sdk", specifier = ">=2.19.2,<3.0.0" }, { name = "sphinx", specifier = ">=5,<6" }, { name = "tomli", specifier = ">=2.2.1,<3.0.0" },