From 6bc8f171c22dbdda054f88032b59f6b0f3ca41be Mon Sep 17 00:00:00 2001 From: Bradley Reynolds Date: Tue, 1 Aug 2023 03:15:10 +0000 Subject: [PATCH] Switch to HTTPX Signed-off-by: GitHub --- README.md | 18 ++++++++-------- pyproject.toml | 14 ++----------- src/letsbuilda/pypi/async_client.py | 32 ++++++++++------------------- src/letsbuilda/pypi/sync_client.py | 10 ++++----- 4 files changed, 28 insertions(+), 46 deletions(-) diff --git a/README.md b/README.md index afef73b..8e7b57e 100644 --- a/README.md +++ b/README.md @@ -7,23 +7,25 @@ A wrapper for [PyPI's API and RSS feeds](https://warehouse.pypa.io/api-reference ### Sync client ```py -from requests import Session +from httpx import Client from letsbuilda.pypi import PyPIServices -http_session = Session() -pypi_client = PyPIServices(http_session) +http_client = Client() +pypi_client = PyPIServices(http_client) -package_metadata = pypi_client.get_package_metadata("letsbuilda-pypi") +print(pypi_client.get_rss_feed(pypi_client.NEWEST_PACKAGES_FEED_URL)) +print(pypi_client.get_package_metadata("letsbuilda-pypi")) ``` ### Async client ```py -from aiohttp import ClientSession -from letsbuilda.pypi.clients.async_client import PyPIServices +from httpx import AsyncClient +from letsbuilda.pypi.async_client import PyPIServices -http_session = aiohttp.ClientSession() +http_client = AsyncClient() pypi_client = PyPIServices(http_session) -package_metadata = await pypi_client.get_package_metadata("letsbuilda-pypi") +print(await pypi_client.get_rss_feed(pypi_client.NEWEST_PACKAGES_FEED_URL)) +print(await pypi_client.get_package_metadata("letsbuilda-pypi")) ``` diff --git a/pyproject.toml b/pyproject.toml index 71846b9..914ca9d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "letsbuilda-pypi" -version = "5.0.0b3" +version = "5.0.0" description = "A wrapper for PyPI's API and RSS feed" authors = [ { name = "Bradley Reynolds", email = "bradley.reynolds@darbia.dev" }, @@ -9,7 +9,7 @@ license = { text = "MIT" } readme = "README.md" requires-python = ">=3.11" dependencies = [ - "requests", + "httpx", "xmltodict", ] @@ -18,9 +18,6 @@ repository = "https://github.com/letsbuilda/letsbuilda-pypi/" documentation = "https://docs.letsbuilda.dev/letsbuilda-pypi/" [project.optional-dependencies] -async = [ - "aiohttp", -] dev = [ "pre-commit", "black", @@ -28,19 +25,12 @@ dev = [ ] tests = [ "pytest", - - # from async extra - "aiohttp", ] docs = [ "sphinx", "furo", "sphinx-autoapi", "releases", - "toml", - - # from async extra - "aiohttp", ] [build-system] diff --git a/src/letsbuilda/pypi/async_client.py b/src/letsbuilda/pypi/async_client.py index e3f2dae..b768458 100644 --- a/src/letsbuilda/pypi/async_client.py +++ b/src/letsbuilda/pypi/async_client.py @@ -1,19 +1,10 @@ """The async client.""" from http import HTTPStatus -from typing import Final +from typing import Final, Self import xmltodict - -try: - pass -except ImportError as error: - msg = "Please install letsbuilda[async] for async support!" - raise ImportError(msg) from error - -from typing import Self - -from aiohttp import ClientSession +from httpx import AsyncClient from .exceptions import PackageNotFoundError from .models import JSONPackageMetadata, Package, RSSPackageMetadata @@ -25,15 +16,14 @@ class PyPIServices: NEWEST_PACKAGES_FEED_URL: Final[str] = "https://pypi.org/rss/packages.xml" PACKAGE_UPDATES_FEED_URL: Final[str] = "https://pypi.org/rss/updates.xml" - def __init__(self: Self, http_session: ClientSession) -> None: - self.http_session = http_session + def __init__(self: Self, http_client: AsyncClient) -> None: + self.http_client = http_client async def get_rss_feed(self: Self, feed_url: str) -> list[RSSPackageMetadata]: """Get the new packages RSS feed.""" - async with self.http_session.get(feed_url) as response: - response_text = await response.text() - rss_data = xmltodict.parse(response_text)["rss"]["channel"]["item"] - return [RSSPackageMetadata.build_from(package_data) for package_data in rss_data] + response = await self.http_client.get(feed_url) + rss_data = xmltodict.parse(response.text)["rss"]["channel"]["item"] + return [RSSPackageMetadata.build_from(package_data) for package_data in rss_data] async def get_package_json_metadata( self: Self, @@ -45,10 +35,10 @@ async def get_package_json_metadata( url = f"https://pypi.org/pypi/{package_title}/{package_version}/json" else: url = f"https://pypi.org/pypi/{package_title}/json" - async with self.http_session.get(url) as response: - if response.status == HTTPStatus.NOT_FOUND: - raise PackageNotFoundError(package_title, package_version) - return JSONPackageMetadata.from_dict(await response.json()) + response = await self.http_client.get(url) + if response.status_code == HTTPStatus.NOT_FOUND: + raise PackageNotFoundError(package_title, package_version) + return JSONPackageMetadata.from_dict(response.json()) async def get_package_metadata( self: Self, diff --git a/src/letsbuilda/pypi/sync_client.py b/src/letsbuilda/pypi/sync_client.py index 7c39f81..5557a11 100644 --- a/src/letsbuilda/pypi/sync_client.py +++ b/src/letsbuilda/pypi/sync_client.py @@ -4,7 +4,7 @@ from typing import Final, Self import xmltodict -from requests import Session +from httpx import Client from .exceptions import PackageNotFoundError from .models import JSONPackageMetadata, Package, RSSPackageMetadata @@ -16,12 +16,12 @@ class PyPIServices: NEWEST_PACKAGES_FEED_URL: Final[str] = "https://pypi.org/rss/packages.xml" PACKAGE_UPDATES_FEED_URL: Final[str] = "https://pypi.org/rss/updates.xml" - def __init__(self: Self, http_session: Session) -> None: - self.http_session = http_session + def __init__(self: Self, http_client: Client) -> None: + self.http_client = http_client def get_rss_feed(self: Self, feed_url: str) -> list[RSSPackageMetadata]: """Get the new packages RSS feed.""" - response_text = self.http_session.get(feed_url).text + response_text = self.http_client.get(feed_url).text rss_data = xmltodict.parse(response_text)["rss"]["channel"]["item"] return [RSSPackageMetadata.build_from(package_data) for package_data in rss_data] @@ -35,7 +35,7 @@ def get_package_json_metadata( url = f"https://pypi.org/pypi/{package_title}/{package_version}/json" else: url = f"https://pypi.org/pypi/{package_title}/json" - response = self.http_session.get(url) + response = self.http_client.get(url) if response.status_code == HTTPStatus.NOT_FOUND: raise PackageNotFoundError(package_title, package_version) return JSONPackageMetadata.from_dict(response.json())