Repository: hugovk/pypistats

Issue:
Some functional question
When I wrote the code as `pypistats overall pandas`,  is that means the number of downloading pandas from PyPi in the history?

Discussion:
deepcode-ci-bot[bot]: [**DeepCode Report (#e1cf57)**](https://www.deepcode.ai/app/gh/hugovk/pypistats/65349dea85ff97c329310cb2044cef11a5403ad1/hugovk/pypistats/e1cf57c309ec668c7a9afa94bad162d0e6d43ac8/_/%2F/code/)
---
DeepCode analyzed this pull request.
There are 2 new info reports. 

Patch:
diff --git a/src/pypistats/__init__.py b/src/pypistats/__init__.py
index 36f5a49..f184ce2 100644
--- a/src/pypistats/__init__.py
+++ b/src/pypistats/__init__.py
@@ -125,9 +125,16 @@ def pypi_stats_api(
 
         _save_cache(cache_file, res)
 
+    first, last = _date_range(res["data"])
+
     if start_date or end_date:
         res["data"] = _filter(res["data"], start_date, end_date)
 
+    if start_date:
+        first = start_date
+    if end_date:
+        last = end_date
+
     if total == "monthly":
         res["data"] = _monthly_total(res["data"])
     elif total == "all":
@@ -144,7 +151,12 @@ def pypi_stats_api(
     data = _percent(data)
     data = _grand_total(data)
 
-    return _tabulate(data, format)
+    output = _tabulate(data, format)
+
+    if first:
+        return f"{output}\nDate range: {first} - {last}\n"
+    else:
+        return output
 
 
 def _filter(data, start_date=None, end_date=None):
@@ -223,6 +235,24 @@ def _total(data):
     return data
 
 
+def _date_range(data):
+    """Return the first and last dates in data"""
+    try:
+        first = data[0]["date"]
+        last = data[0]["date"]
+    except KeyError:
+        # /recent has no dates
+        return None, None
+    for row in data:
+        date = row["date"]
+        if date < first:
+            first = date
+        elif date > last:
+            last = date
+
+    return first, last
+
+
 def _grand_total(data):
     """Add a grand total row"""
 
diff --git a/tox.ini b/tox.ini
index df0617c..26fbb8b 100644
--- a/tox.ini
+++ b/tox.ini
@@ -11,7 +11,7 @@ deps =
     requests_mock
 commands =
     # Unit tests
-    {envpython} -m pytest --cov pypistats --cov tests {posargs}
+    {envpython} -m pytest --cov pypistats {posargs}
 
     # Test runs
     pypistats --version


Test patch:
diff --git a/tests/test_pypistats.py b/tests/test_pypistats.py
index 0977f12..1fa00f3 100644
--- a/tests/test_pypistats.py
+++ b/tests/test_pypistats.py
@@ -35,6 +35,14 @@ SAMPLE_DATA_VERSION_STRINGS = [
     {"category": "3.1", "date": "2018-08-15", "downloads": 10},
     {"category": "3.10", "date": "2018-08-15", "downloads": 1},
 ]
+SAMPLE_RESPONSE_OVERALL = """{
+          "data": [
+            {"category": "without_mirrors", "date": "2018-11-01", "downloads": 2295765},
+            {"category": "without_mirrors", "date": "2018-11-02", "downloads": 2297591}
+          ],
+          "package": "pip",
+          "type": "overall_downloads"
+        }"""
 
 
 def stub__cache_filename(*args):
@@ -380,6 +388,35 @@ class TestPypiStats(unittest.TestCase):
         # Assert
         self.assertEqual(output, SAMPLE_DATA_RECENT)
 
+    def test__date_range(self):
+        # Arrange
+        data = copy.deepcopy(PYTHON_MINOR_DATA)
+
+        # Act
+        first, last = pypistats._date_range(data)
+
+        # Assert
+        self.assertEqual(first, "2018-04-16")
+        self.assertEqual(last, "2018-09-23")
+
+    def test__date_range_no_dates_in_data(self):
+        # Arrange
+        # recent
+        data = [
+            {
+                "data": {"last_day": 70, "last_month": 445, "last_week": 268},
+                "package": "dapy",
+                "type": "recent_downloads",
+            }
+        ]
+
+        # Act
+        first, last = pypistats._date_range(data)
+
+        # Assert
+        self.assertIsNone(first)
+        self.assertIsNone(last)
+
     def test__grand_total(self):
         # Arrange
         data = copy.deepcopy(PYTHON_MINOR_DATA)
@@ -499,18 +536,13 @@ class TestPypiStats(unittest.TestCase):
         # Arrange
         package = "pip"
         mocked_url = "https://pypistats.org/api/packages/pip/overall"
-        mocked_response = """{
-          "data": [
-            {"category": "without_mirrors", "date": "2018-11-01", "downloads": 2295765},
-            {"category": "without_mirrors", "date": "2018-11-02", "downloads": 2297591}
-          ],
-          "package": "pip",
-          "type": "overall_downloads"
-        }"""
+        mocked_response = SAMPLE_RESPONSE_OVERALL
         expected_output = """
 |    category     | downloads |
 |-----------------|----------:|
 | without_mirrors | 2,297,591 |
+
+Date range: 2018-11-02 - 2018-11-02
 """
 
         # Act
@@ -521,6 +553,27 @@ class TestPypiStats(unittest.TestCase):
         # Assert
         self.assertEqual(output.strip(), expected_output.strip())
 
+    def test_overall_tabular_end_date(self):
+        # Arrange
+        package = "pip"
+        mocked_url = "https://pypistats.org/api/packages/pip/overall"
+        mocked_response = SAMPLE_RESPONSE_OVERALL
+        expected_output = """
+|    category     | downloads |
+|-----------------|----------:|
+| without_mirrors | 2,295,765 |
+
+Date range: 2018-11-01 - 2018-11-01
+"""
+
+        # Act
+        with requests_mock.Mocker() as m:
+            m.get(mocked_url, text=mocked_response)
+            output = pypistats.overall(package, mirrors=False, end_date="2018-11-01")
+
+        # Assert
+        self.assertEqual(output.strip(), expected_output.strip())
+
     def test_python_major_json(self):
         # Arrange
         package = "pip"
diff --git a/tests/test_pypistats_cache.py b/tests/test_pypistats_cache.py
index 9d61c32..1edea97 100644
--- a/tests/test_pypistats_cache.py
+++ b/tests/test_pypistats_cache.py
@@ -102,6 +102,8 @@ class TestPypiStatsCache(unittest.TestCase):
 |    category     | downloads |
 |-----------------|----------:|
 | without_mirrors | 2,295,765 |
+
+Date range: 2018-11-01 - 2018-11-01
 """
 
         # Act