Skip to content

Commit 9ccc585

Browse files
authored
Merge pull request #67 from astronomy-commons/issue/50/plot
Add file helper methods needed for hipscat-import.
2 parents da2edd3 + b83ae86 commit 9ccc585

File tree

4 files changed

+143
-8
lines changed

4 files changed

+143
-8
lines changed

src/hipscat/io/file_io/file_io.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import json
22
import os
3+
import shutil
34
from typing import Any
45

56
import healpy as hp
@@ -19,14 +20,24 @@ def make_directory(file_pointer: FilePointer, exist_ok: bool = False):
1920
Args:
2021
file_pointer: location in file system to make directory
2122
exist_ok: Default False. If false will raise error if directory exists. If true existing
22-
directories will be ignored and not modified
23+
directories will be ignored and not modified
2324
2425
Raises:
2526
OSError
2627
"""
2728
os.makedirs(file_pointer, exist_ok=exist_ok)
2829

2930

31+
def remove_directory(file_pointer: FilePointer, ignore_errors=False):
32+
"""Remove a directory, and all contents, recursively.
33+
34+
Args:
35+
file_pointer: directory in file system to remove
36+
ignore_errors: if True errors resulting from failed removals will be ignored
37+
"""
38+
shutil.rmtree(file_pointer, ignore_errors=ignore_errors)
39+
40+
3041
def write_string_to_file(
3142
file_pointer: FilePointer, string: str, encoding: str = "utf-8"
3243
):

src/hipscat/io/file_io/file_pointer.py

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1+
import glob
12
import os
2-
from typing import NewType
3+
from typing import List, NewType
34

45
FilePointer = NewType("FilePointer", str)
56

@@ -33,3 +34,58 @@ def does_file_or_directory_exist(pointer: FilePointer) -> bool:
3334
True if file or directory at `pointer` exists, False if not
3435
"""
3536
return os.path.exists(pointer)
37+
38+
39+
def is_regular_file(pointer: FilePointer) -> bool:
40+
"""Checks if a regular file (NOT a directory) exists for a given file pointer.
41+
42+
Args:
43+
pointer: File Pointer to check if a regular file
44+
45+
Returns:
46+
True if regular file at `pointer` exists, False if not or is a directory
47+
"""
48+
return os.path.isfile(pointer)
49+
50+
51+
def find_files_matching_path(*paths: str) -> List[FilePointer]:
52+
"""Find files or directories matching the provided path parts.
53+
54+
Args:
55+
paths: any number of directory names optionally followed by a file name.
56+
directory or file names may be replaced with `*` as a matcher.
57+
Returns:
58+
New file pointers to files found matching the path
59+
"""
60+
matcher = append_paths_to_pointer(*paths)
61+
return [get_file_pointer_from_path(x) for x in glob.glob(matcher)]
62+
63+
64+
def directory_has_contents(pointer: FilePointer) -> bool:
65+
"""Checks if a directory already has some contents (any files or subdirectories)
66+
67+
Args:
68+
pointer: File Pointer to check for existing contents
69+
70+
Returns:
71+
True if there are any files or subdirectories below this directory.
72+
"""
73+
return len(find_files_matching_path(pointer, "*")) > 0
74+
75+
76+
def get_directory_contents(pointer: FilePointer) -> List[FilePointer]:
77+
"""Finds all files and directories in the specified directory.
78+
79+
NBL This is not recursive, and will return only the first level of directory contents.
80+
81+
Args:
82+
pointer: File Pointer in which to find contents
83+
84+
Returns:
85+
New file pointers to files or subdirectories below this directory.
86+
"""
87+
contents = os.listdir(pointer)
88+
if len(contents) == 0:
89+
return []
90+
contents.sort()
91+
return [append_paths_to_pointer(pointer, x) for x in contents]

tests/hipscat/io/file_io/test_file_io.py

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,12 @@
77

88
from hipscat.io.file_io import (
99
get_file_pointer_from_path,
10-
make_directory,
11-
write_string_to_file,
12-
load_json_file,
1310
load_csv_to_pandas,
11+
load_json_file,
12+
make_directory,
13+
remove_directory,
1414
write_dataframe_to_csv,
15+
write_string_to_file,
1516
)
1617

