def test_compare_packages_module(match_module): match_info = PyPIChecker().get_match_info([match_module]) packages = { ("umbrella", "3.2"): ({ "path/to/file.py": "class MyClass(object):\n" " return None\n" "def yay():\n" " pass" }, { "path/to/file.py": "class MyClass(object):\n" " return None" }) } result = list(PyPIChecker().compare_packages(packages, match_info)) assert result == [("Code is different:\n" "--- path/to/file.py\n" "+++ path/to/file.py\n" "@@ -1,4 +1,2 @@\n" " class MyClass(object):\n" " return None\n" "-def yay():\n" "- pass", match_module)]
def test_get_packages_package_cache(mocker, match, match_other_version): match_info = PyPIChecker().get_match_info([match, match_other_version]) source = mocker.patch("raincoat.match.pypi.source") mocker.patch("raincoat.match.pypi.Cleaner.mkdir", return_value="/tmp/clean") source.get_current_or_latest_version.return_value = True, "3.5" source.get_current_path.return_value = "/sites_packages/umbrella" source.open_downloaded.return_value = 1 source.open_installed.return_value = 2 result = list(PyPIChecker().get_packages(match_info)) assert source.mock_calls == [ mocker.call.get_current_or_latest_version("umbrella"), # First version mocker.call.download_package("umbrella", "3.2", "/tmp/clean"), mocker.call.open_downloaded("/tmp/clean", ["path/to/file.py"], "umbrella"), mocker.call.get_current_path("umbrella"), mocker.call.open_installed("/sites_packages/umbrella", ["path/to/file.py"]), # Second version, current version is cached mocker.call.download_package("umbrella", "3.4", "/tmp/clean"), mocker.call.open_downloaded("/tmp/clean", ["path/to/file.py"], "umbrella"), ] assert result == [(("umbrella", "3.2"), (1, 2)), (("umbrella", "3.4"), (1, 2))]
def test_compare_files_identical(): checker = PyPIChecker() func_a = """ def a(): return 1 """ checker.compare_files(func_a, func_a, [get_match(element="a")]) assert checker.errors == []
def test_compare_contents_missing_match(mocker): mocker.patch("raincoat.match.pypi.PyPIChecker.compare_files") checker = PyPIChecker() contents_a = {"file_a.py": "code"} contents_b = {"file_a.py": "code", "file_b.py": "code"} with pytest.raises(ValueError): checker.compare_contents(contents_a, contents_b, [get_match(path="file_b.py")])
def test_compare_files_missing_match(): checker = PyPIChecker() func_a = """ """ func_b = """ def a(): return 2 """ with pytest.raises(ValueError): checker.compare_files(func_a, func_b, [get_match(element="a")])
def test_compare_contents_identical(mocker): compare_files = mocker.patch( "raincoat.match.pypi.PyPIChecker.compare_files") checker = PyPIChecker() contents_a = {"file_a.py": "code"} checker.compare_contents(contents_a, contents_a, [get_match(path="file_a.py")]) assert len(checker.errors) == 0 assert compare_files.mock_calls == []
def test_check_package_identical_version(mocker): compare_content = mocker.patch( "raincoat.match.pypi.PyPIChecker.compare_contents") version = mocker.patch("raincoat.source.get_current_or_latest_version") version.return_value = (True, "1.2.3") checker = PyPIChecker() checker.check_package("umbrella", "1.2.3", [get_match()]) assert len(checker.errors) == 0 assert compare_content.mock_calls == []
def test_compare_contents_different_code(mocker): compare_files = mocker.patch( "raincoat.match.pypi.PyPIChecker.compare_files") checker = PyPIChecker() contents_a = {"file_a.py": "code_a"} contents_b = {"file_a.py": "code_b"} match = get_match(path="file_a.py") checker.compare_contents(contents_a, contents_b, [match]) assert len(checker.errors) == 0 assert compare_files.mock_calls == [mock.call("code_a", "code_b", [match])]
def test_compare_files_missing_current(): checker = PyPIChecker() func_a = """ def a(): return 2 """ func_b = """ """ checker.compare_files(func_a, func_b, [get_match(element="a")]) assert len(checker.errors) == 1 assert checker.errors[0][0].startswith("Code object a has disappeared")
def test_compare_contents_missing_current(mocker): compare_files = mocker.patch( "raincoat.match.pypi.PyPIChecker.compare_files") checker = PyPIChecker() contents_a = {"file_a.py": "code", "file_b.py": "code"} contents_b = {"file_a.py": "code"} checker.compare_contents(contents_a, contents_b, [get_match(path="file_b.py")]) assert len(checker.errors) == 1 assert checker.errors[0][0].startswith("File file_b.py has disappeared") assert compare_files.mock_calls == []
def test_compare_files_different(): checker = PyPIChecker() func_a = """ def a(): return 1 """ func_b = """ def a(): return 2 """ checker.compare_files(func_a, func_b, [get_match(element="a")]) assert len(checker.errors) == 1 assert checker.errors[0][0].startswith("Code is different")
def test_compare_files_different_but_elsewhere(): checker = PyPIChecker() func_a = """# A def a(): return 1 """ func_b = """# B def a(): return 1 """ checker.compare_files(func_a, func_b, [get_match(element="a")]) assert checker.errors == []
def test_get_differences_missing_in_match(): match_dict = {} current_dict = {"a": "b"} result = list(PyPIChecker().get_differences(match_dict, current_dict)) assert result == [("a", (None, "b"))]
def test_get_differences_identical(): match_dict = {"a": "b"} current_dict = {"a": "b"} result = list(PyPIChecker().get_differences(match_dict, current_dict)) assert result == []
def test_get_differences(): match_dict = {"a": "b"} current_dict = {"a": "c"} result = list(PyPIChecker().get_differences(match_dict, current_dict)) assert result == [("a", ("b", "c"))]
def test_get_match_info(match, match_module, match_other_file, match_other_package, match_other_version): result = PyPIChecker().get_match_info([ match_module, match, match_other_file, match_other_package, match_other_version ]) assert result == ({ ("umbrella", "3.2"): { "path/to/file.py": { "MyClass": [match], None: [match_module] }, "path/to/other_file.py": { "MyOtherClass": [match_other_file] } }, ("umbrella", "3.4"): { "path/to/file.py": { "MyClass": [match_other_version] } }, ("poncho", "3.2"): { "some/file.py": { "SomeClass": [match_other_package] } }, })
def test_get_all_matches(match, match_module, match_other_file): result = (set(PyPIChecker().get_all_matches({ "a": { "b": [match, match_module] }, "c": [match_other_file] }))) assert result == {match, match_module, match_other_file}
def test_checker_check(mocker): check_package = mocker.patch( "raincoat.match.pypi.PyPIChecker.check_package") matches = [ get_match(package="a==1.0.0", path="a"), get_match(package="b==1.0.0"), get_match(package="a==1.0.0", path="b"), ] match1, match2, match3 = matches checker = PyPIChecker() checker.check(matches) assert len(check_package.mock_calls) == 2 assert check_package.mock_calls == [ mock.call("a", "1.0.0", [match1, match3]), mock.call("b", "1.0.0", [match2]), ]
def test_check_package_not_installed(mocker): compare_content = mocker.patch( "raincoat.match.pypi.PyPIChecker.compare_contents") source = mocker.patch("raincoat.match.pypi.source") source.get_current_or_latest_version.return_value = (False, "1.2.3") source.open_downloaded.return_value = {"file_a.py": "code"} source.open_installed.return_value = {"file_a.py": "code"} checker = PyPIChecker() with checker.cleaner_ctx(): checker.check_package("umbrella", "1.2.2", [get_match()]) assert len(source.download_package.mock_calls) == 2 assert len(source.open_downloaded.mock_calls) == 2 assert len(source.open_installed.mock_calls) == 0 assert len(checker.errors) == 0 assert compare_content.mock_calls == []
def test_get_packages_identical(mocker, match_info): source = mocker.patch("raincoat.match.pypi.source") mocker.patch("raincoat.match.pypi.Cleaner.mkdir", return_value="/tmp/clean") source.get_current_or_latest_version.return_value = True, "3.4" source.get_current_path.return_value = "/sites_packages/umbrella" source.open_downloaded.return_value = 1 source.open_installed.return_value = 1 result = list(PyPIChecker().get_packages(match_info)) assert result == []
def test_compare_packages_missing_file_in_current(match, match_info): packages = { ("umbrella", "3.2"): ({ "path/to/file.py": "class MyClass(object):\n" " return None" }, {}) } result = list(PyPIChecker().compare_packages(packages, match_info)) assert result == [("File path/to/file.py disappeared from umbrella", match) ]
def test_compare_blocks(match): result = PyPIChecker().compare_blocks(match=match, match_block=["a", "b"], current_block=["a", "c"], path="path") assert result == ("""Code is different: --- path +++ path @@ -1,2 +1,2 @@ a -b +c""", match)
def test_compare_packages_missing_file_in_match(match, match_info): packages = { ("umbrella", "3.2"): ({}, { "path/to/file.py": "class MyClass(object):\n" " return None" }) } result = list(PyPIChecker().compare_packages(packages, match_info)) assert result == [("Invalid Raincoat PyPI comment : " "path/to/file.py does not exist in " "umbrella==3.2", match)]
def test_check_package_installed_no_fast_escape(mocker): compare_content = mocker.patch( "raincoat.match.pypi.PyPIChecker.compare_contents") source = mocker.patch("raincoat.match.pypi.source") source.get_current_or_latest_version.return_value = (True, "1.2.3") source.open_downloaded.return_value = {"file_a.py": "code"} source.open_installed.return_value = {"file_a.py": "code2"} match = get_match() checker = PyPIChecker() with checker.cleaner_ctx(): checker.check_package("umbrella", "1.2.2", [match]) assert len(source.download_package.mock_calls) == 1 assert len(source.open_downloaded.mock_calls) == 1 assert len(source.open_installed.mock_calls) == 1 assert len(checker.errors) == 0 assert compare_content.mock_calls == [ mock.call({"file_a.py": "code"}, {"file_a.py": "code2"}, [match]) ]
def test_compare_packages_identical(match, match_info): packages = { ("umbrella", "3.2"): ({ "path/to/file.py": "class MyClass(object):\n" " return None" }, { "path/to/file.py": "class MyClass(object):\n" " return None" }) } result = list(PyPIChecker().compare_packages(packages, match_info)) assert result == []
def test_compare_packages_difference_elsewhere(match, match_info): packages = { ("umbrella", "3.2"): ({ "path/to/file.py": "class MyClass(object):\n" " return None\n" "def yay():\n" " pass" }, { "path/to/file.py": "class MyClass(object):\n" " return None" }) } result = list(PyPIChecker().compare_packages(packages, match_info)) assert result == []
def test_get_package_not_installed(mocker, match_info): source = mocker.patch("raincoat.match.pypi.source") mocker.patch("raincoat.match.pypi.Cleaner.mkdir", return_value="/tmp/clean") source.get_current_or_latest_version.return_value = False, "3.4" source.get_current_path.return_value = "/sites_packages/umbrella" source.open_downloaded.side_effect = [1, 2] result = list(PyPIChecker().get_packages(match_info)) assert source.mock_calls == [ mocker.call.get_current_or_latest_version("umbrella"), mocker.call.download_package("umbrella", "3.2", "/tmp/clean"), mocker.call.open_downloaded("/tmp/clean", ["path/to/file.py"], "umbrella"), mocker.call.download_package("umbrella", "3.4", "/tmp/clean"), mocker.call.open_downloaded("/tmp/clean", ["path/to/file.py"], "umbrella"), ] assert result == [(("umbrella", "3.2"), (1, 2))]
def test_compare_packages(match, match_info): packages = { ("umbrella", "3.2"): ({ "path/to/file.py": "class MyClass(object):\n" " pass" }, { "path/to/file.py": "class MyClass(object):\n" " return None" }) } result = list(PyPIChecker().compare_packages(packages, match_info)) assert result == [("Code is different:\n" "--- path/to/file.py\n" "+++ path/to/file.py\n" "@@ -1,2 +1,2 @@\n" " class MyClass(object):\n" "- pass\n" "+ return None", match)]
def test_check(mocker, match): source = mocker.patch("raincoat.match.pypi.source") mocker.patch("raincoat.match.pypi.Cleaner.mkdir", return_value="/tmp/clean") source.get_current_or_latest_version.return_value = True, "3.4" source.get_current_path.return_value = "/sites_packages/umbrella" source.open_downloaded.return_value = { "path/to/file.py": "class MyClass():\n" " pass" } source.open_installed.return_value = { "path/to/file.py": "class MyClass():\n" " return None" } assert list(PyPIChecker().check([match])) == [("Code is different:\n" "--- path/to/file.py\n" "+++ path/to/file.py\n" "@@ -1,2 +1,2 @@\n" " class MyClass():\n" "- pass\n" "+ return None", match)]
def match_info(match): return PyPIChecker().get_match_info([match])