diff --git a/README.md b/README.md index 9c7fe41..6c7e9b2 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,8 @@ Positional argument `` is required. When force is not specified, yo `-a --all` will download *all* distributions of a given package/version combination. +`--url` will download and expand a file directly from the specified URL. + ```plaintext py -m safepull numpy numpy v.1.25.0 diff --git a/src/safepull/safepull.py b/src/safepull/safepull.py index 9a4cb27..ad4d3f2 100644 --- a/src/safepull/safepull.py +++ b/src/safepull/safepull.py @@ -49,6 +49,15 @@ def unpack(byte_object: BytesIO, filename: str) -> None: whl_zip.extractall(path=Path.cwd().joinpath(f"{filename[:-4]}")) +def download_from_url(url: str) -> None: + """Download and unpack a file from a URL.""" + response = requests.get(url, stream=True, timeout=60) + response.raise_for_status() + filename = url.split("/")[-1] + byteobject = BytesIO(response.content) + unpack(byteobject, filename) + + def run() -> None: """Run the program.""" console = Console() @@ -80,8 +89,16 @@ def run() -> None: action="store_true", help="Downloads all distributions of a package.", ) + parser.add_argument( + "--url", + help="Download and expand a file directly from the specified URL.", + ) args = parser.parse_args() + if args.url: + download_from_url(args.url) + return + use_in = args.package if not args.package: use_in = input("Input a package title: ") diff --git a/tests/test_safepull.py b/tests/test_safepull.py index 1aa9303..a08eb53 100644 --- a/tests/test_safepull.py +++ b/tests/test_safepull.py @@ -7,7 +7,7 @@ import pytest from safepull.models import Package -from safepull.safepull import query_package, run, unpack +from safepull.safepull import query_package, run, unpack, download_from_url @pytest.fixture() @@ -100,6 +100,7 @@ def test_run( # noqa: PLR0913 force=False, metadata=False, all=True, + url=None, ), ): run() @@ -119,6 +120,7 @@ def test_run( # noqa: PLR0913 force=False, metadata=True, all=False, + url=None, ), ): run() @@ -133,8 +135,29 @@ def test_run( # noqa: PLR0913 force=False, metadata=False, all=False, + url=None, ), ): run() mock_console_print.assert_called_once_with("Mocked Table") mock_unpack.assert_called_once() + + +@patch("safepull.safepull.download_from_url") +def test_run_with_url(mock_download_from_url: MagicMock) -> None: + """Test the run function with --url flag.""" + with patch( + "argparse.ArgumentParser.parse_args", + return_value=argparse.Namespace( + package=None, + version=None, + force=False, + metadata=False, + all=False, + url="https://example.com/example-1.0.0.tar.gz", + ), + ): + run() + mock_download_from_url.assert_called_once_with( + "https://example.com/example-1.0.0.tar.gz", + )