diff --git a/python/hdfs_native/cli.py b/python/hdfs_native/cli.py index b931162..49e265c 100644 --- a/python/hdfs_native/cli.py +++ b/python/hdfs_native/cli.py @@ -1,5 +1,6 @@ import functools import os +import sys from argparse import ArgumentParser, Namespace from typing import List, Optional, Sequence from urllib.parse import urlparse @@ -48,12 +49,23 @@ def _glob_path(client: Client, glob: str) -> List[str]: return [glob] +def cat(args: Namespace): + for src in args.src: + client = _client_for_url(src) + for path in _glob_path(client, _path_for_url(src)): + with client.read(path) as file: + while chunk := file.read(1024 * 1024): + sys.stdout.buffer.write(chunk) + + sys.stdout.buffer.flush() + + def mkdir(args: Namespace): create_parent = args.parent - for path in args.path: - client = _client_for_url(path) - client.mkdirs(path, create_parent=create_parent) + for url in args.path: + client = _client_for_url(url) + client.mkdirs(_path_for_url(url), create_parent=create_parent) def mv(args: Namespace): @@ -69,7 +81,9 @@ def mv(args: Namespace): pass resolved_src = [ - path for pattern in args.src for path in _glob_path(client, pattern) + path + for pattern in args.src + for path in _glob_path(client, _path_for_url(pattern)) ] if len(resolved_src) > 1 and not dst_isdir: @@ -95,6 +109,14 @@ def main(in_args: Optional[Sequence[str]] = None): subparsers = parser.add_subparsers(title="Subcommands", required=True) + cat_parser = subparsers.add_parser( + "cat", + help="Print the contents of a file", + description="Print the contents of a file to stdout", + ) + cat_parser.add_argument("src", nargs="+", help="File pattern to print") + cat_parser.set_defaults(func=cat) + mkdir_parser = subparsers.add_parser( "mkdir", help="Create a directory", diff --git a/python/pyproject.toml b/python/pyproject.toml index a99cca4..068c8b4 100644 --- a/python/pyproject.toml +++ b/python/pyproject.toml @@ -7,6 +7,7 @@ name = "hdfs-native" description = "Python bindings for hdfs-native Rust library" readme = "README.md" requires-python = ">=3.9" +dynamic = ["version"] classifiers = [ "Programming Language :: Rust", "Programming Language :: Python :: Implementation :: CPython", diff --git a/python/tests/test_cli.py b/python/tests/test_cli.py index 0047629..bbbe506 100644 --- a/python/tests/test_cli.py +++ b/python/tests/test_cli.py @@ -1,3 +1,6 @@ +import contextlib +import io + import pytest from hdfs_native import Client @@ -7,6 +10,29 @@ def test_cli(minidfs: str): client = Client(minidfs) + # cat + with client.create("/testfile") as file: + file.write(b"1234") + + buf = io.BytesIO() + with contextlib.redirect_stdout(io.TextIOWrapper(buf)): + cli_main(["cat", "/testfile"]) + assert buf.getvalue() == b"1234" + + with client.create("/testfile2") as file: + file.write(b"5678") + + buf = io.BytesIO() + with contextlib.redirect_stdout(io.TextIOWrapper(buf)): + cli_main(["cat", "/testfile", "/testfile2"]) + assert buf.getvalue() == b"12345678" + + with pytest.raises(FileNotFoundError): + cli_main(["cat", "/nonexistent"]) + + client.delete("/testfile") + client.delete("/testfile2") + # mkdir cli_main(["mkdir", "/testdir"]) assert client.get_file_info("/testdir").isdir