Skip to content

Commit 270d9db

Browse files
authored
Merge pull request #13 from agoose77/feat-support-local
2 parents 5a1cbee + e151471 commit 270d9db

File tree

3 files changed

+92
-68
lines changed

3 files changed

+92
-68
lines changed

hatch_nodejs_version/metadata_source.py

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ def path(self) -> str:
4040
version_file = self.config.get("path", "package.json")
4141
if not isinstance(version_file, str):
4242
raise TypeError(
43-
"Option `path` for build hook `{}` must be a string".format(
43+
"Option `path` for metadata hook `{}` must be a string".format(
4444
self.PLUGIN_NAME
4545
)
4646
)
@@ -60,7 +60,7 @@ def fields(self) -> None | set[str]:
6060
isinstance(fields, list) and all(isinstance(f, str) for f in fields)
6161
):
6262
raise TypeError(
63-
"Option `fields` for build hook `{}` "
63+
"Option `fields` for metadata hook `{}` "
6464
"must be a list of strings".format(self.PLUGIN_NAME)
6565
)
6666
self.__fields = set(fields)
@@ -74,7 +74,7 @@ def contributors_as_maintainers(self) -> bool:
7474
)
7575
if not isinstance(contributors_as_maintainers, bool):
7676
raise TypeError(
77-
"Option `contributors-as-maintainers` for build hook `{}` "
77+
"Option `contributors-as-maintainers` for metadata hook `{}` "
7878
"must be a boolean".format(self.PLUGIN_NAME)
7979
)
8080
self.__contributors_as_maintainers = contributors_as_maintainers
@@ -87,7 +87,7 @@ def homepage_label(self) -> bool:
8787

8888
if not isinstance(homepage_label, str):
8989
raise TypeError(
90-
"Option `homepage-label` for build hook `{}` "
90+
"Option `homepage-label` for metadata hook `{}` "
9191
"must be a string".format(self.PLUGIN_NAME)
9292
)
9393
self.__homepage_label = homepage_label
@@ -100,9 +100,8 @@ def bugs_label(self) -> bool:
100100

101101
if not isinstance(bug_tracker_label, str):
102102
raise TypeError(
103-
"Option `bugs-label` for build hook `{}` must be a string".format(
104-
self.PLUGIN_NAME
105-
)
103+
"Option `bugs-label` for metadata hook `{}` "
104+
"must be a string".format(self.PLUGIN_NAME)
106105
)
107106
self.__bugs_label = bug_tracker_label
108107
return self.__bugs_label
@@ -114,7 +113,7 @@ def repository_label(self) -> bool:
114113

115114
if not isinstance(bug_tracker_label, str):
116115
raise TypeError(
117-
"Option `repository-label` for build hook `{}` "
116+
"Option `repository-label` for metadata hook `{}` "
118117
"must be a string".format(self.PLUGIN_NAME)
119118
)
120119
self.__repository_label = bug_tracker_label

hatch_nodejs_version/version_source.py

Lines changed: 56 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -4,45 +4,69 @@
44
import json
55
import os
66
import re
7-
from hatchling.version.source.plugin.interface import VersionSourceInterface
87

8+
from hatchling.version.source.plugin.interface import VersionSourceInterface
99

1010
# The Python-aware NodeJS version regex
1111
# This is very similar to `packaging.version.VERSION_PATTERN`, with a few changes:
1212
# - Don't accept underscores
13-
# - Only support three-component release and prerelease segments
13+
# - Only support four-component release, prerelease, and build segments
1414
# - Require - to indicate prerelease
1515
NODE_VERSION_PATTERN = r"""
16-
(?P<major>[0-9]+) # major
16+
(?P<major>[0-9]+) # major
1717
\.
18-
(?P<minor>[0-9]+) # minor
18+
(?P<minor>[0-9]+) # minor
1919
\.
20-
(?P<patch>[0-9]+) # patch
21-
(?P<pre> # pre-release
20+
(?P<patch>[0-9]+) # patch
21+
(?P<pre> # pre-release
2222
-
2323
(?P<pre_l>(a|b|c|rc|alpha|beta|pre|preview))
2424
[-\.]?
2525
(?P<pre_n>[0-9]+)?
2626
)?
27+
(?:
28+
\+
29+
(?P<build>
30+
[0-9A-Za-z][0-9A-Za-z-_]* # non-hyphen/dash leading identifier
31+
(?:
32+
(?:\.[0-9A-Za-z-_]+)* # dot-prefixed identifier segments
33+
\. # Final dot-delimited segment
34+
[0-9A-Za-z_-]* # non-hyphen/dash trailing identifier
35+
[0-9A-Za-z]
36+
)?
37+
)
38+
)?
2739
"""
2840

