Command-line interface to PyPI Stats API to get download stats for Python packages

Overview

pypistats

PyPI version Supported Python versions PyPI downloads Azure Pipelines status GitHub Actions status codecov GitHub DOI Code style: Black

Python 3.6+ interface to PyPI Stats API to get aggregate 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. (For longer time periods, pypinfo can help, you'll need an API key and get free quota.)

Installation

From PyPI

pip install --upgrade pypistats

From source

git clone https://github.com/hugovk/pypistats
cd pypistats
pip install .

Example command-line use

Run pypistats with a subcommand (corresponding to PyPI Stats endpoints), then options for that subcommand.

Top-level help:

$ pypistats --help
usage: pypistats [-h] [-V] {recent,overall,python_major,python_minor,system} ...

positional arguments:
  {recent,overall,python_major,python_minor,system}

optional arguments:
  -h, --help            show this help message and exit
  -V, --version         show program's version number and exit

Help for a subcommand:

$ pypistats recent --help
usage: pypistats recent [-h] [-p {day,week,month}] [-f {html,json,markdown,rst,tsv}] [-j] [-v] package

Retrieve the aggregate download quantities for the last day/week/month

positional arguments:
  package

optional arguments:
  -h, --help            show this help message and exit
  -p {day,week,month}, --period {day,week,month}
  -f {html,json,markdown,rst,tsv}, --format {html,json,markdown,rst,tsv}
                        The format of output (default: markdown)
  -j, --json            Shortcut for "-f json" (default: False)
  -v, --verbose         Print debug messages to stderr (default: False)

Get recent downloads:

$ pypistats recent pillow
| last_day  | last_month | last_week |
| --------: | ---------: | --------: |
| 1,083,451 | 30,750,398 | 7,088,038 |

Help for another subcommand:

$ pypistats python_minor --help
usage: pypistats python_minor [-h] [-V VERSION]
                              [-f {html,json,markdown,rst,tsv}] [-j]
                              [-sd yyyy-mm[-dd]|name] [-ed yyyy-mm[-dd]|name]
                              [-m yyyy-mm|name] [-l] [-t] [-d] [--monthly]
                              [-v]
                              package

Retrieve the aggregate daily download time series by Python minor version
number

positional arguments:
  package

optional arguments:
  -h, --help            show this help message and exit
  -V VERSION, --version VERSION
                        eg. 2.7 or 3.6 (default: None)
  -f {html,json,markdown,rst,tsv}, --format {html,json,markdown,rst,tsv}
                        The format of output (default: markdown)
  -j, --json            Shortcut for "-f json" (default: False)
  -sd yyyy-mm[-dd]|name, --start-date yyyy-mm[-dd]|name
                        Start date (default: None)
  -ed yyyy-mm[-dd]|name, --end-date yyyy-mm[-dd]|name
                        End date (default: None)
  -m yyyy-mm|name, --month yyyy-mm|name
                        Shortcut for -sd & -ed for a single month (default:
                        None)
  -l, --last-month      Shortcut for -sd & -ed for last month (default: False)
  -t, --this-month      Shortcut for -sd for this month (default: False)
  -d, --daily           Show daily downloads (default: False)
  --monthly             Show monthly downloads (default: False)
  -v, --verbose         Print debug messages to stderr (default: False)

Get version downloads:

$ pypistats python_minor pillow --last-month
| category | percent | downloads  |
| -------- | ------: | ---------: |
| 3.7      |  35.93% | 11,002,680 |
| 3.6      |  33.00% | 10,107,822 |
| 3.8      |  15.04% |  4,605,236 |
| 3.9      |   5.03% |  1,540,571 |
| 3.5      |   4.73% |  1,449,591 |
| null     |   3.39% |  1,037,124 |
| 2.7      |   2.84% |    870,677 |
| 3.4      |   0.03% |     10,055 |
| 3.10     |   0.01% |      2,863 |
| 2.6      |   0.00% |         58 |
| 3.3      |   0.00% |         44 |
| 3.2      |   0.00% |         39 |
| Total    |         | 30,626,760 |

Date range: 2021-04-01 - 2021-04-30

The table is Markdown, ready for pasting in GitHub issues and PRs:

category percent downloads
3.7 35.93% 11,002,680
3.6 33.00% 10,107,822
3.8 15.04% 4,605,236
3.9 5.03% 1,540,571
3.5 4.73% 1,449,591
null 3.39% 1,037,124
2.7 2.84% 870,677
3.4 0.03% 10,055
3.10 0.01% 2,863
2.6 0.00% 58
3.3 0.00% 44
3.2 0.00% 39
Total 30,626,760

These are equivalent (in May 2019):

pypistats python_major pip --last-month
pypistats python_major pip --month april
pypistats python_major pip --month apr
pypistats python_major pip --month 2019-04

And:

pypistats python_major pip --start-date december --end-date january
pypistats python_major pip --start-date dec      --end-date jan
pypistats python_major pip --start-date 2018-12  --end-date 2019-01

Example programmatic use

Return values are from the JSON responses documented in the API: https://pypistats.org/api/

import pypistats
from pprint import pprint

# Call the API
print(pypistats.recent("pillow"))
print(pypistats.recent("pillow", "day", format="markdown"))
print(pypistats.recent("pillow", "week", format="rst"))
print(pypistats.recent("pillow", "month", format="html"))
pprint(pypistats.recent("pillow", "week", format="json"))
print(pypistats.recent("pillow", "day"))

print(pypistats.overall("pillow"))
print(pypistats.overall("pillow", mirrors=True, format="markdown"))
print(pypistats.overall("pillow", mirrors=False, format="rst"))
print(pypistats.overall("pillow", mirrors=True, format="html"))
pprint(pypistats.overall("pillow", mirrors=False, format="json"))

print(pypistats.python_major("pillow"))
print(pypistats.python_major("pillow", version=2, format="markdown"))
print(pypistats.python_major("pillow", version=3, format="rst"))
print(pypistats.python_major("pillow", version="2", format="html"))
pprint(pypistats.python_major("pillow", version="3", format="json"))

print(pypistats.python_minor("pillow"))
print(pypistats.python_minor("pillow", version=2.7, format="markdown"))
print(pypistats.python_minor("pillow", version="2.7", format="rst"))
print(pypistats.python_minor("pillow", version=3.7, format="html"))
pprint(pypistats.python_minor("pillow", version="3.7", format="json"))

print(pypistats.system("pillow"))
print(pypistats.system("pillow", os="darwin", format="markdown"))
print(pypistats.system("pillow", os="linux", format="rst"))
print(pypistats.system("pillow", os="darwin", format="html"))
pprint(pypistats.system("pillow", os="linux", format="json"))

NumPy and pandas

To use with either NumPy or pandas, make sure they are first installed, or:

pip install --upgrade "pypistats[numpy]"
pip install --upgrade "pypistats[pandas]"
pip install --upgrade "pypistats[numpy,pandas]"

Return data in a NumPy array for further processing:

print(numpy_array) # [['with_mirrors' '2019-09-20' '2.23%' 1204] # ['without_mirrors' '2019-09-20' '2.08%' 1122] # ['with_mirrors' '2019-09-19' '0.92%' 496] # ... # ['with_mirrors' '2019-10-26' '0.02%' 13] # ['without_mirrors' '2019-10-26' '0.02%' 12] # ['Total' None None 54041]] ">
import pypistats
numpy_array = pypistats.overall("pyvista", total=True, format="numpy")
print(type(numpy_array))
# 
   
print(numpy_array)
# [['with_mirrors' '2019-09-20' '2.23%' 1204]
#  ['without_mirrors' '2019-09-20' '2.08%' 1122]
#  ['with_mirrors' '2019-09-19' '0.92%' 496]
#  ...
#  ['with_mirrors' '2019-10-26' '0.02%' 13]
#  ['without_mirrors' '2019-10-26' '0.02%' 12]
#  ['Total' None None 54041]]

Or in a pandas DataFrame:

print(pandas_dataframe) # category date percent downloads # 0 with_mirrors 2019-09-20 2.23% 1204 # 1 without_mirrors 2019-09-20 2.08% 1122 # 2 with_mirrors 2019-09-19 0.92% 496 # 3 with_mirrors 2019-08-22 0.90% 489 # 4 without_mirrors 2019-09-19 0.86% 466 # .. ... ... ... ... # 354 without_mirrors 2019-11-03 0.03% 15 # 355 without_mirrors 2019-11-16 0.03% 15 # 356 with_mirrors 2019-10-26 0.02% 13 # 357 without_mirrors 2019-10-26 0.02% 12 # 358 Total None None 54041 # # [359 rows x 4 columns] ">
import pypistats
pandas_dataframe = pypistats.overall("pyvista", total=True, format="pandas")
print(type(pandas_dataframe))
# 
   
print(pandas_dataframe)
#             category        date percent  downloads
# 0       with_mirrors  2019-09-20   2.23%       1204
# 1    without_mirrors  2019-09-20   2.08%       1122
# 2       with_mirrors  2019-09-19   0.92%        496
# 3       with_mirrors  2019-08-22   0.90%        489
# 4    without_mirrors  2019-09-19   0.86%        466
# ..               ...         ...     ...        ...
# 354  without_mirrors  2019-11-03   0.03%         15
# 355  without_mirrors  2019-11-16   0.03%         15
# 356     with_mirrors  2019-10-26   0.02%         13
# 357  without_mirrors  2019-10-26   0.02%         12
# 358            Total        None    None      54041
#
# [359 rows x 4 columns]

For example, create charts with pandas:

# Show overall downloads over time, excluding mirrors
import pypistats
data = pypistats.overall("pillow", total=True, format="pandas")
data = data.groupby("category").get_group("without_mirrors").sort_values("date")

chart = data.plot(x="date", y="downloads", figsize=(10, 2))
chart.figure.show()
chart.figure.savefig("overall.png")  # alternatively

overall.png

# Show Python 3 downloads over time
import pypistats
data = pypistats.python_major("pillow", total=True, format="pandas")
data = data.groupby("category").get_group(3).sort_values("date")

chart = data.plot(x="date", y="downloads", figsize=(10, 2))
chart.figure.show()
chart.figure.savefig("python3.png")  # alternatively

python3.png

See also

Related projects

Comments
  • Added --format

    Added --format

    Related to #20

    Added --format flag (for short, -f) to cli args. --json is kept for convenience.

      -j, --json            Output JSON. Shortcut for "-f json".
      -f FORMAT, --format FORMAT
                            The format of output. Supported: json, markdown.
                            Default is "markdown".
    

    The default is markdown. The cli tool also provides a UserWarning if given format is not supported and will inform user that it will fallback to default, which is, again, markdown. An example below:

    $ pypistats recent pyairmore -f mp3  # siriously, wth?
    foo/bar/pypistats/pypistats/cli.py:132: UserWarning: Unknown format: mp3. Using "markdown".
      warnings.warn(f'Unknown format: {args.format}. Using "markdown".')
    | last_day | last_month | last_week |
    |---------:|-----------:|----------:|
    |        3 |        151 |        33 |
    

    Other Minor Changes

    • Verbose flake8 and black output on Travis
    • flake8 and black now checks pypistats/ and tests/ directory instead of whole project which makes it a little bit faster (especially black).
    • Added tests_require to setup.py.

    The only problem is that the code I provided was not tested by pytest since it is not quite possible to both mock HTTP requests and test cli at the same time. The codebase was tested by hand :cry:. This will probably drop code coverage by ~5%. If you are strict about testing, I can find a way around (then inform me, don't merge this PR).

    If you'd like to test for yourself by hand, you can clone forked copy and checkout feat/format-arg branch.

    opened by erayerdin 11
  • Fixed overall table information, fixing issue #177

    Fixed overall table information, fixing issue #177

    I've changed the way the data is manipulated when you request overall statistics. Before this fix, the table for overall looked like this: | category | percent | downloads | |-----------------|--------:|----------:| | with_mirrors | 85.66% | 239 | | without_mirrors | 14.34% | 40 | | Total | | 279 |

    Which has an incorrect value for the total row as with_mirrors is actually the total including mirrors (the naming is confusing, but that's the API's fault). Now, the table looks like this: | category | downloads | |-----------|----------:| | End Users | 40 | | Mirrors | 199 | | Total | 239 |

    hacktoberfest-accepted 
    opened by w-henderson 10
  • httpx.ConnectError on simple pypistats cli test

    httpx.ConnectError on simple pypistats cli test

    First of all, love the repo, super useful. I've used pypistats before but for some reason on a fresh env i'm getting this error:

    httpx.ConnectError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain (_ssl.c:1129)
    

    Have you seen this before? Could this be a firewall issue?

    Environment:

    • Fresh python 3.9 env
    • macos v11.6.1
    • iterm2 3.4.12

    Steps to reproduce:

    1. conda create --name test python=3.9
    2. pip install pypistats
    3. pypistats recent pillow

    Full traceback:

    Traceback (most recent call last):
      File "/Users/gbuster/miniconda3/envs/test/lib/python3.9/site-packages/httpcore/_exceptions.py", line 8, in map_exceptions
        yield
      File "/Users/gbuster/miniconda3/envs/test/lib/python3.9/site-packages/httpcore/backends/sync.py", line 51, in start_tls
        sock = ssl_context.wrap_socket(self._sock, server_hostname=server_hostname)
      File "/Users/gbuster/miniconda3/envs/test/lib/python3.9/ssl.py", line 500, in wrap_socket
        return self.sslsocket_class._create(
      File "/Users/gbuster/miniconda3/envs/test/lib/python3.9/ssl.py", line 1040, in _create
        self.do_handshake()
      File "/Users/gbuster/miniconda3/envs/test/lib/python3.9/ssl.py", line 1309, in do_handshake
        self._sslobj.do_handshake()
    ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain (_ssl.c:1129)
    
    During handling of the above exception, another exception occurred:
    
    Traceback (most recent call last):
      File "/Users/gbuster/miniconda3/envs/test/lib/python3.9/site-packages/httpx/_transports/default.py", line 60, in map_httpcore_exceptions
        yield
      File "/Users/gbuster/miniconda3/envs/test/lib/python3.9/site-packages/httpx/_transports/default.py", line 187, in handle_request
        resp = self._pool.handle_request(req)
      File "/Users/gbuster/miniconda3/envs/test/lib/python3.9/site-packages/httpcore/_sync/connection_pool.py", line 248, in handle_request
        raise exc
      File "/Users/gbuster/miniconda3/envs/test/lib/python3.9/site-packages/httpcore/_sync/connection_pool.py", line 232, in handle_request
        response = connection.handle_request(request)
      File "/Users/gbuster/miniconda3/envs/test/lib/python3.9/site-packages/httpcore/_sync/connection.py", line 90, in handle_request
        raise exc
      File "/Users/gbuster/miniconda3/envs/test/lib/python3.9/site-packages/httpcore/_sync/connection.py", line 67, in handle_request
        stream = self._connect(request)
      File "/Users/gbuster/miniconda3/envs/test/lib/python3.9/site-packages/httpcore/_sync/connection.py", line 146, in _connect
        stream = stream.start_tls(**kwargs)
      File "/Users/gbuster/miniconda3/envs/test/lib/python3.9/site-packages/httpcore/backends/sync.py", line 51, in start_tls
        sock = ssl_context.wrap_socket(self._sock, server_hostname=server_hostname)
      File "/Users/gbuster/miniconda3/envs/test/lib/python3.9/contextlib.py", line 137, in __exit__
        self.gen.throw(typ, value, traceback)
      File "/Users/gbuster/miniconda3/envs/test/lib/python3.9/site-packages/httpcore/_exceptions.py", line 12, in map_exceptions
        raise to_exc(exc)
    httpcore.ConnectError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain (_ssl.c:1129)
    
    The above exception was the direct cause of the following exception:
    
    Traceback (most recent call last):
      File "/Users/gbuster/miniconda3/envs/test/bin/pypistats", line 8, in <module>
        sys.exit(main())
      File "/Users/gbuster/miniconda3/envs/test/lib/python3.9/site-packages/pypistats/cli.py", line 338, in main
        args.func(args)
      File "/Users/gbuster/miniconda3/envs/test/lib/python3.9/site-packages/pypistats/cli.py", line 187, in recent
        pypistats.recent(
      File "/Users/gbuster/miniconda3/envs/test/lib/python3.9/site-packages/pypistats/__init__.py", line 446, in recent
        return pypi_stats_api(endpoint, params, **kwargs)
      File "/Users/gbuster/miniconda3/envs/test/lib/python3.9/site-packages/pypistats/__init__.py", line 116, in pypi_stats_api
        r = httpx.get(url, headers={"User-Agent": USER_AGENT})
      File "/Users/gbuster/miniconda3/envs/test/lib/python3.9/site-packages/httpx/_api.py", line 189, in get
        return request(
      File "/Users/gbuster/miniconda3/envs/test/lib/python3.9/site-packages/httpx/_api.py", line 100, in request
        return client.request(
      File "/Users/gbuster/miniconda3/envs/test/lib/python3.9/site-packages/httpx/_client.py", line 802, in request
        return self.send(request, auth=auth, follow_redirects=follow_redirects)
      File "/Users/gbuster/miniconda3/envs/test/lib/python3.9/site-packages/httpx/_client.py", line 889, in send
        response = self._send_handling_auth(
      File "/Users/gbuster/miniconda3/envs/test/lib/python3.9/site-packages/httpx/_client.py", line 917, in _send_handling_auth
        response = self._send_handling_redirects(
      File "/Users/gbuster/miniconda3/envs/test/lib/python3.9/site-packages/httpx/_client.py", line 954, in _send_handling_redirects
        response = self._send_single_request(request)
      File "/Users/gbuster/miniconda3/envs/test/lib/python3.9/site-packages/httpx/_client.py", line 990, in _send_single_request
        response = transport.handle_request(request)
      File "/Users/gbuster/miniconda3/envs/test/lib/python3.9/site-packages/httpx/_transports/default.py", line 187, in handle_request
        resp = self._pool.handle_request(req)
      File "/Users/gbuster/miniconda3/envs/test/lib/python3.9/contextlib.py", line 137, in __exit__
        self.gen.throw(typ, value, traceback)
      File "/Users/gbuster/miniconda3/envs/test/lib/python3.9/site-packages/httpx/_transports/default.py", line 77, in map_httpcore_exceptions
        raise mapped_exc(message) from exc
    httpx.ConnectError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain (_ssl.c:1129)
    
    opened by grantbuster 8
  • Add support for NumPy and Pandas data output

    Add support for NumPy and Pandas data output

    Now you can make NumPy arrays and Pandas DataFrames from the stats queries:

    import pypistats
    import pandas as pd
    import numpy as np
    
    exec(pypistats.overall("pyvista", total=True, 
                           format="pandas",
                           table_name="downloads"))
    downloads
    
    Screen Shot 2019-09-02 at 4 21 29 PM

    And you could plot the results by:

    mirrors = downloads.groupby("category").get_group("without_mirrors").sort_values("date")
    mirrors.plot(x="date", y="downloads", figsize=(10,2))
    

    download

    enhancement 
    opened by banesullivan 8
  • Codecov failures

    Codecov failures

    Codecov is regularly failing to upload coverage, and failing the build.

    Possibly same as https://github.com/codecov/codecov-bash/issues/330.

    For example: https://github.com/hugovk/pypistats/pull/129 failed 3/24 (12.5%) jobs.

    Test / build (3.6, ubuntu-16.04)

    Run curl --retry 8 -s https://codecov.io/bash -o codecov.sh
      curl --retry 8 -s https://codecov.io/bash -o codecov.sh
      bash codecov.sh -F GHA_Ubuntu_16
      shell: /bin/bash -e {0}
      env:
        pythonLocation: /opt/hostedtoolcache/Python/3.6.11/x64
        CODECOV_NAME: ubuntu-16.04 Python 3.6
    ##[error]Process completed with exit code 7.
    

    Test / build (3.7, ubuntu-16.04)

    Run curl --retry 8 -s https://codecov.io/bash -o codecov.sh
      curl --retry 8 -s https://codecov.io/bash -o codecov.sh
      bash codecov.sh -F GHA_Ubuntu_16
      shell: /bin/bash -e {0}
      env:
        pythonLocation: /opt/hostedtoolcache/Python/3.7.8/x64
        CODECOV_NAME: ubuntu-16.04 Python 3.7
    ##[error]Process completed with exit code 7.
    

    Test / build (3.7, windows-latest)

    Run curl --retry 8 -s https://codecov.io/bash -o codecov.sh
      curl --retry 8 -s https://codecov.io/bash -o codecov.sh
      bash codecov.sh -F GHA_Windows
      shell: C:\Program Files\PowerShell\7\pwsh.EXE -command ". '{0}'"
      env:
        pythonLocation: C:\hostedtoolcache\windows\Python\3.7.8\x64
        CODECOV_NAME: windows-latest Python 3.7
    /usr/bin/bash: codecov.sh: No such file or directory
    ##[error]Process completed with exit code 1.
    
    opened by hugovk 7
  • Bump pytablewriter[html] from 0.58.0 to 0.59.0

    Bump pytablewriter[html] from 0.58.0 to 0.59.0

    Bumps pytablewriter[html] from 0.58.0 to 0.59.0.

    Release notes

    Sourced from pytablewriter[html]'s releases.

    v0.59.0

    • Add support for Python 3.10
    • Drop support for Python 3.5
    • Markdown alignment cells respect margin #36 (Thanks to @​shawalli)
    • Add validation to margin setter
    • Make it possible to set more writer settings via writer class constructors
    • Forced to set margin to zero for CSV/sourcecode writer classes
    • Fix _repr_html_ method to properly apply writer settings
    • Fix to margin value setting changes are properly applied after written a table
    • Modify type annotations
    • Update requirements
    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    changelog: skip dependencies 
    opened by dependabot[bot] 4
  • Fix overall total and percent

    Fix overall total and percent

    Fixes #177. Replaces and closes #178.

    When fetching overall downloads, the without_mirrors numbers are a subset of the with_mirrors numbers, so don't add them up.

    Before

    pypistats overall pip

    | category | percent | downloads | |-----------------|--------:|------------:| | with_mirrors | 50.50% | 344,559,191 | | without_mirrors | 49.50% | 337,696,964 | | Total | | 682,256,155 |

    After

    pypistats overall pip

    | category | percent | downloads | |-----------------|--------:|------------:| | with_mirrors | 100.00% | 344,559,191 | | without_mirrors | 98.01% | 337,696,964 | | Total | | 344,559,191 |

    More info

    @w-henderson Hi! I said I'd tag you in to this PR and say what's going on!

    Here's a description of each commit, feel free to ask if you've any questions!


    https://github.com/hugovk/pypistats/commit/e23620fdf758e4cfa7433e690b320d020b71ad52 updates the expected results from the API for a given API call.

    The test use mocking, so that when running tests, it doesn't make real network calls because we don't want to test the actual network connection or the API at the other end, just how we process the data and show outputs. So we use a mocking library requests_mock to help fake what we get from using the request library. Also makes sure the expected return values are always the same, which of course isn't true with the live service.

    Before it only faked returning "without_mirrors" data, now we fake returning both "without_mirrors" and "without_mirrors" so we can check we sum it correctly.


    The next commit https://github.com/hugovk/pypistats/commit/cc7dc2bbd1d9fa3537a26117980da5c70ca567aa changes the code to fix the test: instead of summing all the downloads, if we're dealing with data of category "with_mirrors" or "without_mirrors" (aka overall data), then only sum the "with_mirrors" downloads.

    Also updates the expected result so the total is as it should be: total == "with_mirrors".


    We also need to calculate the percentages so "with_mirrors" is 100%, and "without_mirrors" is a fraction. Luckily this is easy, we put the same code from the previous commit's _grand_total into _percent. Plus update expected output.

    https://github.com/hugovk/pypistats/commit/922f1db1048843b1a861b0da99a9b628f9edeafa


    Next, the previous two commits use the same code, let's refactor it out to avoid duplication. https://github.com/hugovk/pypistats/commit/78a196a4b3ddc5342e1608eb26186a95314b222a


    I had been doing this on Python 3.9, which skipped NumPy and pandas tests because they're not yet available for 3.9. I hadn't noticed and pushed my branch. Not to worry, the CI ran it on < 3.9 and failed. All that was needed was updating their tests' expected results so the percents/totals matched the fixed results.

    https://github.com/hugovk/pypistats/commit/d74f40bf047f08577a9ef06c30adcd5504f87ffd


    The next two commits aren't related, but I took this opportunity to slip in some updates to linting (https://github.com/hugovk/pypistats/commit/6756a63afa6a18f9c6cab5e437a314935cb90844) and simplify a CI config file (https://github.com/hugovk/pypistats/commit/f5ca670b6153a5b46962d6a42f4272eccdb48ba7).

    bug changelog: Fixed 
    opened by hugovk 4
  • Add GitHub Action to create a release from a tag

    Add GitHub Action to create a release from a tag

    Uses https://github.com/actions/create-release to simplify the release process.

    When pushing a tag, this will create a corresponding release at https://github.com/hugovk/pypistats/releases.

    Note: The body text won't be created as "* TODO" from the config, but "Release [x.y.z]". This has been fixed in the action, but not yet released: https://github.com/actions/create-release/issues/38.

    opened by hugovk 4
  • Warn if --start-date is before earliest available data

    Warn if --start-date is before earliest available data

    Fixes #85.

    Add info to README and show a warning when called with --start-date before the earliest available data:

    $ pypistats python_major torchtext --start-date 2019-06-01 --end-date 2019-06-30
    /Users/hugo/github/pypistats/src/pypistats/cli.py:232: UserWarning: Requested start date (2019-06-01) is before earliest available data (2019-07-07), because data is only available for 180 days. See https://pypistats.org/about#data
      verbose=args.verbose,
    | category | downloads |
    |----------|----------:|
    | Total    |         0 |
    
    Date range: 2019-06-01 - 2019-06-30
    

    Warning not an error, because end date can be in range:

    $ pypistats python_major torchtext --start-date 2019-06-01
    /Users/hugo/github/pypistats/src/pypistats/cli.py:232: UserWarning: Requested start date (2019-06-01) is before earliest available data (2019-07-07), because data is only available for 180 days. See https://pypistats.org/about#data
      verbose=args.verbose,
    | category | percent | downloads |
    |----------|--------:|----------:|
    | 3        |  94.26% |   177,080 |
    | 2        |   5.09% |     9,559 |
    | null     |   0.66% |     1,234 |
    | Total    |         |   187,873 |
    
    Date range: 2019-06-01 - 2020-01-03
    

    Perhaps an error could be shown when --end-date is before earliest available data?

    enhancement 
    opened by hugovk 4
  • Fail to have the data more than half year

    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
    
    opened by zhangguanheng66 4
  • API to access data of last 6 months

    API to access data of last 6 months

    As mentioned in documentation, timeline data is retained for 180 days. But currently I did not find a way to see how the package fared in last 6 month let's say. It gives last day, week and month.

    I would love to see a functionality which can give monthly downloads for past 6 months.

    enhancement 
    opened by drdhaval2785 4
  • Dependency Dashboard

    Dependency Dashboard

    This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

    Awaiting Schedule

    These updates are awaiting their schedule. Click on a checkbox to get an update now.

    • [ ] Update dependency httpx to v0.23.2

    Detected dependencies

    github-actions
    .github/workflows/deploy.yml
    • actions/checkout v3
    • actions/setup-python v4
    .github/workflows/labels.yml
    • actions/checkout v3
    • micnncim/action-label-syncer v1
    .github/workflows/lint.yml
    • actions/checkout v3
    • actions/setup-python v4
    • pre-commit/action v3.0.0
    .github/workflows/release-drafter.yml
    • release-drafter/release-drafter v5
    .github/workflows/require-pr-label.yml
    • mheap/github-action-required-labels v3
    .github/workflows/test.yml
    • actions/checkout v3
    • actions/setup-python v4
    • codecov/codecov-action v3
    pip_requirements
    requirements.txt
    • freezegun ==1.2.2
    • httpx ==0.23.1
    • numpy ==1.24.1
    • pandas ==1.5.2
    • platformdirs ==2.6.2
    • pytablewriter ==0.64.2
    • pytest ==7.2.0
    • pytest-cov ==4.0.0
    • python-slugify ==7.0.0
    • respx ==0.20.1

    • [ ] Check this box to trigger a request for Renovate to run again on this repository
    opened by renovate[bot] 0
Releases(1.2.1)
  • 1.2.1(Dec 3, 2022)

  • 1.2.0(Dec 3, 2022)

    Added

    • Add and use PrettyTable's SINGLE_BORDER as the default (#347) @hugovk

    Changed

    • Migrate from setuptools + setuptools_scm to hatchling + hatch-vcs (#355) @hugovk
    • Migrate setup.cfg to pyproject.toml (#354) @hugovk

    Fixed

    • Remove redundant wheel dependency from pyproject.toml (#332) @hugovk
    Source code(tar.gz)
    Source code(zip)
  • 1.1.0(May 2, 2022)

  • 1.0.0(Nov 26, 2021)

    Added

    • Add --color option (#291) @hugovk

    Removed

    • Drop Python 3.6 and add some type hints (#282) @hugovk

    Fixed

    • Use cog to update README usage (#293) @hugovk
    Source code(tar.gz)
    Source code(zip)
  • 0.15.0(Nov 3, 2021)

  • 0.14.0(Sep 15, 2021)

  • 0.13.0(Aug 27, 2021)

    Added

    • Add support for Python 3.10 (#268) @hugovk

    Changed

    • Replace Requests with HTTPX (#88) @hugovk
    • Replace appdirs with platformdirs fork (#246) @hugovk
    • Rename master to main (#267) @hugovk
    • Convert setup.py to static setup.cfg (#244) @hugovk
    • Replace 3.9-dev with 3.9 in .travis.yml to use Python 3.9 final (#186) @CozyDoomer

    Fixed

    • Docs: Travis CI has been replaced with GHA (#250) @hugovk
    Source code(tar.gz)
    Source code(zip)
  • 0.12.1(Oct 15, 2020)

  • 0.12.0(Oct 7, 2020)

  • 0.11.0(Apr 12, 2020)

  • 0.10.1(Feb 16, 2020)

    Fixed

    • Require pytablewriter 0.48+ to fix NumpyTableWriter regression (#96) @hugovk
    • Only Python 3 is supported: don't create universal wheel (#92) @hugovk

    Other changes

    • Travis CI: test Python 3.9 alpha (#89) @hugovk
    • GHA: use release drafter to draft releases (#95) @hugovk
    • GHA: sync issue labels using GitHub Actions (#94) @hugovk
    • GHA: simplify CI config (#91) @hugovk
    • Update Azure Pipelines (#90) @hugovk
    Source code(tar.gz)
    Source code(zip)
  • 0.10.0(Jan 7, 2020)

    • Add support for NumPy and Pandas data output (#84)
    • Warn if --start-date is before earliest available data (#86)
    • Error if --end-date is before earliest available data (#87)
    Source code(tar.gz)
    Source code(zip)
  • 0.9.0(Nov 14, 2019)

  • 0.8.0(Oct 12, 2019)

  • 0.7.1(Jul 30, 2019)

  • 0.7.0(Jul 22, 2019)

    • Add User-Agent to API requests (#65)
    • Use tox and pre-commit for testing (#64)
    • Use setuptools_scm to simplify versioning during release (#59, #61, #62, #63)
    Source code(tar.gz)
    Source code(zip)
  • 0.6.0(May 14, 2019)

  • 0.5.0(Mar 31, 2019)

    • Add -v --verbose, use capped -V for version: #46
    • Add --this-month for stats so far this month: #55
    • Optional days: --start-date and --end-date can take yyyy-mm-dd or yyyy-mm: #47
    Source code(tar.gz)
    Source code(zip)
  • 0.4.1(Jan 15, 2019)

    • Specify optional dependency of pytablewriter to ensure smooth install: https://github.com/hugovk/pypistats/pull/44
    • Refactor use of pytablewriter as a method may be removed in the future: https://github.com/hugovk/pypistats/pull/42
    Source code(tar.gz)
    Source code(zip)
  • 0.4.0(Jan 1, 2019)

    • Add --monthly option: https://github.com/hugovk/pypistats/pull/38
    • Add local caching of API calls: https://github.com/hugovk/pypistats/pull/39
    • Fix ValueError: month must be in 1..12: https://github.com/hugovk/pypistats/pull/41
    Source code(tar.gz)
    Source code(zip)
  • 0.3.0(Dec 17, 2018)

  • 0.2.1(Nov 5, 2018)

    Fix a bug:

    • Comma-separate the thousands in recent tables, like the others

    Before

    pypistats recent pip
    | last_day | last_month | last_week |
    |---------:|-----------:|----------:|
    |  1799469 |   67307635 |  15490986 |
    

    After

    $ pypistats recent pip
    | last_day  | last_month | last_week  |
    |----------:|-----------:|-----------:|
    | 1,799,469 | 67,307,635 | 15,490,986 |
    
    Source code(tar.gz)
    Source code(zip)
  • 0.2.0(Nov 2, 2018)

Owner
Hugo van Kemenade
Hugo van Kemenade
commandpack - A package of modules for working with commands, command packages, files with command packages.

commandpack Help the project financially: Donate: https://smartlegion.github.io/donate/ Yandex Money: https://yoomoney.ru/to/4100115206129186 PayPal:

null 4 Sep 4, 2021
A command-line based, minimal torrent streaming client made using Python and Webtorrent-cli. Stream your favorite shows straight from the command line.

A command-line based, minimal torrent streaming client made using Python and Webtorrent-cli. Installation pip install -r requirements.txt It use

Jonardon Hazarika 17 Dec 11, 2022
pypinfo is a simple CLI to access PyPI download statistics via Google's BigQuery.

pypinfo: View PyPI download statistics with ease. pypinfo is a simple CLI to access PyPI download statistics via Google's BigQuery. Installation pypin

Ofek Lev 351 Dec 26, 2022
A simple CLI based any Download Tool, that find files and let you stream or download thorugh WebTorrent CLI or Aria or any command tool

Privateer A simple CLI based any Download Tool, that find files and let you stream or download thorugh WebTorrent CLI or Aria or any command tool How

Shreyash Chavan 2 Apr 4, 2022
A simple weather tool. I made this as a way for me to learn Python, API, and PyPi packaging.

A simple weather tool. I made this as a way for me to learn Python, API, and PyPi packaging.

Clint E. 105 Dec 31, 2022
Spotify Offline is a command line tool that allows one to download Spotify playlists in MP3 format.

Spotify Offline v0.0.2 listen to your favorite spotify songs, offline Overview Spotify Offline (spotifyoffline) is a command line tool that allows one

Aarush Gupta 1 Nov 28, 2021
Quo is a Python based toolkit for writing Command-Line Interface(CLI) applications.

Quo is a Python based toolkit for writing Command-Line Interface(CLI) applications. Quo is making headway towards composing speedy and orderly CLI applications while forestalling any disappointments brought about by the failure to execute a CLI API. Simple to code, easy to learn, and does not come with needless baggage.

Secretum Inc. 16 Oct 15, 2022
A collection of command-line interface games written in python

Command Line Interface Python Games Collection of some starter python game projects for beginners How to play these games Clone this repository git cl

Paras Gupta 7 Jun 6, 2022
Command line interface to watch your childhood shows in hindi and english, designed with python

Sweet dreams: Most of your childhood shows Command line interface to watch your

Not Your Surya 3 Feb 13, 2022
Get latest astronomy job and rumor news in your command line

astrojobs Tired of checking the AAS job register and astro rumor mill for job news? Get the latest updates in the command line! astrojobs automaticall

Philip Mocz 19 Jul 20, 2022
Simple script to download OTA packages from Realme's endpoint.

Realme OTA Downloader CLI tool (based on this C# program) to create requests to the Realme's endpoint. Requirements Python 3.9. pycryptodome. Installa

Roger Ortiz 64 Dec 28, 2022
A supercharged AWS command line interface (CLI).

SAWS Motivation AWS CLI Although the AWS CLI is a great resource to manage your AWS-powered services, it's tough to remember usage of: 70+ top-level c

Donne Martin 5.1k Jan 5, 2023
Command line interface for testing internet bandwidth using speedtest.net

speedtest-cli Command line interface for testing internet bandwidth using speedtest.net Versions speedtest-cli works with Python 2.4-3.7 Installation

Matt Martz 12.4k Jan 8, 2023
Universal Command Line Interface for Amazon Web Services

This package provides a unified command line interface to Amazon Web Services.

Amazon Web Services 13.3k Jan 7, 2023
command line interface to manage VALORANT skins

A PROPER RELEASE IS COMING SOON, IF YOU KNOW HOW TO USE PYTHON YOU CAN USE IT NOW! valorant skin manager command line interface simple command line in

colinh 131 Dec 25, 2022
Microsoft Azure CLI - Azure Command-Line Interface

A great cloud needs great tools; we're excited to introduce Azure CLI, our next generation multi-platform command line experience for Azure.

Microsoft Azure 3.4k Dec 30, 2022
flora-dev-cli (fd-cli) is command line interface software to interact with flora blockchain.

Install git clone https://github.com/Flora-Network/fd-cli.git cd fd-cli python3 -m venv venv source venv/bin/activate pip install -e . --extra-index-u

null 14 Sep 11, 2022
A command line interface to buy things in stregsystemet

Stregsystemet-CLI This repository is the Stregsystemet CLI, to buy things in Stregsystemet, at AAU. Use of this cli-tool is at your own risk and there

F-klubben 14 Oct 18, 2022
moviepy-cli: Command line interface for MoviePy.

Moviepy-cli is designed to apply several video editing in a single command with Moviepy as an alternative to Video-cli.

Kentaro Wada 23 Jun 29, 2022