kopia lustrzana https://github.com/crahan/ipyfilechooser
116 wiersze
3.3 KiB
Python
116 wiersze
3.3 KiB
Python
"""Helper functions for ipyfilechooser."""
|
|
import fnmatch
|
|
import os
|
|
import string
|
|
import sys
|
|
from typing import List, Sequence, Iterable, Optional
|
|
|
|
|
|
def get_subpaths(path: str, root_path: str = '') -> List[str]:
|
|
"""Walk a path and return a list of subpaths."""
|
|
if os.path.isfile(path):
|
|
path = os.path.dirname(path)
|
|
|
|
path = strip_root_path(path, root_path)
|
|
paths = [path]
|
|
|
|
path, tail = os.path.split(path)
|
|
|
|
while tail:
|
|
paths.append(path)
|
|
path, tail = os.path.split(path)
|
|
|
|
if not root_path:
|
|
try:
|
|
# Add Windows drive letters, but remove the current drive
|
|
drives = get_drive_letters(paths[-1])
|
|
paths.extend(drives)
|
|
except ValueError:
|
|
pass
|
|
return paths
|
|
|
|
|
|
def strip_root_path(path: str, root_path: str) -> str:
|
|
"""Remove a root path from a path"""
|
|
if path == root_path:
|
|
return os.path.sep
|
|
elif path.startswith(root_path):
|
|
return path[len(root_path):]
|
|
return ''
|
|
|
|
|
|
def has_parent(path: str) -> bool:
|
|
"""Check if a path has a parent folder."""
|
|
return os.path.basename(path) != ''
|
|
|
|
|
|
def match_item(item: str, filter_pattern: Sequence[str]) -> bool:
|
|
"""Check if a string matches one or more fnmatch patterns."""
|
|
if isinstance(filter_pattern, str):
|
|
filter_pattern = [filter_pattern]
|
|
|
|
idx = 0
|
|
found = False
|
|
|
|
while idx < len(filter_pattern) and not found:
|
|
found |= fnmatch.fnmatch(item.lower(), filter_pattern[idx].lower())
|
|
idx += 1
|
|
|
|
return found
|
|
|
|
|
|
def get_dir_contents(
|
|
path: str,
|
|
show_hidden: bool = False,
|
|
prepend_icons: bool = False,
|
|
show_only_dirs: bool = False,
|
|
filter_pattern: Optional[Sequence[str]] = None,
|
|
root_path: str = '') -> List[str]:
|
|
"""Get directory contents."""
|
|
files = list()
|
|
dirs = list()
|
|
|
|
if os.path.isdir(path):
|
|
for item in os.listdir(path):
|
|
append = True
|
|
if item.startswith('.') and not show_hidden:
|
|
append = False
|
|
full_item = os.path.join(path, item)
|
|
if append and os.path.isdir(full_item):
|
|
dirs.append(item)
|
|
elif append and not show_only_dirs:
|
|
if filter_pattern:
|
|
if match_item(item, filter_pattern):
|
|
files.append(item)
|
|
else:
|
|
files.append(item)
|
|
if has_parent(strip_root_path(path, root_path)):
|
|
dirs.insert(0, '..')
|
|
if prepend_icons:
|
|
return prepend_dir_icons(sorted(dirs)) + sorted(files)
|
|
else:
|
|
return sorted(dirs) + sorted(files)
|
|
|
|
|
|
def prepend_dir_icons(dir_list: Iterable[str]) -> List[str]:
|
|
"""Prepend unicode folder icon to directory names."""
|
|
return ['\U0001F4C1 ' + dirname for dirname in dir_list]
|
|
|
|
|
|
def get_drive_letters(path: str) -> List[str]:
|
|
"""Get all drive letters minus the drive used in path."""
|
|
if sys.platform == 'win32':
|
|
# Check if path uses upper or lowercase drive letters
|
|
chars = string.ascii_lowercase
|
|
|
|
if path[0].isupper():
|
|
chars = string.ascii_uppercase
|
|
|
|
# Windows has drive letters
|
|
drives = [f'{d}:\\' for d in chars if os.path.exists(f'{d}:')]
|
|
drives.remove(path)
|
|
return drives
|
|
else:
|
|
# Unix does not have drive letters
|
|
return []
|