Skip to content

Commit 587fd93

Browse files
committed
Upgrade dependencies, bootstrap and fix typing issues
1 parent e1997e9 commit 587fd93

11 files changed

+70
-56
lines changed

Diff for: .pre-commit-config.yaml

+3-3
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,15 @@ repos:
77
- id: trailing-whitespace
88
- id: end-of-file-fixer
99
- repo: https://github.com/psf/black
10-
rev: "24.1.1"
10+
rev: "24.2.0"
1111
hooks:
1212
- id: black
1313
- repo: https://github.com/astral-sh/ruff-pre-commit
14-
rev: v0.2.0
14+
rev: v0.2.1
1515
hooks:
1616
- id: ruff
1717
- repo: https://github.com/RobertCraigie/pyright-python
18-
rev: v1.1.349
18+
rev: v1.1.350
1919
hooks:
2020
- id: pyright
2121
name: pyright (system)

Diff for: README.md

+4
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ This provides a [Hatch](https://pypi.org/project/hatch/)(ling) plugin for common
1313

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

16+
hatch-openzim adheres to openZIM's [Contribution Guidelines](https://github.com/openzim/overview/wiki/Contributing).
17+
18+
hatch-openzim has implemented openZIM's [Python bootstrap, conventions and policies](https://github.com/openzim/_python-bootstrap/docs/Policy.md) **v1.0.0**.
19+
1620
## Quick start
1721

1822
Assuming you have an openZIM project, you could use such a configuration in your `pyproject.toml`

Diff for: pyproject.toml

+11-19
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,13 @@
11
[build-system]
2-
requires = ["hatchling"]
2+
requires = ["hatchling", "hatch-openzim"]
33
build-backend = "hatchling.build"
44

55
[project]
66
name = "hatch-openzim"
7-
authors = [
8-
{ name = "Kiwix", email = "[email protected]" },
9-
]
10-
keywords = ["hatch","plugin","download","file"]
117
requires-python = ">=3.8,<3.13"
128
description = "Download files at build time"
139
readme = "README.md"
14-
license = {text = "GPL-3.0-or-later"}
15-
classifiers = [
10+
classifiers = [ # needs hatch-openzim 0.2.0 to make it dynamic with additional-classifiers
1611
"Framework :: Hatch",
1712
"Programming Language :: Python :: 3",
1813
"Programming Language :: Python :: 3.8",
@@ -25,38 +20,34 @@ classifiers = [
2520
dependencies = [
2621
"hatchling==1.21.1",
2722
"packaging==23.2",
28-
"toml==0.10.2", # to be replaced by tomllib once only 3.11 and above is supported
23+
"toml==0.10.2", # to be removed once only 3.11 and above is supported
2924
]
30-
dynamic = ["version"]
25+
dynamic = ["authors", "keywords", "license", "version", "urls"]
3126

3227
[project.optional-dependencies]
3328
scripts = [
3429
"invoke==2.2.0",
3530
]
3631
lint = [
37-
"black==24.1.1",
38-
"ruff==0.2.0",
32+
"black==24.2.0",
33+
"ruff==0.2.1",
3934
]
4035
check = [
41-
"pyright==1.1.349",
36+
"pyright==1.1.350",
4237
]
4338
test = [
4439
"pytest==8.0.0",
4540
"coverage==7.4.1",
4641
]
4742
dev = [
48-
"pre-commit==3.6.0",
49-
"debugpy==1.8.0",
43+
"pre-commit==3.6.1",
44+
"debugpy==1.8.1",
5045
"hatch-openzim[scripts]",
5146
"hatch-openzim[lint]",
5247
"hatch-openzim[test]",
5348
"hatch-openzim[check]",
5449
]
5550

56-
[project.urls]
57-
Homepage = "https://github.com/openzim/hatch-openzim"
58-
Donate = "https://www.kiwix.org/en/support-us/"
59-
6051
[project.entry-points.hatch]
6152
openzim = "hatch_openzim.hooks"
6253

@@ -239,4 +230,5 @@ include = ["src", "tests", "tasks.py"]
239230
exclude = [".env/**", ".venv/**"]
240231
extraPaths = ["src"]
241232
pythonVersion = "3.8"
242-
typeCheckingMode="basic"
233+
typeCheckingMode="strict"
234+
disableBytesTypePromotions = true

Diff for: src/hatch_openzim/build_hook.py

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
1+
from typing import Any, Dict
2+
13
from hatchling.builders.hooks.plugin.interface import BuildHookInterface
24

35
from hatch_openzim.files_install import process as process_files_install
46

57

6-
class OpenzimBuildHook(BuildHookInterface):
8+
class OpenzimBuildHook(
9+
BuildHookInterface # pyright: ignore[reportMissingTypeArgument]
10+
):
711
"""Hatch build hook to perform custom openzim actions
812
913
This hook performs:
@@ -12,7 +16,7 @@ class OpenzimBuildHook(BuildHookInterface):
1216

1317
PLUGIN_NAME = "openzim-build"
1418

15-
def initialize(self, version, build_data): # noqa: ARG002
19+
def initialize(self, version: str, build_data: Dict[str, Any]): # noqa: ARG002
1620
if "toml-config" in self.config:
1721
process_files_install(openzim_toml_location=self.config["toml-config"])
1822
else:

Diff for: src/hatch_openzim/files_install.py

+6-5
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from urllib.request import urlopen
88

99
try:
10-
import tomllib
10+
import tomllib # pyright: ignore[reportMissingTypeStubs]
1111
except ImportError: # pragma: no cover
1212
import toml as tomllib
1313

@@ -190,9 +190,10 @@ def _process_extract_items_action(
190190
return
191191

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

215216

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

223224

224-
def _extract_zip_from_url(url, extract_to):
225+
def _extract_zip_from_url(url: str, extract_to: Path):
225226
"""downloads ZIP from URL and extract in given directory
226227
227228
Nota: the ZIP is temporarily saved on disk (there is no convenient function

Diff for: src/hatch_openzim/metadata.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
from pathlib import Path
2+
from typing import Any, Dict
23

34
from hatch_openzim.utils import get_github_info, get_python_versions
45

56

6-
def update(root: str, config: dict, metadata: dict):
7+
def update(root: str, config: Dict[str, Any], metadata: Dict[str, Any]):
78
"""Update the project table's metadata."""
89

910
# Check for absence of metadata we will set + presence in the dynamic property

Diff for: src/hatch_openzim/metadata_hook.py

+8-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
from __future__ import annotations
22

3+
from typing import Any, Dict
4+
35
from hatchling.metadata.plugin.interface import MetadataHookInterface
46

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

1517
PLUGIN_NAME = "openzim-metadata"
1618

17-
def update(self, metadata: dict):
19+
def update(self, metadata: Dict[str, Any]): # noqa: UP006
1820
"""Update the project table's metadata."""
19-
update(root=self.root, config=self.config, metadata=metadata)
21+
update(
22+
root=self.root,
23+
config=self.config, # pyright: ignore[reportUnknownMemberType, reportUnknownArgumentType]
24+
metadata=metadata,
25+
)

Diff for: src/hatch_openzim/utils.py

+9-5
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import configparser
22
import re
3-
from collections import namedtuple
43
from pathlib import Path
5-
from typing import List
4+
from typing import List, NamedTuple, Optional
65

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

17-
GithubInfo = namedtuple("GithubInfo", ["homepage", "organization", "repository"])
16+
17+
class GithubInfo(NamedTuple):
18+
homepage: str
19+
organization: Optional[str]
20+
repository: Optional[str]
21+
1822

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

60-
major_versions = []
61-
minor_versions = []
64+
major_versions: list[str] = []
65+
minor_versions: list[str] = []
6266
for major in range(1, 10): # this will work up to Python 10 ...
6367
major_added = False
6468
last_minor = 100 # this supposes we will never have Python x.100

Diff for: tests/test_files_install.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ def test_no_arg():
5353
("other_stuff.toml"),
5454
],
5555
)
56-
def test_ignored_silently(config_file):
56+
def test_ignored_silently(config_file: str):
5757
"""Test cases where the config file is passed but there is no relevant content"""
5858
files_install.process(
5959
str((Path(__file__).parent / "configs" / config_file).absolute())

Diff for: tests/test_metadata.py

+8-8
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import os
22
import shutil
33
from pathlib import Path
4-
from typing import Dict, List, Union
4+
from typing import Any, Dict, List, Union
55

66
import pytest
77

@@ -131,7 +131,7 @@ def test_metadata_preserve_value(
131131
metadata: Metadata, metadata_key: str, root_folder: str
132132
):
133133
metadata[metadata_key] = f"some_value_for_{metadata_key}"
134-
config = {}
134+
config: Dict[str, Any] = {}
135135
config[f"preserve-{metadata_key}"] = True
136136
update(
137137
root=root_folder,
@@ -142,7 +142,7 @@ def test_metadata_preserve_value(
142142

143143

144144
def test_metadata_additional_keywords(metadata: Metadata, root_folder: str):
145-
config = {}
145+
config: Dict[str, Any] = {}
146146
config["additional-keywords"] = ["keyword1", "keyword2"]
147147
update(
148148
root=root_folder,
@@ -154,7 +154,7 @@ def test_metadata_additional_keywords(metadata: Metadata, root_folder: str):
154154

155155

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

177177

178178
def test_metadata_additional_authors(metadata: Metadata, root_folder: str):
179-
config = {}
179+
config: Dict[str, Any] = {}
180180
config["additional-authors"] = [{"email": "[email protected]", "name": "Some One"}]
181181
update(
182182
root=root_folder,
@@ -203,9 +203,9 @@ def test_metadata_additional_authors(metadata: Metadata, root_folder: str):
203203
],
204204
)
205205
def test_metadata_organization(
206-
organization: str, expected_result: str, metadata, root_folder: str
206+
organization: str, expected_result: str, metadata: Metadata, root_folder: str
207207
):
208-
config = {}
208+
config: Dict[str, Any] = {}
209209
if organization:
210210
config["organization"] = organization
211211
update(
@@ -224,7 +224,7 @@ def test_metadata_organization(
224224

225225

226226
def test_metadata_is_scraper(metadata: Metadata, root_folder: str):
227-
config = {}
227+
config: Dict[str, Any] = {}
228228
config["kind"] = "scraper"
229229
update(
230230
root=root_folder,

Diff for: tests/test_utils.py

+12-10
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
import tempfile
22
from contextlib import contextmanager
33
from pathlib import Path
4-
from typing import List
4+
from typing import Any, Callable, Generator, List
55

66
import pytest
77

88
from hatch_openzim.utils import GithubInfo, get_github_info, get_python_versions
99

1010

1111
@pytest.fixture
12-
def mock_git_config():
12+
def mock_git_config() -> Generator[Callable[[str, str], Any], None, None]:
1313
@contextmanager
1414
def _mock_git_config(git_origin_url: str, remote_name: str = "origin"):
1515
with tempfile.NamedTemporaryFile() as temp_file:
@@ -55,11 +55,11 @@ def _mock_git_config(git_origin_url: str, remote_name: str = "origin"):
5555
],
5656
)
5757
def test_get_github_project_homepage_valid_url(
58-
mock_git_config,
59-
git_url,
60-
expected_homepage_url,
61-
expected_organization,
62-
expected_repository,
58+
mock_git_config: Callable[[str], Any],
59+
git_url: str,
60+
expected_homepage_url: str,
61+
expected_organization: str,
62+
expected_repository: str,
6363
):
6464
with mock_git_config(git_url) as git_config_path:
6565
assert get_github_info(git_config_path=git_config_path) == GithubInfo(
@@ -69,7 +69,7 @@ def test_get_github_project_homepage_valid_url(
6969
)
7070

7171

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

8686

87-
def test_get_github_project_homepage_invalid_remote(mock_git_config):
87+
def test_get_github_project_homepage_invalid_remote(
88+
mock_git_config: Callable[[str, str], Any],
89+
):
8890
# Test the function with an invalid URL
8991
with mock_git_config(
90-
"https://github.com/oneuser/onerepo.git", remote_name="origin2"
92+
"https://github.com/oneuser/onerepo.git", "origin2"
9193
) as git_config_path:
9294
assert get_github_info(git_config_path=git_config_path) == GithubInfo(
9395
homepage="https://www.kiwix.org", organization=None, repository=None

0 commit comments

Comments
 (0)