deepcode-ci-bot[bot]: ## DeepCode's analysis on [#bf0fe6](https://www.deepcode.ai/app/gh/hugovk/pypistats/b704363160891a8fe4a79cce1db6ef2553cfbcca/hugovk/pypistats/bf0fe665e1dbf66f6ea125623ebe46ab555354c8/_/%2F/code/?utm_source=gh_review) found:

- :x: **0** critical issues.  :warning: **0** warnings  and **0** minor issues.  :heavy_check_mark: **0** issues were fixed.

:speech_balloon: This comment has been generated by the [**DeepCode bot**](https://github.com/apps/deepcode-ci-bot/), installed by the owner of the repository. The DeepCode bot **protects** your repository by detecting and commenting on security vulnerabilities or other critical issues.

---
:relaxed: If you want to provide feedback on our bot, here is how to [contact us](https://www.deepcode.ai/feedback?select=4&utm_source=gh_review).

codecov[bot]: # [Codecov](https://codecov.io/gh/hugovk/pypistats/pull/86?src=pr&el=h1) Report
> Merging [#86](https://codecov.io/gh/hugovk/pypistats/pull/86?src=pr&el=desc) into [master](https://codecov.io/gh/hugovk/pypistats/commit/b704363160891a8fe4a79cce1db6ef2553cfbcca?src=pr&el=desc) will **increase** coverage by `<.01%`.
> The diff coverage is `100%`.

[![Impacted file tree graph](https://codecov.io/gh/hugovk/pypistats/pull/86/graphs/tree.svg?width=650&token=I5tpSvAIKP&height=150&src=pr)](https://codecov.io/gh/hugovk/pypistats/pull/86?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master      #86      +/-   ##
==========================================
+ Coverage   99.55%   99.56%   +<.01%     
==========================================
  Files           6        6              
  Lines         675      687      +12     
==========================================
+ Hits          672      684      +12     
  Misses          3        3
```


| [Impacted Files](https://codecov.io/gh/hugovk/pypistats/pull/86?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [tests/test\_pypistats.py](https://codecov.io/gh/hugovk/pypistats/pull/86/diff?src=pr&el=tree#diff-dGVzdHMvdGVzdF9weXBpc3RhdHMucHk=) | `100% <100%> (ø)` | :arrow_up: |
| [src/pypistats/\_\_init\_\_.py](https://codecov.io/gh/hugovk/pypistats/pull/86/diff?src=pr&el=tree#diff-c3JjL3B5cGlzdGF0cy9fX2luaXRfXy5weQ==) | `99.13% <100%> (+0.01%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/hugovk/pypistats/pull/86?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/hugovk/pypistats/pull/86?src=pr&el=footer). Last update [b704363...bf0fe66](https://codecov.io/gh/hugovk/pypistats/pull/86?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

diff --git a/LICENSE.txt b/LICENSE.txt
index f1a4761..0d4270c 100644
--- a/LICENSE.txt
+++ b/LICENSE.txt
@@ -1,6 +1,6 @@
 MIT License
 
-Copyright (c) 2018-2019 Hugo van Kemenade
+Copyright (c) 2018-2020 Hugo van Kemenade
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
diff --git a/README.md b/README.md
index 72c5e7b..95351a6 100644
--- a/README.md
+++ b/README.md
@@ -14,6 +14,10 @@ Python 3.6+ interface to [PyPI Stats API](https://pypistats.org/api) to get aggr
 download statistics on Python packages on the Python Package Index without having to
 execute queries directly against Google BigQuery.
 
+Data is available for the [last 180 days](https://pypistats.org/about#data). (For longer
+time periods, [pypinfo](https://github.com/ofek/pypinfo) can help, you'll need an API
+key and get free quota.)
+
 ## Installation
 
 ### From PyPI
diff --git a/src/pypistats/__init__.py b/src/pypistats/__init__.py
index 308953a..b05121b 100644
--- a/src/pypistats/__init__.py
+++ b/src/pypistats/__init__.py
@@ -7,6 +7,7 @@ import atexit
 import datetime as dt
 import json
 import sys
+import warnings
 from pathlib import Path
 
 import pkg_resources
@@ -125,8 +126,17 @@ def pypi_stats_api(
 
         _save_cache(cache_file, res)
 
+    # Actual first and last dates of the fetched data
     first, last = _date_range(res["data"])
 
+    if start_date and start_date < first:
+        warnings.warn(
+            f"Requested start date ({start_date}) is before earliest available "
+            f"data ({first}), because data is only available for 180 days. "
+            "See https://pypistats.org/about#data",
+            stacklevel=3,
+        )
+
     if start_date or end_date:
         res["data"] = _filter(res["data"], start_date, end_date)
 

Fail to have the data more than half year
It seems the download numbers are not available for the timeline more than half year.
```
pypistats python_major torchtext --start-date 2019-06-01 --end-date 2019-06-30
```

returned:
```
| category | downloads |
|----------|----------:|
| Total    |         0 |

Date range: 2019-06-01 - 2019-06-30
```
diff --git a/tests/test_pypistats.py b/tests/test_pypistats.py
index a6bf262..e925f9b 100644
--- a/tests/test_pypistats.py
+++ b/tests/test_pypistats.py
@@ -119,6 +119,27 @@ class TestPypiStats(unittest.TestCase):
             self.assertGreaterEqual(row["date"], start_date)
             self.assertLessEqual(row["date"], end_date)
 
+    def test_warn_if_start_date_before_earliest_available(self):
+        # Arrange
+        start_date = "2000-01-01"
+        package = "pip"
+        mocked_url = "https://pypistats.org/api/packages/pip/python_major"
+        mocked_response = """{
+            "data": [
+                {"category": "2", "date": "2018-11-01", "downloads": 2008344},
+                {"category": "3", "date": "2018-11-01", "downloads": 280299},
+                {"category": "null", "date": "2018-11-01", "downloads": 7122}
+            ],
+            "package": "pip",
+            "type": "python_major_downloads"
+        }"""
+
+        with requests_mock.Mocker() as m:
+            m.get(mocked_url, text=mocked_response)
+            # Act / Assert
+            with self.assertWarns(UserWarning):
+                pypistats.python_major(package, start_date=start_date)
+
     def test__paramify_none(self):
         # Arrange
         period = None

pip install -e .[numpy,pandas]
parse_log_pytest
requirements.txt
freezegun pytest pytest-cov requests_mock
3.9
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
appdirs==1.4.4
certifi==2025.1.31
chardet==5.2.0
charset-normalizer==3.4.1
coverage==7.8.0
DataProperty==1.1.0
dominate==2.9.1
exceptiongroup==1.2.2
freezegun==1.5.1
idna==3.10
iniconfig==2.1.0
mbstrdecoder==1.1.4
numpy==2.0.2
packaging==24.2
pandas==2.2.3
pathvalidate==3.2.3
pluggy==1.5.0
-e git+https://github.com/hugovk/pypistats.git@99b3d7c65d7d2b1d6610b29b6449a6bc75123949#egg=pypistats
pytablewriter==1.2.1
pytest==8.3.5
pytest-cov==6.0.0
python-dateutil==2.9.0.post0
python-slugify==8.0.4
pytz==2025.2
requests==2.32.3
requests-mock==1.12.1
six==1.17.0
tabledata==1.3.4
tcolorpy==0.1.7
text-unidecode==1.3
tomli==2.2.1
typepy==1.3.4
tzdata==2025.2
urllib3==2.3.0

name: pypistats
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=3.0.16=h5eee18b_0
  - pip=25.0=py39h06a4308_0
  - python=3.9.21=he870216_1
  - readline=8.2=h5eee18b_0
  - setuptools=75.8.0=py39h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - wheel=0.45.1=py39h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - appdirs==1.4.4
      - certifi==2025.1.31
      - chardet==5.2.0
      - charset-normalizer==3.4.1
      - coverage==7.8.0
      - dataproperty==1.1.0
      - dominate==2.9.1
      - exceptiongroup==1.2.2
      - freezegun==1.5.1
      - idna==3.10
      - iniconfig==2.1.0
      - mbstrdecoder==1.1.4
      - numpy==2.0.2
      - packaging==24.2
      - pandas==2.2.3
      - pathvalidate==3.2.3
      - pluggy==1.5.0
      - pypistats==0.9.1.dev20
      - pytablewriter==1.2.1
      - pytest==8.3.5
      - pytest-cov==6.0.0
      - python-dateutil==2.9.0.post0
      - python-slugify==8.0.4
      - pytz==2025.2
      - requests==2.32.3
      - requests-mock==1.12.1
      - six==1.17.0
      - tabledata==1.3.4
      - tcolorpy==0.1.7
      - text-unidecode==1.3
      - tomli==2.2.1
      - typepy==1.3.4
      - tzdata==2025.2
      - urllib3==2.3.0
prefix: /opt/conda/envs/pypistats

tests/test_pypistats.py::TestPypiStats::test_warn_if_start_date_before_earliest_available
tests/test_pypistats.py::TestPypiStats::test__tabulate_html tests/test_pypistats.py::TestPypiStats::test__tabulate_markdown tests/test_pypistats.py::TestPypiStats::test__tabulate_noarg tests/test_pypistats.py::TestPypiStats::test__tabulate_rst tests/test_pypistats.py::TestPypiStats::test_format_numpy tests/test_pypistats.py::TestPypiStats::test_format_pandas tests/test_pypistats.py::TestPypiStats::test_overall_tabular_end_date tests/test_pypistats.py::TestPypiStats::test_overall_tabular_start_date tests/test_pypistats.py::TestPypiStats::test_recent_tabular tests/test_pypistats.py::TestPypiStats::test_system_tabular tests/test_pypistats.py::TestPypiStats::test_versions_are_strings
tests/test_pypistats.py::TestPypiStats::test__date_range tests/test_pypistats.py::TestPypiStats::test__date_range_no_dates_in_data tests/test_pypistats.py::TestPypiStats::test__filter_end_date tests/test_pypistats.py::TestPypiStats::test__filter_no_filters_no_change tests/test_pypistats.py::TestPypiStats::test__filter_start_and_end_date tests/test_pypistats.py::TestPypiStats::test__filter_start_date tests/test_pypistats.py::TestPypiStats::test__grand_total tests/test_pypistats.py::TestPypiStats::test__grand_total_one_row tests/test_pypistats.py::TestPypiStats::test__grand_total_recent tests/test_pypistats.py::TestPypiStats::test__monthly_total tests/test_pypistats.py::TestPypiStats::test__paramify_bool tests/test_pypistats.py::TestPypiStats::test__paramify_float tests/test_pypistats.py::TestPypiStats::test__paramify_int tests/test_pypistats.py::TestPypiStats::test__paramify_none tests/test_pypistats.py::TestPypiStats::test__paramify_string tests/test_pypistats.py::TestPypiStats::test__percent tests/test_pypistats.py::TestPypiStats::test__percent_one_row tests/test_pypistats.py::TestPypiStats::test__percent_recent tests/test_pypistats.py::TestPypiStats::test__sort tests/test_pypistats.py::TestPypiStats::test__sort_recent tests/test_pypistats.py::TestPypiStats::test__total tests/test_pypistats.py::TestPypiStats::test__total_recent tests/test_pypistats.py::TestPypiStats::test_python_major_json tests/test_pypistats.py::TestPypiStats::test_python_minor_json tests/test_pypistats.py::TestPypiStats::test_python_minor_monthly tests/test_pypistats.py::TestPypiStats::test_valid_json
src/pypistats/__init__.py README.md LICENSE.txt
src/pypistats/__init__.py README.md LICENSE.txt