#!/usr/bin/env py.test """Tests for manage.py.""" from __future__ import absolute_import, print_function, unicode_literals from pathlib import Path from unittest.mock import Mock import py import pytest from pypiserver import manage from pypiserver.core import PkgFile from pypiserver.pkg_helpers import guess_pkgname_and_version, parse_version from pypiserver.manage import ( PipCmd, build_releases, filter_stable_releases, filter_latest_pkgs, is_stable_version, update_package, update_all_packages, ) def touch_files(root, files): root = py.path.local(root) # pylint: disable=no-member for f in files: root.join(f).ensure() def pkgfile_from_path(fn): pkgname, version = guess_pkgname_and_version(fn) return PkgFile( pkgname=pkgname, version=version, root=py.path.local(fn) .parts()[1] .strpath, # noqa pylint: disable=no-member fn=fn, ) @pytest.mark.parametrize( ("version", "is_stable"), [ ("1.0", True), ("0.0.0", True), ("1.1beta1", False), ("1.2.10-123", True), ("5.5.0-DEV", False), ("1.2-rc1", False), ("1.0b1", False), ], ) def test_is_stable_version(version, is_stable): parsed_version = parse_version(version) assert is_stable_version(parsed_version) == is_stable def test_build_releases(): p = pkgfile_from_path("/home/ralf/pypiserver/d/greenlet-0.2.zip") expected = dict( parsed_version=("00000000", "00000003", "*final"), pkgname="greenlet", replaces=p, version="0.3.0", ) (res,) = list(build_releases(p, ["0.3.0"])) for k, v in expected.items(): assert getattr(res, k) == v def test_filter_stable_releases(): p = pkgfile_from_path("/home/ralf/pypiserver/d/greenlet-0.2.zip") assert list(filter_stable_releases([p])) == [p] p2 = pkgfile_from_path("/home/ralf/pypiserver/d/greenlet-0.5rc1.zip") assert list(filter_stable_releases([p2])) == [] def test_filter_latest_pkgs(): paths = [ "/home/ralf/greenlet-0.2.zip", "/home/ralf/foo/baz-1.0.zip" "/home/ralf/bar/greenlet-0.3.zip", ] pkgs = [pkgfile_from_path(x) for x in paths] assert frozenset(filter_latest_pkgs(pkgs)) == frozenset(pkgs[1:]) def test_filter_latest_pkgs_case_insensitive(): paths = [ "/home/ralf/greenlet-0.2.zip", "/home/ralf/foo/baz-1.0.zip" "/home/ralf/bar/Greenlet-0.3.zip", ] pkgs = [pkgfile_from_path(x) for x in paths] assert frozenset(filter_latest_pkgs(pkgs)) == frozenset(pkgs[1:]) @pytest.mark.parametrize( "pip_ver, cmd_type", ( ("10.0.0", "d"), ("10.0.0rc10", "d"), ("10.0.0b10", "d"), ("10.0.0a3", "d"), ("10.0.0.dev8", "d"), ("10.0.0.dev8", "d"), ("18.0", "d"), ("9.9.8", "i"), ("9.9.8rc10", "i"), ("9.9.8b10", "i"), ("9.9.8a10", "i"), ("9.9.8.dev10", "i"), ("9.9", "i"), ), ) def test_pip_cmd_root(pip_ver, cmd_type): """Verify correct determination of the command root by pip version.""" exp_cmd = ( "pip", "-q", "install" if cmd_type == "i" else "download", ) assert tuple(PipCmd.update_root(pip_ver)) == exp_cmd def test_pip_cmd_update(): """Verify the correct determination of a pip command.""" index = "https://pypi.org/simple" destdir = "foo/bar" pkg_name = "mypkg" pkg_version = "12.0" cmd_root = ("pip", "-q", "download") exp_cmd = cmd_root + ( "--no-deps", "-i", index, "-d", destdir, "{}=={}".format(pkg_name, pkg_version), ) assert exp_cmd == tuple( PipCmd.update(cmd_root, destdir, pkg_name, pkg_version) ) def test_pip_cmd_update_index_overridden(): """Verify the correct determination of a pip command.""" index = "https://pypi.org/complex" destdir = "foo/bar" pkg_name = "mypkg" pkg_version = "12.0" cmd_root = ("pip", "-q", "download") exp_cmd = cmd_root + ( "--no-deps", "-i", index, "-d", destdir, "{}=={}".format(pkg_name, pkg_version), ) assert exp_cmd == tuple( PipCmd.update(cmd_root, destdir, pkg_name, pkg_version, index=index) ) def test_update_package(monkeypatch): """Test generating an update command for a package.""" monkeypatch.setattr(manage, "call", Mock()) pkg = PkgFile("mypkg", "1.0", replaces=PkgFile("mypkg", "0.9")) update_package(pkg, ".") manage.call.assert_called_once_with( ( # pylint: disable=no-member "pip", "-q", "download", "--no-deps", "-i", "https://pypi.org/simple", "-d", ".", "mypkg==1.0", ) ) def test_update_package_dry_run(monkeypatch): """Test generating an update command for a package.""" monkeypatch.setattr(manage, "call", Mock()) pkg = PkgFile("mypkg", "1.0", replaces=PkgFile("mypkg", "0.9")) update_package(pkg, ".", dry_run=True) assert not manage.call.mock_calls # pylint: disable=no-member def test_update_all_packages(monkeypatch): """Test calling update_all_packages()""" public_pkg_1 = PkgFile("Flask", "1.0") public_pkg_2 = PkgFile("requests", "1.0") private_pkg_1 = PkgFile("my_private_pkg", "1.0") private_pkg_2 = PkgFile("my_other_private_pkg", "1.0") roots_mock = { Path("/opt/pypi"): [ public_pkg_1, private_pkg_1, ], Path("/data/pypi"): [public_pkg_2, private_pkg_2], } def core_listdir_mock(path: Path): return roots_mock.get(path, []) monkeypatch.setattr(manage, "listdir", core_listdir_mock) monkeypatch.setattr(manage, "update", Mock(return_value=None)) destdir = None dry_run = False stable_only = True update_all_packages( roots=list(roots_mock.keys()), destdir=destdir, dry_run=dry_run, stable_only=stable_only, ignorelist=None, ) manage.update.assert_called_once_with( # pylint: disable=no-member frozenset([public_pkg_1, public_pkg_2, private_pkg_1, private_pkg_2]), destdir, dry_run, stable_only, ) def test_update_all_packages_with_blacklist(monkeypatch): """Test calling update_all_packages()""" public_pkg_1 = PkgFile("Flask", "1.0") public_pkg_2 = PkgFile("requests", "1.0") private_pkg_1 = PkgFile("my_private_pkg", "1.0") private_pkg_2 = PkgFile("my_other_private_pkg", "1.0") roots_mock = { Path("/opt/pypi"): [ public_pkg_1, private_pkg_1, ], Path("/data/pypi"): [public_pkg_2, private_pkg_2], } def core_listdir_mock(path: Path): return roots_mock.get(path, []) monkeypatch.setattr(manage, "listdir", core_listdir_mock) monkeypatch.setattr(manage, "update", Mock(return_value=None)) destdir = None dry_run = False stable_only = True update_all_packages( roots=list(roots_mock.keys()), destdir=destdir, dry_run=dry_run, stable_only=stable_only, ignorelist=["my_private_pkg", "my_other_private_pkg"], ) manage.update.assert_called_once_with( # pylint: disable=no-member frozenset([public_pkg_1, public_pkg_2]), destdir, dry_run, stable_only )