2941
# The NodeJS-aware Python version regex
3042
# This is very similar to `packaging.version.VERSION_PATTERN`, with a few changes:
31-
# - Only support three-component release and prerelease segments
43+
# - Only support four-component release, prerelease, and build segments
3244
PYTHON_VERSION_PATTERN = r"""
3345
v?
3446
(?:
35-
(?P<major>[0-9]+) # major
47+
(?P<major>[0-9]+) # major
3648
\.
37-
(?P<minor>[0-9]+) # minor
49+
(?P<minor>[0-9]+) # minor
3850
\.
39-
(?P<patch>[0-9]+) # patch
40-
(?P<pre> # pre-release
51+
(?P<patch>[0-9]+) # patch
52+
(?P<pre> # pre-release
4153
[-_\.]?
42-
(?P<pre_l>(a|b|c|rc|alpha|beta|pre|preview))
54+
(?P<pre_l>(alpha|beta|preview|a|b|c|rc|pre))
4355
[-_\.]?
4456
(?P<pre_n>[0-9]+)?
4557
)?
58+
(?:
59+
\+
60+
(?P<local>
61+
[0-9A-Za-z][0-9A-Za-z-_]* # non-hyphen/dash leading identifier
62+
(?:
63+
(?:\.[0-9A-Za-z-_]+)* # dot-prefixed identifier
64+
\.
65+
[0-9A-Za-z_-]* # non-hyphen/dash trailing identifier
66+
[0-9A-Za-z]
67+
)?
68+
)
69+
)?
4670
)
4771
"""
4872

@@ -55,6 +79,21 @@ def __init__(self, *args, **kwargs):
5579

5680
self.__path = None
5781

82+
@property
83+
def path(self):
84+
if self.__path is None:
85+
version_file = self.config.get("path", "package.json")
86+
if not isinstance(version_file, (str, bytes, os.PathLike)):
87+
raise TypeError(
88+
"Option `path` for version source `{}` must be a string".format(
89+
self.PLUGIN_NAME
90+
)
91+
)
92+
93+
self.__path = os.fspath(version_file)
94+
95+
return self.__path
96+
5897
@staticmethod
5998
def node_version_to_python(version: str) -> str:
6099
# NodeJS version strings are a near superset of Python version strings
@@ -74,6 +113,9 @@ def node_version_to_python(version: str) -> str:
74113
else:
75114
parts.append("{pre_l}{pre_n}".format_map(match))
76115

116+
if match["build"]:
117+
parts.append("+{build}".format_map(match))
118+
77119
return "".join(parts)
78120

79121
@staticmethod
@@ -95,23 +137,10 @@ def python_version_to_node(version: str) -> str:
95137
else:
96138
parts.append("-{pre_l}{pre_n}".format_map(match))
97139

140+
if match["local"]:
141+
parts.append("+{local}".format_map(match))
98142
return "".join(parts)
99143

100-
@property
101-
def path(self):
102-
if self.__path is None:
103-
version_file = self.config.get("path", "package.json")
104-
if not isinstance(version_file, str):
105-
raise TypeError(
106-
"Option `path` for build hook `{}` must be a string".format(
107-
self.PLUGIN_NAME
108-
)
109-
)
110-
111-
self.__path = version_file
112-
113-
return self.__path
114-
115144
def get_version_data(self):
116145
path = os.path.normpath(os.path.join(self.root, self.path))
117146
if not os.path.isfile(path):

tests/test_version_config.py

Lines changed: 29 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
# SPDX-FileCopyrightText: 2022-present Angus Hollands <[email protected]>
22
#
33
# SPDX-License-Identifier: MIT
4-
import pytest
54
import json
65

6+
import pytest
7+
78
from hatch_nodejs_version.version_source import NodeJSVersionSource
89

