Skip to content

Commit

Permalink
Upgrade dependencies, bootstrap and fix typing issues
Browse files Browse the repository at this point in the history
  • Loading branch information
benoit74 committed Feb 16, 2024
1 parent 3d70199 commit 7dc426e
Show file tree
Hide file tree
Showing 11 changed files with 70 additions and 56 deletions.
6 changes: 3 additions & 3 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@ repos:
- id: trailing-whitespace
- id: end-of-file-fixer
- repo: https://github.com/psf/black
rev: "24.1.1"
rev: "24.2.0"
hooks:
- id: black
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.2.0
rev: v0.2.1
hooks:
- id: ruff
- repo: https://github.com/RobertCraigie/pyright-python
rev: v1.1.349
rev: v1.1.350
hooks:
- id: pyright
name: pyright (system)
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ This provides a [Hatch](https://pypi.org/project/hatch/)(ling) plugin for common

This plugin intentionally has few dependencies, using the Python standard library whenever possible and hence limiting footprint to a minimum.

hatch-openzim adheres to openZIM's [Contribution Guidelines](https://github.com/openzim/overview/wiki/Contributing).

hatch-openzim has implemented openZIM's [Python bootstrap, conventions and policies](https://github.com/openzim/_python-bootstrap/docs/Policy.md) **v1.0.0**.

## Quick start

Assuming you have an openZIM project, you could use such a configuration in your `pyproject.toml`
Expand Down
30 changes: 11 additions & 19 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,18 +1,13 @@
[build-system]
requires = ["hatchling"]
requires = ["hatchling", "hatch-openzim"]
build-backend = "hatchling.build"

[project]
name = "hatch-openzim"
authors = [
{ name = "Kiwix", email = "[email protected]" },
]
keywords = ["hatch","plugin","download","file"]
requires-python = ">=3.8,<3.13"
description = "Download files at build time"
readme = "README.md"
license = {text = "GPL-3.0-or-later"}
classifiers = [
classifiers = [ # needs hatch-openzim 0.2.0 to make it dynamic with additional-classifiers
"Framework :: Hatch",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.8",
Expand All @@ -25,38 +20,34 @@ classifiers = [
dependencies = [
"hatchling==1.21.1",
"packaging==23.2",
"toml==0.10.2", # to be replaced by tomllib once only 3.11 and above is supported
"toml==0.10.2", # to be removed once only 3.11 and above is supported
]
dynamic = ["version"]
dynamic = ["authors", "keywords", "license", "version", "urls"]

[project.optional-dependencies]
scripts = [
"invoke==2.2.0",
]
lint = [
"black==24.1.1",
"ruff==0.2.0",
"black==24.2.0",
"ruff==0.2.1",
]
check = [
"pyright==1.1.349",
"pyright==1.1.350",
]
test = [
"pytest==8.0.0",
"coverage==7.4.1",
]
dev = [
"pre-commit==3.6.0",
"debugpy==1.8.0",
"pre-commit==3.6.1",
"debugpy==1.8.1",
"hatch-openzim[scripts]",
"hatch-openzim[lint]",
"hatch-openzim[test]",
"hatch-openzim[check]",
]

[project.urls]
Homepage = "https://github.com/openzim/hatch-openzim"
Donate = "https://www.kiwix.org/en/support-us/"

[project.entry-points.hatch]
openzim = "hatch_openzim.hooks"

Expand Down Expand Up @@ -239,4 +230,5 @@ include = ["src", "tests", "tasks.py"]
exclude = [".env/**", ".venv/**"]
extraPaths = ["src"]
pythonVersion = "3.8"
typeCheckingMode="basic"
typeCheckingMode="strict"
disableBytesTypePromotions = true
8 changes: 6 additions & 2 deletions src/hatch_openzim/build_hook.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
from typing import Any, Dict

from hatchling.builders.hooks.plugin.interface import BuildHookInterface

from hatch_openzim.files_install import process as process_files_install


class OpenzimBuildHook(BuildHookInterface):
class OpenzimBuildHook(
BuildHookInterface # pyright: ignore[reportMissingTypeArgument]
):
"""Hatch build hook to perform custom openzim actions
This hook performs:
Expand All @@ -12,7 +16,7 @@ class OpenzimBuildHook(BuildHookInterface):

PLUGIN_NAME = "openzim-build"

def initialize(self, version, build_data): # noqa: ARG002
def initialize(self, version: str, build_data: Dict[str, Any]): # noqa: ARG002
if "toml-config" in self.config:
process_files_install(openzim_toml_location=self.config["toml-config"])
else:
Expand Down
11 changes: 6 additions & 5 deletions src/hatch_openzim/files_install.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from urllib.request import urlopen

try:
import tomllib
import tomllib # pyright: ignore[reportMissingTypeStubs]
except ImportError: # pragma: no cover
import toml as tomllib

Expand Down Expand Up @@ -190,9 +190,10 @@ def _process_extract_items_action(
return

with tempfile.TemporaryDirectory() as tempdir:
_extract_zip_from_url(url=source, extract_to=tempdir)
tempath = Path(tempdir)
_extract_zip_from_url(url=source, extract_to=tempath)
for index, zip_path in enumerate(zip_paths):
item_src = Path(tempdir) / str(zip_path)
item_src = tempath / str(zip_path)
item_dst = base_target_dir / str(target_paths[index])
if item_dst.parent and not item_dst.parent.exists():
item_dst.parent.mkdir(parents=True, exist_ok=True)
Expand All @@ -213,15 +214,15 @@ def _remove_items(directory: Path, globs: List[str]):
shutil.rmtree(match)


def _download_file(url, download_to):
def _download_file(url: str, download_to: Path):
"""downloads a file to a given location"""
if not url.startswith(("http:", "https:")):
raise ValueError("URL must start with 'http:' or 'https:'")
with urlopen(url) as response, open(download_to, "wb") as file: # noqa: S310
file.write(response.read())


def _extract_zip_from_url(url, extract_to):
def _extract_zip_from_url(url: str, extract_to: Path):
"""downloads ZIP from URL and extract in given directory
Nota: the ZIP is temporarily saved on disk (there is no convenient function
Expand Down
3 changes: 2 additions & 1 deletion src/hatch_openzim/metadata.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
from pathlib import Path
from typing import Any, Dict

from hatch_openzim.utils import get_github_info, get_python_versions


def update(root: str, config: dict, metadata: dict):
def update(root: str, config: Dict[str, Any], metadata: Dict[str, Any]):
"""Update the project table's metadata."""

# Check for absence of metadata we will set + presence in the dynamic property
Expand Down
10 changes: 8 additions & 2 deletions src/hatch_openzim/metadata_hook.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from __future__ import annotations

from typing import Any, Dict

from hatchling.metadata.plugin.interface import MetadataHookInterface

from hatch_openzim.metadata import update
Expand All @@ -14,6 +16,10 @@ class OpenzimMetadataHook(MetadataHookInterface):

PLUGIN_NAME = "openzim-metadata"

def update(self, metadata: dict):
def update(self, metadata: Dict[str, Any]): # noqa: UP006
"""Update the project table's metadata."""
update(root=self.root, config=self.config, metadata=metadata)
update(
root=self.root,
config=self.config, # pyright: ignore[reportUnknownMemberType, reportUnknownArgumentType]
metadata=metadata,
)
14 changes: 9 additions & 5 deletions src/hatch_openzim/utils.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import configparser
import re
from collections import namedtuple
from pathlib import Path
from typing import List
from typing import List, NamedTuple, Optional

from packaging.specifiers import SpecifierSet
from packaging.version import Version
Expand All @@ -14,7 +13,12 @@
r"""(?P<repository>.*?)(?:.git)?$"""
)

GithubInfo = namedtuple("GithubInfo", ["homepage", "organization", "repository"])

class GithubInfo(NamedTuple):
homepage: str
organization: Optional[str]
repository: Optional[str]


DEFAULT_GITHUB_INFO = GithubInfo(
homepage="https://www.kiwix.org", organization=None, repository=None
Expand Down Expand Up @@ -57,8 +61,8 @@ def get_python_versions(requires_python: str) -> List[str]:
last_py1_minor = 6
last_py2_minor = 7

major_versions = []
minor_versions = []
major_versions: list[str] = []
minor_versions: list[str] = []
for major in range(1, 10): # this will work up to Python 10 ...
major_added = False
last_minor = 100 # this supposes we will never have Python x.100
Expand Down
2 changes: 1 addition & 1 deletion tests/test_files_install.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def test_no_arg():
("other_stuff.toml"),
],
)
def test_ignored_silently(config_file):
def test_ignored_silently(config_file: str):
"""Test cases where the config file is passed but there is no relevant content"""
files_install.process(
str((Path(__file__).parent / "configs" / config_file).absolute())
Expand Down
16 changes: 8 additions & 8 deletions tests/test_metadata.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import os
import shutil
from pathlib import Path
from typing import Dict, List, Union
from typing import Any, Dict, List, Union

import pytest

Expand Down Expand Up @@ -131,7 +131,7 @@ def test_metadata_preserve_value(
metadata: Metadata, metadata_key: str, root_folder: str
):
metadata[metadata_key] = f"some_value_for_{metadata_key}"
config = {}
config: Dict[str, Any] = {}
config[f"preserve-{metadata_key}"] = True
update(
root=root_folder,
Expand All @@ -142,7 +142,7 @@ def test_metadata_preserve_value(


def test_metadata_additional_keywords(metadata: Metadata, root_folder: str):
config = {}
config: Dict[str, Any] = {}
config["additional-keywords"] = ["keyword1", "keyword2"]
update(
root=root_folder,
Expand All @@ -154,7 +154,7 @@ def test_metadata_additional_keywords(metadata: Metadata, root_folder: str):


def test_metadata_additional_classifiers(metadata: Metadata, root_folder: str):
config = {}
config: Dict[str, Any] = {}
config["additional-classifiers"] = [
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
Expand All @@ -176,7 +176,7 @@ def test_metadata_additional_classifiers(metadata: Metadata, root_folder: str):


def test_metadata_additional_authors(metadata: Metadata, root_folder: str):
config = {}
config: Dict[str, Any] = {}
config["additional-authors"] = [{"email": "[email protected]", "name": "Some One"}]
update(
root=root_folder,
Expand All @@ -203,9 +203,9 @@ def test_metadata_additional_authors(metadata: Metadata, root_folder: str):
],
)
def test_metadata_organization(
organization: str, expected_result: str, metadata, root_folder: str
organization: str, expected_result: str, metadata: Metadata, root_folder: str
):
config = {}
config: Dict[str, Any] = {}
if organization:
config["organization"] = organization
update(
Expand All @@ -224,7 +224,7 @@ def test_metadata_organization(


def test_metadata_is_scraper(metadata: Metadata, root_folder: str):
config = {}
config: Dict[str, Any] = {}
config["kind"] = "scraper"
update(
root=root_folder,
Expand Down
22 changes: 12 additions & 10 deletions tests/test_utils.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import tempfile
from contextlib import contextmanager
from pathlib import Path
from typing import List
from typing import Any, Callable, Generator, List

import pytest

from hatch_openzim.utils import GithubInfo, get_github_info, get_python_versions


@pytest.fixture
def mock_git_config():
def mock_git_config() -> Generator[Callable[[str, str], Any], None, None]:
@contextmanager
def _mock_git_config(git_origin_url: str, remote_name: str = "origin"):
with tempfile.NamedTemporaryFile() as temp_file:
Expand Down Expand Up @@ -55,11 +55,11 @@ def _mock_git_config(git_origin_url: str, remote_name: str = "origin"):
],
)
def test_get_github_project_homepage_valid_url(
mock_git_config,
git_url,
expected_homepage_url,
expected_organization,
expected_repository,
mock_git_config: Callable[[str], Any],
git_url: str,
expected_homepage_url: str,
expected_organization: str,
expected_repository: str,
):
with mock_git_config(git_url) as git_config_path:
assert get_github_info(git_config_path=git_config_path) == GithubInfo(
Expand All @@ -69,7 +69,7 @@ def test_get_github_project_homepage_valid_url(
)


def test_get_github_project_homepage_invalid_url(mock_git_config):
def test_get_github_project_homepage_invalid_url(mock_git_config: Callable[[str], Any]):
# Test the function with an invalid URL
with mock_git_config("http://github.com/oneuser/onerepo.git") as git_config_path:
assert get_github_info(git_config_path=git_config_path) == GithubInfo(
Expand All @@ -84,10 +84,12 @@ def test_get_github_project_missing_git_config():
)


def test_get_github_project_homepage_invalid_remote(mock_git_config):
def test_get_github_project_homepage_invalid_remote(
mock_git_config: Callable[[str, str], Any],
):
# Test the function with an invalid URL
with mock_git_config(
"https://github.com/oneuser/onerepo.git", remote_name="origin2"
"https://github.com/oneuser/onerepo.git", "origin2"
) as git_config_path:
assert get_github_info(git_config_path=git_config_path) == GithubInfo(
homepage="https://www.kiwix.org", organization=None, repository=None
Expand Down

0 comments on commit 7dc426e

Please sign in to comment.