diff --git a/pip_review.py b/pip_review.py index 7c749b4a..0322fd99 100755 --- a/pip_review.py +++ b/pip_review.py @@ -249,7 +249,7 @@ def ask(self, prompt: str) -> str: _ask_to_install: partial[str] = partial(_InteractiveAsker().ask, prompt="Upgrade now?") -class _Package(NamedTuple): +class _OutdatedPackageInfo(NamedTuple): name: str version: str latest_version: str @@ -265,13 +265,13 @@ def from_dct(cls, dct: dict[str, str]) -> Self: ) -def freeze_outdated_packages(file: Path, packages: list[_Package]) -> None: +def freeze_outdated_packages(file: Path, packages: list[_OutdatedPackageInfo]) -> None: outdated_packages: str = "\n".join(f"{pkg.name}=={pkg.version}" for pkg in packages) file.write_text(f"{outdated_packages}\n", encoding="utf-8") def update_packages( - packages: list[_Package], + packages: list[_OutdatedPackageInfo], forwarded: list[str], *, continue_on_fail: bool, @@ -292,7 +292,7 @@ def update_packages( def _get_outdated_packages( forwarded: list[str], -) -> list[_Package]: +) -> list[_OutdatedPackageInfo]: command: list[str] = [ *_PIP_CMD, "list", @@ -302,34 +302,40 @@ def _get_outdated_packages( *forwarded, ] output: str = subprocess.check_output(command).decode("utf-8") # nosec - packages: list[_Package] = [_Package.from_dct(pkg) for pkg in json.loads(output)] + packages: list[_OutdatedPackageInfo] = [ + _OutdatedPackageInfo.from_dct(pkg) for pkg in json.loads(output) + ] return packages -class _Column(NamedTuple): +class _ColumnSpec(NamedTuple): title: str field: str # nicer headings for the columns in the oudated package table -_DEFAULT_COLUMNS: Final[tuple[_Column, ...]] = ( - _Column("Package", "name"), - _Column("Version", "version"), - _Column("Latest", "latest_version"), - _Column("Type", "latest_filetype"), +_DEFAULT_COLUMNS: Final[tuple[_ColumnSpec, ...]] = ( + _ColumnSpec("Package", "name"), + _ColumnSpec("Version", "version"), + _ColumnSpec("Latest", "latest_version"), + _ColumnSpec("Type", "latest_filetype"), ) # Next two functions describe how to collect data for the table. # Note how they are not concerned with columns widths. -def _extract_column(data: list[_Package], field: str, title: str) -> list[str]: +def _extract_column( + data: list[_OutdatedPackageInfo], + field: str, + title: str, +) -> list[str]: return [title, *[getattr(item, field) for item in data]] def _extract_table( - outdated: list[_Package], - columns: tuple[_Column, ...] = _DEFAULT_COLUMNS, + outdated: list[_OutdatedPackageInfo], + columns: tuple[_ColumnSpec, ...] = _DEFAULT_COLUMNS, ) -> list[list[str]]: return [_extract_column(outdated, field, title) for title, field in columns] @@ -379,7 +385,7 @@ def main(argv: Sequence[str] | None = None) -> int: logger.error("--auto and --interactive cannot be used together") return 1 - outdated: list[_Package] = _get_outdated_packages(list_args) + outdated: list[_OutdatedPackageInfo] = _get_outdated_packages(list_args) logger.debug("Outdated packages: %s", outdated) if not outdated and not args.raw: @@ -406,7 +412,7 @@ def main(argv: Sequence[str] | None = None) -> int: ) return 0 - selected: list[_Package] = [] + selected: list[_OutdatedPackageInfo] = [] for pkg in outdated: logger.info( "%s==%s is available (you have %s)", diff --git a/tests/pip_review_test.py b/tests/pip_review_test.py index 5cf106bd..00b388f1 100755 --- a/tests/pip_review_test.py +++ b/tests/pip_review_test.py @@ -15,10 +15,10 @@ @pytest.fixture() -def test_packages() -> list[pip_review._Package]: +def test_packages() -> list[pip_review._OutdatedPackageInfo]: return [ - pip_review._Package("test1", "1.0.0", "1.1.0", "wheel"), - pip_review._Package("test2", "1.9.9", "2.0.0", "wheel"), + pip_review._OutdatedPackageInfo("test1", "1.0.0", "1.1.0", "wheel"), + pip_review._OutdatedPackageInfo("test2", "1.9.9", "2.0.0", "wheel"), ] @@ -118,18 +118,22 @@ def test_subprocess_output() -> bytes: pytest.param( pip_review._DEFAULT_COLUMNS, ( - pip_review._Column("Package", "name"), - pip_review._Column("Version", "version"), - pip_review._Column("Latest", "latest_version"), - pip_review._Column("Type", "latest_filetype"), + pip_review._ColumnSpec("Package", "name"), + pip_review._ColumnSpec("Version", "version"), + pip_review._ColumnSpec("Latest", "latest_version"), + pip_review._ColumnSpec("Type", "latest_filetype"), ), id="_DEFAULT_COLUMNS", ), ], ) def test_constants( - constant: str | frozenset[str] | tuple[str, ...] | tuple[pip_review._Column, ...], - expected: str | frozenset[str] | tuple[str, ...] | tuple[pip_review._Column, ...], + constant: ( + str | frozenset[str] | tuple[str, ...] | tuple[pip_review._ColumnSpec, ...] + ), + expected: ( + str | frozenset[str] | tuple[str, ...] | tuple[pip_review._ColumnSpec, ...] + ), ) -> None: assert constant == expected @@ -425,11 +429,11 @@ def test_ask_to_install_with_last_answer_and_invalid_input(last_answer: str) -> def test_package_is_tuple() -> None: - assert issubclass(pip_review._Package, tuple) + assert issubclass(pip_review._OutdatedPackageInfo, tuple) def test_package_fields() -> None: - assert pip_review._Package._fields == ( + assert pip_review._OutdatedPackageInfo._fields == ( "name", "version", "latest_version", @@ -489,12 +493,12 @@ def test_package_fields() -> None: ], ) def test_package_from_dct(dct: dict[str, str], expected: tuple[str, ...]) -> None: - assert pip_review._Package.from_dct(dct) == expected + assert pip_review._OutdatedPackageInfo.from_dct(dct) == expected def test_freeze_outdated_packages( tmp_path: Path, - test_packages: list[pip_review._Package], + test_packages: list[pip_review._OutdatedPackageInfo], ) -> None: tmp_file: Path = tmp_path / "outdated.txt" pip_review.freeze_outdated_packages(tmp_file, test_packages) @@ -507,7 +511,7 @@ def test_freeze_outdated_packages( ) def test_update_packages_continue_on_fail_set_to_false( forwarded: list[str], - test_packages: list[pip_review._Package], + test_packages: list[pip_review._OutdatedPackageInfo], ) -> None: with mock.patch("subprocess.call") as mock_subprocess_call: pip_review.update_packages( @@ -537,7 +541,7 @@ def test_update_packages_continue_on_fail_set_to_false( ) def test_update_packages_continue_on_fail_set_to_true( forwarded: list[str], - test_packages: list[pip_review._Package], + test_packages: list[pip_review._OutdatedPackageInfo], ) -> None: with mock.patch("subprocess.call") as mock_subprocess_call: pip_review.update_packages( @@ -574,21 +578,21 @@ def test_update_packages_continue_on_fail_set_to_true( def test_get_outdated_packages( - test_packages: list[pip_review._Package], + test_packages: list[pip_review._OutdatedPackageInfo], test_subprocess_output: bytes, ) -> None: with mock.patch( "subprocess.check_output", return_value=test_subprocess_output, ): - outdated_packages: list[pip_review._Package] = ( + outdated_packages: list[pip_review._OutdatedPackageInfo] = ( pip_review._get_outdated_packages([]) ) assert outdated_packages == test_packages def test_column_fields() -> None: - assert pip_review._Column._fields == ( + assert pip_review._ColumnSpec._fields == ( "title", "field", ) @@ -603,7 +607,10 @@ def test_column_fields() -> None: "latest_filetype", ], ) -def test_extract_column(test_packages: list[pip_review._Package], field: str) -> None: +def test_extract_column( + test_packages: list[pip_review._OutdatedPackageInfo], + field: str, +) -> None: assert pip_review._extract_column(test_packages, field, "TEST") == [ "TEST", getattr(test_packages[0], field), @@ -611,7 +618,7 @@ def test_extract_column(test_packages: list[pip_review._Package], field: str) -> ] -def test_extract_table(test_packages: list[pip_review._Package]) -> None: +def test_extract_table(test_packages: list[pip_review._OutdatedPackageInfo]) -> None: expected_result: list[list[str]] = [ ["Package", "test1", "test2"], ["Version", "1.0.0", "1.9.9"],