Skip to content

Commit e29078f

Browse files
authored
Add mkdir to CLI (#188)
1 parent e8cf125 commit e29078f

File tree

3 files changed

+66
-15
lines changed

3 files changed

+66
-15
lines changed

python/conftest.py

+3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import os
12
import subprocess
23
import urllib
34
import urllib.parse
@@ -32,6 +33,8 @@ def minidfs():
3233
output = child.stdout.readline().strip()
3334
assert output == "Ready!", output
3435

36+
os.environ["HADOOP_CONF_DIR"] = "target/test"
37+
3538
yield "hdfs://127.0.0.1:9000"
3639

3740
try:

python/hdfs_native/cli.py

+46-5
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,31 @@
1+
import functools
12
import os
23
from argparse import ArgumentParser, Namespace
3-
from typing import Optional, Sequence
4+
from typing import List, Optional, Sequence
45
from urllib.parse import urlparse
56

67
from hdfs_native import Client
78

89

10+
@functools.cache
11+
def _get_client(connection_url: Optional[str] = None):
12+
return Client(connection_url)
13+
14+
915
def _client_for_url(url: str) -> Client:
1016
parsed = urlparse(url)
1117

1218
if parsed.scheme:
1319
connection_url = f"{parsed.scheme}://{parsed.hostname}"
1420
if parsed.port:
1521
connection_url += f":{parsed.port}"
16-
return Client(connection_url)
22+
return _get_client(connection_url)
1723
elif parsed.hostname or parsed.port:
1824
raise ValueError(
1925
f"Cannot provide host or port without scheme: {parsed.hostname}"
2026
)
2127
else:
22-
return Client()
28+
return _get_client()
2329

2430

2531
def _verify_nameservices_match(url: str, *urls: str) -> None:
@@ -37,6 +43,19 @@ def _path_for_url(url: str) -> str:
3743
return urlparse(url).path
3844

3945

46+
def _glob_path(client: Client, glob: str) -> List[str]:
47+
# TODO: Actually implement this, for now just pretend we have multiple results
48+
return [glob]
49+
50+
51+
def mkdir(args: Namespace):
52+
create_parent = args.parent
53+
54+
for path in args.path:
55+
client = _client_for_url(path)
56+
client.mkdirs(path, create_parent=create_parent)
57+
58+
4059
def mv(args: Namespace):
4160
_verify_nameservices_match(args.dst, *args.src)
4261

@@ -49,12 +68,16 @@ def mv(args: Namespace):
4968
except FileNotFoundError:
5069
pass
5170

52-
if len(args.src) > 1 and not dst_isdir:
71+
resolved_src = [
72+
path for pattern in args.src for path in _glob_path(client, pattern)
73+
]
74+
75+
if len(resolved_src) > 1 and not dst_isdir:
5376
raise ValueError(
5477
"destination must be a directory if multiple sources are provided"
5578
)
5679

57-
for src in args.src:
80+
for src in resolved_src:
5881
src_path = _path_for_url(src)
5982
if dst_isdir:
6083
target_path = os.path.join(dst_path, os.path.basename(src_path))
@@ -72,6 +95,24 @@ def main(in_args: Optional[Sequence[str]] = None):
7295

7396
subparsers = parser.add_subparsers(title="Subcommands", required=True)
7497

98+
mkdir_parser = subparsers.add_parser(
99+
"mkdir",
100+
help="Create a directory",
101+
description="Create a directory in a specified path",
102+
)
103+
mkdir_parser.add_argument(
104+
"path",
105+
nargs="+",
106+
help="Path for the directory to create",
107+
)
108+
mkdir_parser.add_argument(
109+
"-p",
110+
"--parent",
111+
action="store_true",
112+
help="Create any missing parent directories",
113+
)
114+
mkdir_parser.set_defaults(func=mkdir)
115+
75116
mv_parser = subparsers.add_parser(
76117
"mv",
77118
help="Move files or directories",

python/tests/test_cli.py

+17-10
Original file line numberDiff line numberDiff line change
@@ -7,36 +7,43 @@
77
def test_cli(minidfs: str):
88
client = Client(minidfs)
99

10-
def qualify(path: str) -> str:
11-
return f"{minidfs}{path}"
10+
# mkdir
11+
cli_main(["mkdir", "/testdir"])
12+
assert client.get_file_info("/testdir").isdir
13+
14+
with pytest.raises(RuntimeError):
15+
cli_main(["mkdir", "/testdir/nested/dir"])
16+
17+
cli_main(["mkdir", "-p", "/testdir/nested/dir"])
18+
assert client.get_file_info("/testdir/nested/dir").isdir
19+
20+
client.delete("/testdir", True)
1221

1322
# mv
1423
client.create("/testfile").close()
1524
client.mkdirs("/testdir")
1625

17-
cli_main(["mv", qualify("/testfile"), qualify("/testfile2")])
26+
cli_main(["mv", "/testfile", "/testfile2"])
1827

1928
client.get_file_info("/testfile2")
2029

2130
with pytest.raises(ValueError):
22-
cli_main(["mv", qualify("/testfile2"), "hdfs://badnameservice/testfile"])
31+
cli_main(["mv", "/testfile2", "hdfs://badnameservice/testfile"])
2332

2433
with pytest.raises(RuntimeError):
25-
cli_main(["mv", qualify("/testfile2"), qualify("/nonexistent/testfile")])
34+
cli_main(["mv", "/testfile2", "/nonexistent/testfile"])
2635

27-
cli_main(["mv", qualify("/testfile2"), qualify("/testdir")])
36+
cli_main(["mv", "/testfile2", "/testdir"])
2837

2938
client.get_file_info("/testdir/testfile2")
3039

3140
client.rename("/testdir/testfile2", "/testfile1")
3241
client.create("/testfile2").close()
3342

3443
with pytest.raises(ValueError):
35-
cli_main(
36-
["mv", qualify("/testfile1"), qualify("/testfile2"), qualify("/testfile3")]
37-
)
44+
cli_main(["mv", "/testfile1", "/testfile2", "/testfile3"])
3845

39-
cli_main(["mv", qualify("/testfile1"), qualify("/testfile2"), qualify("/testdir/")])
46+
cli_main(["mv", "/testfile1", "/testfile2", "/testdir/"])
4047

4148
client.get_file_info("/testdir/testfile1")
4249
client.get_file_info("/testdir/testfile2")

0 commit comments

Comments
 (0)