Git Product home page Git Product logo

pypistats's Introduction

pypistats

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

Python 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

python3 -m pip install --upgrade pypistats

From source

git clone https://github.com/hugovk/pypistats
cd pypistats
python3 -m 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}

options:
  -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,pretty,md,markdown,rst,tsv}] [-j]
                        [-v]
                        package

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

positional arguments:
  package

options:
  -h, --help            show this help message and exit
  -p {day,week,month}, --period {day,week,month}
  -f {html,json,pretty,md,markdown,rst,tsv}, --format {html,json,pretty,md,markdown,rst,tsv}
                        The format of output (default: pretty)
  -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 │
├───────────┼────────────┼────────────┤
│ 3,419,597 │ 91,237,125 │ 21,259,217 │
└───────────┴────────────┴────────────┘

Help for another subcommand:

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

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

positional arguments:
  package

options:
  -h, --help            show this help message and exit
  -V VERSION, --version VERSION
                        eg. 2.7 or 3.6 (default: None)
  -f {html,json,pretty,md,markdown,rst,tsv}, --format {html,json,pretty,md,markdown,rst,tsv}
                        The format of output (default: pretty)
  -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)
  -c {yes,no,auto}, --color {yes,no,auto}
                        Color terminal output (default: auto)
  -v, --verbose         Print debug messages to stderr (default: False)

Get version downloads:

$ pypistats python_minor pillow --last-month
┌──────────┬─────────┬────────────┐
│ category │ percent │  downloads │
├──────────┼─────────┼────────────┤
│ 3.8      │  18.37% │ 16,161,117 │
│ 3.10     │  17.47% │ 15,373,666 │
│ 3.7      │  16.70% │ 14,691,371 │
│ 3.11     │  15.49% │ 13,630,259 │
│ 3.9      │  13.19% │ 11,605,389 │
│ 3.6      │   9.68% │  8,519,789 │
│ null     │   4.64% │  4,085,994 │
│ 3.12     │   3.26% │  2,871,386 │
│ 2.7      │   0.95% │    837,638 │
│ 3.5      │   0.25% │    216,308 │
│ 3.13     │   0.00% │      2,830 │
│ 3.4      │   0.00% │      1,237 │
│ 3.3      │   0.00% │        109 │
│ 3.1      │   0.00% │          3 │
│ 3.2      │   0.00% │          2 │
│ Total    │         │ 87,997,098 │
└──────────┴─────────┴────────────┘

Date range: 2024-02-01 - 2024-02-29

You can format in Markdown, ready for pasting in GitHub issues and PRs:

category percent downloads
3.8 18.37% 16,161,117
3.10 17.47% 15,373,666
3.7 16.70% 14,691,371
3.11 15.49% 13,630,259
3.9 13.19% 11,605,389
3.6 9.68% 8,519,789
null 4.64% 4,085,994
3.12 3.26% 2,871,386
2.7 0.95% 837,638
3.5 0.25% 216,308
3.13 0.00% 2,830
3.4 0.00% 1,237
3.3 0.00% 109
3.1 0.00% 3
3.2 0.00% 2
Total 87,997,098

Date range: 2024-02-01 - 2024-02-29

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:

import pypistats
numpy_array = pypistats.overall("pyvista", total=True, format="numpy")
print(type(numpy_array))
# <class 'numpy.ndarray'>
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:

import pypistats
pandas_dataframe = pypistats.overall("pyvista", total=True, format="pandas")
print(type(pandas_dataframe))
# <class 'pandas.core.frame.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

pypistats's People

Contributors

azure-pipelines[bot] avatar banesullivan avatar cclauss avatar cozydoomer avatar dependabot-preview[bot] avatar dependabot[bot] avatar erayerdin avatar github-actions[bot] avatar hugovk avatar liisberg avatar lnxpy avatar pre-commit-ci[bot] avatar renovate[bot] avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

pypistats's Issues

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.

Dependency Dashboard

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

Ignored or Blocked

These are blocked by an existing closed PR and will not be recreated unless you click a checkbox below.

Detected dependencies

github-actions
.github/workflows/deploy.yml
  • actions/checkout v4
  • hynek/build-and-inspect-python-package v2
  • actions/download-artifact v4
  • actions/download-artifact v4
