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

Small fixes #12

Merged
merged 7 commits into from
Feb 16, 2024
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
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
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added

- Metadata hook: add suport for additional-classifiers property #10

### Fixed

- Build hook: fix issue with extract_items when target_path is in a subfolder #11
- Tests: ensure tests are also ok when ran from a fork or outside any Git structure

## [0.1.0] - 2024-02-05

### Added
Expand Down
7 changes: 6 additions & 1 deletion 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 Expand Up @@ -63,6 +67,7 @@ NOTA: the `dependencies` attribute is not specific to our hook(s), it is a gener
| Variable | Required | Description |
|---|---|---|
| `additional-authors` | N | List of authors that will be appended to the automatic one |
| `additional-classifiers` | N | List of classifiers that will be appended to the automatic ones |
| `additional-keywords` | N | List of keywords that will be appended to the automatic ones |
| `kind` | N | If set to `scraper`, scrapers keywords will be automatically added as well |
| `organization` | N | Override organization (otherwise detected from Github repository to set author and keyword appropriately). Case-insentive. Supported values are `openzim`, `kiwix` and `offspot` |
Expand Down Expand Up @@ -208,7 +213,7 @@ Some sub-items in the Zip content can be removed afterwards.
| `source`| Y | URL of the online ZIP to download |
| `zip_paths` | Y | List of relative path in ZIP to select |
| `target_paths` | Y | Relative path of the target directory where selected items will be moved (relative to ZIP home folder) |
| `remove` | N | List of glob patterns of ZIP content to remove after extraction (must include the target paths, they are relative to the section `target_dir`) |
| `remove` | N | List of glob patterns of ZIP content to remove after extraction (must include the necessary `target_paths`, they are relative to the section `target_dir`) |
| `execute_after` | N | List of shell commands to execute once ZIP extraction is completed; actions are executed with the section `target_dir` as current working directory |

Nota:
Expand Down
36 changes: 16 additions & 20 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"
description = "openZIM hatch plugin to set metadata automatically and 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,38 @@ 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"]

[tool.hatch.metadata.hooks.openzim-metadata]
additional-keywords = ["hatch","plugin","download","file"]
preserve-classifiers = true # to be removed once 0.2.0 is used

[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 +234,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
13 changes: 8 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,10 +190,13 @@ 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)
shutil.move(src=str(item_src), dst=item_dst)

if "remove" in action_data:
Expand All @@ -211,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
4 changes: 3 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 Expand Up @@ -60,4 +61,5 @@ def update(root: str, config: dict, metadata: dict):
]
for python_version in get_python_versions(metadata["requires-python"]):
classifiers.append(f"Programming Language :: Python :: {python_version}")
classifiers.extend(config.get("additional-classifiers", []))
metadata["classifiers"] = classifiers
10 changes: 7 additions & 3 deletions src/hatch_openzim/metadata_hook.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from __future__ import annotations
from typing import Any, Dict

from hatchling.metadata.plugin.interface import MetadataHookInterface

Expand All @@ -14,6 +14,10 @@ class OpenzimMetadataHook(MetadataHookInterface):

PLUGIN_NAME = "openzim-metadata"

def update(self, metadata: dict):
def update(self, metadata: Dict[str, Any]):
"""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
6 changes: 6 additions & 0 deletions tests/configs/full.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ source="https://tmp.kiwix.org/ci/hatch_openzim_testsets/testset2.zip"
zip_paths=["keep1/file1.txt"]
target_paths=["file123.txt"]

[files.part2.actions.action5]
action="extract_items"
source="https://tmp.kiwix.org/ci/hatch_openzim_testsets/testset2.zip"
zip_paths=["keep1/file1.txt"]
target_paths=["action5/subfolder1/file123.txt"]

# part without any actions
[files.part3.config]
target_dir="part3"
Expand Down
11 changes: 11 additions & 0 deletions tests/configs/gitconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
[remote "origin"]
url = [email protected]:openzim/hatch-openzim.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "main"]
remote = origin
merge = refs/heads/main
3 changes: 2 additions & 1 deletion tests/test_files_install.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ def nominal_files():
"part1/somewhere/something.txt",
"part1/somewhere_else/something.txt",
"part2/file123.txt",
"part2/action5/subfolder1/file123.txt",
"part2/action2/file1.txt",
"part2/action2/file2.txt",
"part2/action3/file1.json",
Expand Down Expand Up @@ -52,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
Loading
Loading