From b8cfc50f171942b3ab654bc2785ee013d0cbf481 Mon Sep 17 00:00:00 2001 From: benoit74 Date: Fri, 2 Feb 2024 10:24:28 +0100 Subject: [PATCH 1/3] Add support for more precise metadata --- README.md | 16 +++++++++-- src/hatch_openzim/metadata.py | 22 ++++++++++---- src/hatch_openzim/utils.py | 21 +++++++++----- tests/test_metadata.py | 54 ++++++++++++++++++++++++++++++++--- tests/test_utils.py | 38 ++++++++++++++---------- 5 files changed, 117 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index d9765fc..c9ef9f6 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,16 @@ dynamic = ["authors", "classifiers", "keywords", "license", "version", "urls"] additional-keywords = ["awesome"] # some additional keywords kind = "scraper" # indicate this is a scraper, so that additional keywords are added +# Additional author #1 +[[tool.hatch.metadata.hooks.openzim-metadata.additional-authors]] +name="Bob" +email="bob@acme.com" + +# Additional author #2 +[[tool.hatch.metadata.hooks.openzim-metadata.additional-authors]] +name="Alice" +email="alice@acme.com" + # Enable the hatch-openzim build hook to install files (e.g. JS libs) at build time. [tool.hatch.build.hooks.openzim-build] toml-config = "openzim.toml" # optional location of the configuration file @@ -52,13 +62,15 @@ 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-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` | | `preserve-authors` | N | Boolean indicating that we do not want to set `authors` metadata but use the ones of `pyproject.toml` | | `preserve-classifiers` | N | Boolean indicating that we do not want to set `classifiers` metadata but use the ones of `pyproject.toml` | | `preserve-keywords` | N | Boolean indicating that we do not want to set `keywords` metadata but use the ones of `pyproject.toml` | | `preserve-license` | N | Boolean indicating that we do not want to set `license` metadata but use the one of `pyproject.toml` | | `preserve-urls` | N | Boolean indicating that we do not want to set `urls` metadata but use the ones of `pyproject.toml` | -| `additional_keywords` | N | List of keywords that will be appended to the automatically added ones | -| `kind` | N | If set to `scraper`, scrapers keywords will be automatically added as well | ### Behavior diff --git a/src/hatch_openzim/metadata.py b/src/hatch_openzim/metadata.py index 84f5203..9530f37 100644 --- a/src/hatch_openzim/metadata.py +++ b/src/hatch_openzim/metadata.py @@ -1,6 +1,6 @@ from pathlib import Path -from hatch_openzim.utils import get_github_project_homepage, get_python_versions +from hatch_openzim.utils import get_github_info, get_python_versions def update(root: str, config: dict, metadata: dict): @@ -23,19 +23,29 @@ def update(root: str, config: dict, metadata: dict): "openzim metadata hook." ) + github_info = get_github_info(git_config_path=Path(root) / ".git/config") + + organization = config.get("organization", github_info.organization) + if not config.get("preserve-urls", False): metadata["urls"] = { "Donate": "https://www.kiwix.org/en/support-us/", - "Homepage": get_github_project_homepage( - git_config_path=Path(root) / ".git/config" - ), + "Homepage": github_info.homepage, } if not config.get("preserve-authors", False): - metadata["authors"] = [{"name": "Kiwix", "email": "dev@kiwix.org"}] + if str(organization).lower() in ("kiwix", "offspot"): + authors = [{"name": "Kiwix", "email": "dev@kiwix.org"}] + else: + authors = [{"name": "openZIM", "email": "dev@openzim.org"}] + authors.extend(config.get("additional-authors", [])) + metadata["authors"] = authors if not config.get("preserve-keywords", False): - keywords = ["kiwix"] + if str(organization).lower() in ("kiwix", "offspot"): + keywords = ["kiwix"] + else: + keywords = ["openzim"] if config.get("kind", "") == "scraper": keywords.extend(["zim", "offline"]) keywords.extend(config.get("additional-keywords", [])) diff --git a/src/hatch_openzim/utils.py b/src/hatch_openzim/utils.py index 35c8fa2..7cfab79 100644 --- a/src/hatch_openzim/utils.py +++ b/src/hatch_openzim/utils.py @@ -1,5 +1,6 @@ import configparser import re +from collections import namedtuple from pathlib import Path from typing import List @@ -13,12 +14,16 @@ r"""(?P.*?)(?:.git)?$""" ) -DEFAULT_GITHUB_PROJECT_HOMEPAGE = "https://www.kiwix.org" +GithubInfo = namedtuple("GithubInfo", ["homepage", "organization", "repository"]) + +DEFAULT_GITHUB_INFO = GithubInfo( + homepage="https://www.kiwix.org", organization=None, repository=None +) -def get_github_project_homepage(git_config_path: Path, remote: str = "origin") -> str: +def get_github_info(git_config_path: Path, remote: str = "origin") -> GithubInfo: if not git_config_path.exists() or not git_config_path.is_file(): - return DEFAULT_GITHUB_PROJECT_HOMEPAGE + return DEFAULT_GITHUB_INFO try: config = configparser.ConfigParser() @@ -27,13 +32,15 @@ def get_github_project_homepage(git_config_path: Path, remote: str = "origin") - match = REMOTE_REGEXP.match(git_remote_url) if not match: raise Exception(f"Unexpected remote url: {git_remote_url}") - return ( - f"https://github.com/{match.group('organization')}/" - f"{match.group('repository')}" + return GithubInfo( + homepage=f"https://github.com/{match.group('organization')}/" + f"{match.group('repository')}", + organization=match.group("organization"), + repository=match.group("repository"), ) except Exception as exc: logger.error("Failed to read Github URL", exc_info=exc) - return DEFAULT_GITHUB_PROJECT_HOMEPAGE + return DEFAULT_GITHUB_INFO def get_python_versions(requires_python: str) -> List[str]: diff --git a/tests/test_metadata.py b/tests/test_metadata.py index 8169b71..77c4410 100644 --- a/tests/test_metadata.py +++ b/tests/test_metadata.py @@ -32,14 +32,14 @@ def test_metadata_nominal(metadata): metadata=metadata, ) - assert metadata["authors"] == [{"email": "dev@kiwix.org", "name": "Kiwix"}] + assert metadata["authors"] == [{"email": "dev@openzim.org", "name": "openZIM"}] assert metadata["classifiers"] == [ "License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", ] - assert metadata["keywords"] == ["kiwix"] + assert metadata["keywords"] == ["openzim"] assert metadata["license"] == {"text": "GPL-3.0-or-later"} assert metadata["urls"] == { "Donate": "https://www.kiwix.org/en/support-us/", @@ -126,7 +126,53 @@ def test_metadata_additional_keywords(metadata): metadata=metadata, ) # we compare sets because order is not relevant - assert set(metadata["keywords"]) == {"kiwix", "keyword1", "keyword2"} + assert set(metadata["keywords"]) == {"openzim", "keyword1", "keyword2"} + + +def test_metadata_additional_authors(metadata): + config = {} + config["additional-authors"] = [{"email": "someone@acme.org", "name": "Some One"}] + update( + root=str(Path(os.path.dirname(os.path.abspath(__file__))).parent), + config=config, + metadata=metadata, + ) + # we compare sets because order is not relevant + assert metadata["authors"] == [ + {"email": "dev@openzim.org", "name": "openZIM"}, + {"email": "someone@acme.org", "name": "Some One"}, + ] + + +@pytest.mark.parametrize( + "organization, expected_result", + [ + ("kiwix", "kiwix"), + ("Kiwix", "kiwix"), + ("openzim", "openzim"), + ("openZIM", "openzim"), + ("offspot", "kiwix"), + ("unknown", "openzim"), + (None, "openzim"), + ], +) +def test_metadata_organization(organization, expected_result, metadata): + config = {} + if organization: + config["organization"] = organization + update( + root=str(Path(os.path.dirname(os.path.abspath(__file__))).parent), + config=config, + metadata=metadata, + ) + if expected_result == "kiwix": + assert metadata["authors"] == [{"email": "dev@kiwix.org", "name": "Kiwix"}] + assert metadata["keywords"] == ["kiwix"] + elif expected_result == "openzim": + assert metadata["authors"] == [{"email": "dev@openzim.org", "name": "openZIM"}] + assert metadata["keywords"] == ["openzim"] + else: + raise Exception(f"Unexpected expected result: {expected_result}") def test_metadata_is_scraper(metadata): @@ -138,4 +184,4 @@ def test_metadata_is_scraper(metadata): metadata=metadata, ) # we compare sets because order is not relevant - assert set(metadata["keywords"]) == {"kiwix", "offline", "zim"} + assert set(metadata["keywords"]) == {"openzim", "offline", "zim"} diff --git a/tests/test_utils.py b/tests/test_utils.py index 887aa54..f0ce928 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -5,7 +5,7 @@ import pytest -from hatch_openzim.utils import get_github_project_homepage, get_python_versions +from hatch_openzim.utils import GithubInfo, get_github_info, get_python_versions @pytest.fixture @@ -32,46 +32,55 @@ def _mock_git_config(git_origin_url: str, remote_name: str = "origin"): @pytest.mark.parametrize( - "git_url, expected_homepage_url", + "git_url, expected_homepage_url, expected_organization, expected_repository", [ ( "https://github.com/oneuser/onerepo.git", "https://github.com/oneuser/onerepo", + "oneuser", + "onerepo", ), ( "https://github.com/oneuser/onerepo", "https://github.com/oneuser/onerepo", + "oneuser", + "onerepo", ), ( "git@github.com:oneuser/one-repo.git", "https://github.com/oneuser/one-repo", + "oneuser", + "one-repo", ), ], ) def test_get_github_project_homepage_valid_url( - mock_git_config, git_url, expected_homepage_url + mock_git_config, + git_url, + expected_homepage_url, + expected_organization, + expected_repository, ): with mock_git_config(git_url) as git_config_path: - assert ( - get_github_project_homepage(git_config_path=git_config_path) - == expected_homepage_url + assert get_github_info(git_config_path=git_config_path) == GithubInfo( + homepage=expected_homepage_url, + organization=expected_organization, + repository=expected_repository, ) def test_get_github_project_homepage_invalid_url(mock_git_config): # Test the function with an invalid URL with mock_git_config("http://github.com/oneuser/onerepo.git") as git_config_path: - assert ( - get_github_project_homepage(git_config_path=git_config_path) - == "https://www.kiwix.org" + assert get_github_info(git_config_path=git_config_path) == GithubInfo( + homepage="https://www.kiwix.org", organization=None, repository=None ) def test_get_github_project_missing_git_config(): # Test the function with an invalid URL - assert ( - get_github_project_homepage(git_config_path=Path("i_m_not_here.config")) - == "https://www.kiwix.org" + assert get_github_info(git_config_path=Path("i_m_not_here.config")) == GithubInfo( + homepage="https://www.kiwix.org", organization=None, repository=None ) @@ -80,9 +89,8 @@ def test_get_github_project_homepage_invalid_remote(mock_git_config): with mock_git_config( "https://github.com/oneuser/onerepo.git", remote_name="origin2" ) as git_config_path: - assert ( - get_github_project_homepage(git_config_path=git_config_path) - == "https://www.kiwix.org" + assert get_github_info(git_config_path=git_config_path) == GithubInfo( + homepage="https://www.kiwix.org", organization=None, repository=None ) From faf99225821bef233dec2fdbc3697c92638063aa Mon Sep 17 00:00:00 2001 From: benoit74 Date: Fri, 2 Feb 2024 10:53:29 +0100 Subject: [PATCH 2/3] Ignore security warning --- src/hatch_openzim/files_install.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hatch_openzim/files_install.py b/src/hatch_openzim/files_install.py index 5df1a6e..15b98c3 100644 --- a/src/hatch_openzim/files_install.py +++ b/src/hatch_openzim/files_install.py @@ -112,7 +112,7 @@ def _process_execute_after(base_target_dir: Path, actions: List[str]): logger.info(f" Executing '{action}'") process = subprocess.run( action, - shell=True, # noqa: S602 + shell=True, # noqa: S602 # nosec: B602 cwd=base_target_dir, text=True, check=True, From 631f953a75dde81f3b8392e1e239f1457583693b Mon Sep 17 00:00:00 2001 From: benoit74 Date: Fri, 2 Feb 2024 11:11:16 +0100 Subject: [PATCH 3/3] Fix logging issue --- src/hatch_openzim/shared.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/hatch_openzim/shared.py b/src/hatch_openzim/shared.py index 5f2faec..01f6ad2 100644 --- a/src/hatch_openzim/shared.py +++ b/src/hatch_openzim/shared.py @@ -1,6 +1,16 @@ import logging import os +import sys +DEFAULT_FORMAT = "%(name)s:%(levelname)s:%(message)s" + +# create logger logger = logging.getLogger("hatch_openzim") +logger.setLevel(logging.DEBUG) + +# setup console logging +console_handler = logging.StreamHandler(sys.stdout) +console_handler.setFormatter(logging.Formatter(DEFAULT_FORMAT)) log_level = logging.getLevelName(os.getenv("HATCH_OPENZIM_LOG_LEVEL", "INFO")) -logger.setLevel(log_level) +console_handler.setLevel(log_level) +logger.addHandler(console_handler)