diff --git a/cellxgene_gateway/cache_entry.py b/cellxgene_gateway/cache_entry.py index c8dbeef..8ddb2be 100644 --- a/cellxgene_gateway/cache_entry.py +++ b/cellxgene_gateway/cache_entry.py @@ -168,9 +168,8 @@ class CacheEntry: headers[h] = request.headers[h] full_path = self.cellxgene_basepath() + subpath + querystring() - + cellxgene_response = None try: - cellxgene_response = None if request.method in ["GET", "HEAD", "OPTIONS"]: cellxgene_response = get(full_path, headers=headers) elif request.method == "PUT": diff --git a/cellxgene_gateway/gateway.py b/cellxgene_gateway/gateway.py index 6420f95..f99d09e 100644 --- a/cellxgene_gateway/gateway.py +++ b/cellxgene_gateway/gateway.py @@ -332,11 +332,13 @@ def launch(): app.launchtime = current_time_stamp() app.run(host="0.0.0.0", port=env.gateway_port, debug=False) + # When using servers like Gunicorn or uWSGI, this file is imported rather than run directly. # As a result, the main() function is never called automatically. # Therefore, we must initialize the data sources at import time to ensure they are available. initialize_data_sources() + def main(): """CLI entry point for Flask development server.""" launch() diff --git a/tests/items/s3/test_s3item_source.py b/tests/items/s3/test_s3item_source.py index d96855c..1ff675d 100644 --- a/tests/items/s3/test_s3item_source.py +++ b/tests/items/s3/test_s3item_source.py @@ -1,13 +1,32 @@ import unittest +import os +import shutil +import tempfile + from unittest.mock import MagicMock, Mock, patch -from cellxgene_gateway.gateway import app from cellxgene_gateway.items.item import ItemType from cellxgene_gateway.items.s3.s3item import S3Item from cellxgene_gateway.items.s3.s3item_source import S3ItemSource class TestScanDirectory(unittest.TestCase): + def setUp(self): + self._tmpdir = tempfile.mkdtemp() + self._cellxgene_data = os.environ.get("CELLXGENE_DATA", "") + os.environ["CELLXGENE_DATA"] = self._tmpdir + + from cellxgene_gateway.gateway import app + + self.app = app + + def tearDown(self): + if self._cellxgene_data: + os.environ["CELLXGENE_DATA"] = self._cellxgene_data + else: + del os.environ["CELLXGENE_DATA"] + shutil.rmtree(self._tmpdir) + @patch("s3fs.S3FileSystem") def test_GIVEN_invalid_bucket_THEN_throws_error(self, s3func): class S3Mock: @@ -26,6 +45,7 @@ class TestScanDirectory(unittest.TestCase): @patch("s3fs.S3FileSystem") def test__GIVEN_multilevel_bucket_THEN_properly_recurses_suburls(self, s3func): + class S3Mock: def exists(path): if path in [ @@ -82,7 +102,7 @@ class TestScanDirectory(unittest.TestCase): s3func.return_value = S3Mock source = S3ItemSource("my-bucket") - with app.test_request_context(query_string="refresh=true") as test_context: + with self.app.test_request_context(query_string="refresh=true") as test_context: tree = source.scan_directory() def s3item_compare(i1, i2, msg=""): diff --git a/tests/test_cache_entry.py b/tests/test_cache_entry.py index 697e8d1..3c1054f 100644 --- a/tests/test_cache_entry.py +++ b/tests/test_cache_entry.py @@ -1,14 +1,15 @@ import unittest +import tempfile +import os +import shutil from flask import Flask - from cellxgene_gateway import flask_util from cellxgene_gateway.cache_entry import CacheEntry, CacheEntryStatus from cellxgene_gateway.cache_key import CacheKey -from cellxgene_gateway.gateway import app +from cellxgene_gateway.items.item import ItemType from cellxgene_gateway.items.file.fileitem import FileItem from cellxgene_gateway.items.file.fileitem_source import FileItemSource -from cellxgene_gateway.items.item import ItemType key = CacheKey( FileItem("/czi/", name="pbmc3k.h5ad", type=ItemType.h5ad), @@ -18,11 +19,25 @@ key = CacheKey( class TestRenderEntry(unittest.TestCase): def setUp(self): + self._tmpdir = tempfile.mkdtemp() + self._cellxgene_data = os.environ.get("CELLXGENE_DATA", "") + os.environ["CELLXGENE_DATA"] = self._tmpdir + + from cellxgene_gateway.gateway import app + self.app = app self.app_context = self.app.test_request_context() self.app_context.push() self.client = self.app.test_client() + def tearDown(self): + self.app_context.pop() + if self._cellxgene_data: + os.environ["CELLXGENE_DATA"] = self._cellxgene_data + else: + del os.environ["CELLXGENE_DATA"] + shutil.rmtree(self._tmpdir) + def test_GIVEN_key_and_port_THEN_returns_loading_CacheEntry(self): entry = CacheEntry.for_key("some-key", 1) self.assertEqual(entry.status, CacheEntryStatus.loading) diff --git a/tests/test_filecrawl.py b/tests/test_filecrawl.py index ade01e6..d42d783 100644 --- a/tests/test_filecrawl.py +++ b/tests/test_filecrawl.py @@ -1,3 +1,6 @@ +import os +import shutil +import tempfile import unittest from collections import defaultdict from unittest.mock import patch @@ -25,6 +28,25 @@ def make_entry(subpath="somepath", annotations=None): class TestRenderEntry(unittest.TestCase): + def setUp(self): + self._tmpdir = tempfile.mkdtemp() + self._cellxgene_data = os.environ.get("CELLXGENE_DATA", "") + os.environ["CELLXGENE_DATA"] = self._tmpdir + + from cellxgene_gateway.gateway import app + + self.app = app + self.app_context = self.app.test_request_context() + self.app_context.push() + + def tearDown(self): + self.app_context.pop() + if self._cellxgene_data: + os.environ["CELLXGENE_DATA"] = self._cellxgene_data + else: + del os.environ["CELLXGENE_DATA"] + shutil.rmtree(self._tmpdir) + def test_GIVEN_path_both_slash_THEN_view_has_single_slash(self): entry = make_entry(subpath="/somepath/") rendered = render_item(entry, source) @@ -47,6 +69,26 @@ class TestRenderEntry(unittest.TestCase): class TestRenderAnnotation(unittest.TestCase): + + def setUp(self): + self._tmpdir = tempfile.mkdtemp() + self._cellxgene_data = os.environ.get("CELLXGENE_DATA", "") + os.environ["CELLXGENE_DATA"] = self._tmpdir + + from cellxgene_gateway.gateway import app + + self.app = app + self.app_context = self.app.test_request_context() + self.app_context.push() + + def tearDown(self): + self.app_context.pop() + if self._cellxgene_data: + os.environ["CELLXGENE_DATA"] = self._cellxgene_data + else: + del os.environ["CELLXGENE_DATA"] + shutil.rmtree(self._tmpdir) + @patch("cellxgene_gateway.filecrawl.enable_annotations", new=True) def test_GIVEN_no_annotation_THEN_new_alone(self): entry = make_entry(annotations=None) @@ -103,12 +145,24 @@ class TestRenderItemSource(unittest.TestCase): class TestRenderItemTree(unittest.TestCase): def setUp(self): + self._tmpdir = tempfile.mkdtemp() + self._cellxgene_data = os.environ.get("CELLXGENE_DATA", "") + os.environ["CELLXGENE_DATA"] = self._tmpdir + from cellxgene_gateway.gateway import app self.app = app self.app_context = self.app.test_request_context() self.app_context.push() + def tearDown(self): + self.app_context.pop() + if self._cellxgene_data: + os.environ["CELLXGENE_DATA"] = self._cellxgene_data + else: + del os.environ["CELLXGENE_DATA"] + shutil.rmtree(self._tmpdir) + @patch("cellxgene_gateway.items.file.fileitem_source.FileItemSource") def test_GIVEN_deep_nested_dirs_THEN_includes_dirs_in_output(self, item_source): item_source.name = "FakeSource"