.github/workflows/labels.yml
  • actions/checkout v4
  • micnncim/action-label-syncer v1
.github/workflows/lint.yml
  • actions/checkout v4
  • actions/setup-python v5
  • pre-commit/action v3.0.1
.github/workflows/release-drafter.yml
  • release-drafter/release-drafter v6
.github/workflows/require-pr-label.yml
  • mheap/github-action-required-labels v5
.github/workflows/test.yml
  • actions/checkout v4
  • actions/setup-python v5
  • codecov/codecov-action v3.1.5
pep621
pyproject.toml
  • httpx >=0.19
  • prettytable >=2.4
  • pytablewriter >=0.63
  • termcolor >=2.1
  • tests/respx >=0.11
pip_requirements
requirements.txt
  • freezegun ==1.5.0
  • httpx ==0.27.0
  • numpy ==1.26.4
  • pandas ==2.2.2
  • platformdirs ==4.2.1
  • prettytable ==3.10.0
  • pytablewriter ==1.2.0
  • pytest ==8.2.0
  • pytest-cov ==5.0.0
  • python-slugify ==8.0.4
  • respx ==0.21.1
  • termcolor ==2.4.0

  • Check this box to trigger a request for Renovate to run again on this repository

Add commas to downloads in table

category downloads
2.6 1968
2.7 1594594
3.1 3
3.2 244
3.3 1824

->

category downloads
2.6 1,968
2.7 1,594,594
3.1 3
3.2 244
3.3 1,824

ValueError: month must be in 1..12

$ pypistats python_minor pylast -m 2018-11
| category | percent | downloads |
|----------|--------:|----------:|
|      2.7 |  48.62% |     2,307 |
|      3.6 |  31.63% |     1,501 |
| null     |   7.31% |       347 |
|      3.7 |   6.91% |       328 |
|      3.5 |   4.85% |       230 |
|      3.4 |   0.59% |        28 |
|      3.3 |   0.08% |         4 |
| Total    |         |     4,745 |

$ pypistats python_minor pylast -m 2018-12
Traceback (most recent call last):
  File "/usr/local/bin/pypistats", line 11, in <module>
    load_entry_point('pypistats', 'console_scripts', 'pypistats')()
  File "/Users/hugo/github/pypistats/pypistats/cli.py", line 266, in main
    args.start_date, args.end_date = _month(args.month)
  File "/Users/hugo/github/pypistats/pypistats/cli.py", line 246, in _month
    last = date(year, month + 1, 1) - relativedelta(days=1)
ValueError: month must be in 1..12

$ pypistats python_minor pylast -m 2017-12
Traceback (most recent call last):
  File "/usr/local/bin/pypistats", line 11, in <module>
    load_entry_point('pypistats', 'console_scripts', 'pypistats')()
  File "/Users/hugo/github/pypistats/pypistats/cli.py", line 266, in main
    args.start_date, args.end_date = _month(args.month)
  File "/Users/hugo/github/pypistats/pypistats/cli.py", line 246, in _month
    last = date(year, month + 1, 1) - relativedelta(days=1)
ValueError: month must be in 1..12

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

Yearly downloads?

I checked the online api. But, I haven't find any endpoint which gives total or total yearly download counts. Is there any option to do that?

Some functional question

When I wrote the code as pypistats overall pandas, is that means the number of downloading pandas from PyPi in the history?

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)

Add --format

Instead of defaulting markdown and providing extra --json argument, you can provide a --format argument default argument of which can be markdown.

# Instead of these
pypistats recent pillow  # default markdown output
pypistats recent pillow --json  # json output

# can be these
pypistats recent pillow  # markdown output
pypistats recent pillow --format markdown  # also markdown output
pypistats recent pillow --format json  # json output
pypistats recent pillow --format rst
pypistats recent pillow --format yaml
pypistats recent pillow --format html

And, as seen above, formats can be extended.

If you want, I can provide a PR to close this issue.

Declare support for Python 3.9

Python 3.9.0 is due out today.

Let's declare support by adding the 3.9 Trove classifier to setup.py.


When doing this, if 3.9.0 is available on Travis CI or GitHub Actions (i.e. 3.9, not 3.9-dev), also update/add 3.9 to .travis.yml or .github/workflows/test.yml,

But please test it actually works by enabling the CI on your fork first.

Codecov failures

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

