mirror of
https://github.com/Novartis/cellxgene-gateway.git
synced 2026-10-09 02:48:12 +08:00
Merge pull request #77 from aeisenbarth/filter-empty-folders
Filter directories without h5ad files
This commit is contained in:
@@ -68,7 +68,7 @@ class FileItemSource(ItemSource):
|
|||||||
|
|
||||||
return item_tree
|
return item_tree
|
||||||
|
|
||||||
def scan_directory(self, subpath="") -> dict:
|
def scan_directory(self, subpath: str = "") -> ItemTree:
|
||||||
base_path = os.path.join(self.base_path, subpath)
|
base_path = os.path.join(self.base_path, subpath)
|
||||||
|
|
||||||
if not os.path.exists(base_path):
|
if not os.path.exists(base_path):
|
||||||
@@ -105,6 +105,11 @@ class FileItemSource(ItemSource):
|
|||||||
branches = [
|
branches = [
|
||||||
self.scan_directory(os.path.join(subpath, subdir)) for subdir in subdirs
|
self.scan_directory(os.path.join(subpath, subdir)) for subdir in subdirs
|
||||||
]
|
]
|
||||||
|
# Exclude branches without files as leaves. Since traversal is applied pre-order,
|
||||||
|
# branch.branches has already been processed and we don't need to check deeper nesting.
|
||||||
|
branches = [
|
||||||
|
branch for branch in branches if branch.items or branch.branches
|
||||||
|
]
|
||||||
|
|
||||||
return ItemTree(subpath, items, branches)
|
return ItemTree(subpath, items, branches)
|
||||||
|
|
||||||
|
|||||||
@@ -116,6 +116,9 @@ class S3ItemSource(ItemSource):
|
|||||||
branches = None
|
branches = None
|
||||||
if len(subdir_keys) > 0:
|
if len(subdir_keys) > 0:
|
||||||
branches = [self.scan_directory(key) for key in subdir_keys]
|
branches = [self.scan_directory(key) for key in subdir_keys]
|
||||||
|
branches = [
|
||||||
|
branch for branch in branches if branch.items or branch.branches
|
||||||
|
]
|
||||||
|
|
||||||
return ItemTree(directory_key, items, branches)
|
return ItemTree(directory_key, items, branches)
|
||||||
|
|
||||||
|
|||||||
+39
-2
@@ -1,4 +1,5 @@
|
|||||||
import unittest
|
import unittest
|
||||||
|
from collections import defaultdict
|
||||||
from unittest.mock import MagicMock, patch
|
from unittest.mock import MagicMock, patch
|
||||||
|
|
||||||
from cellxgene_gateway.filecrawl import (
|
from cellxgene_gateway.filecrawl import (
|
||||||
@@ -48,12 +49,48 @@ class TestRenderItemSource(unittest.TestCase):
|
|||||||
|
|
||||||
|
|
||||||
class TestRenderItemTree(unittest.TestCase):
|
class TestRenderItemTree(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
from cellxgene_gateway.gateway import app
|
||||||
|
|
||||||
|
self.app = app
|
||||||
|
self.app_context = self.app.test_request_context()
|
||||||
|
self.app_context.push()
|
||||||
|
|
||||||
@patch("cellxgene_gateway.items.file.fileitem_source.FileItemSource")
|
@patch("cellxgene_gateway.items.file.fileitem_source.FileItemSource")
|
||||||
def test_GIVEN_deep_nested_dirs_THEN_includes_dirs_in_output(self, item_source):
|
def test_GIVEN_deep_nested_dirs_THEN_includes_dirs_in_output(self, item_source):
|
||||||
item_source.name = "FakeSource"
|
item_source.name = "FakeSource"
|
||||||
item_tree = ItemTree("foo/bar/baz", [], [])
|
item_source.get_annotations_subpath = lambda _: "FakeAnnotations"
|
||||||
|
file_item = FileItem(
|
||||||
|
subpath="foo/bar/baz", name="file.h5ad", type=ItemType.h5ad
|
||||||
|
)
|
||||||
|
item_tree = ItemTree("foo/bar/baz", [file_item], [])
|
||||||
rendered = render_item_tree(item_tree, item_source)
|
rendered = render_item_tree(item_tree, item_source)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
rendered,
|
rendered,
|
||||||
"<li><a href='/filecrawl/foo/bar/baz?source=FakeSource'>baz</a><ul></ul></li>",
|
"<li><a href='/filecrawl/foo/bar/baz?source=FakeSource'>baz</a><ul>"
|
||||||
|
"<li> <a href='/source/FakeSource/view/foo/bar/baz/file.h5ad/'>file.h5ad</a>"
|
||||||
|
" | annotations: <a class='new' href='/source/FakeSource/view/FakeAnnotations'>new</a>"
|
||||||
|
"</li></ul></li>",
|
||||||
|
)
|
||||||
|
|
||||||
|
@patch(
|
||||||
|
"os.listdir",
|
||||||
|
side_effect=lambda parent: defaultdict(
|
||||||
|
list, {"tmp": ["foo"], "tmp/foo": ["bar"]}
|
||||||
|
)[parent],
|
||||||
|
)
|
||||||
|
@patch("os.path.exists", return_value=True)
|
||||||
|
def test_GIVEN_dirs_without_h5ad_THEN_excludes_dirs_in_output(
|
||||||
|
self, listdir, exists
|
||||||
|
):
|
||||||
|
# Directories:
|
||||||
|
# - tmp
|
||||||
|
# - foo
|
||||||
|
# - bar (no h5ad files)
|
||||||
|
item_source = FileItemSource("tmp", name="local")
|
||||||
|
item_tree = item_source.list_items("foo")
|
||||||
|
rendered = render_item_tree(item_tree, item_source)
|
||||||
|
self.assertEqual(
|
||||||
|
rendered,
|
||||||
|
"<li><a href='/filecrawl/foo?source=local'>foo</a><ul></ul></li>",
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user