2019-12-02 22:06:42 +00:00
|
|
|
"""Helper functions for ipyfilechooser."""
|
2020-08-04 20:37:56 +00:00
|
|
|
import fnmatch
|
2019-04-12 01:08:29 +00:00
|
|
|
import os
|
2019-12-03 01:24:59 +00:00
|
|
|
import string
|
|
|
|
import sys
|
2021-05-26 21:00:23 +00:00
|
|
|
from typing import List, Sequence, Iterable, Optional
|
2021-09-14 22:39:05 +00:00
|
|
|
from .errors import InvalidPathError
|
2019-04-12 01:08:29 +00:00
|
|
|
|
|
|
|
|
2021-09-06 20:50:08 +00:00
|
|
|
def get_subpaths(path: str) -> List[str]:
|
2019-11-22 23:58:06 +00:00
|
|
|
"""Walk a path and return a list of subpaths."""
|
2019-04-12 01:08:29 +00:00
|
|
|
if os.path.isfile(path):
|
|
|
|
path = os.path.dirname(path)
|
|
|
|
|
|
|
|
paths = [path]
|
|
|
|
path, tail = os.path.split(path)
|
|
|
|
|
|
|
|
while tail:
|
|
|
|
paths.append(path)
|
|
|
|
path, tail = os.path.split(path)
|
|
|
|
|
|
|
|
return paths
|
|
|
|
|
|
|
|
|
2021-05-26 21:00:23 +00:00
|
|
|
def has_parent(path: str) -> bool:
|
2019-11-22 23:58:06 +00:00
|
|
|
"""Check if a path has a parent folder."""
|
2019-04-12 01:08:29 +00:00
|
|
|
return os.path.basename(path) != ''
|
|
|
|
|
|
|
|
|
2021-09-14 09:56:38 +00:00
|
|
|
def has_parent_path(path: str, parent_path: Optional[str]) -> bool:
|
2021-09-08 22:21:49 +00:00
|
|
|
"""Verifies if path falls under parent_path."""
|
2021-09-13 23:30:17 +00:00
|
|
|
check = True
|
|
|
|
|
2021-09-08 22:40:01 +00:00
|
|
|
if parent_path:
|
|
|
|
check = os.path.commonpath([path, parent_path]) == parent_path
|
|
|
|
|
|
|
|
return check
|
2021-09-08 22:21:49 +00:00
|
|
|
|
|
|
|
|
2021-09-14 09:56:38 +00:00
|
|
|
def strip_parent_path(path: str, parent_path: Optional[str]) -> str:
|
|
|
|
"""Remove a parent path from a path."""
|
|
|
|
stripped_path = path
|
|
|
|
|
|
|
|
if parent_path and path.startswith(parent_path):
|
|
|
|
stripped_path = path[len(parent_path):]
|
|
|
|
|
|
|
|
return stripped_path
|
|
|
|
|
|
|
|
|
2021-05-21 09:54:10 +00:00
|
|
|
def match_item(item: str, filter_pattern: Sequence[str]) -> bool:
|
2021-02-07 22:44:51 +00:00
|
|
|
"""Check if a string matches one or more fnmatch patterns."""
|
2021-02-07 22:53:08 +00:00
|
|
|
if isinstance(filter_pattern, str):
|
|
|
|
filter_pattern = [filter_pattern]
|
|
|
|
|
2021-02-07 22:44:51 +00:00
|
|
|
idx = 0
|
|
|
|
found = False
|
|
|
|
|
2021-02-07 22:53:08 +00:00
|
|
|
while idx < len(filter_pattern) and not found:
|
2021-06-22 23:46:02 +00:00
|
|
|
found |= fnmatch.fnmatch(item.lower(), filter_pattern[idx].lower())
|
2021-02-07 22:44:51 +00:00
|
|
|
idx += 1
|
|
|
|
|
|
|
|
return found
|
|
|
|
|
|
|
|
|
2020-07-23 20:37:41 +00:00
|
|
|
def get_dir_contents(
|
2021-05-26 21:00:23 +00:00
|
|
|
path: str,
|
2021-05-21 09:54:10 +00:00
|
|
|
show_hidden: bool = False,
|
|
|
|
show_only_dirs: bool = False,
|
2021-09-13 21:49:04 +00:00
|
|
|
dir_icon: Optional[str] = None,
|
2021-09-14 10:18:24 +00:00
|
|
|
dir_icon_append: bool = False,
|
2021-09-05 22:00:48 +00:00
|
|
|
filter_pattern: Optional[Sequence[str]] = None,
|
2021-09-14 09:56:38 +00:00
|
|
|
top_path: Optional[str] = None) -> List[str]:
|
2019-11-22 23:58:06 +00:00
|
|
|
"""Get directory contents."""
|
2019-04-12 01:08:29 +00:00
|
|
|
files = list()
|
|
|
|
dirs = list()
|
|
|
|
|
|
|
|
if os.path.isdir(path):
|
|
|
|
for item in os.listdir(path):
|
|
|
|
append = True
|
2020-07-23 20:37:41 +00:00
|
|
|
if item.startswith('.') and not show_hidden:
|
2019-04-12 01:08:29 +00:00
|
|
|
append = False
|
|
|
|
full_item = os.path.join(path, item)
|
2020-07-23 20:37:41 +00:00
|
|
|
if append and os.path.isdir(full_item):
|
2019-04-12 01:08:29 +00:00
|
|
|
dirs.append(item)
|
2020-07-24 00:34:27 +00:00
|
|
|
elif append and not show_only_dirs:
|
2020-08-04 20:37:56 +00:00
|
|
|
if filter_pattern:
|
2021-02-07 22:44:51 +00:00
|
|
|
if match_item(item, filter_pattern):
|
2020-08-04 20:37:56 +00:00
|
|
|
files.append(item)
|
|
|
|
else:
|
|
|
|
files.append(item)
|
2021-09-08 22:21:49 +00:00
|
|
|
if has_parent(strip_parent_path(path, top_path)):
|
|
|
|
dirs.insert(0, os.pardir)
|
2021-09-13 21:49:04 +00:00
|
|
|
if dir_icon:
|
2021-09-14 10:18:24 +00:00
|
|
|
return prepend_dir_icons(sorted(dirs), dir_icon, dir_icon_append) + sorted(files)
|
2020-01-24 14:42:23 +00:00
|
|
|
else:
|
|
|
|
return sorted(dirs) + sorted(files)
|
|
|
|
|
2020-02-14 09:51:20 +00:00
|
|
|
|
2021-09-14 10:18:24 +00:00
|
|
|
def prepend_dir_icons(dir_list: Iterable[str], dir_icon: str, dir_icon_append: bool = False) -> List[str]:
|
2020-02-14 22:34:47 +00:00
|
|
|
"""Prepend unicode folder icon to directory names."""
|
2021-09-14 10:18:24 +00:00
|
|
|
if dir_icon_append:
|
|
|
|
str_ = [dirname + f'{dir_icon}' for dirname in dir_list]
|
|
|
|
else:
|
|
|
|
str_ = [f'{dir_icon}' + dirname for dirname in dir_list]
|
|
|
|
|
|
|
|
return str_
|
2019-12-03 01:24:59 +00:00
|
|
|
|
|
|
|
|
2021-09-08 22:21:49 +00:00
|
|
|
def get_drive_letters() -> List[str]:
|
2021-09-05 21:16:41 +00:00
|
|
|
"""Get all drive letters minus the drive used in path."""
|
2021-09-08 22:21:49 +00:00
|
|
|
drives: List[str] = []
|
2021-09-05 20:49:48 +00:00
|
|
|
|
2021-09-08 22:21:49 +00:00
|
|
|
if sys.platform == 'win32':
|
2019-12-03 01:24:59 +00:00
|
|
|
# Windows has drive letters
|
2021-09-13 22:51:25 +00:00
|
|
|
drives = [os.path.realpath(f'{d}:\\') for d in string.ascii_uppercase if os.path.exists(f'{d}:')]
|
2021-09-08 22:21:49 +00:00
|
|
|
|
|
|
|
return drives
|
2021-09-06 23:04:20 +00:00
|
|
|
|
|
|
|
|
|
|
|
def is_valid_filename(filename: str) -> bool:
|
|
|
|
"""Verifies if a filename does not contain illegal character sequences"""
|
2021-09-08 22:21:49 +00:00
|
|
|
valid = True
|
|
|
|
valid = valid and os.pardir not in filename
|
|
|
|
valid = valid and os.sep not in filename
|
|
|
|
|
|
|
|
if os.altsep:
|
|
|
|
valid = valid and os.altsep not in filename
|
|
|
|
|
|
|
|
return valid
|
|
|
|
|
|
|
|
|
|
|
|
def normalize_path(path: str) -> str:
|
|
|
|
"""Normalize a path string."""
|
2021-09-14 22:39:05 +00:00
|
|
|
normalized_path = os.path.realpath(path)
|
|
|
|
|
|
|
|
if not os.path.isdir(normalized_path):
|
|
|
|
raise InvalidPathError(path)
|
|
|
|
|
|
|
|
return normalized_path
|