Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ Add file source with regex search #34

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,14 @@ Alternatively, it can read it from a **git tag**, set with a GitHub release or w
$ git tag 0.1.0
```

Or it can read it from a **file** and a custom **regex** search.
```md
# Example Changelog

## 0.0.1 (2023-10-26)
- Added feature
```

🚨 Consider this in the alpha stage. Read the warning below.

## When to use
Expand Down Expand Up @@ -112,6 +120,45 @@ Building my-awesome-package (0.1.3)
- Built my-awesome-package-0.1.3-py3-none-any.whl
```

### Set the version in a file

Set your package version from a file content, for example a `VERSION` file:
```
0.0.1
```

Then edit your `pyproject.toml` and add a section:
```toml
[tool.poetry-version-plugin]
source = "file"
path = "VERSION"
```

### Set the version in regex search in a file

Set the package version from the first regex match that is found in a file, for example `CHANGELOG.md`:
```
# Changelog

## [0.0.2] - 2023-10-26

- Update version

## [0.0.1] - 2023-10-26

- Add changelog
```

Configure the regex pattern in your `pyproject.toml`:
```toml
[tool.poetry-version-plugin]
source = "file"
path = "CHANGELOG.md"
match = '^## \[(?P<version>\d+(\.\d+)+)]'
```

The version will be the named match group `version` if available, else the first match group or the full match.

## Version in `pyproject.toml`

Currently (2021-05-24) Poetry requires a `version` configuration in the `pyproject.toml`, even if you use this plugin.
Expand Down
61 changes: 61 additions & 0 deletions poetry_version_plugin/plugin.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import ast
import re
import subprocess
from pathlib import Path
from typing import Any, Dict, Optional
Expand Down Expand Up @@ -104,3 +105,63 @@ def activate(self, poetry: Poetry, io: IO) -> None:
)
io.write_error_line(message)
raise RuntimeError(message)
elif version_source == "file":
file_path_config = poetry_version_config.get("path")
if not file_path_config:
message = (
"<b>poetry-version-plugin</b>: No <b>path</b> configuration found "
"in [tool.poetry-version-plugin] in pyproject.toml, cannot extract "
"dynamic version"
)
io.write_error_line(message)
raise RuntimeError(message)
file_path = Path(file_path_config)
if not file_path.is_file():
message = (
f"<b>poetry-version-plugin</b>: File <b>path</b> at {file_path} "
"not found, cannot extract dynamic version"
)
io.write_error_line(message)
raise RuntimeError(message)
io.write_line(
"<b>poetry-version-plugin</b>: Using file at "
f"{file_path} for dynamic version"
)
version = file_path.read_text()
version_pattern = poetry_version_config.get("match")
if not version_pattern:
io.write_line(
"<b>poetry-version-plugin</b>: Setting package dynamic version "
f"to file contents from {file_path}: <b>{version}</b>"
)
poetry.package._set_version(version.strip())
return
else:
try:
match = re.search(version_pattern, version, flags=re.MULTILINE)
except re.error as exc:
message = (
"<b>poetry-version-plugin</b>: Invalid regex <b>match</b> "
"configuration, cannot extract dynamic version"
)
io.write_error_line(message)
raise RuntimeError(message) from exc
if not match:
message = (
"<b>poetry-version-plugin</b>: No regex match found in file "
f"{file_path}, cannot extract dynamic version"
)
io.write_error_line(message)
raise RuntimeError(message)
version = (
match.groupdict().get("version")
or next(iter(match.groups()), None)
or match.group()
)
io.write_line(
"<b>poetry-version-plugin</b>: Setting package "
"dynamic version to regex match result of file contents "
f"from {file_path}: <b>{version}</b>"
)
poetry.package._set_version(version)
return
Empty file.
16 changes: 16 additions & 0 deletions tests/assets/file_no_path/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[tool.poetry]
name = "test-custom-version"
version = "0"
description = ""
authors = ["Sebastián Ramírez <[email protected]>"]
readme = "README.md"

[tool.poetry.dependencies]
python = "^3.7"

