Merge branch 'feature/ChangeHandleUnavailable' into dev

This commit is contained in:
JackDandy 2023-03-14 01:23:37 +00:00
commit 35132a1e8d
3 changed files with 51 additions and 58 deletions

View file

@ -23,6 +23,7 @@
* Update package resource API 63.2.0 (3ae44cd) to 67.3.2 (b9bf2ec) * Update package resource API 63.2.0 (3ae44cd) to 67.3.2 (b9bf2ec)
* Refactor `timestamp_near` to `SGDatetime.timestamp_near` * Refactor `timestamp_near` to `SGDatetime.timestamp_near`
* Change re-add deprecated endpoint used by external scripts * Change re-add deprecated endpoint used by external scripts
* Fix UI by marking resource as unavailable if cannot determine its free space
### 3.27.12 (2023-03-08 23:30:00 UTC) ### 3.27.12 (2023-03-08 23:30:00 UTC)

View file

@ -57,6 +57,11 @@ from sg_helpers import chmod_as_parent, clean_data, copy_file, download_file, fi
get_url, indent_xml, make_path, maybe_plural, md5_for_text, move_file, proxy_setting, remove_file, \ get_url, indent_xml, make_path, maybe_plural, md5_for_text, move_file, proxy_setting, remove_file, \
remove_file_perm, replace_extension, sanitize_filename, scantree, touch_file, try_int, try_ord, write_file remove_file_perm, replace_extension, sanitize_filename, scantree, touch_file, try_int, try_ord, write_file
# deprecated item, remove in 2020, kept here as rollback uses it
copyFile = copy_file
moveFile = move_file
tryInt = try_int # one legacy custom provider is keeping this signature here
# noinspection PyUnreachableCode # noinspection PyUnreachableCode
if False: if False:
# noinspection PyUnresolvedReferences # noinspection PyUnresolvedReferences
@ -319,19 +324,20 @@ def search_infosrc_for_show_id(reg_show_name, tvid=None, prodid=None, ui=None):
return None, None, None return None, None, None
def sizeof_fmt(num): def sizeof_fmt(number, digits=1, sep=' '):
# type: (int, int, AnyStr) -> AnyStr
""" """
format given bytes to human readable string format given bytes to human-readable text
:param num: number :param number: value to convert
:type num: int or long :param digits: number of digits after decimal point
:return: human readable formatted string :param sep: seperater of value and dimension
:rtype: AnyStr :return: human-readable formatted text
""" """
for x in ['bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']: for cur_dimension in ['bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']:
if 1024.0 > num: if 1024.0 > number:
return "%3.1f %s" % (num, x) return f'{number:3.{digits}f}{sep}{cur_dimension}'
num /= 1024.0 number /= 1024.0
def list_media_files(path): def list_media_files(path):
@ -352,30 +358,6 @@ def list_media_files(path):
return result return result
def copyFile(src_file, dest_file):
""" deprecated_item, remove in 2020, kept here as rollback uses it
:param src_file: source file
:type src_file: AnyStr
:param dest_file: destination file
:type dest_file: AnyStr
:return: nothing
:rtype: None
"""
return copy_file(src_file, dest_file)
def moveFile(src_file, dest_file):
""" deprecated_item, remove in 2020, kept here as rollback uses it
:param src_file: source file
:type src_file: AnyStr
:param dest_file: destination file
:type dest_file: AnyStr
:return: nothing
:rtype: None
"""
return move_file(src_file, dest_file)
def link(src_file, dest_file): def link(src_file, dest_file):
""" """
@ -759,12 +741,6 @@ def restore_versioned_file(backup_file, version):
return True return True
# one legacy custom provider is keeping this signature here,
# a monkey patch could fix that so that this can be removed
def tryInt(s, s_default=0):
return try_int(s, s_default)
# try to convert to float, return default on failure # try to convert to float, return default on failure
def try_float(s, s_default=0.0): def try_float(s, s_default=0.0):
try: try:
@ -1416,34 +1392,49 @@ def find_mount_point(path):
# type: (AnyStr) -> AnyStr # type: (AnyStr) -> AnyStr
""" """
returns the mount point for the given path returns the mount point for the given path
:param path: path to find the mount point
:return: mount point for path :param path: to find the mount path
:return: mount point for path or path if no mount
""" """
path = os.path.realpath(os.path.abspath(path)) result = path
while not os.path.ismount(path): if os.path.exists(path):
path = os.path.dirname(path) result = os.path.realpath(os.path.abspath(path))
return path try:
while not os.path.ismount(result):
new_path = os.path.dirname(result)
if new_path == result:
# return input path if mount point not found
return path
result = new_path
except (BaseException, Exception):
return path
return result
def df(): def df():
# type: (...) -> Tuple[List[Tuple[AnyStr, AnyStr]], bool]
""" """
Return disk free space at known parent locations Return disk free space at known parent locations
:return: string path, string value that is formatted size :return: string path, string value that is formatted size
:rtype: Tuple[List[Tuple[AnyStr, AnyStr]], bool]
""" """
result = [] result = []
min_output = True min_output = True # flag ui to output minimal (e.g. vol: size, vol: size)
if sickgear.ROOT_DIRS and sickgear.DISPLAY_FREESPACE: if sickgear.ROOT_DIRS and sickgear.DISPLAY_FREESPACE:
targets = [] targets = []
for path in sickgear.ROOT_DIRS.split('|')[1:]: for cur_target in filter(lambda _t: _t and _t not in targets,
target = find_mount_point(path) map(find_mount_point, sickgear.ROOT_DIRS.split('|')[1:])):
if target and target not in targets: targets += [cur_target]
free = freespace(cur_target)
if 'win32' == sys.platform and None is not free:
cur_target = os.path.splitdrive(cur_target)[0]
if any(['win32' == sys.platform and not re.match('(?i)[a-z]:(\\\\)?$', cur_target),
# Windows, if a simple drive letter isn't found, fallback to full path. On Linux, full path is used
# trigger ui to output long paths instead of minimal volume letters layout
sys.platform.startswith(('linux', 'darwin', 'sunos5')), 'bsd' in sys.platform]):
min_output = False min_output = False
targets += [target] result += [(cur_target, 'unavailable' if None is free else sizeof_fmt(free, sep=''))]
free = freespace(path)
if None is not free:
result += [(target, sizeof_fmt(free).replace(' ', ''))]
return result, min_output return result, min_output

View file

@ -822,7 +822,7 @@ def _get_root_dirs(get_freespace=False):
default_dir = root_dirs[default_index] default_dir = root_dirs[default_index]
if root_dirs and get_freespace: if root_dirs and get_freespace and sickgear.DISPLAY_FREESPACE:
diskfree, _ = df() diskfree, _ = df()
for cur_root_dir in root_dirs: for cur_root_dir in root_dirs:
@ -836,8 +836,9 @@ def _get_root_dirs(get_freespace=False):
if get_freespace: if get_freespace:
# noinspection PyUnboundLocalVariable # noinspection PyUnboundLocalVariable
new_entry.update({'free_space': next((space for disk, space in diskfree or [] new_entry['free_space'] = 'Required setting "Display freespace" is not enabled' \
if disk == find_mount_point(cur_root_dir)), '')}) if not sickgear.DISPLAY_FREESPACE \
else next((_space for _disk, _space in diskfree or [] if _disk == find_mount_point(cur_root_dir)), '')
dir_list.append(new_entry) dir_list.append(new_entry)