Possibly same as codecov/codecov-bash#330.

For example: #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.

pytablewriter now has 'optional' dependency on dominate

HTML related test fails on No module named 'dominate' with latest pytablewriter -- pytablewriter==0.41.1.

This doesn't help:

pipenv install pytablewriter[html] --skip-lock

The library author expects dependent libraries to pip install dominate independently

pipenv install dominate --skip-lock

After that, tests pass again.

`rich` format option is not implemented but included!

Since the rich option for --format is not implemented yet, wouldn't it be better if you (permanently) remove the rich item from FORMATS here in a hotfix? It's actually causing KeyError. I looked over pytablewriter and they don't seem to be supporting rich at all. Like they've never even had the rich integration. You can use rich.table.Table though.

Thank you for maintaining this amazing package! :)

Sort table by downloads

category downloads
2.6 1968
2.7 1594594
3.1 3
3.2 244
3.3 1824

->

category downloads
2.7 1,594,594
2.6 1,968
3.3 1,824
3.2 244
3.1 3

`IndexError` while using the arguments with unavailable option values

When using any of the python_major, python_minor, and system positional arguments with an invalid value for their option, it raises IndexError and the exception should be handled properly IMO.

For example, see the following results.

$ pypistats python_minor pillow -V 3.0
...
    first = data[0]["date"]
            ~~~~^^^
IndexError: list index out of range
$
$ pypistats python_major pillow
┌──────────┬─────────┬─────────────┐
│ category │ percent │   downloads │
├──────────┼─────────┼─────────────┤
│ 3        │  93.48% │ 303,004,748 │    ---> v4 is not available
│ null     │   4.90% │  15,894,348 │
│ 2        │   1.62% │   5,247,610 │
│ Total    │         │ 324,146,706 │
└──────────┴─────────┴─────────────┘

Date range: 2023-01-16 - 2023-07-15

$ pypistats python_major pillow -V 4    ---> when we ask for it
...
    first = data[0]["date"]
            ~~~~^^^
IndexError: list index out of range
$
$ pypistats system pillow -o bsd
...
    first = data[0]["date"]
            ~~~~^^^
IndexError: list index out of range
$

Add the ability to retrieve stats as a deserialized/unformatted `dict`

When I use this library, I don't want it to give me a formatted string; I want the actual stats instead. Currently, I achieve this by doing json.loads(pypistats.recent(package, format="json")), but it would be more convenient if pypistats had a built-in way to get the unformatted stats.

Add cron to GitHub Actions

Add to lint.yml and test.yml.

Similar to Travis CI:

image

Related:

  • Lint removed from Travis, still on GHA, so not covered by cron: #103

Repeated minor version

> pypistats python_minor requests
| category | percent |  downloads  |
|----------|--------:|------------:|
|      2.7 |  53.63% | 145,754,775 |
|      3.6 |  23.26% |  63,207,276 |
|      3.7 |  10.27% |  27,918,514 |
|      3.5 |   7.79% |  21,173,697 |
|      3.4 |   3.48% |   9,458,366 |
|      2.6 |   0.80% |   2,170,184 |
| null     |   0.73% |   1,978,215 |
|      3.8 |   0.04% |      97,944 |
|      3.3 |   0.01% |      34,798 |
|      3.2 |   0.00% |       3,278 |
|      3.9 |   0.00% |       2,764 |
|      2.8 |   0.00% |         240 |
|      3.1 |   0.00% |          16 |
|      2.5 |   0.00% |           4 |
|      3.1 |   0.00% |           1 |
| Total    |         | 271,800,072 |

How come is version 3.1 present twice?

Add --json

If you want JSON output rather than a table.

Fix for pytablewriter v0.51.0

https://travis-ci.org/github/hugovk/pypistats/jobs/674106443

https://github.com/thombashi/pytablewriter/releases/tag/v0.51.0

self = <[AttributeError("'Style' object has no attribute '_Style__font_size'") raised in repr()] Style object at 0x7fe9bb8b72e8>
attr_name = 'align', expected_type = <enum 'Align'>
    def __validate_attr(self, attr_name: str, expected_type) -> None:
        value = getattr(self, attr_name)
        if isinstance(expected_type, (list, tuple)):
            expected = " or ".join([c.__name__ for c in expected_type])
        else:
            expected = expected_type.__name__
    
        if not isinstance(value, expected_type):
            raise TypeError(
>               "{} must be a {} instancce: actual={}".format(attr_name, expected, type(value))
            )
