Repository: janeklb/gh-search (language: python)

Issue:
Check # of search results before applying content filter
If there are lots of search results (ie. 500+) you might not want to scan all of them using the content filter. Either stop the script, or prompt the user to ask them if they want to continue (at the risk of consuming a lot of their api quota)


Discussion / hints:

Fix patch:
diff --git a/.coveragerc b/.coveragerc
index 8cebcca..3d3d1af 100644
--- a/.coveragerc
+++ b/.coveragerc
@@ -1,2 +1,4 @@
 [report]
-fail_under = 90
\ No newline at end of file
+fail_under = 90
+exclude_lines =
+    raise NotImplementedError
diff --git a/ghsearch/gh_search.py b/ghsearch/gh_search.py
index 3171ac1..599e8a6 100644
--- a/ghsearch/gh_search.py
+++ b/ghsearch/gh_search.py
@@ -10,15 +10,34 @@
 from ghsearch.filters import Filter
 from ghsearch.terminal import ProgressPrinter
 
-CORE_LIMIT_THRESHOLD = 0.1
-CORE_LIMIT_WARNING_MESSAGE = """
-Warning: you are at risk of using more than the remaining {threshold:.0%} of your core api limit.
-Your search yielded {num} results, and each result may trigger up to {calls_per_res} core api call(s) per result.
+CORE_LIMIT_RELATIVE_THRESHOLD = 0.1
+CORE_LIMIT_ABSOLUTE_THRESHOLD = 500
 
-Your current usage is {remaining}/{limit} (resets at {reset})
 
-Do you want to continue?
-"""
+def _confirm_continue_many_calls(core_rate: Rate, num_results: int, calls_per_res: int) -> None:
+    click.confirm(
+        f"""
+Warning: you are about to potentially make more than {CORE_LIMIT_ABSOLUTE_THRESHOLD} core api requests.
+Your search yielded {num_results} results, and gh-search may make up to {calls_per_res} core api call(s) per result.
+
+Your current core api usage is {core_rate.remaining}/{core_rate.limit} (resets {core_rate.reset})
+
+Do you want to continue?""".strip(),
+        abort=True,
+    )
+
+
+def _confirm_continue_near_limit(core_rate: Rate, num_results: int, calls_per_res: int) -> None:
+    click.confirm(
+        f"""
+Warning: you are at risk of using more than the remaining {CORE_LIMIT_RELATIVE_THRESHOLD:.0%} of your core api limit.
+Your search yielded {num_results} results, and gh-search may make up to {calls_per_res} core api call(s) per result.
+
+Your current core api usage is {core_rate.remaining}/{core_rate.limit} (resets {core_rate.reset})
+
+Do you want to continue?""".strip(),
+        abort=True,
+    )
 
 
 def _echo_rate_limits(rate_limit: RateLimit) -> None:
@@ -68,16 +87,9 @@ def _check_core_limit_threshold(self, num_results: int, core_rate: Rate) -> None
         max_core_api_calls_per_result = sum(bool(f.uses_core_api) for f in self.filters)
         if max_core_api_calls_per_result > 0:
 
-            remaining_worst_case = core_rate.remaining - (num_results * max_core_api_calls_per_result)
-            if remaining_worst_case / core_rate.limit < CORE_LIMIT_THRESHOLD:
-                click.confirm(
-                    CORE_LIMIT_WARNING_MESSAGE.format(
-                        threshold=CORE_LIMIT_THRESHOLD,
-                        reset=core_rate.reset,
-                        limit=core_rate.limit,
-                        remaining=core_rate.remaining,
-                        num=num_results,
-                        calls_per_res=max_core_api_calls_per_result,
-                    ).strip(),
-                    abort=True,
-                )
+            num_core_api_calls_worst_case = num_results * max_core_api_calls_per_result
+            remaining_worst_case = core_rate.remaining - num_core_api_calls_worst_case
+            if remaining_worst_case / core_rate.limit < CORE_LIMIT_RELATIVE_THRESHOLD:
+                _confirm_continue_near_limit(core_rate, num_results, max_core_api_calls_per_result)
+            elif num_core_api_calls_worst_case > CORE_LIMIT_ABSOLUTE_THRESHOLD:
+                _confirm_continue_many_calls(core_rate, num_results, max_core_api_calls_per_result)


Test patch:
diff --git a/tests/unit/__init__.py b/tests/unit/__init__.py
index 28922b4..83c2be1 100644
--- a/tests/unit/__init__.py
+++ b/tests/unit/__init__.py
@@ -5,9 +5,9 @@
 
 
 class MockPaginatedList:
-    def __init__(self, *items):
+    def __init__(self, *items, total_count=None):
         self.items = items
-        self.totalCount = len(items)
+        self.totalCount = total_count if total_count else len(items)
 
     def __iter__(self):
         return iter(self.items)
diff --git a/tests/unit/gh_search_test.py b/tests/unit/gh_search_test.py
index 033ee89..8db2eda 100644
--- a/tests/unit/gh_search_test.py
+++ b/tests/unit/gh_search_test.py
@@ -76,7 +76,7 @@ def test_get_filtered_results_verbose(mock_client, mock_result_1, mock_result_2,
     mock_click.echo.assert_any_call("Skipping result for org/repo2 via Mock")
 
 
-def test_get_filtered_results_crosses_threshold(mock_client, mock_click):
+def test_get_filtered_results_near_limit(mock_client, mock_click):
     mock_client.get_rate_limit.return_value = MockRateLimit(1, 10, "sometime in the future", 10, 10, "now")
     mock_filter = Mock()
     mock_filter.uses_core_api = True
@@ -87,9 +87,30 @@ def test_get_filtered_results_crosses_threshold(mock_client, mock_click):
     mock_click.confirm.assert_called_once_with(
         """
 Warning: you are at risk of using more than the remaining 10% of your core api limit.
-Your search yielded 3 results, and each result may trigger up to 1 core api call(s) per result.
+Your search yielded 3 results, and gh-search may make up to 1 core api call(s) per result.
 
-Your current usage is 1/10 (resets at sometime in the future)
+Your current core api usage is 1/10 (resets sometime in the future)
+
+Do you want to continue?""".strip(),
+        abort=True,
+    )
+
+
+def test_get_filtered_results_many_calls(mock_client, mock_click):
+    mock_client.get_rate_limit.return_value = MockRateLimit(10000, 10000, "sometime in the future", 10, 10, "now")
+    mock_client.search_code.return_value = MockPaginatedList(*[], total_count=257)
+    mock_filter = Mock()
+    mock_filter.uses_core_api = True
+
+    ghsearch = GHSearch(mock_client, [mock_filter, mock_filter])
+    ghsearch.get_filtered_results(["query", "org:bort"])
+
+    mock_click.confirm.assert_called_once_with(
+        """
+Warning: you are about to potentially make more than 500 core api requests.
+Your search yielded 257 results, and gh-search may make up to 2 core api call(s) per result.
+
+Your current core api usage is 10000/10000 (resets sometime in the future)
 
 Do you want to continue?""".strip(),
         abort=True,