Exclude media-free subtrees from the destination picker too
The previous leaf-item fix only caught a single stray file with no subfolders - it missed a course whose bundled extras (downloaded source code, a Python virtualenv/dependency dump, project assets) have plenty of subfolders but no video/audio anywhere in them, which still left the course itself, and every one of those subfolders, selectable as destinations. Add a subtree-wide media check (bounded depth) so a folder with subfolders but no media anywhere beneath it is excluded the same way, while a folder that still has a real course's media somewhere inside it - or is simply empty, e.g. a freshly-created category - stays pickable. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
+46
-7
@@ -1286,6 +1286,44 @@ def _is_unrecognized_leaf_item(directory: Path) -> bool:
|
||||
return any(e.is_file() and not e.name.startswith('.') for e in entries)
|
||||
|
||||
|
||||
def _subtree_has_any_media(directory: Path, max_depth: int = 8) -> bool:
|
||||
"""Whether `directory` or anything under it (bounded depth, so a huge
|
||||
non-course tree can't make a scan slow) contains at least one
|
||||
recognized video/audio file anywhere. False for a folder that's really
|
||||
a course's bundled extras - downloaded source code, a Python
|
||||
virtualenv/dependency dump, a project's asset tree, etc. - which can
|
||||
have plenty of subfolders (so _is_unrecognized_leaf_item doesn't catch
|
||||
it) but no lecture content anywhere in them."""
|
||||
try:
|
||||
entries = list(directory.iterdir())
|
||||
except (PermissionError, OSError):
|
||||
return False
|
||||
for e in entries:
|
||||
if e.is_file() and not e.name.startswith('.') and e.suffix.lower() in VIDEO_EXTENSIONS | AUDIO_EXTENSIONS:
|
||||
return True
|
||||
if max_depth <= 0:
|
||||
return False
|
||||
for e in entries:
|
||||
if e.is_dir() and not e.name.startswith('.') and _subtree_has_any_media(e, max_depth - 1):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def _is_media_free_subtree(directory: Path) -> bool:
|
||||
"""A folder that has subfolders (so it isn't just an intentionally
|
||||
empty, freshly-created category) but no video/audio anywhere beneath
|
||||
it - excluded from the destination picker for the same reason as
|
||||
_is_unrecognized_leaf_item, just for a deeper non-course tree instead
|
||||
of a single stray file."""
|
||||
try:
|
||||
has_subdir = any(e.is_dir() and not e.name.startswith('.') for e in directory.iterdir())
|
||||
except (PermissionError, OSError):
|
||||
return False
|
||||
if not has_subdir:
|
||||
return False
|
||||
return not _subtree_has_any_media(directory)
|
||||
|
||||
|
||||
def _build_category_index() -> List[Dict[str, Any]]:
|
||||
"""
|
||||
Every category/subcategory folder currently in the library (e.g. IT,
|
||||
@@ -1305,13 +1343,14 @@ def _build_category_index() -> List[Dict[str, Any]]:
|
||||
categories' course titles) can't outweigh a specific match
|
||||
elsewhere just by sharing more of it.
|
||||
Stops recursing into a folder once it reads as a course itself
|
||||
(_looks_like_course, the same rule the Library browser uses) or as an
|
||||
(_looks_like_course, the same rule the Library browser uses), an
|
||||
unrecognized leaf item (_is_unrecognized_leaf_item - an ebook/
|
||||
audiobook/misc file that isn't video or audio, so _looks_like_course
|
||||
doesn't catch it either), so individual courses and standalone files
|
||||
never show up as if they were categories to file things under. The
|
||||
Unsorted folder itself is excluded - it's the source, never a valid
|
||||
destination.
|
||||
audiobook/misc file that isn't video or audio), or a subtree with no
|
||||
video/audio anywhere in it at all (_is_media_free_subtree - a course's
|
||||
bundled source code/project files, a Python virtualenv, etc.), so
|
||||
individual courses and their non-lecture contents never show up as if
|
||||
they were categories to file things under. The Unsorted folder itself
|
||||
is excluded - it's the source, never a valid destination.
|
||||
"""
|
||||
library_root = Path(get_library_root())
|
||||
try:
|
||||
@@ -1334,7 +1373,7 @@ def _build_category_index() -> List[Dict[str, Any]]:
|
||||
continue
|
||||
except OSError:
|
||||
pass
|
||||
if _looks_like_course(entry) or _is_unrecognized_leaf_item(entry):
|
||||
if _looks_like_course(entry) or _is_unrecognized_leaf_item(entry) or _is_media_free_subtree(entry):
|
||||
continue
|
||||
new_parts = path_parts + [entry.name]
|
||||
path_tokens: Set[str] = set()
|
||||
|
||||
Reference in New Issue
Block a user