Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add cat to CLI #190

Merged
merged 4 commits into from
Jan 2, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 26 additions & 4 deletions python/hdfs_native/cli.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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):
Expand All @@ -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:
Expand All @@ -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",
Expand Down
1 change: 1 addition & 0 deletions python/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
26 changes: 26 additions & 0 deletions python/tests/test_cli.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import contextlib
import io

import pytest

from hdfs_native import Client
Expand All @@ -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
Expand Down
Loading