Skip to content

Commit

Permalink
Merge pull request #47 from letsbuilda/tests-docs
Browse files Browse the repository at this point in the history
Limit support to Python 3.11
  • Loading branch information
shenanigansd authored Aug 1, 2023
2 parents c263335 + 61b3cc4 commit 3bc175d
Show file tree
Hide file tree
Showing 11 changed files with 133 additions and 96 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/python-ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
strategy:
matrix:
os: [ ubuntu-latest, windows-latest, macos-latest ]
python-version: [ "3.9", "3.10", "3.11" ]
python-version: [ "3.11" ]

uses: darbiadev/.github/.github/workflows/python-test.yaml@4aa7c64159244d12bf9a39d42da89e80004d4af6 # v1.0.1
with:
Expand Down
14 changes: 6 additions & 8 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,14 +78,12 @@ def linkcode_resolve(domain: str, info: dict) -> str:

if isinstance(
val,
(
types.ModuleType,
types.MethodType,
types.FunctionType,
types.TracebackType,
types.FrameType,
types.CodeType,
),
types.ModuleType
| types.MethodType
| types.FunctionType
| types.TracebackType
| types.FrameType
| types.CodeType,
):
try:
lines, first = inspect.getsourcelines(val)
Expand Down
7 changes: 3 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@ authors = [
]
license = { text = "MIT" }
readme = "README.md"
requires-python = ">=3.9"
requires-python = ">=3.11"
dependencies = [
"typing-extensions; python_version < '3.11'",
"requests",
"xmltodict",
]
Expand Down Expand Up @@ -49,11 +48,11 @@ requires = ["setuptools", "wheel"]
build-backend = "setuptools.build_meta"

[tool.black]
target-version = ["py39"]
target-version = ["py311"]
line-length = 120

