Skip to content

Commit

Permalink
Merge pull request #42 from letsbuilda/gh41
Browse files Browse the repository at this point in the history
Backport support for up to Python 3.9
  • Loading branch information
shenanigansd authored Jul 22, 2023
2 parents 5b55df6 + 921f14b commit d2e2132
Show file tree
Hide file tree
Showing 14 changed files with 141 additions and 68 deletions.
16 changes: 4 additions & 12 deletions .github/dependabot.yaml
Original file line number Diff line number Diff line change
@@ -1,19 +1,11 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates

version: 2

updates:
- package-ecosystem: "github-actions"
# Workflow files stored in the
# default location of `.github/workflows`
directory: "/"
schedule:
interval: "daily"
interval: "monthly"

- package-ecosystem: "pip" # See documentation for possible values
directory: "/" # Location of package manifests
- package-ecosystem: "pip"
directory: "/"
schedule:
interval: "daily"
interval: "monthly"
16 changes: 0 additions & 16 deletions .github/workflows/github-pages-python-sphinx.yaml

This file was deleted.

17 changes: 13 additions & 4 deletions .github/workflows/python-ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,29 @@ on:

jobs:
pre-commit:
uses: darbiadev/.github/.github/workflows/generic-precommit.yaml@main
uses: darbiadev/.github/.github/workflows/generic-precommit.yaml@4aa7c64159244d12bf9a39d42da89e80004d4af6 # v1.0.1

lint:
needs: pre-commit
uses: darbiadev/.github/.github/workflows/python-lint.yaml@main
uses: darbiadev/.github/.github/workflows/python-lint.yaml@4aa7c64159244d12bf9a39d42da89e80004d4af6 # v1.0.1

test:
needs: lint
strategy:
matrix:
os: [ ubuntu-latest, windows-latest, macos-latest ]
python-version: [ "3.11.4" ]
python-version: [ "3.9", "3.10", "3.11" ]

uses: darbiadev/.github/.github/workflows/python-test.yaml@main
uses: darbiadev/.github/.github/workflows/python-test.yaml@4aa7c64159244d12bf9a39d42da89e80004d4af6 # v1.0.1
with:
os: ${{ matrix.os }}
python-version: ${{ matrix.python-version }}

docs:
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
contents: read
pages: write
id-token: write

uses: darbiadev/.github/.github/workflows/github-pages-python-sphinx.yaml@4aa7c64159244d12bf9a39d42da89e80004d4af6 # v1.0.1
4 changes: 2 additions & 2 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@
releases_release_uri = f"{REPO_LINK}/releases/tag/v%s"


def linkcode_resolve(domain, info):
"""linkcode_resolve"""
def linkcode_resolve(domain: str, info: dict) -> str:
"""linkcode_resolve."""
if domain != "py":
return None
if not info["module"]:
Expand Down
6 changes: 3 additions & 3 deletions make.ps1
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<#
.SYNOPSIS
Testing using PowerShell to replace my Makefile
Makefile
.DESCRIPTION
USAGE
Expand Down Expand Up @@ -52,8 +52,8 @@ function Invoke-Upgrade-Deps
function Invoke-Lint
{
pre-commit run --all-files
python -m black src/
python -m ruff --fix src/
python -m black .
python -m ruff --fix .
}

function Invoke-Test
Expand Down
21 changes: 16 additions & 5 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ authors = [
]
license = { text = "MIT" }
readme = "README.md"
requires-python = ">=3.11"
requires-python = ">=3.9"
dependencies = [
"typing-extensions; python_version < '3.11'",
"requests",
"xmltodict",
]
Expand Down Expand Up @@ -48,16 +49,26 @@ requires = ["setuptools", "wheel"]
build-backend = "setuptools.build_meta"

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

[tool.ruff]
target-version = "py39"
line-length = 120
select = ["ALL"]
ignore = [
"PLC0414", # (Import alias does not rename original package) - Re-exporting
"PLC0414", # (Import alias does not rename original package) - Re-exporting
]

[tool.ruff.extend-per-file-ignores]
"docs/*" = [
"INP001", # (File `tests/*.py` is part of an implicit namespace package. Add an `__init__.py`.) - Docs are not modules
"FA102", # (Missing `from __future__ import annotations`, but uses PEP 585 collection) - Docs are actually built on the latest stable release of Python
]
"tests/*" = [
"INP001", # (File `tests/*.py` is part of an implicit namespace package. Add an `__init__.py`.) - Tests are not modules
"S101", # (Use of `assert` detected) - Yes, that's the point
]
target-version = "py311"
line-length = 120

