Skip to content

Commit b1ffb2a

Browse files
committed
Move validate_ functions from relink to shared.
1 parent f98dfc6 commit b1ffb2a

4 files changed

Lines changed: 195 additions & 184 deletions

File tree

relink.py

Lines changed: 2 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
DEFAULT_STAGING_ROOT,
1818
get_log_level,
1919
add_parser_verbosity_group,
20+
validate_paths,
21+
validate_directory,
2022
)
2123

2224
# Set up logger
@@ -282,48 +284,6 @@ def replace_one_file_with_symlink(inputdata_root, target_dir, file_path, dry_run
282284
logger.error("Error creating symlink for %s: %s. Skipping.", link_name, e)
283285

284286

285-
def validate_paths(path, check_is_dir=False):
286-
"""
287-
Validate that one or more paths exist.
288-
289-
Args:
290-
path (str or list): The path to validate, or a list of such paths.
291-
292-
Returns:
293-
str or list: The absolute path(s) if valid.
294-
295-
Raises:
296-
argparse.ArgumentTypeError: If a path doesn't exist.
297-
"""
298-
if isinstance(path, list):
299-
result = []
300-
for item in path:
301-
result.append(validate_paths(item, check_is_dir=check_is_dir))
302-
return result
303-
304-
if not os.path.exists(path):
305-
raise argparse.ArgumentTypeError(f"'{path}' does not exist")
306-
if check_is_dir and not os.path.isdir(path):
307-
raise argparse.ArgumentTypeError(f"'{path}' is not a directory")
308-
return os.path.abspath(path)
309-
310-
311-
def validate_directory(path):
312-
"""
313-
Validate that one or more directories exist.
314-
315-
Args:
316-
path (str or list): The directory to validate, or a list of such directories.
317-
318-
Returns:
319-
str or list: The absolute path(s) if valid.
320-
321-
Raises:
322-
argparse.ArgumentTypeError: If a path doesn't exist.
323-
"""
324-
return validate_paths(path, check_is_dir=True)
325-
326-
327287
def parse_arguments():
328288
"""
329289
Parse command-line arguments.

shared.py

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
"""
44

55
import logging
6-
from argparse import ArgumentParser
6+
import argparse
7+
import os
78

89
DEFAULT_INPUTDATA_ROOT = "/glade/campaign/cesm/cesmdata/cseg/inputdata/"
910
DEFAULT_STAGING_ROOT = (
@@ -31,7 +32,7 @@ def get_log_level(quiet: bool = False, verbose: bool = False) -> int:
3132
return logging.INFO
3233

3334

34-
def add_parser_verbosity_group(parser: ArgumentParser):
35+
def add_parser_verbosity_group(parser: argparse.ArgumentParser):
3536
"""Add mutually exclusive verbosity options to an argument parser.
3637
3738
Adds -v/--verbose and -q/--quiet flags as a mutually exclusive group.
@@ -53,3 +54,45 @@ def add_parser_verbosity_group(parser: ArgumentParser):
5354
help="Quiet mode (show only warnings and errors)",
5455
)
5556
return verbosity_group
57+
58+
59+
def validate_paths(path, check_is_dir=False):
60+
"""
61+
Validate that one or more paths exist.
62+
63+
Args:
64+
path (str or list): The path to validate, or a list of such paths.
65+
66+
Returns:
67+
str or list: The absolute path(s) if valid.
68+
69+
Raises:
70+
argparse.ArgumentTypeError: If a path doesn't exist.
71+
"""
72+
if isinstance(path, list):
73+
result = []
74+
for item in path:
75+
result.append(validate_paths(item, check_is_dir=check_is_dir))
76+
return result
77+
78+
if not os.path.exists(path):
79+
raise argparse.ArgumentTypeError(f"'{path}' does not exist")
80+
if check_is_dir and not os.path.isdir(path):
81+
raise argparse.ArgumentTypeError(f"'{path}' is not a directory")
82+
return os.path.abspath(path)
83+
84+
85+
def validate_directory(path):
86+
"""
87+
Validate that one or more directories exist.
88+
89+
Args:
90+
path (str or list): The directory to validate, or a list of such directories.
91+
92+
Returns:
93+
str or list: The absolute path(s) if valid.
94+
95+
Raises:
96+
argparse.ArgumentTypeError: If a path doesn't exist.
97+
"""
98+
return validate_paths(path, check_is_dir=True)

tests/relink/test_args.py

Lines changed: 0 additions & 140 deletions
Original file line numberDiff line numberDiff line change
@@ -205,146 +205,6 @@ def test_inputdata_arguments_accepted(self, temp_dirs, inputdata_flag):
205205
assert args.inputdata_root == inputdata_root
206206

207207

208-
class TestValidateDirectory:
209-
"""Test suite for validate_directory function."""
210-
211-
def test_valid_directory(self, tmp_path):
212-
"""Test that valid directory is accepted and returns absolute path."""
213-
test_dir = tmp_path / "valid_dir"
214-
test_dir.mkdir()
215-
216-
result = relink.validate_directory(str(test_dir))
217-
assert result == str(test_dir.resolve())
218-
219-
def test_nonexistent_directory(self):
220-
"""Test that nonexistent directory raises ArgumentTypeError."""
221-
nonexistent = os.path.join(os.sep, "nonexistent", "directory", "12345")
222-
223-
with pytest.raises(argparse.ArgumentTypeError) as exc_info:
224-
relink.validate_directory(nonexistent)
225-
226-
assert "does not exist" in str(exc_info.value)
227-
assert nonexistent in str(exc_info.value)
228-
229-
def test_relative_path_converted_to_absolute(self, tmp_path):
230-
"""Test that relative paths are converted to absolute."""
231-
test_dir = tmp_path / "relative_test"
232-
test_dir.mkdir()
233-
234-
# Change to parent directory and use relative path
235-
cwd = os.getcwd()
236-
try:
237-
os.chdir(str(tmp_path))
238-
result = relink.validate_directory("relative_test")
239-
assert os.path.isabs(result)
240-
assert result == str(test_dir.resolve())
241-
finally:
242-
os.chdir(cwd)
243-
244-
def test_symlink_to_directory(self, tmp_path):
245-
"""Test that symlink to a directory is accepted."""
246-
real_dir = tmp_path / "real_dir"
247-
real_dir.mkdir()
248-
249-
link_dir = tmp_path / "link_dir"
250-
link_dir.symlink_to(real_dir)
251-
252-
result = relink.validate_paths(str(link_dir))
253-
# validate_directory returns absolute path of the symlink itself
254-
assert result == str(link_dir.absolute())
255-
# Verify it's still a symlink
256-
assert os.path.islink(result)
257-
258-
def test_list_with_invalid_directory(self, tmp_path):
259-
"""Test that a list with one invalid directory raises error."""
260-
dir1 = tmp_path / "dir1"
261-
dir1.mkdir()
262-
nonexistent = tmp_path / "nonexistent"
263-
264-
with pytest.raises(argparse.ArgumentTypeError) as exc_info:
265-
relink.validate_paths([str(dir1), str(nonexistent)])
266-
267-
assert "does not exist" in str(exc_info.value)
268-
269-
270-
class TestValidatePaths:
271-
"""Test suite for validate_paths function."""
272-
273-
def test_valid_directory(self, tmp_path):
274-
"""Test that valid directory is accepted and returns absolute path."""
275-
test_dir = tmp_path / "valid_dir"
276-
test_dir.mkdir()
277-
278-
result = relink.validate_paths(str(test_dir))
279-
assert result == str(test_dir.resolve())
280-
281-
def test_nonexistent_directory(self):
282-
"""Test that nonexistent directory raises ArgumentTypeError."""
283-
nonexistent = os.path.join(os.sep, "nonexistent", "directory", "12345")
284-
285-
with pytest.raises(argparse.ArgumentTypeError) as exc_info:
286-
relink.validate_paths(nonexistent)
287-
288-
assert "does not exist" in str(exc_info.value)
289-
assert nonexistent in str(exc_info.value)
290-
291-
def test_file_instead_of_directory(self, tmp_path):
292-
"""Test that a file path doesn't raise ArgumentTypeError (or any error)."""
293-
test_file = tmp_path / "test_file.txt"
294-
test_file.write_text("content")
295-
296-
relink.validate_paths(str(test_file))
297-
298-
def test_relative_path_converted_to_absolute(self, tmp_path):
299-
"""Test that relative paths are converted to absolute."""
300-
test_dir = tmp_path / "relative_test"
301-
test_dir.mkdir()
302-
303-
# Change to parent directory and use relative path
304-
cwd = os.getcwd()
305-
try:
306-
os.chdir(str(tmp_path))
307-
result = relink.validate_paths("relative_test")
308-
assert os.path.isabs(result)
309-
assert result == str(test_dir.resolve())
310-
finally:
311-
os.chdir(cwd)
312-
313-
def test_symlink_to_directory(self, tmp_path):
314-
"""Test that symlink to a directory is accepted."""
315-
real_dir = tmp_path / "real_dir"
316-
real_dir.mkdir()
317-
318-
link_dir = tmp_path / "link_dir"
319-
link_dir.symlink_to(real_dir)
320-
321-
result = relink.validate_paths(str(link_dir))
322-
# validate_directory returns absolute path of the symlink itself
323-
assert result == str(link_dir.absolute())
324-
# Verify it's still a symlink
325-
assert os.path.islink(result)
326-
327-
def test_list_with_invalid_directory(self, tmp_path):
328-
"""Test that a list with one invalid directory raises error."""
329-
dir1 = tmp_path / "dir1"
330-
dir1.mkdir()
331-
nonexistent = tmp_path / "nonexistent"
332-
333-
with pytest.raises(argparse.ArgumentTypeError) as exc_info:
334-
relink.validate_paths([str(dir1), str(nonexistent)])
335-
336-
assert "does not exist" in str(exc_info.value)
337-
338-
def test_list_with_file_instead_of_directory(self, tmp_path):
339-
"""Test that a list containing a file doesn't raise error."""
340-
dir1 = tmp_path / "dir1"
341-
dir1.mkdir()
342-
file1 = tmp_path / "file.txt"
343-
file1.write_text("content")
344-
345-
relink.validate_paths([str(dir1), str(file1)])
346-
347-
348208
class TestProcessArgs:
349209
"""Test suite for process_args function."""
350210

0 commit comments

Comments
 (0)