Skip to content

Commit

Permalink
Add unit tests for dependency version patching
Browse files Browse the repository at this point in the history
  • Loading branch information
alexdewar committed Aug 13, 2024
1 parent ecf3fce commit 1c83a1d
Show file tree
Hide file tree
Showing 7 changed files with 99 additions and 10 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/ci-pip-tools.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ jobs:
- name: Install dependencies
run: pip install -r dev-requirements.txt

- name: Run unit tests
run: pytest

- name: Create project from template
# Choose default options
run: cookiecutter . --no-input packaging=pip-tools
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/ci-poetry.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ jobs:
- name: Install dependencies
run: pip install -r dev-requirements.txt

- name: Run unit tests
run: pytest

- name: Create project from template
# Choose default options
run: cookiecutter . --no-input packaging=poetry
Expand Down
1 change: 1 addition & 0 deletions dev-requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
# This file contains dependencies for development and CI workflows
cookiecutter==2.6.0
pytest==8.3.2
Empty file added hooks/__init__.py
Empty file.
19 changes: 9 additions & 10 deletions hooks/post_gen_project.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,11 @@ def main():
remove_unneeded_files()


def read_package_versions() -> dict[str, str]:
def read_package_versions(*filenames: str) -> dict[str, str]:
"""Read package versions from *requirements.txt."""
regex = re.compile("^([^# ]+)==(.+)$")
packages: dict[str, str] = {}
for filename in (
"doc-requirements.txt",
"dev-requirements.txt",
"requirements.txt",
):
for filename in filenames:
with open(filename) as f:
for line in f.readlines():
if match := regex.match(line):
Expand All @@ -41,19 +37,22 @@ def read_package_versions() -> dict[str, str]:
return packages


def update_poetry_dependencies():
def update_poetry_dependencies(pyproject_path: str = "pyproject.toml"):
"""Patch the versions of packages in pyproject.toml."""
packages = read_package_versions()
packages = read_package_versions(
"doc-requirements.txt", "dev-requirements.txt", "requirements.txt"
)

output = ""
regex = re.compile('^([^ ]+) = "VERSION"$')
with open("pyproject.toml") as f:
with open(pyproject_path) as f:
for line in f.readlines():
if match := regex.match(line):
name = match.group(1)
output += f'{name} = "^{packages[name.lower()]}"\n'
else:
output += line
with open("pyproject.toml", "w") as f:
with open(pyproject_path, "w") as f:
f.write(output)


Expand Down
3 changes: 3 additions & 0 deletions pytest.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[pytest]
pythonpath = .
testpaths = tests
80 changes: 80 additions & 0 deletions tests/test_pyproject_patching.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
from hooks.post_gen_project import read_package_versions, update_poetry_dependencies
from pathlib import Path
from unittest.mock import patch, Mock


def test_read_package_versions(tmp_path: Path):
REQUIREMENTS1 = """
# This is a comment
package_a==1.2.3
package_b==4.5.6
"""
path1 = tmp_path / "requirements1.txt"
with path1.open("w") as f:
f.write(REQUIREMENTS1)

# Single file
assert read_package_versions(str(path1)) == {
"package_a": "1.2.3",
"package_b": "4.5.6",
}

REQUIREMENTS2 = """
package_b==1.2.3
# Another comment
package_c==4.5.6
"""
path2 = tmp_path / "requirements2.txt"
with path2.open("w") as f:
f.write(REQUIREMENTS2)

# Multiple files
assert read_package_versions(str(path1), str(path2)) == {
"package_a": "1.2.3",
"package_b": "1.2.3",
"package_c": "4.5.6",
}

REQUIREMENTS3 = "package_B==1.2.3"
path3 = tmp_path / "requirements3.txt"
with path3.open("w") as f:
f.write(REQUIREMENTS3)

# Package names should be converted to lowercase
assert read_package_versions(str(path1), str(path3)) == {
"package_a": "1.2.3",
"package_b": "1.2.3",
}


PYPROJECT = """[tool.poetry]
name = "my_project"
authors = [
"Jane Doe <[email protected]>",
]
[tool.poetry.dependencies]
python = "^3.12"
package_a = "{package_a}"
[tool.poetry.group.dev.dependencies]
package_b = "{package_b}"
[tool.mypy]
disallow_any_explicit = true
def test_update_poetry_dependencies(tmp_path: Path):
"""


@patch("hooks.post_gen_project.read_package_versions")
def test_update_poetry_dependencies(read_versions_mock: Mock, tmp_path: Path):
pyproject_path = tmp_path / "pyproject.toml"
with pyproject_path.open("w") as f:
f.write(PYPROJECT.format(package_a="VERSION", package_b="VERSION"))

read_versions_mock.return_value = {"package_a": "1.2.3", "package_b": "4.5.6"}
update_poetry_dependencies(str(pyproject_path))
with pyproject_path.open() as f:
content = f.read()
assert content == PYPROJECT.format(package_a="^1.2.3", package_b="^4.5.6")

0 comments on commit 1c83a1d

Please sign in to comment.