[tool.ruff.isort]
known-first-party = ["letsbuilda.pypi"]
Expand Down
16 changes: 14 additions & 2 deletions src/letsbuilda/pypi/async_client.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,31 @@
"""The async client."""

from __future__ import annotations

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

import xmltodict

try:
from aiohttp import ClientSession
pass
except ImportError as error:
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 aiohttp import ClientSession

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
11 changes: 10 additions & 1 deletion src/letsbuilda/pypi/exceptions.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
"""Custom exceptions."""

from __future__ import annotations

from typing import Self
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


class PackageNotFoundError(Exception):
Expand Down
6 changes: 6 additions & 0 deletions src/letsbuilda/pypi/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,9 @@
from .models_json import JSONPackageMetadata as JSONPackageMetadata
from .models_package import Package as Package
from .models_rss import RSSPackageMetadata as RSSPackageMetadata

__all__ = [
"Package",
"JSONPackageMetadata",
"RSSPackageMetadata",
]
26 changes: 18 additions & 8 deletions src/letsbuilda/pypi/models/models_json.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
"""Models for JSON responses."""

from __future__ import annotations

from dataclasses import dataclass
from datetime import datetime
from typing import Self
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


@dataclass(frozen=True, slots=True)
@dataclass(frozen=True)
class Vulnerability:
"""Security vulnerability."""

Expand All @@ -27,7 +37,7 @@ def from_dict(cls: type[Self], data: dict) -> Self:
return cls(**data)


@dataclass(frozen=True, slots=True)
@dataclass(frozen=True)
class Downloads:
"""Release download counts."""

Expand All @@ -41,7 +51,7 @@ def from_dict(cls: type[Self], data: dict) -> Self:
return cls(**data)


@dataclass(frozen=True, slots=True)
@dataclass(frozen=True)
class Digests:
"""URL file digests."""

Expand All @@ -55,7 +65,7 @@ def from_dict(cls: type[Self], data: dict) -> Self:
return cls(**data)


@dataclass(frozen=True, slots=True)
@dataclass(frozen=True)
class URL:
"""Package release URL."""

Expand Down Expand Up @@ -84,7 +94,7 @@ def from_dict(cls: type[Self], data: dict) -> Self:
return cls(**data)


@dataclass(frozen=True, slots=True)
@dataclass(frozen=True)
class Info:
"""Package metadata internal info block."""

Expand Down Expand Up @@ -121,14 +131,14 @@ def from_dict(cls: type[Self], data: dict) -> Self:
return cls(**data)


@dataclass(frozen=True, slots=True)
@dataclass(frozen=True)
class JSONPackageMetadata:
"""Package metadata."""

info: Info
last_serial: int
urls: list[URL]
vulnerabilities: list["Vulnerability"]
vulnerabilities: list[Vulnerability]

@classmethod
def from_dict(cls: type[Self], data: dict) -> Self:
Expand Down
20 changes: 15 additions & 5 deletions src/letsbuilda/pypi/models/models_package.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,22 @@
"""Models for package metadata."""

from __future__ import annotations

from dataclasses import dataclass
from typing import Self
from typing import TYPE_CHECKING

if TYPE_CHECKING:
import sys

from .models_json import URL, JSONPackageMetadata

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


@dataclass(frozen=True, slots=True)
@dataclass(frozen=True)
class Distribution:
"""Metadata for a distribution."""

Expand All @@ -22,7 +32,7 @@ def from_json_api_data(cls: type[Self], data: URL) -> Self:
)


@dataclass(frozen=True, slots=True)
@dataclass(frozen=True)
class Release:
"""Metadata for a release."""

Expand All @@ -38,7 +48,7 @@ def from_json_api_data(cls: type[Self], data: JSONPackageMetadata) -> Self:
)


@dataclass(frozen=True, slots=True)
@dataclass(frozen=True)
class Package:
"""Metadata for a package."""

Expand Down
18 changes: 14 additions & 4 deletions src/letsbuilda/pypi/models/models_rss.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,22 @@
"""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 Self
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


@dataclass(frozen=True, slots=True)
@dataclass(frozen=True)
class RSSPackageMetadata:
"""RSS Package metadata."""

Expand All @@ -19,7 +29,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]) -> RSSPackageMetadata:
"""Build an instance from raw data."""
split_title = data.get("title").removesuffix(" added to PyPI").split()
title = split_title[0]
Expand Down
15 changes: 13 additions & 2 deletions src/letsbuilda/pypi/sync_client.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,25 @@
"""The sync client."""

from __future__ import annotations

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

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
Loading

0 comments on commit d2e2132

Please sign in to comment.