[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

[tool.poetry-version-plugin]
source = "file"
Empty file.
Empty file.
17 changes: 17 additions & 0 deletions tests/assets/file_not_found/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[tool.poetry]
name = "test-custom-version"
version = "0"
description = ""
authors = ["Sebastián Ramírez <[email protected]>"]
readme = "README.md"

[tool.poetry.dependencies]
python = "^3.7"

[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

[tool.poetry-version-plugin]
source = "file"
path = "VERSION"
Empty file.
Empty file.
1 change: 1 addition & 0 deletions tests/assets/file_plain/VERSION
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0.0.1
17 changes: 17 additions & 0 deletions tests/assets/file_plain/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[tool.poetry]
name = "test-custom-version"
version = "0"
description = ""
authors = ["Sebastián Ramírez <[email protected]>"]
readme = "README.md"

[tool.poetry.dependencies]
python = "^3.7"

[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

[tool.poetry-version-plugin]
source = "file"
path = "VERSION"
Empty file.
9 changes: 9 additions & 0 deletions tests/assets/file_regex/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Changelog

## [0.0.2] - 2023-10-26

- Update version

## [0.0.1] - 2023-10-26

- Add changelog
Empty file.
18 changes: 18 additions & 0 deletions tests/assets/file_regex/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[tool.poetry]
name = "test-custom-version"
version = "0"
description = ""
authors = ["Sebastián Ramírez <[email protected]>"]
readme = "README.md"

[tool.poetry.dependencies]
python = "^3.7"

[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

[tool.poetry-version-plugin]
source = "file"
path = "CHANGELOG.md"
match = '^## \[(?P<version>\d+(\.\d+)+)]'
Empty file.
9 changes: 9 additions & 0 deletions tests/assets/file_regex_invalid/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Changelog

## [0.0.2] - 2023-10-26

- Update version

## [0.0.1] - 2023-10-26

- Add changelog
Empty file.
18 changes: 18 additions & 0 deletions tests/assets/file_regex_invalid/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[tool.poetry]
name = "test-custom-version"
version = "0"
description = ""
authors = ["Sebastián Ramírez <[email protected]>"]
readme = "README.md"

[tool.poetry.dependencies]
python = "^3.7"

[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

[tool.poetry-version-plugin]
source = "file"
path = "CHANGELOG.md"
match = '('
Empty file.
9 changes: 9 additions & 0 deletions tests/assets/file_regex_no_match/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Changelog

## [0.0.2] - 2023-10-26

- Update version

## [0.0.1] - 2023-10-26

- Add changelog
Empty file.
18 changes: 18 additions & 0 deletions tests/assets/file_regex_no_match/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[tool.poetry]
name = "test-custom-version"
version = "0"
description = ""
authors = ["Sebastián Ramírez <[email protected]>"]
readme = "README.md"

[tool.poetry.dependencies]
python = "^3.7"

[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

[tool.poetry-version-plugin]
source = "file"
path = "CHANGELOG.md"
match = '^# (?P<version>\d+(\.\d+)+)'
Empty file.
84 changes: 84 additions & 0 deletions tests/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,3 +210,87 @@ def test_git_tag(tmp_path: Path):
wheel_path = testing_dir / "dist" / "test_custom_version-0.0.9-py3-none-any.whl"
info = pkginfo.get_metadata(str(wheel_path))
assert info.version == "0.0.9"


def test_file_regex(tmp_path: Path):
testing_dir = tmp_path / "testing_package"
copy_assets("file_regex", testing_dir)
result = build_package(testing_dir=testing_dir)
assert result.returncode == 0
assert (
"poetry-version-plugin: Using file at "
"CHANGELOG.md for dynamic version" in result.stdout
)
assert (
"poetry-version-plugin: Setting package "
"dynamic version to regex match result of file contents "
"from CHANGELOG.md: 0.0.2" in result.stdout
)
assert "Built test_custom_version-0.0.2-py3-none-any.whl" in result.stdout
wheel_path = testing_dir / "dist" / "test_custom_version-0.0.2-py3-none-any.whl"
info = pkginfo.get_metadata(str(wheel_path))
assert info.version == "0.0.2"


def test_file_plain(tmp_path: Path):
testing_dir = tmp_path / "testing_package"
copy_assets("file_plain", testing_dir)
result = build_package(testing_dir=testing_dir)
assert result.returncode == 0
assert (
"poetry-version-plugin: Using file at "
"VERSION for dynamic version" in result.stdout
)
assert (
"poetry-version-plugin: Setting package dynamic version "
"to file contents from VERSION: 0.0.1" in result.stdout
)
assert "Built test_custom_version-0.0.1-py3-none-any.whl" in result.stdout
wheel_path = testing_dir / "dist" / "test_custom_version-0.0.1-py3-none-any.whl"
info = pkginfo.get_metadata(str(wheel_path))
assert info.version == "0.0.1"


def test_file_no_path(tmp_path: Path):
testing_dir = tmp_path / "testing_package"
copy_assets("file_no_path", testing_dir)
result = build_package(testing_dir=testing_dir)
assert (
"poetry-version-plugin: No path configuration found "
"in [tool.poetry-version-plugin] in pyproject.toml, cannot extract "
"dynamic version"
) in result.stderr
assert result.returncode != 0


def test_file_not_found(tmp_path: Path):
testing_dir = tmp_path / "testing_package"
copy_assets("file_not_found", testing_dir)
result = build_package(testing_dir=testing_dir)
assert (
"poetry-version-plugin: File path at VERSION "
"not found, cannot extract dynamic version"
) in result.stderr
assert result.returncode != 0


def test_file_regex_invalid(tmp_path: Path):
testing_dir = tmp_path / "testing_package"
copy_assets("file_regex_invalid", testing_dir)
result = build_package(testing_dir=testing_dir)
assert (
"poetry-version-plugin: Invalid regex match "
"configuration, cannot extract dynamic version"
) in result.stderr
assert result.returncode != 0


def test_file_regex_no_match(tmp_path: Path):
testing_dir = tmp_path / "testing_package"
copy_assets("file_regex_no_match", testing_dir)
result = build_package(testing_dir=testing_dir)
assert (
"poetry-version-plugin: No regex match found in file "
"CHANGELOG.md, cannot extract dynamic version"
) in result.stderr
assert result.returncode != 0
Loading