E           TypeError: align must be a Align instancce: actual=<class 'NoneType'>
.tox/py37/lib/python3.7/site-packages/pytablewriter/style/_style.py:221: TypeError

dependencies listed multiple times

If a dependency is listed more than once in install_requires or extra_requires (which is perfectly possible), e.g.,

    install_requires=["numpy"],
    extras_require={
        "all": ["netCDF4", "h5py", "lxml"],
        "exodus": ["netCDF4"],
        "hdf5": ["h5py"],
        "xml": ["lxml"],
    },

then it is listed multiple times in the web interface too, where it makes less sense:
m
Perhaps this can be uniqued.

Perhaps optional (extra) dependencies could be listed as such in the web interface, too.

Declare typing support via `py.typed` file

Running mypy on code that uses the latest version of pypistats fails with the error message "module is installed, but missing library stubs or py.typed marker". A quick look at pypistats's source indicates that it is using type annotations, but because there is no py.typed file, mypy will not use the annotations when type-checking code that uses pypistats.

To resolve this, please do the following:

  • If not already, ensure that all public items in pypistats are type-annotated and validated by mypy.
  • Add an empty file named py.typed inside src/pypistats/.
  • Ensure that the pypistats/py.typed file is included in sdists & wheels built from the project. This may involve configuration specific to your build backend (hatch) that is beyond the scope of this comment.

Further references:

UnicodeEncodeError: 'latin-1' codec can't encode characters in position 0-38: ordinal not in range(256)

Hi there,

I wanted to collect some statistics of a package with pypistats but encountered the error.