1718

@@ -45,6 +46,24 @@ def test_make_existing_directory_existok(tmp_path):
4546
assert os.path.exists(test_inner_dir_path)
4647

4748

49+
def test_make_and_remove_directory(tmp_path):
50+
test_dir_path = os.path.join(tmp_path, "test_path")
51+
assert not os.path.exists(test_dir_path)
52+
test_dir_pointer = get_file_pointer_from_path(test_dir_path)
53+
make_directory(test_dir_pointer)
54+
assert os.path.exists(test_dir_path)
55+
remove_directory(test_dir_pointer)
56+
assert not os.path.exists(test_dir_path)
57+
58+
## Directory no longer exists to be deleted.
59+
with pytest.raises(FileNotFoundError):
60+
remove_directory(test_dir_pointer)
61+
62+
## Directory doesn't exist, but shouldn't throw an error.
63+
remove_directory(test_dir_pointer, ignore_errors=True)
64+
assert not os.path.exists(test_dir_path)
65+
66+
4867
def test_write_string_to_file(tmp_path):
4968
test_file_path = os.path.join(tmp_path, "text_file.txt")
5069
test_file_pointer = get_file_pointer_from_path(test_file_path)

tests/hipscat/io/file_io/test_file_pointers.py

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
import os
22

33
from hipscat.io.file_io import (
4-
get_file_pointer_from_path,
5-
does_file_or_directory_exist,
64
append_paths_to_pointer,
7-
FilePointer,
5+
directory_has_contents,
6+
does_file_or_directory_exist,
7+
find_files_matching_path,
8+
get_directory_contents,
9+
get_file_pointer_from_path,
10+
is_regular_file,
811
)
912

1013

@@ -31,3 +34,49 @@ def test_append_paths_to_pointer(tmp_path):
3134
test_path = os.path.join(tmp_path, *test_paths)
3235
tmp_pointer = get_file_pointer_from_path(str(tmp_path))
3336
assert append_paths_to_pointer(tmp_pointer, *test_paths) == test_path
37+
38+
39+
def test_is_regular_file(small_sky_dir):
40+
partition_info_file = os.path.join(small_sky_dir, "partition_info.csv")
41+
assert is_regular_file(partition_info_file)
42+
43+
assert not is_regular_file(small_sky_dir)
44+
45+
partition_dir = os.path.join(small_sky_dir, "Norder=0")
46+
assert not is_regular_file(partition_dir)
47+
48+
49+
def test_find_files_matching_path(small_sky_dir):
50+
## no_wildcard
51+
assert len(find_files_matching_path(small_sky_dir, "partition_info.csv")) == 1
52+
53+
## wilcard in the name
54+
assert len(find_files_matching_path(small_sky_dir, "*.csv")) == 1
55+
56+
57+
def test_find_files_matching_path_directory(small_sky_order1_dir):
58+
assert len(find_files_matching_path(small_sky_order1_dir)) == 1
59+
60+
## wildcard in directory - will match all files at indicated depth
61+
assert len(find_files_matching_path(small_sky_order1_dir, "*", "*", "*")) == 4
62+
63+
64+
def test_directory_has_contents(small_sky_order1_dir, tmp_path):
65+
assert directory_has_contents(small_sky_order1_dir)
66+
assert not directory_has_contents(tmp_path)
67+
68+
69+
def test_get_directory_contents(small_sky_order1_dir, tmp_path):
70+
small_sky_contents = get_directory_contents(small_sky_order1_dir)
71+
assert len(small_sky_contents) == 4
72+
73+
expected = [
74+
os.path.join(small_sky_order1_dir, "Norder=1"),
75+
os.path.join(small_sky_order1_dir, "catalog_info.json"),
76+
os.path.join(small_sky_order1_dir, "partition_info.csv"),
77+
os.path.join(small_sky_order1_dir, "point_map.fits"),
78+
]
79+
80+
assert small_sky_contents == expected
81+
82+
assert len(get_directory_contents(tmp_path)) == 0

0 commit comments

Comments
 (0)