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)

Standalone Tailwind CSS CLI, installable via pip

Standalone Tailwind CSS CLI, installable via pip Use Tailwind CSS without Node.j

Tim Kamanin 144 Dec 22, 2022
eBay's TSV Utilities: Command line tools for large, tabular data files. Filtering, statistics, sampling, joins and more.

Command line utilities for tabular data files This is a set of command line utilities for manipulating large tabular data files. Files of numeric and

eBay 1.4k Jan 09, 2023
CLI Web-CAT interface for people who use VIM.

CLI Web-CAT CLI Web-CAT interface. Installation git clone https://github.com/phuang1024/cliwebcat cd cliwebcat python setup.py bdist_wheel sdist cd di

Patrick 4 Apr 11, 2022
Gitfetch is a simple tool to get github user details

Gitfetch Just a (cli?) tool to get github user details ๐Ÿ™‚ Installation ๐Ÿ“‚ Install Gitfetch via pypi pip install gitfetch or pip install git+https://g

I'm Not A Bot #Left_TG 7 Jan 23, 2022
Animefetch is an anime command-line system information tool written in python

Animefetch - v0.0.3 An anime command-line system information tool written in python. Description Animefetch is an anime command-line system informatio

Thadeuks 6 Jun 17, 2022
Simple CLI tool to track your cryptocurrency portfolio in real time.

Simple tool to track your crypto portfolio in realtime. It can be used to track any coin on the BNB network, even obscure coins that are not listed or trackable by major portfolio tracking applicatio

Trevor White 69 Oct 24, 2022
Wordle-cli - Command-line clone of Josh Wardle's WORDLE

Command-line clone of Josh Wardle's WORDLE, inspired by Paul Battley's Ruby vers

Klipspringer 32 Jan 03, 2023
Unconventional ways to save an Image

Unexpected Image Saves Unconventional ways to save an image ๐Ÿ˜„ Have you ever been bored by the same old .png, .jpg, .jpeg, .gif and all other image ex

Eric Mendes 15 Nov 06, 2022
๐Ÿ“ฆ A command line utility to put text in a box.

boxie A command line utility to put text in a box. Installation pip install boxie If you are on Linux you may need to use sudo to access this globally

Eliaz Bobadilla 10 Jun 30, 2022
This is a CLI utility that allows you to view RedFlagDeals.com on the command line.

RFD Description Motivation Installation Usage View Hot Deals View and Sort Hot Deals Search Advanced View Posts Shell Completion bash zsh Description

Dave G 8 Nov 29, 2022
img-proof (IPA) provides a command line utility to test images in the Public Cloud

overview img-proof (IPA) provides a command line utility to test images in the Public Cloud (AWS, Azure, GCE, etc.). With img-proof you can now test c

13 Jan 07, 2022
Centauro - a command line tool with some network management functionality

Centauro Ferramenta de rede O Centauro รฉ uma ferramenta de linha de comando com

1 Jan 01, 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

14 Sep 11, 2022
Tarstats - A simple Python commandline application that collects statistics about tarfiles

A simple Python commandline application that collects statistics about tarfiles.

Kristian Koehntopp 13 Feb 20, 2022
A CLI/Shell supporting OpenRobot API and more!

A CLI/Shell supporting JeyyAPI, OpenRobot API and RePI API.

OpenRobot Packages 1 Jan 06, 2022
Execute shell command lines in parallel on Slurm, S(on) of Grid Engine (SGE), PBS/Torque clusters

qbatch Execute shell command lines in parallel on Slurm, S(on) of Grid Engine (SGE), PBS/Torque clusters qbatch is a tool for executing commands in pa

Jon Pipitone 26 Dec 12, 2022
A CLI Password Manager made using Python and Postgresql database.

ManageMyPasswords (CLI Edition) A CLI Password Manager made using Python and Postgresql database. Quick Start Guide First Clone The Project git clone

Imira Randeniya 1 Sep 11, 2022
Python command line tool and python engine to label table fields and fields in data files.

Python command line tool and python engine to label table fields and fields in data files. It could help to find meaningful data in your tables and data files or to find Personal identifable informat

APICrafter 22 Dec 05, 2022
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

Secretum Inc. 16 Oct 15, 2022
A simple command line chat app to communicate via the terminal.

A simple command line chat app to communicate via the terminal. I'm new to networking so sorry if some of my terminology or code is messed up.

PotNoodle 1 Oct 26, 2021