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)

Simple Python Library to display text with color in Python Terminal

pyTextColor v1.0 Introduction pyTextColor is a simple Python Library to display colorful outputs in Terminal, etc. Note: Your Terminal or any software

Siddhesh Chavan 1 Jan 23, 2022
Autosub - Command-line utility for auto-generating subtitles for any video file

Auto-generated subtitles for any video Autosub is a utility for automatic speech recognition and subtitle generation. It takes a video or an a

Anastasis Germanidis 3.9k Jan 05, 2023
Standalone script written in Python 3 for generating Reverse Shell one liner snippets and handles the communication between target and client using custom Netcat binaries

Standalone script written in Python 3 for generating Reverse Shell one liner snippets and handles the communication between target and client using custom Netcat binaries. It automates the boring stu

Yash Bhardwaj 3 Sep 27, 2022
CLI tool to fix linked references for dates.

Fix Logseq dates This is a CLI tool to fix the date references following a change in date format since the current version (0.4.4) of Logseq does not

Isaac Dadzie 5 May 18, 2022
A minimal ascii-representation of your local weather.

Ascii-Weather A simple, ascii-based weather visualizer for the terminal. The ascii-art updates to match the current weather and conditions. Uses ipinf

Aaron R. 12 Jan 29, 2022
CLI helper to install Github releases on your system.

gh-release-install is a CLI helper to install Github releases on your system. It can be used for pretty much anything, to install a formatter in your CI, deploy some binary using an orcherstration to

Jonas L. 28 Nov 06, 2022
An open source terminal project made in python

Calamity-Terminal An open source terminal project made in python. Calamity Terminal is a free and open source lightweight terminal. Its made 100% off

1 Mar 08, 2022
PyDropper - pick colors everywhere

PyDropper - pick colors everywhere Downloads Settings PyDropper is an eyedropper

Herman Brunberg 2 Jan 04, 2022
Fylm is a wonderful automated command line app for organizing your film media.

Overview Fylm is a wonderful automated command line app for organizing your film media. You can pronounce it Film or File 'em, whichever you like! It

Brandon Shelley 30 Dec 05, 2022
Convert shellcode into :sparkles: different :sparkles: formats!

Bluffy Convert shellcode into โœจ different โœจ formats! Bluffy is a utility which was used in experiments to bypass Anti-Virus products (statically) by f

pre.empt.dev 305 Dec 17, 2022
Interact with Replit remotely with the Replit CLI

Replit CLI pip install repl-cli Welcome to Replit CLI! With the Replit CLI Application, you can work with your repls locally, including clone, pull,

Shuchir Jain 4 Aug 18, 2022
A Tempmail Tool for Terminal and Termux.

A Tempmail Tool for Terminal and Termux.

MAO-COMMUNITY 8 Oct 19, 2022
๐Ÿ•ฐ The command line tool for scheduling Python scripts

hickory is a simple command line tool for scheduling Python scripts.

Max Humber 146 Dec 07, 2022
Tablicate - Python library for easy table creation and output to terminal

Tablicate Tablicate - Python library for easy table creation and output to terminal Features Column-wise justification alignment (left, right, center)

3 Dec 14, 2022
Helicopter animation in terminal

helicopter-helicopter Helicopter animation in terminal (scroll down for instructions) Why does this exist? It's because of a meme Click for details Se

Wasi Master 7 Mar 14, 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
Tools crack instagram + fb ayok dicoba keburu premium ๐Ÿ˜

FITUR INSTALLASI [1] pkg update && pkg upgrade [2] pkg install git [3] pkg install python [4] pkg install python2 [5] pkg install nano [6]

Jeeck 1 Dec 11, 2021
Python wrapper and CLI utility to render LaTeX markup and equations as SVG using dvisvgm and svgo.

latex2svg Python wrapper and CLI utility to render LaTeX markup and equations as SVG using dvisvgm and svgo. Based on the original work by Tino Wagner

Matthias C. Hormann 4 Feb 18, 2022
CLI/GUI Math commands based on python 3

PyMath Commands Syntax Installation Commands: pymath add: usage: pymath add 12.5 12.5 sub: usage: pymath sub 25 12.5 div: usage: pymath div 144 12 mul

eggsnham07 0 Nov 22, 2021
A Julia library for solving Wordle puzzles.

Wordle.jl A Julia library for solving Wordle puzzles. Usage julia import Wordle: play julia play("panic") 4 julia play("panic", verbose = true) I

John Myles White 3 Jan 23, 2022