Skip to content

Commit e4da3d3

Browse files
authored
Merge pull request #9 from agoose77/feat-add-labels
2 parents 24d3606 + 8fb1651 commit e4da3d3

File tree

5 files changed

+136
-39
lines changed

5 files changed

+136
-39
lines changed

.flake8

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[flake8]
2+
max-line-length = 88
3+
extend-ignore = E203

.pre-commit-config.yaml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
repos:
2+
- repo: https://github.com/pre-commit/pre-commit-hooks
3+
rev: v2.3.0
4+
hooks:
5+
- id: check-yaml
6+
- id: end-of-file-fixer
7+
- id: trailing-whitespace
8+
- repo: https://github.com/psf/black
9+
rev: 22.8.0
10+
hooks:
11+
- id: black
12+
- repo: https://github.com/pycqa/isort
13+
rev: 5.10.1
14+
hooks:
15+
- id: isort
16+
name: isort
17+
- repo: https://github.com/pycqa/flake8
18+
rev: 5.0.4
19+
hooks:
20+
- id: flake8

README.md

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@
66

77
-----
88
This package provides two Hatch plugins:
9-
- [version source plugin](https://hatch.pypa.io/latest/plugins/version-source/) that reads/writes the package version from the `version` field of the NodeJS `package.json` file.
10-
- [metadata hook plugin](https://hatch.pypa.io/latest/plugins/metadata-hook/) that reads PEP 621 metadata from the NodeJS `package.json` file.
119

10+
- [version source plugin](https://hatch.pypa.io/latest/plugins/version-source/) that reads/writes the package version
11+
from the `version` field of the NodeJS `package.json` file.
12+
- [metadata hook plugin](https://hatch.pypa.io/latest/plugins/metadata-hook/) that reads PEP 621 metadata from the
13+
NodeJS `package.json` file.
1214

1315
**Table of Contents**
1416

@@ -45,17 +47,19 @@ The [version source plugin](https://hatch.pypa.io/latest/plugins/version-source/
4547
[version]
4648
source = "nodejs"
4749
```
48-
50+
4951
### Semver
5052

5153
The semver specification defines the following version sections:
54+
5255
- `major`
5356
- `minor`
5457
- `patch`
5558
- `pre-release`
5659
- `build`
5760

5861
Meanwhile, [PEP 440](https://peps.python.org/pep-0440/#version-scheme) defines:
62+
5963
- `epoch`
6064
- `major`
6165
- `minor`
@@ -64,21 +68,22 @@ Meanwhile, [PEP 440](https://peps.python.org/pep-0440/#version-scheme) defines:
6468
- `post-release`
6569
- `dev-release`
6670

67-
In order to ensure round-trip support, and ensure semantic consistency between NodeJS and Python, this plugin only accepts the common version parts:
71+
In order to ensure round-trip support, and ensure semantic consistency between NodeJS and Python, this plugin only
72+
accepts the common version parts:
73+
6874
- `major`
6975
- `minor`
7076
- `patch`
7177
- `pre-release`
7278

73-
e.g. `1.2.3-rc0`.
79+
e.g. `1.2.3-rc0`.
7480

7581
### Version source options
7682

7783
| Option | Type | Default | Description |
7884
|---------------| --- |---------------|--------------------------------------------|
7985
| `path` | `str` | `package.json` | Relative path to the `package.json` file. |
8086

81-
8287
## Metadata hook
8388

8489
The [metadata hook plugin](https://hatch.pypa.io/dev/plugins/metadata-hook/reference/) name is `nodejs`.
@@ -97,12 +102,14 @@ The [metadata hook plugin](https://hatch.pypa.io/dev/plugins/metadata-hook/refer
97102

98103
### Metadata hook options
99104

100-
| Option | Type | Default | Description |
101-
|-------------------------------|-----------------|----------------|------------------------------------------------------------------------------------------------------------|
102-
| `path` | `str` | `package.json` | Relative path to the `package.json` file. |
103-
| `fields` | `list` of `str` | `None` | Optional list of `pyproject.toml` fields to take from their counterparts in `package.json`. |
104-
| `contributors-as-maintainers` | `bool` | `True` | Whether contributors in `package.json` should be considered maintainers (otherwise, treat them as authors).|
105-
105+
| Option | Type | Default | Description |
106+
|-------------------------------|-----------------|------------------|-------------------------------------------------------------------------------------------------------------|
107+
| `path` | `str` | `"package.json"` | Relative path to the `package.json` file. |
108+
| `fields` | `list` of `str` | `None` | Optional list of `pyproject.toml` fields to take from their counterparts in `package.json`. |
109+
| `contributors-as-maintainers` | `bool` | `True` | Whether contributors in `package.json` should be considered maintainers (otherwise, treat them as authors). |
110+
| `bugs-label` | `str` | `"Bug Tracker"` | The key in the URLs table of `pyproject.toml` that is populated by the `bugs` field in `package.json` |
111+
| `homepage-label` | `str` | `"Homepage"` | The key in the URLs table of `pyproject.toml` that is populated by the `homepage` field in `package.json` |
112+
| `repository-label` | `str` | `"Repository"` | The key in the URLs table of `pyproject.toml` that is populated by the `repository` field in `package.json` |
106113

107114
## License
108115

hatch_nodejs_version/metadata_source.py

Lines changed: 58 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ def __init__(self, *args, **kwargs):
3030
self.__path = None
3131
self.__fields = None
3232
self.__contributors_as_maintainers = None
33+
self.__homepage_label = None
34+
self.__bugs_label = None
35+
self.__repository_label = None
3336

3437
@property
3538
def path(self) -> str:
@@ -57,21 +60,66 @@ def fields(self) -> None | set[str]:
5760
isinstance(fields, list) and all(isinstance(f, str) for f in fields)
5861
):
5962
raise TypeError(
60-
"Option `fields` for build hook `{}` must be a list of strings".format(
61-
self.PLUGIN_NAME
62-
)
63+
"Option `fields` for build hook `{}` "
64+
"must be a list of strings".format(self.PLUGIN_NAME)
6365
)
6466
self.__fields = set(fields)
6567
return self.__fields
6668

6769
@property
6870
def contributors_as_maintainers(self) -> bool:
6971
if self.__contributors_as_maintainers is None:
70-
self.__contributors_as_maintainers = self.config.get(
72+
contributors_as_maintainers = self.config.get(
7173
"contributors-as-maintainers", True
7274
)
75+
if not isinstance(contributors_as_maintainers, bool):
76+
raise TypeError(
77+
"Option `contributors-as-maintainers` for build hook `{}` "
78+
"must be a boolean".format(self.PLUGIN_NAME)
79+
)
80+
self.__contributors_as_maintainers = contributors_as_maintainers
7381
return self.__contributors_as_maintainers
7482

83+
@property
84+
def homepage_label(self) -> bool:
85+
if self.__homepage_label is None:
86+
homepage_label = self.config.get("homepage-label", "Homepage")
87+
88+
if not isinstance(homepage_label, str):
89+
raise TypeError(
90+
"Option `homepage-label` for build hook `{}` "
91+
"must be a string".format(self.PLUGIN_NAME)
92+
)
93+
self.__homepage_label = homepage_label
94+
return self.__homepage_label
95+
96+
@property
97+
def bugs_label(self) -> bool:
98+
if self.__bugs_label is None:
99+
bug_tracker_label = self.config.get("bugs-label", "Bug Tracker")
100+
101+
if not isinstance(bug_tracker_label, str):
102+
raise TypeError(
103+
"Option `bugs-label` for build hook `{}` must be a string".format(
104+
self.PLUGIN_NAME
105+
)
106+
)
107+
self.__bugs_label = bug_tracker_label
108+
return self.__bugs_label
109+
110+
@property
111+
def repository_label(self) -> bool:
112+
if self.__repository_label is None:
113+
bug_tracker_label = self.config.get("repository-label", "Repository")
114+
115+
if not isinstance(bug_tracker_label, str):
116+
raise TypeError(
117+
"Option `repository-label` for build hook `{}` "
118+
"must be a string".format(self.PLUGIN_NAME)
119+
)
120+
self.__repository_label = bug_tracker_label
121+
return self.__repository_label
122+
75123
def load_package_data(self):
76124
path = os.path.normpath(os.path.join(self.root, self.path))
77125
if not os.path.isfile(path):
@@ -129,19 +177,17 @@ def update(self, metadata: dict[str, Any]):
129177
authors = [self._parse_person(package["author"])]
130178

131179
if "contributors" in package:
132-
contributors = [
133-
self._parse_person(p) for p in package["contributors"]
134-
]
180+
contributors = [self._parse_person(p) for p in package["contributors"]]
135181
if self.contributors_as_maintainers:
136182
maintainers = contributors
137183
else:
138184
authors = [*(authors or []), *contributors]
139185

140186
if authors is not None:
141-
new_metadata['authors'] = authors
187+
new_metadata["authors"] = authors
142188

143189
if maintainers is not None:
144-
new_metadata['maintainers'] = maintainers
190+
new_metadata["maintainers"] = maintainers
145191

146192
if "keywords" in package:
147193
new_metadata["keywords"] = package["keywords"]
@@ -155,13 +201,13 @@ def update(self, metadata: dict[str, Any]):
155201
# Construct URLs
156202
urls = {}
157203
if "homepage" in package:
158-
urls["homepage"] = package["homepage"]
204+
urls[self.homepage_label] = package["homepage"]
159205
if "bugs" in package:
160206
bugs_url = self._parse_bugs(package["bugs"])
161207
if bugs_url is not None:
162-
urls["bug tracker"] = bugs_url
208+
urls[self.bugs_label] = bugs_url
163209
if "repository" in package:
164-
urls["repository"] = self._parse_repository(package["repository"])
210+
urls[self.repository_label] = self._parse_repository(package["repository"])
165211

166212
# Write URLs
167213
if urls:

tests/test_metadata_config.py

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55

66
from hatch_nodejs_version.metadata_source import NodeJSMetadataHook
77

8-
98
TRIVIAL_PYPROJECT_CONTENTS = """
109
[build-backend]
1110
requires = ["hatchling", "hatch-vcs"]
@@ -16,7 +15,7 @@
1615
[tool.hatch.metadata.hooks.nodejs]
1716
"""
1817

19-
DEMO_PACKAGE_CONTENTS = """
18+
TRIVIAL_PACKAGE_CONTENTS = """
2019
{
2120
"name": "my-app",
2221
"version": "1.0.0",
@@ -50,12 +49,12 @@
5049
}
5150
"""
5251

53-
EXPECTED_METADATA = {
52+
TRIVIAL_EXPECTED_METADATA = {
5453
"license": "MIT",
5554
"urls": {
56-
"bug tracker": "https://www.send-help.com",
57-
"repository": "https://github.com/some/code.git",
58-
"homepage": "https://where-the-heart-is.com",
55+
"Bug Tracker": "https://www.send-help.com",
56+
"Repository": "https://github.com/some/code.git",
57+
"Homepage": "https://where-the-heart-is.com",
5958
},
6059
"authors": [
6160
{
@@ -79,14 +78,14 @@ def test_all_metadata(self, project, alt_package_json):
7978
# Create a simple project
8079
package_json = "package.json" if alt_package_json is None else alt_package_json
8180
(project / "pyproject.toml").write_text(TRIVIAL_PYPROJECT_CONTENTS)
82-
(project / package_json).write_text(DEMO_PACKAGE_CONTENTS)
81+
(project / package_json).write_text(TRIVIAL_PACKAGE_CONTENTS)
8382

8483
config = {} if alt_package_json is None else {"path": alt_package_json}
8584
metadata = {}
8685
metadata_source = NodeJSMetadataHook(project, config=config)
8786
metadata_source.update(metadata)
8887

89-
assert metadata == EXPECTED_METADATA
88+
assert metadata == TRIVIAL_EXPECTED_METADATA
9089

9190
@pytest.mark.parametrize(
9291
"pyproject_field",
@@ -103,7 +102,7 @@ def test_all_metadata(self, project, alt_package_json):
103102
def test_subset_metadata(self, project, pyproject_field):
104103
# Create a simple project
105104
(project / "pyproject.toml").write_text(TRIVIAL_PYPROJECT_CONTENTS)
106-
(project / "package.json").write_text(DEMO_PACKAGE_CONTENTS)
105+
(project / "package.json").write_text(TRIVIAL_PACKAGE_CONTENTS)
107106

108107
config = {"fields": [pyproject_field]}
109108

@@ -113,26 +112,26 @@ def test_subset_metadata(self, project, pyproject_field):
113112

114113
assert pyproject_field in metadata
115114
assert len(metadata) == len(config["fields"])
116-
assert metadata[pyproject_field] == EXPECTED_METADATA[pyproject_field]
115+
assert metadata[pyproject_field] == TRIVIAL_EXPECTED_METADATA[pyproject_field]
117116

118117
def test_contributors_as_maintainers(self, project):
119118
# Create a simple project
120119
(project / "pyproject.toml").write_text(TRIVIAL_PYPROJECT_CONTENTS)
121-
(project / "package.json").write_text(DEMO_PACKAGE_CONTENTS)
120+
(project / "package.json").write_text(TRIVIAL_PACKAGE_CONTENTS)
122121

123122
metadata = {}
124123
metadata_source = NodeJSMetadataHook(
125124
project, config={"contributors-as-maintainers": True}
126125
)
127126
metadata_source.update(metadata)
128127

129-
assert metadata["authors"] == EXPECTED_METADATA["authors"]
130-
assert metadata["maintainers"] == EXPECTED_METADATA["maintainers"]
128+
assert metadata["authors"] == TRIVIAL_EXPECTED_METADATA["authors"]
129+
assert metadata["maintainers"] == TRIVIAL_EXPECTED_METADATA["maintainers"]
131130

132131
def test_contributors_as_authors(self, project):
133132
# Create a simple project
134133
(project / "pyproject.toml").write_text(TRIVIAL_PYPROJECT_CONTENTS)
135-
(project / "package.json").write_text(DEMO_PACKAGE_CONTENTS)
134+
(project / "package.json").write_text(TRIVIAL_PACKAGE_CONTENTS)
136135

137136
metadata = {}
138137
metadata_source = NodeJSMetadataHook(
@@ -142,5 +141,27 @@ def test_contributors_as_authors(self, project):
142141

143142
assert (
144143
metadata["authors"]
145-
== EXPECTED_METADATA["authors"] + EXPECTED_METADATA["maintainers"]
144+
== TRIVIAL_EXPECTED_METADATA["authors"]
145+
+ TRIVIAL_EXPECTED_METADATA["maintainers"]
146+
)
147+
148+
def test_labels(self, project):
149+
# Create a simple project
150+
(project / "pyproject.toml").write_text(TRIVIAL_PYPROJECT_CONTENTS)
151+
(project / "package.json").write_text(TRIVIAL_PACKAGE_CONTENTS)
152+
153+
metadata = {}
154+
metadata_source = NodeJSMetadataHook(
155+
project,
156+
config={
157+
"repository-label": "the-repository",
158+
"bugs-label": "the-bug-tracker",
159+
"homepage-label": "the-homepage",
160+
},
146161
)
162+
metadata_source.update(metadata)
163+
164+
urls = metadata["urls"]
165+
assert urls["the-repository"] == "https://github.com/some/code.git"
166+
assert urls["the-bug-tracker"] == "https://www.send-help.com"
167+
assert urls["the-homepage"] == "https://where-the-heart-is.com"

0 commit comments

Comments
 (0)