From a404026fbd62bea9bc975d6aa14878766fcbb886 Mon Sep 17 00:00:00 2001 From: Mousa Zeid Baker Date: Sat, 7 May 2022 15:02:31 +0200 Subject: [PATCH 01/15] refactor: move Dependency class to dependency.py --- src/poetryup/dependency.py | 28 ++++++++++++++++++++++++++++ src/poetryup/pyproject.py | 27 ++------------------------- 2 files changed, 30 insertions(+), 25 deletions(-) create mode 100644 src/poetryup/dependency.py diff --git a/src/poetryup/dependency.py b/src/poetryup/dependency.py new file mode 100644 index 0000000..d600dd2 --- /dev/null +++ b/src/poetryup/dependency.py @@ -0,0 +1,28 @@ +from dataclasses import dataclass +from typing import Union + +from tomlkit import items + + +@dataclass +class Dependency: + """A class to represent a dependency""" + + name: str + version: Union[items.String, items.InlineTable, items.Array] + group: str + + @property + def normalized_name(self) -> str: + # https://www.python.org/dev/peps/pep-0503/#normalized-names + return self.name.replace("_", "-").lower() + + @property + def constraint(self) -> str: + if type(self.version) is items.String: + if self.version[0].startswith(("^", "~")): + return self.version[0] + elif type(self.version) is items.InlineTable: + if self.version.get("version", "").startswith(("^", "~")): + return self.version["version"][0] + return "" # dependencies with exact version or multiple versions diff --git a/src/poetryup/pyproject.py b/src/poetryup/pyproject.py index aafd701..b94752d 100644 --- a/src/poetryup/pyproject.py +++ b/src/poetryup/pyproject.py @@ -1,36 +1,13 @@ import logging import re import subprocess -from dataclasses import dataclass -from typing import List, Optional, Union +from typing import List, Optional import tomlkit from packaging import version as version_ from tomlkit import items - -@dataclass -class Dependency: - """A class to represent a dependency""" - - name: str - version: Union[items.String, items.InlineTable, items.Array] - group: str - - @property - def normalized_name(self) -> str: - # https://www.python.org/dev/peps/pep-0503/#normalized-names - return self.name.replace("_", "-").lower() - - @property - def constraint(self) -> str: - if type(self.version) is items.String: - if self.version[0].startswith(("^", "~")): - return self.version[0] - elif type(self.version) is items.InlineTable: - if self.version.get("version", "").startswith(("^", "~")): - return self.version["version"][0] - return "" # dependencies with exact version or multiple versions +from poetryup.dependency import Dependency class Pyproject: From 6c7ed6345d079cbf3ce1472de338f7cdadf4a344 Mon Sep 17 00:00:00 2001 From: Mousa Zeid Baker Date: Sat, 7 May 2022 16:11:00 +0200 Subject: [PATCH 02/15] test: add tests for Dependency class --- tests/unit/test_dependency.py | 50 +++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 tests/unit/test_dependency.py diff --git a/tests/unit/test_dependency.py b/tests/unit/test_dependency.py new file mode 100644 index 0000000..e50771f --- /dev/null +++ b/tests/unit/test_dependency.py @@ -0,0 +1,50 @@ +from tomlkit import container, items + +from poetryup.dependency import Dependency + + +def test_normalized_name() -> None: + dependency = Dependency( + name="poetry_up", + version="0.1.0", + group="default", + ) + assert dependency.normalized_name == "poetry-up" + + +def test_constraint() -> None: + version = items.String( + items.StringType.SLB, + "^0.1.0", + original="^0.1.0", + trivia=items.Trivia(), + ) + dependency = Dependency( + name="poetry_up", + version=version, + group="default", + ) + assert dependency.constraint == "^" + + version = items.InlineTable( + value=container.Container(), + trivia=items.Trivia(), + ) + version.append("version", "^0.1.0") + dependency = Dependency( + name="poetry_up", + version=version, + group="default", + ) + assert dependency.constraint == "^" + + version = items.Array( + value=[], + trivia=items.Trivia(), + ) + dependency = Dependency( + name="poetry_up", + version=version, + group="default", + ) + assert dependency.constraint == "" From 8cae5b3d19e44886e126de57fe9c0fbe037e95b0 Mon Sep 17 00:00:00 2001 From: Mousa Zeid Baker Date: Sat, 7 May 2022 16:34:53 +0200 Subject: [PATCH 03/15] refactor: get rid of @dataclass decorator in Dependency class --- src/poetryup/dependency.py | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/poetryup/dependency.py b/src/poetryup/dependency.py index d600dd2..afa0030 100644 --- a/src/poetryup/dependency.py +++ b/src/poetryup/dependency.py @@ -1,16 +1,26 @@ -from dataclasses import dataclass from typing import Union from tomlkit import items -@dataclass class Dependency: - """A class to represent a dependency""" + """A class to represent a dependency - name: str - version: Union[items.String, items.InlineTable, items.Array] - group: str + Args: + name: The name of the dependency + version: The version of the dependency + group: The group of the dependency + """ + + def __init__( + self, + name: str, + version: Union[items.String, items.InlineTable, items.Array], + group: str, + ) -> None: + self.name = name + self.version = version + self.group = group @property def normalized_name(self) -> str: From 50566b32da9016fadc6dd7315e28637b6aa2963c Mon Sep 17 00:00:00 2001 From: Mousa Zeid Baker Date: Sat, 7 May 2022 16:39:28 +0200 Subject: [PATCH 04/15] refactor: replace tomlkit types with plain python types --- src/poetryup/dependency.py | 10 ++++------ src/poetryup/pyproject.py | 9 ++++----- tests/unit/test_dependency.py | 23 +++-------------------- 3 files changed, 11 insertions(+), 31 deletions(-) diff --git a/src/poetryup/dependency.py b/src/poetryup/dependency.py index afa0030..8ee00b4 100644 --- a/src/poetryup/dependency.py +++ b/src/poetryup/dependency.py @@ -1,6 +1,4 @@ -from typing import Union - -from tomlkit import items +from typing import Dict, List, Union class Dependency: @@ -15,7 +13,7 @@ class Dependency: def __init__( self, name: str, - version: Union[items.String, items.InlineTable, items.Array], + version: Union[str, Dict, List], group: str, ) -> None: self.name = name @@ -29,10 +27,10 @@ def normalized_name(self) -> str: @property def constraint(self) -> str: - if type(self.version) is items.String: + if isinstance(self.version, str): if self.version[0].startswith(("^", "~")): return self.version[0] - elif type(self.version) is items.InlineTable: + elif isinstance(self.version, Dict): if self.version.get("version", "").startswith(("^", "~")): return self.version["version"][0] return "" # dependencies with exact version or multiple versions diff --git a/src/poetryup/pyproject.py b/src/poetryup/pyproject.py index b94752d..be20355 100644 --- a/src/poetryup/pyproject.py +++ b/src/poetryup/pyproject.py @@ -1,11 +1,10 @@ import logging import re import subprocess -from typing import List, Optional +from typing import Dict, List, Optional import tomlkit from packaging import version as version_ -from tomlkit import items from poetryup.dependency import Dependency @@ -103,10 +102,10 @@ def list_lock_dependencies(self) -> List[Dependency]: ) continue - if type(dependency.version) is items.String: + if isinstance(dependency.version, str): dependency.version = dependency.constraint + lock_dep.version elif ( - type(dependency.version) is items.InlineTable + isinstance(dependency.version, Dict) and dependency.version.get("version") is not None ): dependency.version["version"] = ( @@ -137,7 +136,7 @@ def update_dependencies( if skip_exact and dependency.constraint == "": # skip dependencies with an exact version continue - if type(dependency.version) is items.String: + if isinstance(dependency.version, str): groups[dependency.group] = groups.get( dependency.group, [] ) + [f"{dependency.name}@latest"] diff --git a/tests/unit/test_dependency.py b/tests/unit/test_dependency.py index e50771f..811da13 100644 --- a/tests/unit/test_dependency.py +++ b/tests/unit/test_dependency.py @@ -1,5 +1,3 @@ -from tomlkit import container, items - from poetryup.dependency import Dependency @@ -13,38 +11,23 @@ def test_normalized_name() -> None: def test_constraint() -> None: - version = items.String( - items.StringType.SLB, - "^0.1.0", - original="^0.1.0", - trivia=items.Trivia(), - ) dependency = Dependency( name="poetry_up", - version=version, + version="^0.1.0", group="default", ) assert dependency.constraint == "^" - version = items.InlineTable( - value=container.Container(), - trivia=items.Trivia(), - ) - version.append("version", "^0.1.0") dependency = Dependency( name="poetry_up", - version=version, + version={"version": "^0.1.0"}, group="default", ) assert dependency.constraint == "^" - version = items.Array( - value=[], - trivia=items.Trivia(), - ) dependency = Dependency( name="poetry_up", - version=version, + version=[], group="default", ) assert dependency.constraint == "" From 373a2be6bc9d27e7a2451be92422a0150e321e23 Mon Sep 17 00:00:00 2001 From: Mousa Zeid Baker Date: Sat, 7 May 2022 16:44:33 +0200 Subject: [PATCH 05/15] bump project version --- pyproject.toml | 2 +- src/poetryup/{ => core}/pyproject.py | 2 +- src/poetryup/main.py | 2 +- src/poetryup/{ => models}/dependency.py | 0 tests/conftest.py | 2 +- tests/unit/test_dependency.py | 2 +- tests/unit/test_pyproject.py | 2 +- 7 files changed, 6 insertions(+), 6 deletions(-) rename src/poetryup/{ => core}/pyproject.py (99%) rename src/poetryup/{ => models}/dependency.py (100%) diff --git a/pyproject.toml b/pyproject.toml index 2173ae3..cc3d59f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "poetryup" -version = "0.6.2" +version = "0.6.3" description = "Update dependencies and bump their version in the pyproject.toml file" authors = ["Mousa Zeid Baker"] packages = [ diff --git a/src/poetryup/pyproject.py b/src/poetryup/core/pyproject.py similarity index 99% rename from src/poetryup/pyproject.py rename to src/poetryup/core/pyproject.py index be20355..f6fd152 100644 --- a/src/poetryup/pyproject.py +++ b/src/poetryup/core/pyproject.py @@ -6,7 +6,7 @@ import tomlkit from packaging import version as version_ -from poetryup.dependency import Dependency +from poetryup.models.dependency import Dependency class Pyproject: diff --git a/src/poetryup/main.py b/src/poetryup/main.py index 8cb9e92..7c41d38 100644 --- a/src/poetryup/main.py +++ b/src/poetryup/main.py @@ -6,7 +6,7 @@ import typer -from poetryup.pyproject import Pyproject +from poetryup.core.pyproject import Pyproject logging.basicConfig(level=os.environ.get("LOGLEVEL", "INFO").upper()) diff --git a/src/poetryup/dependency.py b/src/poetryup/models/dependency.py similarity index 100% rename from src/poetryup/dependency.py rename to src/poetryup/models/dependency.py diff --git a/tests/conftest.py b/tests/conftest.py index f1093fb..28de5a8 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,7 +1,7 @@ import pytest from pytest_mock import MockerFixture -from poetryup.pyproject import Pyproject +from poetryup.core.pyproject import Pyproject @pytest.fixture(scope="function") diff --git a/tests/unit/test_dependency.py b/tests/unit/test_dependency.py index 811da13..8e3f976 100644 --- a/tests/unit/test_dependency.py +++ b/tests/unit/test_dependency.py @@ -1,4 +1,4 @@ -from poetryup.dependency import Dependency +from poetryup.models.dependency import Dependency def test_normalized_name() -> None: diff --git a/tests/unit/test_pyproject.py b/tests/unit/test_pyproject.py index fee083e..0d46649 100644 --- a/tests/unit/test_pyproject.py +++ b/tests/unit/test_pyproject.py @@ -3,7 +3,7 @@ from pytest_mock import MockerFixture -from poetryup.pyproject import Pyproject +from poetryup.core.pyproject import Pyproject def test_update_dependencies( From 5ed9aa78b6d738bc9b3d35e686b70fa526a42c8c Mon Sep 17 00:00:00 2001 From: Mousa Zeid Baker Date: Sat, 7 May 2022 18:09:19 +0200 Subject: [PATCH 06/15] refactor: Pyproject class --- src/poetryup/core/pyproject.py | 93 +++++++++++++++++++--------------- 1 file changed, 53 insertions(+), 40 deletions(-) diff --git a/src/poetryup/core/pyproject.py b/src/poetryup/core/pyproject.py index f6fd152..42774db 100644 --- a/src/poetryup/core/pyproject.py +++ b/src/poetryup/core/pyproject.py @@ -1,7 +1,7 @@ import logging import re import subprocess -from typing import Dict, List, Optional +from typing import Dict, List, Optional, Union import tomlkit from packaging import version as version_ @@ -23,14 +23,15 @@ 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._dependencies = None # caches the dependencies - def dumps(self) -> str: - """Dumps pyproject into a string.""" - - return tomlkit.dumps(self.pyproject) + @property + def dependencies(self) -> List[Dependency]: + """The pyproject dependencies""" - def list_dependencies(self) -> List[Dependency]: - """Returns pyproject dependencies""" + if self._dependencies is not None: + # return cached dependencies + return self._dependencies dependencies: List[Dependency] = [] table = self.pyproject["tool"]["poetry"] @@ -66,53 +67,65 @@ def list_dependencies(self) -> List[Dependency]: ) dependencies.append(dependency) + self._dependencies = dependencies # log dependencies for future access return dependencies - def list_lock_dependencies(self) -> List[Dependency]: - """Returns pyproject dependencies with their lock version""" + @property + def lock_dependencies(self) -> List[Dependency]: + """The pyproject dependencies with their lock version""" - # create list of lock dependencies + # run poetry show to get currently installed dependencies output = self.__run_poetry_show() + + # extract dependencies from each line of the output pattern = re.compile("^[a-zA-Z-]+") - lock_deps: List[Dependency] = [] + lock_dependencies: List[Dependency] = [] for line in output.split("\n"): - if pattern.match(line) is not None: - name, version, *_ = line.split() - dependency = Dependency( - name=name, - version=version, - group="", - ) - lock_deps.append(dependency) - - # list dependencies from pyproject and set version to lock version - dependencies = self.list_dependencies() - for dependency in dependencies: - lock_dep = next( - ( - lock_dep - for lock_dep in lock_deps - if lock_dep.normalized_name == dependency.normalized_name - ), - None, - ) - if lock_dep is None: - logging.info( - f"Couldn't find lock dependency for '{dependency.name}'" - ) + if pattern.match(line) is None: + # not a matching line, continue to next + continue + + # extract name and version + lock_name, lock_version, *_ = line.split() + + # find dependency in pyproject.toml file + dependency = self.search_dependency(lock_name) + if dependency is None: + # not found in pyproject.toml, continue to next continue + # replace version with lock version if isinstance(dependency.version, str): - dependency.version = dependency.constraint + lock_dep.version + dependency.version = dependency.constraint + lock_version elif ( isinstance(dependency.version, Dict) and dependency.version.get("version") is not None ): dependency.version["version"] = ( - dependency.constraint + lock_dep.version + dependency.constraint + lock_version ) + lock_dependencies.append(dependency) - return dependencies + return lock_dependencies + + def dumps(self) -> str: + """Dumps pyproject into a string.""" + + return tomlkit.dumps(self.pyproject) + + def search_dependency(self, name: str) -> Union[Dependency, None]: + """Searches for a dependency given a name + + Args: + name: Name of the dependency to search for + + Returns: + A dependency if found, None if not found + """ + + for dependency in self.dependencies: + if dependency.name == name or dependency.normalized_name == name: + return dependency def update_dependencies( self, @@ -132,7 +145,7 @@ def update_dependencies( # to avoid version solver error in case dependencies depend on each # other groups = {} - for dependency in self.list_dependencies(): + for dependency in self.dependencies: if skip_exact and dependency.constraint == "": # skip dependencies with an exact version continue @@ -152,7 +165,7 @@ def update_dependencies( # bump versions in pyproject table = self.pyproject["tool"]["poetry"] - for dependency in self.list_lock_dependencies(): + for dependency in self.lock_dependencies: if dependency.group == "default": table["dependencies"][dependency.name] = dependency.version elif ( From 50ec04b4ff17e50111d5aeeb5953d88b1ca37167 Mon Sep 17 00:00:00 2001 From: Mousa Zeid Baker Date: Sat, 7 May 2022 19:55:36 +0200 Subject: [PATCH 07/15] docs: fix typo in comment --- src/poetryup/core/pyproject.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/poetryup/core/pyproject.py b/src/poetryup/core/pyproject.py index 42774db..40de34a 100644 --- a/src/poetryup/core/pyproject.py +++ b/src/poetryup/core/pyproject.py @@ -67,7 +67,7 @@ def dependencies(self) -> List[Dependency]: ) dependencies.append(dependency) - self._dependencies = dependencies # log dependencies for future access + self._dependencies = dependencies # cache dependencies return dependencies @property From 6589242b3b8a42f1b33cf7993d50637d2946e668 Mon Sep 17 00:00:00 2001 From: Mousa Zeid Baker Date: Sat, 7 May 2022 21:09:17 +0200 Subject: [PATCH 08/15] refactor: tests for Pyproject class --- tests/conftest.py | 19 +- .../expected_pyproject/pyproject.toml | 10 +- .../pyproject_with_capital_letters.toml | 32 -- .../pyproject_with_dependency_groups.toml | 34 -- ...project_with_exact_version_dependency.toml | 32 -- .../pyproject_with_git_dependency.toml | 32 -- .../pyproject_with_restricted_dependency.toml | 32 -- .../pyproject_with_underscore_character.toml | 32 -- .../fixtures/input_pyproject/pyproject.toml | 10 +- .../pyproject_with_capital_letters.toml | 32 -- .../pyproject_with_dependency_groups.toml | 34 -- ...project_with_exact_version_dependency.toml | 32 -- .../pyproject_with_git_dependency.toml | 32 -- .../pyproject_with_restricted_dependency.toml | 32 -- .../pyproject_with_underscore_character.toml | 32 -- tests/unit/test_pyproject.py | 427 ++---------------- 16 files changed, 85 insertions(+), 769 deletions(-) delete mode 100644 tests/unit/fixtures/expected_pyproject/pyproject_with_capital_letters.toml delete mode 100644 tests/unit/fixtures/expected_pyproject/pyproject_with_dependency_groups.toml delete mode 100644 tests/unit/fixtures/expected_pyproject/pyproject_with_exact_version_dependency.toml delete mode 100644 tests/unit/fixtures/expected_pyproject/pyproject_with_git_dependency.toml delete mode 100644 tests/unit/fixtures/expected_pyproject/pyproject_with_restricted_dependency.toml delete mode 100644 tests/unit/fixtures/expected_pyproject/pyproject_with_underscore_character.toml delete mode 100644 tests/unit/fixtures/input_pyproject/pyproject_with_capital_letters.toml delete mode 100644 tests/unit/fixtures/input_pyproject/pyproject_with_dependency_groups.toml delete mode 100644 tests/unit/fixtures/input_pyproject/pyproject_with_exact_version_dependency.toml delete mode 100644 tests/unit/fixtures/input_pyproject/pyproject_with_git_dependency.toml delete mode 100644 tests/unit/fixtures/input_pyproject/pyproject_with_restricted_dependency.toml delete mode 100644 tests/unit/fixtures/input_pyproject/pyproject_with_underscore_character.toml diff --git a/tests/conftest.py b/tests/conftest.py index 28de5a8..21433e7 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -18,10 +18,25 @@ def mock_poetry_commands(mocker: MockerFixture) -> None: Pyproject, "_Pyproject__run_poetry_show", return_value=( - "poetryup 0.2.0 Update dependencies and bump their version in the " + "poetryup 0.2.0 " "pyproject.toml file" "\n└── toml >=0.10.2,<0.11.0\n" - "poetryup-extra 0.2.0 " + "poetryup-tilde 0.2.0 " + "pyproject.toml file" + "\n└── toml >=0.10.2,<0.11.0\n" + "poetryup-exact 0.2.0 " + "pyproject.toml file" + "\n└── toml >=0.10.2,<0.11.0\n" + "poetryup-restricted 0.2.0 " + "pyproject.toml file" + "\n└── toml >=0.10.2,<0.11.0\n" + "poetryup-git 0.2.0 " + "pyproject.toml file" + "\n└── toml >=0.10.2,<0.11.0\n" + "poetryup-underscore 0.2.0 " + "pyproject.toml file" + "\n└── toml >=0.10.2,<0.11.0\n" + "poetryup-capital 0.2.0 " "pyproject.toml file" "\n└── toml >=0.10.2,<0.11.0\n" ), diff --git a/tests/unit/fixtures/expected_pyproject/pyproject.toml b/tests/unit/fixtures/expected_pyproject/pyproject.toml index b6bab57..ff835c4 100644 --- a/tests/unit/fixtures/expected_pyproject/pyproject.toml +++ b/tests/unit/fixtures/expected_pyproject/pyproject.toml @@ -22,7 +22,15 @@ include = ["LICENSE"] python = "^3.6" poetryup = "^0.2.0" -[tool.poetry.dev-dependencies] +[tool.poetry.group.main.dependencies] +poetryup_tilde = "^0.2.0" +poetryup_exact = "0.2.0" +poetryup_restricted = { version = "^0.2.0", python = "<3.7" } +poetryup_git = { git = "https://github.com/MousaZeidBaker/poetryup.git" } +poetryup_underscore = "^0.2.0" +Poetryup_Capital = "^0.2.0" + +[tool.poetry.group.dev.dependencies] [tool.poetry.scripts] poetryup = "src.test_poetryup.test_poetryup:main" diff --git a/tests/unit/fixtures/expected_pyproject/pyproject_with_capital_letters.toml b/tests/unit/fixtures/expected_pyproject/pyproject_with_capital_letters.toml deleted file mode 100644 index e08dd64..0000000 --- a/tests/unit/fixtures/expected_pyproject/pyproject_with_capital_letters.toml +++ /dev/null @@ -1,32 +0,0 @@ -[tool.poetry] -name = "test-poetryup" -version = "0.1.0" -description = "Test PoetryUp" -authors = ["Mousa Zeid Baker"] -packages = [ - { include = "test_poetryup", from = "src" } -] -license = "MIT" -readme = "README.md" -homepage = "https://github.com/MousaZeidBaker/poetryup" -repository = "https://github.com/MousaZeidBaker/poetryup" -keywords=[ - "packaging", - "dependency", - "poetry", - "poetryup", -] -include = ["LICENSE"] - -[tool.poetry.dependencies] -python = "^3.6" -PoetryUp = "^0.2.0" - -[tool.poetry.dev-dependencies] - -[tool.poetry.scripts] -poetryup = "src.test_poetryup.test_poetryup:main" - -[build-system] -requires = ["poetry-core>=1.0.0"] -build-backend = "poetry.core.masonry.api" diff --git a/tests/unit/fixtures/expected_pyproject/pyproject_with_dependency_groups.toml b/tests/unit/fixtures/expected_pyproject/pyproject_with_dependency_groups.toml deleted file mode 100644 index 137f826..0000000 --- a/tests/unit/fixtures/expected_pyproject/pyproject_with_dependency_groups.toml +++ /dev/null @@ -1,34 +0,0 @@ -[tool.poetry] -name = "test-poetryup" -version = "0.1.0" -description = "Test PoetryUp" -authors = ["Mousa Zeid Baker"] -packages = [ - { include = "test_poetryup", from = "src" } -] -license = "MIT" -readme = "README.md" -homepage = "https://github.com/MousaZeidBaker/poetryup" -repository = "https://github.com/MousaZeidBaker/poetryup" -keywords=[ - "packaging", - "dependency", - "poetry", - "poetryup", -] -include = ["LICENSE"] - -[tool.poetry.dependencies] -python = "^3.6" - -[tool.poetry.group.main.dependencies] -poetryup = "^0.2.0" - -[tool.poetry.group.dev.dependencies] - -[tool.poetry.scripts] -poetryup = "src.test_poetryup.test_poetryup:main" - -[build-system] -requires = ["poetry-core>=1.0.0"] -build-backend = "poetry.core.masonry.api" diff --git a/tests/unit/fixtures/expected_pyproject/pyproject_with_exact_version_dependency.toml b/tests/unit/fixtures/expected_pyproject/pyproject_with_exact_version_dependency.toml deleted file mode 100644 index d753455..0000000 --- a/tests/unit/fixtures/expected_pyproject/pyproject_with_exact_version_dependency.toml +++ /dev/null @@ -1,32 +0,0 @@ -[tool.poetry] -name = "test-poetryup" -version = "0.1.0" -description = "Test PoetryUp" -authors = ["Mousa Zeid Baker"] -packages = [ - { include = "test_poetryup", from = "src" } -] -license = "MIT" -readme = "README.md" -homepage = "https://github.com/MousaZeidBaker/poetryup" -repository = "https://github.com/MousaZeidBaker/poetryup" -keywords=[ - "packaging", - "dependency", - "poetry", - "poetryup", -] -include = ["LICENSE"] - -[tool.poetry.dependencies] -python = "^3.6" -poetryup = "0.2.0" - -[tool.poetry.dev-dependencies] - -[tool.poetry.scripts] -poetryup = "src.test_poetryup.test_poetryup:main" - -[build-system] -requires = ["poetry-core>=1.0.0"] -build-backend = "poetry.core.masonry.api" diff --git a/tests/unit/fixtures/expected_pyproject/pyproject_with_git_dependency.toml b/tests/unit/fixtures/expected_pyproject/pyproject_with_git_dependency.toml deleted file mode 100644 index d67dbd3..0000000 --- a/tests/unit/fixtures/expected_pyproject/pyproject_with_git_dependency.toml +++ /dev/null @@ -1,32 +0,0 @@ -[tool.poetry] -name = "test-poetryup" -version = "0.1.0" -description = "Test PoetryUp" -authors = ["Mousa Zeid Baker"] -packages = [ - { include = "test_poetryup", from = "src" } -] -license = "MIT" -readme = "README.md" -homepage = "https://github.com/MousaZeidBaker/poetryup" -repository = "https://github.com/MousaZeidBaker/poetryup" -keywords=[ - "packaging", - "dependency", - "poetry", - "poetryup", -] -include = ["LICENSE"] - -[tool.poetry.dependencies] -python = "^3.6" -poetryup = { git = "https://github.com/MousaZeidBaker/poetryup.git" } - -[tool.poetry.dev-dependencies] - -[tool.poetry.scripts] -poetryup = "src.test_poetryup.test_poetryup:main" - -[build-system] -requires = ["poetry-core>=1.0.0"] -build-backend = "poetry.core.masonry.api" diff --git a/tests/unit/fixtures/expected_pyproject/pyproject_with_restricted_dependency.toml b/tests/unit/fixtures/expected_pyproject/pyproject_with_restricted_dependency.toml deleted file mode 100644 index 2d31915..0000000 --- a/tests/unit/fixtures/expected_pyproject/pyproject_with_restricted_dependency.toml +++ /dev/null @@ -1,32 +0,0 @@ -[tool.poetry] -name = "test-poetryup" -version = "0.1.0" -description = "Test PoetryUp" -authors = ["Mousa Zeid Baker"] -packages = [ - { include = "test_poetryup", from = "src" } -] -license = "MIT" -readme = "README.md" -homepage = "https://github.com/MousaZeidBaker/poetryup" -repository = "https://github.com/MousaZeidBaker/poetryup" -keywords=[ - "packaging", - "dependency", - "poetry", - "poetryup", -] -include = ["LICENSE"] - -[tool.poetry.dependencies] -python = "^3.6" -poetryup = {version = "^0.2.0", python = "<3.7"} - -[tool.poetry.dev-dependencies] - -[tool.poetry.scripts] -poetryup = "src.test_poetryup.test_poetryup:main" - -[build-system] -requires = ["poetry-core>=1.0.0"] -build-backend = "poetry.core.masonry.api" diff --git a/tests/unit/fixtures/expected_pyproject/pyproject_with_underscore_character.toml b/tests/unit/fixtures/expected_pyproject/pyproject_with_underscore_character.toml deleted file mode 100644 index c87a522..0000000 --- a/tests/unit/fixtures/expected_pyproject/pyproject_with_underscore_character.toml +++ /dev/null @@ -1,32 +0,0 @@ -[tool.poetry] -name = "test-poetryup" -version = "0.1.0" -description = "Test PoetryUp" -authors = ["Mousa Zeid Baker"] -packages = [ - { include = "test_poetryup", from = "src" } -] -license = "MIT" -readme = "README.md" -homepage = "https://github.com/MousaZeidBaker/poetryup" -repository = "https://github.com/MousaZeidBaker/poetryup" -keywords=[ - "packaging", - "dependency", - "poetry", - "poetryup", -] -include = ["LICENSE"] - -[tool.poetry.dependencies] -python = "^3.6" -poetryup_extra = "^0.2.0" - -[tool.poetry.dev-dependencies] - -[tool.poetry.scripts] -poetryup = "src.test_poetryup.test_poetryup:main" - -[build-system] -requires = ["poetry-core>=1.0.0"] -build-backend = "poetry.core.masonry.api" diff --git a/tests/unit/fixtures/input_pyproject/pyproject.toml b/tests/unit/fixtures/input_pyproject/pyproject.toml index f57b44c..8f045fe 100644 --- a/tests/unit/fixtures/input_pyproject/pyproject.toml +++ b/tests/unit/fixtures/input_pyproject/pyproject.toml @@ -22,7 +22,15 @@ include = ["LICENSE"] python = "^3.6" poetryup = "^0.1.0" -[tool.poetry.dev-dependencies] +[tool.poetry.group.main.dependencies] +poetryup_tilde = "^0.1.0" +poetryup_exact = "0.1.0" +poetryup_restricted = { version = "^0.1.0", python = "<3.7" } +poetryup_git = { git = "https://github.com/MousaZeidBaker/poetryup.git" } +poetryup_underscore = "^0.1.0" +Poetryup_Capital = "^0.1.0" + +[tool.poetry.group.dev.dependencies] [tool.poetry.scripts] poetryup = "src.test_poetryup.test_poetryup:main" diff --git a/tests/unit/fixtures/input_pyproject/pyproject_with_capital_letters.toml b/tests/unit/fixtures/input_pyproject/pyproject_with_capital_letters.toml deleted file mode 100644 index dea99fe..0000000 --- a/tests/unit/fixtures/input_pyproject/pyproject_with_capital_letters.toml +++ /dev/null @@ -1,32 +0,0 @@ -[tool.poetry] -name = "test-poetryup" -version = "0.1.0" -description = "Test PoetryUp" -authors = ["Mousa Zeid Baker"] -packages = [ - { include = "test_poetryup", from = "src" } -] -license = "MIT" -readme = "README.md" -homepage = "https://github.com/MousaZeidBaker/poetryup" -repository = "https://github.com/MousaZeidBaker/poetryup" -keywords=[ - "packaging", - "dependency", - "poetry", - "poetryup", -] -include = ["LICENSE"] - -[tool.poetry.dependencies] -python = "^3.6" -PoetryUp = "^0.1.0" - -[tool.poetry.dev-dependencies] - -[tool.poetry.scripts] -poetryup = "src.test_poetryup.test_poetryup:main" - -[build-system] -requires = ["poetry-core>=1.0.0"] -build-backend = "poetry.core.masonry.api" diff --git a/tests/unit/fixtures/input_pyproject/pyproject_with_dependency_groups.toml b/tests/unit/fixtures/input_pyproject/pyproject_with_dependency_groups.toml deleted file mode 100644 index 9b1cc17..0000000 --- a/tests/unit/fixtures/input_pyproject/pyproject_with_dependency_groups.toml +++ /dev/null @@ -1,34 +0,0 @@ -[tool.poetry] -name = "test-poetryup" -version = "0.1.0" -description = "Test PoetryUp" -authors = ["Mousa Zeid Baker"] -packages = [ - { include = "test_poetryup", from = "src" } -] -license = "MIT" -readme = "README.md" -homepage = "https://github.com/MousaZeidBaker/poetryup" -repository = "https://github.com/MousaZeidBaker/poetryup" -keywords=[ - "packaging", - "dependency", - "poetry", - "poetryup", -] -include = ["LICENSE"] - -[tool.poetry.dependencies] -python = "^3.6" - -[tool.poetry.group.main.dependencies] -poetryup = "^0.1.0" - -[tool.poetry.group.dev.dependencies] - -[tool.poetry.scripts] -poetryup = "src.test_poetryup.test_poetryup:main" - -[build-system] -requires = ["poetry-core>=1.0.0"] -build-backend = "poetry.core.masonry.api" diff --git a/tests/unit/fixtures/input_pyproject/pyproject_with_exact_version_dependency.toml b/tests/unit/fixtures/input_pyproject/pyproject_with_exact_version_dependency.toml deleted file mode 100644 index fbcfe8e..0000000 --- a/tests/unit/fixtures/input_pyproject/pyproject_with_exact_version_dependency.toml +++ /dev/null @@ -1,32 +0,0 @@ -[tool.poetry] -name = "test-poetryup" -version = "0.1.0" -description = "Test PoetryUp" -authors = ["Mousa Zeid Baker"] -packages = [ - { include = "test_poetryup", from = "src" } -] -license = "MIT" -readme = "README.md" -homepage = "https://github.com/MousaZeidBaker/poetryup" -repository = "https://github.com/MousaZeidBaker/poetryup" -keywords=[ - "packaging", - "dependency", - "poetry", - "poetryup", -] -include = ["LICENSE"] - -[tool.poetry.dependencies] -python = "^3.6" -poetryup = "0.1.0" - -[tool.poetry.dev-dependencies] - -[tool.poetry.scripts] -poetryup = "src.test_poetryup.test_poetryup:main" - -[build-system] -requires = ["poetry-core>=1.0.0"] -build-backend = "poetry.core.masonry.api" diff --git a/tests/unit/fixtures/input_pyproject/pyproject_with_git_dependency.toml b/tests/unit/fixtures/input_pyproject/pyproject_with_git_dependency.toml deleted file mode 100644 index d67dbd3..0000000 --- a/tests/unit/fixtures/input_pyproject/pyproject_with_git_dependency.toml +++ /dev/null @@ -1,32 +0,0 @@ -[tool.poetry] -name = "test-poetryup" -version = "0.1.0" -description = "Test PoetryUp" -authors = ["Mousa Zeid Baker"] -packages = [ - { include = "test_poetryup", from = "src" } -] -license = "MIT" -readme = "README.md" -homepage = "https://github.com/MousaZeidBaker/poetryup" -repository = "https://github.com/MousaZeidBaker/poetryup" -keywords=[ - "packaging", - "dependency", - "poetry", - "poetryup", -] -include = ["LICENSE"] - -[tool.poetry.dependencies] -python = "^3.6" -poetryup = { git = "https://github.com/MousaZeidBaker/poetryup.git" } - -[tool.poetry.dev-dependencies] - -[tool.poetry.scripts] -poetryup = "src.test_poetryup.test_poetryup:main" - -[build-system] -requires = ["poetry-core>=1.0.0"] -build-backend = "poetry.core.masonry.api" diff --git a/tests/unit/fixtures/input_pyproject/pyproject_with_restricted_dependency.toml b/tests/unit/fixtures/input_pyproject/pyproject_with_restricted_dependency.toml deleted file mode 100644 index c252bec..0000000 --- a/tests/unit/fixtures/input_pyproject/pyproject_with_restricted_dependency.toml +++ /dev/null @@ -1,32 +0,0 @@ -[tool.poetry] -name = "test-poetryup" -version = "0.1.0" -description = "Test PoetryUp" -authors = ["Mousa Zeid Baker"] -packages = [ - { include = "test_poetryup", from = "src" } -] -license = "MIT" -readme = "README.md" -homepage = "https://github.com/MousaZeidBaker/poetryup" -repository = "https://github.com/MousaZeidBaker/poetryup" -keywords=[ - "packaging", - "dependency", - "poetry", - "poetryup", -] -include = ["LICENSE"] - -[tool.poetry.dependencies] -python = "^3.6" -poetryup = {version = "^0.1.0", python = "<3.7"} - -[tool.poetry.dev-dependencies] - -[tool.poetry.scripts] -poetryup = "src.test_poetryup.test_poetryup:main" - -[build-system] -requires = ["poetry-core>=1.0.0"] -build-backend = "poetry.core.masonry.api" diff --git a/tests/unit/fixtures/input_pyproject/pyproject_with_underscore_character.toml b/tests/unit/fixtures/input_pyproject/pyproject_with_underscore_character.toml deleted file mode 100644 index 017215e..0000000 --- a/tests/unit/fixtures/input_pyproject/pyproject_with_underscore_character.toml +++ /dev/null @@ -1,32 +0,0 @@ -[tool.poetry] -name = "test-poetryup" -version = "0.1.0" -description = "Test PoetryUp" -authors = ["Mousa Zeid Baker"] -packages = [ - { include = "test_poetryup", from = "src" } -] -license = "MIT" -readme = "README.md" -homepage = "https://github.com/MousaZeidBaker/poetryup" -repository = "https://github.com/MousaZeidBaker/poetryup" -keywords=[ - "packaging", - "dependency", - "poetry", - "poetryup", -] -include = ["LICENSE"] - -[tool.poetry.dependencies] -python = "^3.6" -poetryup_extra = "^0.1.0" - -[tool.poetry.dev-dependencies] - -[tool.poetry.scripts] -poetryup = "src.test_poetryup.test_poetryup:main" - -[build-system] -requires = ["poetry-core>=1.0.0"] -build-backend = "poetry.core.masonry.api" diff --git a/tests/unit/test_pyproject.py b/tests/unit/test_pyproject.py index 0d46649..aa694b5 100644 --- a/tests/unit/test_pyproject.py +++ b/tests/unit/test_pyproject.py @@ -1,405 +1,78 @@ import os from pathlib import Path +from unittest.mock import call from pytest_mock import MockerFixture from poetryup.core.pyproject import Pyproject - -def test_update_dependencies( - mock_poetry_commands, -) -> None: - pyproject_str = Path( - os.path.join( - os.path.dirname(__file__), - "fixtures/input_pyproject/pyproject.toml", - ) - ).read_text() - expected_pyproject_str = Path( - os.path.join( - os.path.dirname(__file__), - "fixtures/expected_pyproject/pyproject.toml", - ) - ).read_text() - - pyproject = Pyproject(pyproject_str) - pyproject.update_dependencies() - assert pyproject.dumps() == expected_pyproject_str - assert ( - pyproject.pyproject["tool"]["poetry"]["dependencies"]["poetryup"] - == "^0.2.0" +pyproject_str = Path( + os.path.join( + os.path.dirname(__file__), + "fixtures/input_pyproject/pyproject.toml", ) +).read_text() - -def test_update_dependencies_latest( - mock_poetry_commands, -) -> None: - pyproject_str = Path( - os.path.join( - os.path.dirname(__file__), - "fixtures/input_pyproject/pyproject.toml", - ) - ).read_text() - expected_pyproject_str = Path( - os.path.join( - os.path.dirname(__file__), - "fixtures/expected_pyproject/pyproject.toml", - ) - ).read_text() - - pyproject = Pyproject(pyproject_str) - pyproject.update_dependencies(latest=True) - assert pyproject.dumps() == expected_pyproject_str - assert ( - pyproject.pyproject["tool"]["poetry"]["dependencies"]["poetryup"] - == "^0.2.0" +expected_pyproject_str = Path( + os.path.join( + os.path.dirname(__file__), + "fixtures/expected_pyproject/pyproject.toml", ) +).read_text() -def test_update_dependencies_with_capital_letters( - mock_poetry_commands, -) -> None: - pyproject_str = Path( - os.path.join( - os.path.dirname(__file__), - "fixtures/input_pyproject/pyproject_with_capital_letters.toml", - ) - ).read_text() - expected_pyproject_str = Path( - os.path.join( - os.path.dirname(__file__), - "fixtures/expected_pyproject/pyproject_with_capital_letters.toml", - ) - ).read_text() - - pyproject = Pyproject(pyproject_str) - pyproject.update_dependencies() - assert pyproject.dumps() == expected_pyproject_str - assert ( - pyproject.pyproject["tool"]["poetry"]["dependencies"]["PoetryUp"] - == "^0.2.0" - ) - - -def test_update_dependencies_latest_with_capital_letters( - mock_poetry_commands, -) -> None: - pyproject_str = Path( - os.path.join( - os.path.dirname(__file__), - "fixtures/input_pyproject/pyproject_with_capital_letters.toml", - ) - ).read_text() - expected_pyproject_str = Path( - os.path.join( - os.path.dirname(__file__), - "fixtures/expected_pyproject/pyproject_with_capital_letters.toml", - ) - ).read_text() - - pyproject = Pyproject(pyproject_str) - pyproject.update_dependencies(latest=True) - assert pyproject.dumps() == expected_pyproject_str - assert ( - pyproject.pyproject["tool"]["poetry"]["dependencies"]["PoetryUp"] - == "^0.2.0" - ) - - -def test_update_dependencies_with_underscore_character( - mock_poetry_commands, -) -> None: - pyproject_str = Path( - os.path.join( - os.path.dirname(__file__), - "fixtures/input_pyproject/pyproject_with_underscore_character.toml", - ) - ).read_text() - expected_pyproject_str = Path( - os.path.join( - os.path.dirname(__file__), - "fixtures/expected_pyproject/", - "pyproject_with_underscore_character.toml", - ) - ).read_text() - - pyproject = Pyproject(pyproject_str) - pyproject.update_dependencies() - assert pyproject.dumps() == expected_pyproject_str - assert ( - pyproject.pyproject["tool"]["poetry"]["dependencies"]["poetryup_extra"] - == "^0.2.0" - ) - - -def test_update_dependencies_latest_with_underscore_character( - mock_poetry_commands, -) -> None: - pyproject_str = Path( - os.path.join( - os.path.dirname(__file__), - "fixtures/input_pyproject/", - "pyproject_with_underscore_character.toml", - ) - ).read_text() - expected_pyproject_str = Path( - os.path.join( - os.path.dirname(__file__), - "fixtures/expected_pyproject/", - "pyproject_with_underscore_character.toml", - ) - ).read_text() - - pyproject = Pyproject(pyproject_str) - pyproject.update_dependencies(latest=True) - assert pyproject.dumps() == expected_pyproject_str - assert ( - pyproject.pyproject["tool"]["poetry"]["dependencies"]["poetryup_extra"] - == "^0.2.0" - ) - - -def test_update_dependencies_with_dependency_groups( +def test_update_dependencies( mock_poetry_commands, ) -> None: - pyproject_str = Path( - os.path.join( - os.path.dirname(__file__), - "fixtures/input_pyproject/pyproject_with_dependency_groups.toml", - ) - ).read_text() - expected_pyproject_str = Path( - os.path.join( - os.path.dirname(__file__), - "fixtures/expected_pyproject/pyproject_with_dependency_groups.toml", - ) - ).read_text() - pyproject = Pyproject(pyproject_str) pyproject.update_dependencies() - assert pyproject.dumps() == expected_pyproject_str - assert ( - pyproject.pyproject["tool"]["poetry"]["group"]["main"]["dependencies"][ - "poetryup" - ] - == "^0.2.0" - ) - - -def test_update_dependencies_latest_with_dependency_groups( - mock_poetry_commands, -) -> None: - pyproject_str = Path( - os.path.join( - os.path.dirname(__file__), - "fixtures/input_pyproject/pyproject_with_dependency_groups.toml", - ) - ).read_text() - expected_pyproject_str = Path( - os.path.join( - os.path.dirname(__file__), - "fixtures/expected_pyproject/pyproject_with_dependency_groups.toml", - ) - ).read_text() - - pyproject = Pyproject(pyproject_str) - pyproject.update_dependencies(latest=True) - assert pyproject.dumps() == expected_pyproject_str - assert ( - pyproject.pyproject["tool"]["poetry"]["group"]["main"]["dependencies"][ - "poetryup" - ] - == "^0.2.0" - ) - - -def test_update_dependencies_with_exact_version_dependency( - mock_poetry_commands, -) -> None: - pyproject_str = Path( - os.path.join( - os.path.dirname(__file__), - "fixtures/input_pyproject/", - "pyproject_with_exact_version_dependency.toml", - ) - ).read_text() - expected_pyproject_str = Path( - os.path.join( - os.path.dirname(__file__), - "fixtures/expected_pyproject/", - "pyproject_with_exact_version_dependency.toml", - ) - ).read_text() - pyproject = Pyproject(pyproject_str) - pyproject.update_dependencies() assert pyproject.dumps() == expected_pyproject_str - assert ( - pyproject.pyproject["tool"]["poetry"]["dependencies"]["poetryup"] - == "0.2.0" - ) + table = pyproject.pyproject["tool"]["poetry"]["dependencies"] + assert table["poetryup"] == "^0.2.0" + + table = pyproject.pyproject["tool"]["poetry"]["group"]["main"][ + "dependencies" + ] + assert table["poetryup_tilde"] == "^0.2.0" + assert table["poetryup_exact"] == "0.2.0" + assert table["poetryup_restricted"] == { + "version": "^0.2.0", + "python": "<3.7", + } + assert table["poetryup_git"] == { + "git": "https://github.com/MousaZeidBaker/poetryup.git" + } + assert table["poetryup_underscore"] == "^0.2.0" + assert table["Poetryup_Capital"] == "^0.2.0" -def test_update_dependencies_latest_with_exact_version_dependency( - mock_poetry_commands, -) -> None: - pyproject_str = Path( - os.path.join( - os.path.dirname(__file__), - "fixtures/input_pyproject/", - "pyproject_with_exact_version_dependency.toml", - ) - ).read_text() - expected_pyproject_str = Path( - os.path.join( - os.path.dirname(__file__), - "fixtures/expected_pyproject/", - "pyproject_with_exact_version_dependency.toml", - ) - ).read_text() - pyproject = Pyproject(pyproject_str) - pyproject.update_dependencies(latest=True) - assert pyproject.dumps() == expected_pyproject_str - assert ( - pyproject.pyproject["tool"]["poetry"]["dependencies"]["poetryup"] - == "0.2.0" - ) - - -def test_update_dependencies_latest_skip_exact_with_exact_version_dependency( +def test_update_dependencies_latest( mock_poetry_commands, mocker: MockerFixture, ) -> None: - pyproject_str = Path( - os.path.join( - os.path.dirname(__file__), - "fixtures/input_pyproject/", - "pyproject_with_exact_version_dependency.toml", - ) - ).read_text() - - mocker.patch.object( - Pyproject, - "_Pyproject__run_poetry_show", - return_value=( - "poetryup 0.1.0 Update dependencies and bump their version in the " - "pyproject.toml file" - "\n└── toml >=0.10.2,<0.11.0\n" - ), - ) - pyproject = Pyproject(pyproject_str) - pyproject.update_dependencies(latest=True) - assert ( - pyproject.pyproject["tool"]["poetry"]["dependencies"]["poetryup"] - == "0.1.0" + mock = mocker.patch.object( + pyproject, + "_Pyproject__run_poetry_add", + return_value=None, ) - - -def test_update_dependencies_with_git_dependency( - mock_poetry_commands, -) -> None: - pyproject_str = Path( - os.path.join( - os.path.dirname(__file__), - "fixtures/input_pyproject/pyproject_with_git_dependency.toml", - ) - ).read_text() - expected_pyproject_str = Path( - os.path.join( - os.path.dirname(__file__), - "fixtures/expected_pyproject/pyproject_with_git_dependency.toml", - ) - ).read_text() - - pyproject = Pyproject(pyproject_str) - pyproject.update_dependencies() - assert pyproject.dumps() == expected_pyproject_str - assert ( - pyproject.pyproject["tool"]["poetry"]["dependencies"]["poetryup"]["git"] - == "https://github.com/MousaZeidBaker/poetryup.git" - ) - - -def test_update_dependencies_latest_with_git_dependency( - mock_poetry_commands, -) -> None: - pyproject_str = Path( - os.path.join( - os.path.dirname(__file__), - "fixtures/input_pyproject/pyproject_with_git_dependency.toml", - ) - ).read_text() - expected_pyproject_str = Path( - os.path.join( - os.path.dirname(__file__), - "fixtures/expected_pyproject/pyproject_with_git_dependency.toml", - ) - ).read_text() - - pyproject = Pyproject(pyproject_str) pyproject.update_dependencies(latest=True) - assert pyproject.dumps() == expected_pyproject_str - assert ( - pyproject.pyproject["tool"]["poetry"]["dependencies"]["poetryup"]["git"] - == "https://github.com/MousaZeidBaker/poetryup.git" - ) - - -def test_update_dependencies_with_restricted_dependency( - mock_poetry_commands, -) -> None: - pyproject_str = Path( - os.path.join( - os.path.dirname(__file__), - "fixtures/input_pyproject/", - "pyproject_with_restricted_dependency.toml", - ) - ).read_text() - expected_pyproject_str = Path( - os.path.join( - os.path.dirname(__file__), - "fixtures/expected_pyproject/", - "pyproject_with_restricted_dependency.toml", - ) - ).read_text() - pyproject = Pyproject(pyproject_str) - pyproject.update_dependencies() - assert pyproject.dumps() == expected_pyproject_str - assert ( - pyproject.pyproject["tool"]["poetry"]["dependencies"]["poetryup"][ - "version" - ] - == "^0.2.0" - ) - - -def test_update_dependencies_latest_with_restricted_dependency( - mock_poetry_commands, -) -> None: - pyproject_str = Path( - os.path.join( - os.path.dirname(__file__), - "fixtures/input_pyproject/", - "pyproject_with_restricted_dependency.toml", - ) - ).read_text() - expected_pyproject_str = Path( - os.path.join( - os.path.dirname(__file__), - "fixtures/expected_pyproject/", - "pyproject_with_restricted_dependency.toml", - ) - ).read_text() - - pyproject = Pyproject(pyproject_str) - pyproject.update_dependencies(latest=True) - assert pyproject.dumps() == expected_pyproject_str - assert ( - pyproject.pyproject["tool"]["poetry"]["dependencies"]["poetryup"][ - "version" - ] - == "^0.2.0" - ) + calls = [ + call( + packages=["poetryup@latest"], + group="default", + ), + call( + packages=[ + "poetryup_tilde@latest", + "poetryup_exact@latest", + "poetryup_underscore@latest", + "Poetryup_Capital@latest", + ], + group="main", + ), + ] + mock.assert_has_calls(calls) From 850f79121a940c630c83ff35322dad2b6ec412be Mon Sep 17 00:00:00 2001 From: Mousa Zeid Baker Date: Sat, 7 May 2022 21:17:54 +0200 Subject: [PATCH 09/15] tests: add tests for search_dependency() --- tests/unit/test_pyproject.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/tests/unit/test_pyproject.py b/tests/unit/test_pyproject.py index aa694b5..bc8e03d 100644 --- a/tests/unit/test_pyproject.py +++ b/tests/unit/test_pyproject.py @@ -76,3 +76,26 @@ def test_update_dependencies_latest( ), ] mock.assert_has_calls(calls) + + +def test_search_dependency( + mock_poetry_commands, +) -> None: + pyproject = Pyproject(pyproject_str) + name = pyproject.dependencies[0].name + assert pyproject.search_dependency(name) is not None + + +def test_search_dependency_by_normalized_name( + mock_poetry_commands, +) -> None: + pyproject = Pyproject(pyproject_str) + normalized_name = pyproject.dependencies[0].normalized_name + assert pyproject.search_dependency(normalized_name) is not None + + +def test_search_dependency_non_existent( + mock_poetry_commands, +) -> None: + pyproject = Pyproject(pyproject_str) + assert pyproject.search_dependency("non_existent") is None From d2c0916a056ba1d1f044d2e401d3efbdd7a3fa28 Mon Sep 17 00:00:00 2001 From: Mousa Zeid Baker Date: Sat, 7 May 2022 21:19:18 +0200 Subject: [PATCH 10/15] tests: add tests for dumps() --- tests/unit/test_pyproject.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/tests/unit/test_pyproject.py b/tests/unit/test_pyproject.py index bc8e03d..790c51e 100644 --- a/tests/unit/test_pyproject.py +++ b/tests/unit/test_pyproject.py @@ -27,8 +27,6 @@ def test_update_dependencies( pyproject = Pyproject(pyproject_str) pyproject.update_dependencies() - assert pyproject.dumps() == expected_pyproject_str - table = pyproject.pyproject["tool"]["poetry"]["dependencies"] assert table["poetryup"] == "^0.2.0" @@ -99,3 +97,12 @@ def test_search_dependency_non_existent( ) -> None: pyproject = Pyproject(pyproject_str) assert pyproject.search_dependency("non_existent") is None + + +def test_dumps( + mock_poetry_commands, +) -> None: + pyproject = Pyproject(pyproject_str) + pyproject.update_dependencies() + + assert pyproject.dumps() == expected_pyproject_str From 819b7fcfb319684ac6c58304959e6b9455928181 Mon Sep 17 00:00:00 2001 From: Mousa Zeid Baker Date: Sat, 7 May 2022 22:41:04 +0200 Subject: [PATCH 11/15] fix: tests to include caret example --- tests/conftest.py | 3 +++ tests/unit/fixtures/expected_pyproject/pyproject.toml | 3 ++- tests/unit/fixtures/input_pyproject/pyproject.toml | 3 ++- tests/unit/test_pyproject.py | 4 +++- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 21433e7..0263368 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -21,6 +21,9 @@ def mock_poetry_commands(mocker: MockerFixture) -> None: "poetryup 0.2.0 " "pyproject.toml file" "\n└── toml >=0.10.2,<0.11.0\n" + "poetryup-caret 0.2.0 " + "pyproject.toml file" + "\n└── toml >=0.10.2,<0.11.0\n" "poetryup-tilde 0.2.0 " "pyproject.toml file" "\n└── toml >=0.10.2,<0.11.0\n" diff --git a/tests/unit/fixtures/expected_pyproject/pyproject.toml b/tests/unit/fixtures/expected_pyproject/pyproject.toml index ff835c4..877ce1c 100644 --- a/tests/unit/fixtures/expected_pyproject/pyproject.toml +++ b/tests/unit/fixtures/expected_pyproject/pyproject.toml @@ -23,7 +23,8 @@ python = "^3.6" poetryup = "^0.2.0" [tool.poetry.group.main.dependencies] -poetryup_tilde = "^0.2.0" +poetryup_caret = "^0.2.0" +poetryup_tilde = "~0.2.0" poetryup_exact = "0.2.0" poetryup_restricted = { version = "^0.2.0", python = "<3.7" } poetryup_git = { git = "https://github.com/MousaZeidBaker/poetryup.git" } diff --git a/tests/unit/fixtures/input_pyproject/pyproject.toml b/tests/unit/fixtures/input_pyproject/pyproject.toml index 8f045fe..e34378e 100644 --- a/tests/unit/fixtures/input_pyproject/pyproject.toml +++ b/tests/unit/fixtures/input_pyproject/pyproject.toml @@ -23,7 +23,8 @@ python = "^3.6" poetryup = "^0.1.0" [tool.poetry.group.main.dependencies] -poetryup_tilde = "^0.1.0" +poetryup_caret = "^0.1.0" +poetryup_tilde = "~0.1.0" poetryup_exact = "0.1.0" poetryup_restricted = { version = "^0.1.0", python = "<3.7" } poetryup_git = { git = "https://github.com/MousaZeidBaker/poetryup.git" } diff --git a/tests/unit/test_pyproject.py b/tests/unit/test_pyproject.py index 790c51e..160fc24 100644 --- a/tests/unit/test_pyproject.py +++ b/tests/unit/test_pyproject.py @@ -33,7 +33,8 @@ def test_update_dependencies( table = pyproject.pyproject["tool"]["poetry"]["group"]["main"][ "dependencies" ] - assert table["poetryup_tilde"] == "^0.2.0" + assert table["poetryup_caret"] == "^0.2.0" + assert table["poetryup_tilde"] == "~0.2.0" assert table["poetryup_exact"] == "0.2.0" assert table["poetryup_restricted"] == { "version": "^0.2.0", @@ -65,6 +66,7 @@ def test_update_dependencies_latest( ), call( packages=[ + "poetryup_caret@latest", "poetryup_tilde@latest", "poetryup_exact@latest", "poetryup_underscore@latest", From 50f756dac719bd1220b20707c8cddce048f79a9b Mon Sep 17 00:00:00 2001 From: Mousa Zeid Baker Date: Sun, 8 May 2022 01:52:05 +0200 Subject: [PATCH 12/15] refactor: lock_dependencies to only contain locked dependencies Previously locked_dependencies property contained dependencies with both locked as well as non locked versions. The reason was some dependencies can't be bumped to their lock version due to their constraint. Instead introduce a new property, bumped_dependencies, to be used to update the pyproject.toml file. --- src/poetryup/core/pyproject.py | 71 +++++++++++++++++++++++++++------- tests/unit/test_pyproject.py | 24 ++++++++++-- 2 files changed, 78 insertions(+), 17 deletions(-) diff --git a/src/poetryup/core/pyproject.py b/src/poetryup/core/pyproject.py index 40de34a..10ed75b 100644 --- a/src/poetryup/core/pyproject.py +++ b/src/poetryup/core/pyproject.py @@ -77,7 +77,7 @@ def lock_dependencies(self) -> List[Dependency]: # run poetry show to get currently installed dependencies output = self.__run_poetry_show() - # extract dependencies from each line of the output + # create dependencies from each line of the output pattern = re.compile("^[a-zA-Z-]+") lock_dependencies: List[Dependency] = [] for line in output.split("\n"): @@ -88,42 +88,85 @@ def lock_dependencies(self) -> List[Dependency]: # extract name and version lock_name, lock_version, *_ = line.split() - # find dependency in pyproject.toml file - dependency = self.search_dependency(lock_name) + # search for dependency in pyproject + dependency = self.search_dependency(self.dependencies, lock_name) if dependency is None: - # not found in pyproject.toml, continue to next + # dependency not found, continue to next continue - # replace version with lock version + lock_dependencies.append( + Dependency( + name=dependency.name, + version=lock_version, + group=dependency.group, + ) + ) + + return lock_dependencies + + @property + def bumped_dependencies(self) -> List[Dependency]: + """The pyproject dependencies with their versions bumped""" + + lock_dependencies = self.lock_dependencies + + bumped_dependencies: List[Dependency] = [] + for dependency in self.dependencies: + # search for lock dependency + lock_dependency = self.search_dependency( + lock_dependencies, + dependency.name, + ) + if isinstance(dependency.version, str): - dependency.version = dependency.constraint + lock_version + bumped_dependencies.append( + Dependency( + name=dependency.name, + version=dependency.constraint + lock_dependency.version, + group=dependency.group, + ) + ) elif ( isinstance(dependency.version, Dict) and dependency.version.get("version") is not None ): - dependency.version["version"] = ( - dependency.constraint + lock_version + version = dependency.version + version["version"] = ( + dependency.constraint + lock_dependency.version + ) + bumped_dependencies.append( + Dependency( + name=dependency.name, + version=version, + group=dependency.group, + ) ) - lock_dependencies.append(dependency) + else: + bumped_dependencies.append(dependency) - return lock_dependencies + return bumped_dependencies def dumps(self) -> str: """Dumps pyproject into a string.""" return tomlkit.dumps(self.pyproject) - def search_dependency(self, name: str) -> Union[Dependency, None]: - """Searches for a dependency given a name + def search_dependency( + self, + dependencies: List[Dependency], + name: str, + ) -> Union[Dependency, None]: + """Search for a dependency by name given a list of dependencies Args: + dependencies: A list of dependencies to search in name: Name of the dependency to search for Returns: A dependency if found, None if not found """ - for dependency in self.dependencies: + for dependency in dependencies: if dependency.name == name or dependency.normalized_name == name: return dependency @@ -165,7 +208,7 @@ def update_dependencies( # bump versions in pyproject table = self.pyproject["tool"]["poetry"] - for dependency in self.lock_dependencies: + for dependency in self.bumped_dependencies: if dependency.group == "default": table["dependencies"][dependency.name] = dependency.version elif ( diff --git a/tests/unit/test_pyproject.py b/tests/unit/test_pyproject.py index 160fc24..e45faf7 100644 --- a/tests/unit/test_pyproject.py +++ b/tests/unit/test_pyproject.py @@ -83,7 +83,13 @@ def test_search_dependency( ) -> None: pyproject = Pyproject(pyproject_str) name = pyproject.dependencies[0].name - assert pyproject.search_dependency(name) is not None + assert ( + pyproject.search_dependency( + pyproject.dependencies, + name, + ) + is not None + ) def test_search_dependency_by_normalized_name( @@ -91,14 +97,26 @@ def test_search_dependency_by_normalized_name( ) -> None: pyproject = Pyproject(pyproject_str) normalized_name = pyproject.dependencies[0].normalized_name - assert pyproject.search_dependency(normalized_name) is not None + assert ( + pyproject.search_dependency( + pyproject.dependencies, + normalized_name, + ) + is not None + ) def test_search_dependency_non_existent( mock_poetry_commands, ) -> None: pyproject = Pyproject(pyproject_str) - assert pyproject.search_dependency("non_existent") is None + assert ( + pyproject.search_dependency( + pyproject.dependencies, + "non_existent", + ) + is None + ) def test_dumps( From 935122cec83603308416e04b3f4c65ef1688f772 Mon Sep 17 00:00:00 2001 From: Mousa Zeid Baker Date: Sun, 8 May 2022 02:09:59 +0200 Subject: [PATCH 13/15] docs: update docstring for bumped_dependencies --- src/poetryup/core/pyproject.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/poetryup/core/pyproject.py b/src/poetryup/core/pyproject.py index 10ed75b..d3f3b50 100644 --- a/src/poetryup/core/pyproject.py +++ b/src/poetryup/core/pyproject.py @@ -106,7 +106,12 @@ def lock_dependencies(self) -> List[Dependency]: @property def bumped_dependencies(self) -> List[Dependency]: - """The pyproject dependencies with their versions bumped""" + """The pyproject dependencies with their version bumped to lock version + + Lock versions will be used if applicable. For instance, using the lock + version for a dependency that is specified with the inequality + constraint '!=x.y.z' would completely change its meaning. + """ lock_dependencies = self.lock_dependencies From 007e917ebc7d31e845fe5bdead75dbf413d7e5ef Mon Sep 17 00:00:00 2001 From: Mousa Zeid Baker Date: Sun, 8 May 2022 02:18:49 +0200 Subject: [PATCH 14/15] refactor: dumped_dependencies --- src/poetryup/core/pyproject.py | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/src/poetryup/core/pyproject.py b/src/poetryup/core/pyproject.py index d3f3b50..3ea5d8d 100644 --- a/src/poetryup/core/pyproject.py +++ b/src/poetryup/core/pyproject.py @@ -123,31 +123,23 @@ def bumped_dependencies(self) -> List[Dependency]: dependency.name, ) - if isinstance(dependency.version, str): - bumped_dependencies.append( - Dependency( - name=dependency.name, - version=dependency.constraint + lock_dependency.version, - group=dependency.group, - ) - ) + version = dependency.version + if isinstance(version, str): + version = dependency.constraint + lock_dependency.version elif ( - isinstance(dependency.version, Dict) - and dependency.version.get("version") is not None + isinstance(version, Dict) and version.get("version") is not None ): - version = dependency.version version["version"] = ( dependency.constraint + lock_dependency.version ) - bumped_dependencies.append( - Dependency( - name=dependency.name, - version=version, - group=dependency.group, - ) + + bumped_dependencies.append( + Dependency( + name=dependency.name, + version=version, + group=dependency.group, ) - else: - bumped_dependencies.append(dependency) + ) return bumped_dependencies From ac0eb064e527db8bfe28a08bd695b232c7af82cb Mon Sep 17 00:00:00 2001 From: Mousa Zeid Baker Date: Sun, 8 May 2022 18:42:21 +0200 Subject: [PATCH 15/15] refactor: add dataclass decorator to dependency class --- src/poetryup/models/dependency.py | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/poetryup/models/dependency.py b/src/poetryup/models/dependency.py index 8ee00b4..6ce8765 100644 --- a/src/poetryup/models/dependency.py +++ b/src/poetryup/models/dependency.py @@ -1,6 +1,8 @@ +from dataclasses import dataclass from typing import Dict, List, Union +@dataclass(frozen=True) class Dependency: """A class to represent a dependency @@ -10,15 +12,9 @@ class Dependency: group: The group of the dependency """ - def __init__( - self, - name: str, - version: Union[str, Dict, List], - group: str, - ) -> None: - self.name = name - self.version = version - self.group = group + name: str + version: Union[str, Dict, List] + group: str @property def normalized_name(self) -> str: