210 lines
5.0 KiB
Python
210 lines
5.0 KiB
Python
import tempfile
|
|
from json import loads as json_loads
|
|
from os import name as os_name, getpid, makedirs, walk
|
|
from pathlib import Path
|
|
from shutil import move
|
|
from shutil import rmtree
|
|
|
|
__dir_name__ = '.PyMangaDownloader'
|
|
|
|
|
|
def mark_as_hidden(_path: str):
|
|
try:
|
|
from ctypes import windll
|
|
windll.kernel32.SetFileAttributesW(_path, 2)
|
|
except Exception:
|
|
pass
|
|
|
|
|
|
def get_temp_path(*args) -> str:
|
|
temp = 'temp_%s' % getpid()
|
|
return path_join(tempfile.gettempdir(), __dir_name__, temp, *args)
|
|
|
|
|
|
def root_path() -> str:
|
|
# fs.py/manga_py/../
|
|
file = Path(__file__).resolve()
|
|
return str(file.parent.parent)
|
|
|
|
|
|
def get_util_home_path() -> str:
|
|
if os_name == 'nt':
|
|
home = path_join(str(Path.home()), 'AppData', 'Roaming', __dir_name__)
|
|
else:
|
|
home = path_join(str(Path.home()), __dir_name__)
|
|
make_dirs(home)
|
|
return str(home)
|
|
|
|
|
|
def make_dirs(directory):
|
|
is_dir(directory) or makedirs(directory)
|
|
|
|
|
|
def remove_file_query_params(name, save_path: bool = True) -> str:
|
|
if name is None:
|
|
raise AttributeError
|
|
file_path = dirname(name)
|
|
name = basename(name)
|
|
position = name.find('?')
|
|
if position == 0:
|
|
name = 'image.png' # fake image name
|
|
elif position > 0:
|
|
name = name[:position]
|
|
return str(path_join(file_path, name) if save_path else name)
|
|
|
|
|
|
def is_file(_path) -> bool:
|
|
return Path(_path).is_file()
|
|
|
|
|
|
def is_dir(_path) -> bool:
|
|
return Path(_path).is_dir()
|
|
|
|
|
|
def basename(_path) -> str:
|
|
return str(Path(_path).name)
|
|
|
|
|
|
def dirname(_path) -> str:
|
|
return str(Path(_path).parent)
|
|
|
|
|
|
def path_join(_path, *args) -> str:
|
|
return str(Path(_path).joinpath(*args))
|
|
|
|
|
|
def unlink(_path, allow_not_empty=False):
|
|
if is_dir(_path):
|
|
if allow_not_empty:
|
|
rmtree(_path)
|
|
else:
|
|
Path(_path).rmdir()
|
|
elif is_file(_path):
|
|
Path(_path).unlink()
|
|
|
|
|
|
def os_stat(_path):
|
|
if is_file(_path):
|
|
return Path(_path).stat()
|
|
return None
|
|
|
|
|
|
def file_size(_path):
|
|
"""
|
|
:param _path:
|
|
:return:
|
|
:rtype: int
|
|
"""
|
|
data = os_stat(_path)
|
|
if data:
|
|
return data.st_size
|
|
return None
|
|
|
|
|
|
def rename(_from, _to):
|
|
if is_file(_from) or is_dir(_from):
|
|
is_dir(dirname(_to)) or makedirs(dirname(_to))
|
|
move(_from, _to)
|
|
|
|
|
|
def storage(_path) -> str:
|
|
_path = get_temp_path('storage', _path)
|
|
make_dirs(dirname(_path))
|
|
return str(_path)
|
|
|
|
|
|
def listing(_path) -> dict:
|
|
"""
|
|
:param _path:
|
|
:return: {'directories': [], 'files': []}
|
|
"""
|
|
_dirname, _dirnames, _filenames = walk(_path)
|
|
return {'directories': _dirnames, 'files': _filenames}
|
|
|
|
|
|
def __get_info(_path):
|
|
try:
|
|
with open(path_join(_path, 'info.json'), 'r') as r:
|
|
return json_loads(r.read())
|
|
except FileNotFoundError:
|
|
return None
|
|
|
|
|
|
def get_info(_path) -> dict:
|
|
"""
|
|
listing subdirectories and reading info.json files
|
|
:param _path: [{..}, {..}, {..}]
|
|
:return:
|
|
"""
|
|
result = {}
|
|
for d in listing(_path)['directories']:
|
|
directory = path_join(_path, d)
|
|
info = __get_info(directory)
|
|
if info is not None:
|
|
result[directory] = info
|
|
return result
|
|
|
|
|
|
def __dirname(_path) -> str:
|
|
if not is_dir(_path):
|
|
_path = __dirname(dirname(_path))
|
|
return str(_path)
|
|
|
|
|
|
def _disk_stat_posix(_path) -> dict:
|
|
import os
|
|
st = os.statvfs(_path)
|
|
free = st.f_bavail * st.f_frsize
|
|
total = st.f_blocks * st.f_frsize
|
|
used = (st.f_blocks - st.f_bfree) * st.f_frsize
|
|
return {'total': total, 'used': used, 'free': free}
|
|
|
|
|
|
def _disc_stat_win(_path) -> dict:
|
|
import ctypes
|
|
_, total, free = ctypes.c_ulonglong(), ctypes.c_ulonglong(), ctypes.c_ulonglong()
|
|
fun = ctypes.windll.kernel32.GetDiskFreeSpaceExA
|
|
ret = fun(_path, ctypes.byref(_), ctypes.byref(total), ctypes.byref(free))
|
|
if ret == 0:
|
|
fun = ctypes.windll.kernel32.GetDiskFreeSpaceExW
|
|
ret = fun(_path, ctypes.byref(_), ctypes.byref(total), ctypes.byref(free))
|
|
if ret == 0:
|
|
raise ctypes.WinError()
|
|
used = total.value - free.value
|
|
return {'total': total.value, 'used': used, 'free': free.value}
|
|
|
|
|
|
def get_disk_stat(_path) -> dict:
|
|
import os
|
|
_path = __dirname(_path)
|
|
|
|
if hasattr(os, 'statvfs'): # POSIX
|
|
return _disk_stat_posix(_path)
|
|
elif os.name == 'nt': # Windows
|
|
return _disc_stat_win(_path)
|
|
else:
|
|
raise NotImplementedError('Platform not supported')
|
|
|
|
|
|
def check_free_space(_path: str, min_size: int = 100, percent: bool = False) -> bool:
|
|
"""
|
|
min_size = 10 # percent = True
|
|
min_size = 10 # percent = False (default)
|
|
|
|
:param _path:
|
|
:param min_size:
|
|
:param percent:
|
|
:return:
|
|
"""
|
|
_stat = get_disk_stat(_path)
|
|
if percent:
|
|
_free = _stat['free'] / _stat['total']
|
|
if (_free * 100) < min_size:
|
|
return False
|
|
return True
|
|
else:
|
|
_free = _stat['free'] / (2 << 19) # 1Mb
|
|
if _free < min_size:
|
|
return False
|
|
return True
|