910
GOOD_NODE_PYTHON_VERSIONS = [
@@ -17,44 +18,40 @@
1718
("1.4.5-beta0", "1.4.5beta0"),
1819
("1.4.5-pre9", "1.4.5pre9"),
1920
("1.4.5-preview0", "1.4.5preview0"),
20-
]
21-
22-
BAD_NODE_VERSIONS = [
23-
"1.4",
24-
"1.4.5a0",
25-
"1.4.5-c0.post1",
26-
"1.4.5-rc0.post1.dev2",
27-
]
28-
BAD_PYTHON_VERSIONS = [
29-
"1.4",
30-
"1.4.5ab",
31-
"1.4.5-c0.smoke2",
32-
"1.4.5rc.post1@dev2",
21+
("1.4.5-preview0+build1.0.0", "1.4.5preview0+build1.0.0"),
22+
("1.4.5-preview0+build-1.0.0", "1.4.5preview0+build-1.0.0"),
23+
("1.4.5-preview0+good-1_0.0", "1.4.5preview0+good-1_0.0"),
3324
]
3425

3526

3627
class TestVersion:
37-
@pytest.mark.parametrize(
38-
"node_version, python_version",
39-
GOOD_NODE_PYTHON_VERSIONS,
40-
)
41-
def test_parse_correct(self, node_version, python_version):
42-
node_version_parsed = NodeJSVersionSource.python_version_to_node(python_version)
43-
assert node_version_parsed == node_version
44-
4528
@pytest.mark.parametrize(
4629
"python_version",
47-
BAD_PYTHON_VERSIONS,
30+
[
31+
"1.4",
32+
"1.4.5ab",
33+
"1.4.5-c0.smoke2",
34+
"1.4.5rc.post1@dev2",
35+
"1.4.5rc0.post1+-bad",
36+
"1.4.5rc0.post1+bad_",
37+
],
4838
)
4939
def test_parse_python_incorrect(self, python_version):
5040
with pytest.raises(ValueError, match=".* did not match regex"):
5141
NodeJSVersionSource.python_version_to_node(python_version)
5242

5343
@pytest.mark.parametrize(
5444
"node_version",
55-
BAD_NODE_VERSIONS,
45+
[
46+
"1.4",
47+
"1.4.5a0",
48+
"1.4.5-c0.post1",
49+
"1.4.5-rc0.post1.dev2",
50+
"1.4.5-rc0.post1+-bad",
51+
"1.4.5-rc0.post1+bad_",
52+
],
5653
)
57-
def test_parse_python_incorrect(self, node_version):
54+
def test_parse_node_incorrect(self, node_version):
5855
with pytest.raises(ValueError, match=".* did not match regex"):
5956
NodeJSVersionSource.node_version_to_python(node_version)
6057

@@ -79,7 +76,7 @@ def test_version_from_package(
7976
name = "my-app"
8077
dynamic = ["version"]
8178
[tool.hatch.version]
82-
source = "nodejs"
79+
source = "nodejs"
8380
"""
8481
)
8582
package_json = "package.json" if alt_package_json is None else alt_package_json
@@ -94,7 +91,7 @@ def test_version_from_package(
9491
config = {} if alt_package_json is None else {"path": alt_package_json}
9592
version_source = NodeJSVersionSource(project, config=config)
9693
data = version_source.get_version_data()
97-
assert data['version'] == python_version
94+
assert data["version"] == python_version
9895

9996
@pytest.mark.parametrize(
10097
"node_version, python_version",
@@ -117,15 +114,15 @@ def test_version_to_package(
117114
name = "my-app"
118115
dynamic = ["version"]
119116
[tool.hatch.version]
120-
source = "nodejs"
117+
source = "nodejs"
121118
"""
122119
)
123120
(project / package_json).write_text(
124-
f"""
125-
{{
121+
"""
122+
{
126123
"name": "my-app",
127124
"version": "0.0.0"
128-
}}
125+
}
129126
"""
130127
)
131128
config = {} if alt_package_json is None else {"path": alt_package_json}
@@ -134,5 +131,4 @@ def test_version_to_package(
134131
version_source.set_version(python_version, version_data)
135132

136133
written_package = json.loads((project / package_json).read_text())
137-
assert written_package['version'] == node_version
138-
134+
assert written_package["version"] == node_version

0 commit comments

Comments
 (0)