diff --git a/src/quetz_client/client.py b/src/quetz_client/client.py index 0d83592..7e5d2ba 100644 --- a/src/quetz_client/client.py +++ b/src/quetz_client/client.py @@ -56,6 +56,16 @@ class Package: latest_change: str + +def _assert_file_is_package(file: Path): + """Raises an error if the file in question does not look like a conda package""" + valid_suffixes =[".tar.bz2", ".conda"] + file_has_valid_suffix = any(file.name.endswith(suffix) for suffix in valid_suffixes) + if not file_has_valid_suffix: + raise ValueError(f"File {file} does not look like a conda package. It should end in one of {valid_suffixes}.") + + return False + @dataclass class QuetzClient: session: requests.Session @@ -172,6 +182,9 @@ def yield_packages( def post_file_to_channel(self, channel: str, file: Path, force: bool = False): file_path = Path(file) + + _assert_file_is_package(file_path) + url = f"{self.url}/api/channels/{channel}/upload/{file_path.name}" body_bytes = file_path.read_bytes() diff --git a/tests/test_mock.py b/tests/test_mock.py index a0a3321..924b32d 100644 --- a/tests/test_mock.py +++ b/tests/test_mock.py @@ -3,7 +3,7 @@ from quetz_client.client import QuetzClient from .conftest import temporary_package_file - +from pathlib import Path @pytest.mark.parametrize( "role", @@ -170,3 +170,16 @@ def test_mock_post_file_to_channel( # thus we need to access all the requests assert len(requests_mock.request_history) <= 2 assert any(r.method == "POST" for r in requests_mock.request_history) + + +def test_mock_post_file_to_channel_invalid_file( + mock_client: QuetzClient, +): + """Test that the client refuses to upload an invalid file that is not a conda package + + This test requires to mock server because no actual request are ever made. + The client should exit before talking to the server. + """ + file = Path("./wrong_suffix.txt") + with pytest.raises(ValueError): + mock_client.post_file_to_channel(channel="doesnotmatter", file=file)