Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backport support for up to Python 3.9 #42

Merged
merged 9 commits into from
Jul 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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