$ python -m pip install --upgrade pypistats
$ pypistats recent pandas
Traceback (most recent call last):
  File "miniconda3/envs/myenv/bin/pypistats", line 8, in <module>
    sys.exit(main())
  File "miniconda3/envs/myenv/lib/python3.9/site-packages/pypistats/cli.py", line 372, in main
    args.func(args)
  File "miniconda3/envs/myenv/lib/python3.9/site-packages/pypistats/cli.py", line 217, in recent
    print(
UnicodeEncodeError: 'latin-1' codec can't encode characters in position 0-39: ordinal not in range(256)

Is there something I am doing wrong?

"Total" category in the CLI is unnecessary and incorrect

When running pypistats overall <package-name>, the output currently produces markdown that looks like this:

category percent downloads
with_mirrors 85.66% 239
without_mirrors 14.34% 40
Total 279

The "Total" category is unnecessary and shouldn't be there, as without_mirrors is a subset of with_mirrors. Instead, it should show either "Only Mirrors, Without Mirrors, and Total" or just "Without Mirrors and With Mirrors (Total)".

Currently, the total is an incorrect number as with_mirrors is the total.

Allow upload to Test PyPI with setuptools_scm

PR #59 added setuptools_scm to simplify versioning during release.

Non-release master builds are uploaded to Test PyPI.

However, the local version part of the version number (the +xyz bit of 0.6.1.dev4+gdf99fe2) isn't compatible with PyPI.

HTTPError: 400 Client Error: '0.6.1.dev4+gdf99fe2' is an invalid value for Version. Error: Can't use PEP 440 local versions. See https://packaging.python.org/specifications/core-metadata for url: https://test.pypi.org/legacy/

https://travis-ci.org/hugovk/pypistats/builds/543062857

To fix, modify so the local version part is removed. Maybe do it like 0.6.1.dev4.gdf99fe2.

https://pypi.org/project/setuptools-scm/

Getting httpx.ProxyError: 403 Forbidden on PythonAnyWhere

I'm using your package in a module deployed on https://pythonanywhere.com, Once I run the script, it raises me the following exception:

  File "/home/pasteme/.virtualenvs/pasteme.pythonanywhere.com/lib/python3.8/site-packages/httpx/_client.py", line 902, in send                                                        
    response = self._send_handling_auth(                                                                                                                                              
  File "/home/pasteme/.virtualenvs/pasteme.pythonanywhere.com/lib/python3.8/site-packages/httpx/_client.py", line 930, in _send_handling_auth                                         
    response = self._send_handling_redirects(                                                                                                                                         
  File "/home/pasteme/.virtualenvs/pasteme.pythonanywhere.com/lib/python3.8/site-packages/httpx/_client.py", line 967, in _send_handling_redirects                                    
    response = self._send_single_request(request)                                                                                                                                     
  File "/home/pasteme/.virtualenvs/pasteme.pythonanywhere.com/lib/python3.8/site-packages/httpx/_client.py", line 1003, in _send_single_request                                       
    response = transport.handle_request(request)                                                                                                                                      
  File "/home/pasteme/.virtualenvs/pasteme.pythonanywhere.com/lib/python3.8/site-packages/httpx/_transports/default.py", line 218, in handle_request                                  
    resp = self._pool.handle_request(req)                                                                                                                                             
  File "/usr/lib/python3.8/contextlib.py", line 131, in __exit__                                                                                                                      
    self.gen.throw(type, value, traceback)                                                                                                                                            
  File "/home/pasteme/.virtualenvs/pasteme.pythonanywhere.com/lib/python3.8/site-packages/httpx/_transports/default.py", line 77, in map_httpcore_exceptions                          
    raise mapped_exc(message) from exc                                                                                                                                                
httpx.ProxyError: 403 Forbidden

Calling the API endpoint with requests:

>>> r = requests.get('https://pypistats.org/api/packages/pasteme-cli/overall')
Traceback (most recent call last):
  File "/home/pasteme/.virtualenvs/pasteme.pythonanywhere.com/lib/python3.8/site-packages/urllib3/connectionpool.py", line 700, in urlopen
    self._prepare_proxy(conn)
  File "/home/pasteme/.virtualenvs/pasteme.pythonanywhere.com/lib/python3.8/site-packages/urllib3/connectionpool.py", line 996, in _prepare_proxy
    conn.connect()
  File "/home/pasteme/.virtualenvs/pasteme.pythonanywhere.com/lib/python3.8/site-packages/urllib3/connection.py", line 369, in connect
    self._tunnel()
  File "/usr/lib/python3.8/http/client.py", line 904, in _tunnel
    raise OSError("Tunnel connection failed: %d %s" % (code,
OSError: Tunnel connection failed: 403 Forbidden

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/pasteme/.virtualenvs/pasteme.pythonanywhere.com/lib/python3.8/site-packages/requests/adapters.py", line 489, in send
    resp = conn.urlopen(
  File "/home/pasteme/.virtualenvs/pasteme.pythonanywhere.com/lib/python3.8/site-packages/urllib3/connectionpool.py", line 787, in urlopen
    retries = retries.increment(
  File "/home/pasteme/.virtualenvs/pasteme.pythonanywhere.com/lib/python3.8/site-packages/urllib3/util/retry.py", line 592, in increment
    raise MaxRetryError(_pool, url, error or ResponseError(cause))
urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='pypistats.org', port=443): Max retries exceeded with url: /api/packages/pasteme-cli/overall (Caused by ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 403 Forbidden')))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/pasteme/.virtualenvs/pasteme.pythonanywhere.com/lib/python3.8/site-packages/requests/api.py", line 73, in get
    return request("get", url, params=params, **kwargs)
  File "/home/pasteme/.virtualenvs/pasteme.pythonanywhere.com/lib/python3.8/site-packages/requests/api.py", line 59, in request
    return session.request(method=method, url=url, **kwargs)
  File "/home/pasteme/.virtualenvs/pasteme.pythonanywhere.com/lib/python3.8/site-packages/requests/sessions.py", line 587, in request
    resp = self.send(prep, **send_kwargs)
  File "/home/pasteme/.virtualenvs/pasteme.pythonanywhere.com/lib/python3.8/site-packages/requests/sessions.py", line 701, in send
    r = adapter.send(request, **kwargs)
  File "/home/pasteme/.virtualenvs/pasteme.pythonanywhere.com/lib/python3.8/site-packages/requests/adapters.py", line 559, in send
    raise ProxyError(e, request=request)
requests.exceptions.ProxyError: HTTPSConnectionPool(host='pypistats.org', port=443): Max retries exceeded with url: /api/packages/pasteme-cli/overall (Caused by ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 403 Forbidden')))

However, my script works perfectly on my local machine!

Wheel statistics

Would it be possible to display source and wheel statistics separately?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.