Skip to content

Commit

Permalink
Add cli next-version (#25)
Browse files Browse the repository at this point in the history
* add find_latest_version

* add cli

* update changelog

* fix increase minor in the case when patch contains characters

* fix typo in test file name
  • Loading branch information
francesco086 authored Feb 8, 2024
1 parent 60a5bc0 commit d546d5d
Show file tree
Hide file tree
Showing 7 changed files with 113 additions and 2 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
Anything MAY change at any time. The public API SHOULD NOT be considered stable.").
While in this phase, we will denote breaking changes with a minor increase.

## 0.4.1

### Added

* Introduce `dac next-version` command, that allows to find the next minor release for a given python package and (optionally) a given major version.

## 0.4.0

### Changed
Expand Down
26 changes: 26 additions & 0 deletions src/dac/_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import sys
from importlib.metadata import requires, version
from pathlib import Path
from typing import Optional

import typer
from rich.console import Console
Expand All @@ -11,6 +12,7 @@
from dac._input.config import PackConfig
from dac._input.pyproject import PyProjectConfig
from dac._packing import pack as py_api_pack
from dac._version_management import find_latest_version, increase_minor

app = typer.Typer()
console = Console()
Expand Down Expand Up @@ -69,6 +71,30 @@ def pack(
)


@app.command()
def next_version(
pkg_name: str = typer.Option(
...,
help="Name of the python package",
),
major: Optional[int] = typer.Option(
None,
"--major",
help="Major of the version that should be increased. "
"If not specified just take it from the latest version of the package.",
),
):
"""
Print the next version of the python package.
It assumes that semantic versioning (https://semver.org) is used,
and that the next version corresponds to a minor upgrade.
"""
latest_version = find_latest_version(pkg_name=pkg_name, major=major)
next_version = increase_minor(version=latest_version)
console.print(next_version)


@app.command()
def info():
"""
Expand Down
29 changes: 29 additions & 0 deletions src/dac/_version_management.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import re
import subprocess
from typing import Optional


def find_latest_version(pkg_name: str, major: Optional[int] = None) -> str:
output = subprocess.check_output(
[
"pip",
"install",
"--no-deps",
"--ignore-installed",
"--no-cache-dir",
"--dry-run",
f"{pkg_name}{f'=={major}.*' if major is not None else ''}",
],
stderr=subprocess.DEVNULL,
)
last_line = output.decode("utf-8").splitlines()[-1]
regex_rule = f"{pkg_name.replace('_', '-')}-{major if major is not None else ''}.[^ ]+"
match = re.search(regex_rule, last_line)
assert match is not None
return match[0][len(f"{pkg_name}-") :]


def increase_minor(version: str) -> str:
major, minor, patch = version.split(".")
assert major.isdigit() and minor.isdigit()
return f"{major}.{int(minor) + 1}.0"
14 changes: 12 additions & 2 deletions test/cli_utilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,9 @@
from typing import Optional

from click.testing import Result
from typer.testing import CliRunner

from dac._cli import app
from dac._input.config import PackConfig
from typer.testing import CliRunner

runner = CliRunner()

Expand Down Expand Up @@ -66,5 +65,16 @@ def invoke_dac_pack_from_config(config: PackConfig) -> Result:
)


def invoke_dac_next_version(
pkg_name: str,
major: Optional[int] = None,
) -> Result:
major_option = [] if major is None else ["--major", str(major)]
return runner.invoke(
app,
["next-version", "--pkg-name", pkg_name] + major_option,
)


def invoke_dac_info() -> Result:
return runner.invoke(app, ["info"])
27 changes: 27 additions & 0 deletions test/integration_test/version_management_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from test.cli_utilities import invoke_dac_next_version

import pytest
from dac._version_management import find_latest_version


def test_if_find_latest_version_is_called_then_return_latest_version():
assert "0.5" == find_latest_version(pkg_name="rainbow-server")


def test_if_find_latest_version_is_called_with_major_constraint_then_return_latest_major_version():
assert "0.25.3" == find_latest_version(pkg_name="pandas", major=0)


def test_if_pkg_does_not_exist_then_find_package_raises_exception():
with pytest.raises(Exception):
find_latest_version(pkg_name="non-existing-package")


def test_if_next_version_without_major_spec_then_return_latest_version_with_minor_upgrade():
result = invoke_dac_next_version(pkg_name="rainbow-saddle")
assert result.stdout == "0.5.0\n"


def test_if_next_version_with_major_spec_then_return_minor_upgrade_for_that_major():
result = invoke_dac_next_version(pkg_name="pandas", major=0)
assert result.stdout == "0.26.0\n"
Empty file.
13 changes: 13 additions & 0 deletions test/unit_test/_version_management/increase_minor_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import pytest
from dac._version_management import increase_minor


def test_increase_minor_then_return_version_with_increased_minor():
assert "0.6.0" == increase_minor(version="0.5.0")
assert "0.6.0" == increase_minor(version="0.5.1rc0")


@pytest.mark.parametrize("version", ["0", "0.5", "guess.what.now", "guess.0.now"])
def test_if_invalid_version_then_increase_minor_raises_exception(version):
with pytest.raises(Exception):
increase_minor(version=version)

0 comments on commit d546d5d

Please sign in to comment.