Skip to content

Commit 77f67a0

Browse files
committed
wip: add support for metadata
1 parent 10d8ee1 commit 77f67a0

File tree

3 files changed

+115
-1
lines changed

3 files changed

+115
-1
lines changed

hatch_nodejs_version/hooks.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,14 @@
44
from hatchling.plugin import hookimpl
55

66
from .version_source import NodeJSVersionSource
7+
from .metadata_source import NodeJSMetadataSource
78

89

910
@hookimpl
1011
def hatch_register_version_source():
1112
return NodeJSVersionSource
13+
14+
15+
@hookimpl
16+
def hatch_register_metadata_source():
17+
return NodeJSMetadataSource
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
# SPDX-FileCopyrightText: 2022-present Angus Hollands <[email protected]>
2+
#
3+
# SPDX-License-Identifier: MIT
4+
from __future__ import annotations
5+
6+
import json
7+
import re
8+
import os.path
9+
import urllib.parse
10+
11+
from hatchling.metadata.plugin.interface import MetadataHookInterface
12+
13+
14+
AUTHOR_PATTERN = r"^([^<(]+?)?[ \t]*(?:<([^>(]+?)>)?[ \t]*(?:\(([^)]+?)\)|$)"
15+
REPOSITORY_PATTERN = r"^(?:(gist|bitbucket|gitlab|github):)?(.*?)$"
16+
REPOSITORY_TABLE = {
17+
"gitlab": "https://gitlab.com",
18+
"github": "https://github.com",
19+
"gist": "https://gist.github.com",
20+
"bitbucket": "https://bitbucket.org",
21+
}
22+
23+
24+
class NodeJSMetadataSource(MetadataHookInterface):
25+
PLUGIN_NAME = "nodejs"
26+
27+
def __init__(self, *args, **kwargs):
28+
super().__init__(*args, **kwargs)
29+
30+
self.__path = None
31+
32+
@property
33+
def path(self):
34+
if self.__path is None:
35+
version_file = self.config.get("path", "package.json")
36+
if not isinstance(version_file, str):
37+
raise TypeError(
38+
"Option `path` for build hook `{}` must be a string".format(
39+
self.PLUGIN_NAME
40+
)
41+
)
42+
43+
self.__path = version_file
44+
45+
return self.__path
46+
47+
def load_package_data(self):
48+
path = os.path.normpath(os.path.join(self.root, self.path))
49+
if not os.path.isfile(path):
50+
raise OSError(f"file does not exist: {self.path}")
51+
52+
with open(path, "r", encoding="utf-8") as f:
53+
return json.load(f)
54+
55+
def _parse_person(self, person: dict[str, str]) -> dict[str, str]:
56+
if {"url", "email"} & person.keys():
57+
result = {"name": person["name"]}
58+
if "email" in person:
59+
result["email"] = person["email"]
60+
else:
61+
name, email, _ = re.match(AUTHOR_PATTERN, person["name"])
62+
result = {"name": name}
63+
if email is not None:
64+
result["email"] = email
65+
66+
return result
67+
68+
def _parse_repository(self, repository: str | dict[str, str]) -> str:
69+
if isinstance(repository, str):
70+
kind, identifier = re.match(REPOSITORY_PATTERN, repository)
71+
if kind is None:
72+
kind = "github"
73+
return urllib.parse.urljoin(REPOSITORY_TABLE[kind], identifier)
74+
75+
return repository["url"]
76+
77+
def update(self, metadata):
78+
package = self.load_package_data()
79+
80+
if "author" in package:
81+
metadata["author"] = self._parse_person(package["author"])
82+
83+
if "contributors" in package:
84+
metadata["maintainers"] = [
85+
self._parse_person(p) for p in package["contributors"]
86+
]
87+
88+
if "keywords" in package:
89+
metadata["keywords"] = package["keywords"]
90+
91+
if "description" in package:
92+
metadata["description"] = package["description"]
93+
94+
if "license" in package:
95+
metadata["license"] = package["license"]
96+
97+
# Construct URLs
98+
urls = {}
99+
if "homepage" in package:
100+
urls["homepage"] = package["homepage"]
101+
if "bugs" in package:
102+
urls["bug tracker"] = package["bugs"]
103+
if "repository" in package:
104+
urls["repository"] = self._parse_repository(package["repository"])
105+
106+
# Write URLs
107+
if urls:
108+
metadata["urls"] = urls

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ authors = [
1010
{name = "Angus Hollands", email = "[email protected]"},
1111
]
1212
dependencies = []
13-
requires-python = ">=3.6"
13+
requires-python = ">= 3.7"
1414
readme = "README.md"
1515
license = {text = "MIT"}
1616

0 commit comments

Comments
 (0)