[tool.ruff]
target-version = "py39"
target-version = "py311"
line-length = 120
select = ["ALL"]
ignore = [
Expand Down
18 changes: 5 additions & 13 deletions src/letsbuilda/pypi/async_client.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
"""The async client."""

from __future__ import annotations

from http import HTTPStatus
from typing import TYPE_CHECKING, Final
from typing import Final

import xmltodict

Expand All @@ -13,18 +11,12 @@
msg = "Please install letsbuilda[async] for async support!"
raise ImportError(msg) from error

from .exceptions import PackageNotFoundError
from .models import JSONPackageMetadata, Package, RSSPackageMetadata

if TYPE_CHECKING:
import sys
from typing import Self

from aiohttp import ClientSession
from aiohttp import ClientSession

if sys.version_info >= (3, 11):
from typing import Self
else:
from typing_extensions import Self
from .exceptions import PackageNotFoundError
from .models import JSONPackageMetadata, Package, RSSPackageMetadata


class PyPIServices:
Expand Down
12 changes: 1 addition & 11 deletions src/letsbuilda/pypi/exceptions.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,6 @@
"""Custom exceptions."""

from __future__ import annotations

from typing import TYPE_CHECKING

if TYPE_CHECKING:
import sys

if sys.version_info >= (3, 11):
from typing import Self
else:
from typing_extensions import Self
from typing import Self


class PackageNotFoundError(Exception):
Expand Down
12 changes: 1 addition & 11 deletions src/letsbuilda/pypi/models/models_json.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,8 @@
"""Models for JSON responses."""

from __future__ import annotations

from dataclasses import dataclass
from datetime import datetime
from typing import TYPE_CHECKING

if TYPE_CHECKING:
import sys

if sys.version_info >= (3, 11):
from typing import Self
else:
from typing_extensions import Self
from typing import Self


@dataclass(frozen=True)
Expand Down
14 changes: 2 additions & 12 deletions src/letsbuilda/pypi/models/models_package.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,9 @@
"""Models for package metadata."""

from __future__ import annotations

from dataclasses import dataclass
from typing import TYPE_CHECKING

if TYPE_CHECKING:
import sys

from .models_json import URL, JSONPackageMetadata
from typing import Self

if sys.version_info >= (3, 11):
from typing import Self
else:
pass
from .models_json import URL, JSONPackageMetadata


@dataclass(frozen=True)
Expand Down
16 changes: 3 additions & 13 deletions src/letsbuilda/pypi/models/models_rss.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,9 @@
"""Models for RSS responses."""

from __future__ import annotations

from dataclasses import dataclass
from datetime import datetime
from email.utils import parsedate_to_datetime
from typing import TYPE_CHECKING

if TYPE_CHECKING:
import sys
from datetime import datetime

if sys.version_info >= (3, 11):
from typing import Self
else:
from typing_extensions import Self
from typing import Self


@dataclass(frozen=True)
Expand All @@ -29,7 +19,7 @@ class RSSPackageMetadata:
publication_date: datetime

@classmethod
def build_from(cls: type[Self], data: dict[str, str]) -> RSSPackageMetadata:
def build_from(cls: type[Self], data: dict[str, str]) -> Self:
"""Build an instance from raw data."""
split_title = data.get("title").removesuffix(" added to PyPI").split()
title = split_title[0]
Expand Down
15 changes: 2 additions & 13 deletions src/letsbuilda/pypi/sync_client.py
Original file line number Diff line number Diff line change
@@ -1,25 +1,14 @@
"""The sync client."""

from __future__ import annotations

from http import HTTPStatus
from typing import TYPE_CHECKING, Final
from typing import Final, Self

import xmltodict
from requests import Session

from .exceptions import PackageNotFoundError
from .models import JSONPackageMetadata, Package, RSSPackageMetadata

if TYPE_CHECKING:
import sys

from requests import Session

if sys.version_info >= (3, 11):
from typing import Self
else:
from typing_extensions import Self


class PyPIServices:
"""A class for interacting with PyPI."""
Expand Down
108 changes: 108 additions & 0 deletions tests/test_json_api_parsing.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
"""Test parsing metadata from the JSON API."""

from datetime import UTC, datetime

from letsbuilda.pypi import JSONPackageMetadata

JSON_API_DATA = {
"info": {
"author": "",
"author_email": "Bradley Reynolds <[email protected]>",
"bugtrack_url": None,
"classifiers": [],
"description": "# letsbuilda-pypi\n\nA wrapper for [PyPI's API and RSS feeds](https://warehouse.pypa.io/api-reference/index.html).\n",
"description_content_type": "text/markdown",
"docs_url": None,
"download_url": "",
"downloads": {"last_day": -1, "last_month": -1, "last_week": -1},
"home_page": "",
"keywords": "",
"license": "MIT",
"maintainer": "",
"maintainer_email": "",
"name": "letsbuilda-pypi",
"package_url": "https://pypi.org/project/letsbuilda-pypi/",
"platform": None,
"project_url": "https://pypi.org/project/letsbuilda-pypi/",
"project_urls": {
"documentation": "https://docs.letsbuilda.dev/letsbuilda-pypi/",
"repository": "https://github.com/letsbuilda/letsbuilda-pypi/",
},
"release_url": "https://pypi.org/project/letsbuilda-pypi/4.0.0/",
"requires_dist": [
"aiohttp",
"xmltodict",
"pendulum",
"black ; extra == 'dev'",
"isort ; extra == 'dev'",
"ruff ; extra == 'dev'",
"sphinx ; extra == 'docs'",
"furo ; extra == 'docs'",
"sphinx-autoapi ; extra == 'docs'",
"releases ; extra == 'docs'",
"toml ; extra == 'docs'",
"pytest ; extra == 'tests'",
],
"requires_python": ">=3.10",
"summary": "A wrapper for PyPI's API and RSS feed",
"version": "4.0.0",
"yanked": False,
"yanked_reason": None,
},
"last_serial": 18988479,
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "cb63f897bdaa98710f9cb96ca1391742192975a776dc70a5a7b0acfbab50b20b",
"md5": "f7b5fd97141a4eae7966002634703002",
"sha256": "67a5925e5a51f761ad3c28f3abf90d0b0b4270c26efd87f596d42e5706a63798",
},
"downloads": -1,
"filename": "letsbuilda_pypi-4.0.0-py3-none-any.whl",
"has_sig": False,
"md5_digest": "f7b5fd97141a4eae7966002634703002",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.10",
"size": 4772,
"upload_time": "2023-04-26T02:40:03",
"upload_time_iso_8601": "2023-04-26T02:40:03.919027Z",
"url": "https://files.pythonhosted.org/packages/cb/63/f897bdaa98710f9cb96ca1391742192975a776dc70a5a7b0acfbab50b20b/letsbuilda_pypi-4.0.0-py3-none-any.whl",
"yanked": False,
"yanked_reason": None,
},
{
"comment_text": "",
"digests": {
"blake2b_256": "71a0d9b47f7a17efb1d296d189ae83c5381c80efa0e0984a96cb2f719136797e",
"md5": "27e181efe8b2f558784439b7878d6600",
"sha256": "0060a9380a89bf772c84c4f39d89417b6529378c4ce39f3b525b40f83c883287",
},
"downloads": -1,
"filename": "letsbuilda-pypi-4.0.0.tar.gz",
"has_sig": False,
"md5_digest": "27e181efe8b2f558784439b7878d6600",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.10",
"size": 4567,
"upload_time": "2023-04-26T02:40:05",
"upload_time_iso_8601": "2023-04-26T02:40:05.331985Z",
"url": "https://files.pythonhosted.org/packages/71/a0/d9b47f7a17efb1d296d189ae83c5381c80efa0e0984a96cb2f719136797e/letsbuilda-pypi-4.0.0.tar.gz",
"yanked": False,
"yanked_reason": None,
},
],
"vulnerabilities": [],
}


def test_json_api_data_parsing() -> None:
"""Confirm sample JSON API data gets parsed correctly."""
model = JSONPackageMetadata.from_dict(JSON_API_DATA)

assert model.info.name == "letsbuilda-pypi"
assert model.info.version == "4.0.0"
assert model.urls[0].upload_time == datetime(2023, 4, 26, 2, 40, 3)
assert model.urls[0].upload_time_iso_8601 == datetime(2023, 4, 26, 2, 40, 3, 919027, tzinfo=UTC)
11 changes: 1 addition & 10 deletions tests/test_rss_feed_parsing.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,8 @@
"""Test parsing metadata from the RSS feeds."""

from __future__ import annotations

import sys
from datetime import UTC, datetime
from typing import Final

if sys.version_info >= (3, 11):
from datetime import UTC, datetime
else:
from datetime import datetime, timezone

UTC = timezone.utc

from letsbuilda.pypi import RSSPackageMetadata

NEW_PACKAGE_DATA: Final[dict[str, str]] = {
Expand Down

0 comments on commit 3bc175d

Please sign in to comment.