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