diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml index 4e51f9b..30bcbc2 100644 --- a/.github/workflows/publish.yaml +++ b/.github/workflows/publish.yaml @@ -21,10 +21,10 @@ jobs: with: python-version: 3.8 - - name: Install poetry 1.1.7 + - name: Install poetry uses: snok/install-poetry@v1 with: - version: 1.1.7 + version: 1.2.1 - name: Install dependencies run: poetry install @@ -61,10 +61,10 @@ jobs: with: python-version: 3.8 - - name: Install poetry 1.1.7 + - name: Install poetry uses: snok/install-poetry@v1 with: - version: 1.1.7 + version: 1.2.1 - name: Install dependencies run: poetry install diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index f4edf80..8587719 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -15,7 +15,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: [ '3.6', '3.7', '3.8', '3.9' ] + python-version: [ '3.7', '3.8', '3.9', '3.10' ] steps: - name: Checkout repository uses: actions/checkout@v2 @@ -25,10 +25,10 @@ jobs: with: python-version: ${{ matrix.python-version }} - - name: Install poetry 1.1.7 + - name: Install poetry uses: snok/install-poetry@v1 with: - version: 1.1.7 + version: 1.2.1 - name: Install dependencies run: poetry install diff --git a/.github/workflows/update-dependencies.yaml b/.github/workflows/update-dependencies.yaml index c175871..411143b 100644 --- a/.github/workflows/update-dependencies.yaml +++ b/.github/workflows/update-dependencies.yaml @@ -18,10 +18,10 @@ jobs: with: python-version: 3.8 - - name: Install poetry 1.1.12 + - name: Install poetry uses: snok/install-poetry@v1 with: - version: 1.1.12 + version: 1.2.1 - name: Update dependencies run: | diff --git a/pyproject.toml b/pyproject.toml index 0393f02..a3ca422 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "poetryup" -version = "0.12.1" +version = "0.12.2" description = "Update dependencies and bump their version in the pyproject.toml file" authors = ["Mousa Zeid Baker"] packages = [ diff --git a/src/poetryup/core/poetry.py b/src/poetryup/core/poetry.py new file mode 100644 index 0000000..3909c9a --- /dev/null +++ b/src/poetryup/core/poetry.py @@ -0,0 +1,53 @@ +import logging +from typing import List, Optional + +from packaging import version as version_ + +from poetryup.core.cmd import cmd_run + + +class Poetry: + """A helper class to run poetry commands""" + + @property + def version(self) -> str: + """Return the installed poetry version""" + + output = cmd_run(["poetry", "--version"], capture_output=True) + # output is: 'Poetry (version x.y.z)' + return output.rsplit(" ", 1).pop().strip().replace(")", "") + + def show(self) -> str: + """Run poetry show command + + Returns: + The output from the poetry show command + """ + + return cmd_run(["poetry", "show", "--tree"], capture_output=True) + + def update(self) -> None: + """Run poetry update command""" + + cmd_run(["poetry", "update"]) + + def add( + self, + packages: List[str], + group: Optional[str], + ) -> None: + """Run poetry add command + + Args: + package: The package(s) to add + group: The group the package(s) should be added to + """ + + if group is None or group == "default": + cmd_run(["poetry", "add", *packages]) + elif group == "dev" and self.version < version_.parse("1.2.0"): + cmd_run(["poetry", "add", *packages, f"--{group}"]) + elif self.version >= version_.parse("1.2.0"): + cmd_run(["poetry", "add", *packages, "--group", group]) + else: + logging.warning(f"Couldn't add package(s) '{packages}'") diff --git a/src/poetryup/core/pyproject.py b/src/poetryup/core/pyproject.py index 84ae297..0d1606f 100644 --- a/src/poetryup/core/pyproject.py +++ b/src/poetryup/core/pyproject.py @@ -1,12 +1,11 @@ import logging import re from collections import defaultdict -from typing import Dict, List, Optional, Union +from typing import Dict, List, Union import tomlkit -from packaging import version as version_ -from poetryup.core.cmd import cmd_run +from poetryup.core.poetry import Poetry from poetryup.models.dependency import Constraint, Dependency @@ -23,7 +22,7 @@ class Pyproject: def __init__(self, pyproject_str: str) -> None: self.pyproject = tomlkit.loads(pyproject_str) - self.poetry_version = version_.parse(self.__get_poetry_version()) + self.poetry = Poetry() self._dependencies = None # caches the dependencies @property @@ -76,7 +75,7 @@ def lock_dependencies(self) -> List[Dependency]: """The pyproject dependencies with their lock version""" # run poetry show to get currently installed dependencies - output = self.__run_poetry_show() + output = self.poetry.show() # create dependencies from each line of the output pattern = re.compile("^[a-zA-Z-]+") @@ -292,13 +291,13 @@ def update_dependencies( dependency_groups[dependency.group].append(package_version) for group, packages in dependency_groups.items(): - self.__run_poetry_add( + self.poetry.add( packages=packages, group=group, ) else: logging.info("Running poetry update command") - self.__run_poetry_update() + self.poetry.update() # bump versions in pyproject bumped_dependencies = self.filter_dependencies( @@ -330,52 +329,3 @@ def update_dependencies( ] = dependency.version else: logging.warning(f"Couldn't bump dependency '{dependency.name}'") - - @staticmethod - def __get_poetry_version() -> str: - """Return the installed poetry version - - Returns: - The poetry version installed - """ - - output = cmd_run(["poetry", "--version"], capture_output=True) - # output is: 'Poetry version x.y.z' - return output.rsplit(" ", 1).pop().strip().replace(")", "") - - @staticmethod - def __run_poetry_show() -> str: - """Run poetry show command - - Returns: - The output from the poetry show command - """ - - return cmd_run(["poetry", "show", "--tree"], capture_output=True) - - @staticmethod - def __run_poetry_update() -> None: - """Run poetry update command""" - - cmd_run(["poetry", "update"]) - - def __run_poetry_add( - self, - packages: List[str], - group: Optional[str], - ) -> None: - """Run poetry add command - - Args: - package: The package(s) to add - group: The group the package(s) should be added to - """ - - if group is None or group == "default": - cmd_run(["poetry", "add", *packages]) - elif group == "dev" and self.poetry_version < version_.parse("1.2.0"): - cmd_run(["poetry", "add", *packages, f"--{group}"]) - elif self.poetry_version >= version_.parse("1.2.0"): - cmd_run(["poetry", "add", *packages, "--group", group]) - else: - logging.warning(f"Couldn't add package(s) '{packages}'") diff --git a/tests/conftest.py b/tests/conftest.py index e353ad4..aa0a5cf 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,19 +1,13 @@ import pytest from pytest_mock import MockerFixture -from poetryup.core.pyproject import Pyproject +from poetryup.core.pyproject import Poetry @pytest.fixture(scope="function") def mock_poetry_commands(mocker: MockerFixture) -> None: """Mock poetry commands""" - mocker.patch.object( - Pyproject, - "_Pyproject__get_poetry_version", - return_value="1.1.0", - ) - dependencies = [ "poetryup", "poetryup-caret", @@ -37,19 +31,19 @@ def mock_poetry_commands(mocker: MockerFixture) -> None: return_value = s.join(dependencies) + s mocker.patch.object( - Pyproject, - "_Pyproject__run_poetry_show", + Poetry, + "show", return_value=return_value, ) mocker.patch.object( - Pyproject, - "_Pyproject__run_poetry_update", + Poetry, + "update", return_value=None, ) mocker.patch.object( - Pyproject, - "_Pyproject__run_poetry_add", + Poetry, + "add", return_value=None, ) diff --git a/tests/unit/test_poetry.py b/tests/unit/test_poetry.py new file mode 100644 index 0000000..ee15d1d --- /dev/null +++ b/tests/unit/test_poetry.py @@ -0,0 +1,25 @@ +from pytest_mock import MockerFixture + +from poetryup.core.poetry import Poetry + + +def test_version_poetry_1_1_x( + mocker: MockerFixture, +) -> None: + mocker.patch( + "poetryup.core.poetry.cmd_run", + return_value="Poetry version 1.2.3", + ) + poetry = Poetry() + assert poetry.version == "1.2.3" + + +def test_version_poetry_1_2_x( + mocker: MockerFixture, +) -> None: + mocker.patch( + "poetryup.core.poetry.cmd_run", + return_value="Poetry (version 1.2.3)", + ) + poetry = Poetry() + assert poetry.version == "1.2.3" diff --git a/tests/unit/test_pyproject.py b/tests/unit/test_pyproject.py index a302b5d..3881574 100644 --- a/tests/unit/test_pyproject.py +++ b/tests/unit/test_pyproject.py @@ -4,7 +4,7 @@ from pytest_mock import MockerFixture -from poetryup.core.pyproject import Pyproject +from poetryup.core.pyproject import Poetry, Pyproject from poetryup.models.dependency import Constraint, Dependency pyproject_str = Path( @@ -67,12 +67,12 @@ def test_update_dependencies_latest( mock_poetry_commands, mocker: MockerFixture, ) -> None: - pyproject = Pyproject(pyproject_str) mock = mocker.patch.object( - pyproject, - "_Pyproject__run_poetry_add", + Poetry, + "add", return_value=None, ) + pyproject = Pyproject(pyproject_str) pyproject.update_dependencies(latest=True) calls = [ @@ -106,12 +106,12 @@ def test_update_dependencies_latest_skip_exact( mock_poetry_commands, mocker: MockerFixture, ) -> None: - pyproject = Pyproject(pyproject_str) mock = mocker.patch.object( - pyproject, - "_Pyproject__run_poetry_add", + Poetry, + "add", return_value=None, ) + pyproject = Pyproject(pyproject_str) pyproject.update_dependencies( latest=True, without_constraints=[Constraint.EXACT], @@ -148,12 +148,12 @@ def test_update_dependencies_latest_with_specific_group( mock_poetry_commands, mocker: MockerFixture, ) -> None: - pyproject = Pyproject(pyproject_str) mock = mocker.patch.object( - pyproject, - "_Pyproject__run_poetry_add", + Poetry, + "add", return_value=None, ) + pyproject = Pyproject(pyproject_str) pyproject.update_dependencies(latest=True, groups=["main"]) calls = [ @@ -183,12 +183,12 @@ def test_update_dependencies_latest_with_specific_name( mock_poetry_commands, mocker: MockerFixture, ) -> None: - pyproject = Pyproject(pyproject_str) mock = mocker.patch.object( - pyproject, - "_Pyproject__run_poetry_add", + Poetry, + "add", return_value=None, ) + pyproject = Pyproject(pyproject_str) pyproject.update_dependencies(latest=True, names=["poetryup"]) calls = [ @@ -204,12 +204,12 @@ def test_update_dependencies_latest_with_exclude_names( mock_poetry_commands, mocker: MockerFixture, ) -> None: - pyproject = Pyproject(pyproject_str) mock = mocker.patch.object( - pyproject, - "_Pyproject__run_poetry_add", + Poetry, + "add", return_value=None, ) + pyproject = Pyproject(pyproject_str) pyproject.update_dependencies( latest=True, exclude_names=["poetryup_caret", "poetryup"] )