Skip to content

Commit da6dc28

Browse files
authored
Add support for Python 3.13, drop EOL 3.8 (#164)
1 parent 14de8c2 commit da6dc28

8 files changed

Lines changed: 30 additions & 23 deletions

File tree

.github/workflows/test.yml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,20 @@ name: Test
22

33
on: [push, pull_request, workflow_dispatch]
44

5+
permissions:
6+
contents: read
7+
58
env:
69
FORCE_COLOR: 1
10+
PIP_DISABLE_PIP_VERSION_CHECK: 1
711

812
jobs:
913
test:
1014
runs-on: ${{ matrix.os }}
1115
strategy:
1216
fail-fast: false
1317
matrix:
14-
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
18+
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
1519
os: [ubuntu-latest, macOS-latest, windows-latest]
1620

1721
steps:
@@ -22,6 +26,7 @@ jobs:
2226
with:
2327
python-version: ${{ matrix.python-version }}
2428
cache: pip
29+
allow-prereleases: true
2530

2631
- name: Install dependencies
2732
run: |

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,7 @@ Estimated cost: $0.01
321321
Click to unfold installation
322322
</summary>
323323

324-
pypinfo is distributed on **PyPI** as a universal wheel and is available on Linux/macOS and Windows and supports Python 3.7+.
324+
pypinfo is distributed on **PyPI** as a universal wheel and is available on Linux, macOS and Windows.
325325

326326
This is relatively painless, I swear.
327327

pypinfo/cli.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
from decimal import ROUND_UP, Decimal
2-
from typing import List
32

43
import click
54
from binary import TEBIBYTE, convert_units
@@ -102,7 +101,7 @@
102101
def pypinfo(
103102
ctx: click.Context,
104103
project: str,
105-
fields: List[str],
104+
fields: list[str],
106105
auth: str,
107106
run: bool,
108107
json: bool,

pypinfo/core.py

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
import json
33
import os
44
from datetime import date, datetime
5-
from typing import Any, Dict, Iterable, List, Optional, Tuple
5+
from typing import Any, Optional
6+
from collections.abc import Iterable
67

78
from google.cloud.bigquery import Client
89
from google.cloud.bigquery.job import QueryJobConfig
@@ -22,7 +23,7 @@
2223
END_DATE = '-1'
2324
DEFAULT_LIMIT = 10
2425

25-
Rows = List[List[str]]
26+
Rows = list[list[str]]
2627

2728

2829
def create_config() -> QueryJobConfig:
@@ -31,7 +32,7 @@ def create_config() -> QueryJobConfig:
3132
return config
3233

3334

34-
def normalize_dates(start_date: str, end_date: str) -> Tuple[str, str]:
35+
def normalize_dates(start_date: str, end_date: str) -> tuple[str, str]:
3536
"""If a date is yyyy-mm, normalize as first or last yyyy-mm-dd of the month.
3637
Otherwise, return unchanged.
3738
"""
@@ -85,7 +86,7 @@ def format_date(date: str, timestamp_format: str) -> str:
8586
return date
8687

8788

88-
def month_ends(yyyy_mm: str) -> Tuple[str, str]:
89+
def month_ends(yyyy_mm: str) -> tuple[str, str]:
8990
"""Helper to return start_date and end_date of a month as yyyy-mm-dd"""
9091
year, month = map(int, yyyy_mm.split("-"))
9192
first = date(year, month, 1)
@@ -94,7 +95,7 @@ def month_ends(yyyy_mm: str) -> Tuple[str, str]:
9495
return str(first), str(last)
9596

9697

97-
def strip_trailing_zero(release: Tuple[int, ...]) -> Tuple[int, ...]:
98+
def strip_trailing_zero(release: tuple[int, ...]) -> tuple[int, ...]:
9899
"""Helper to strip trailing 0 in a tuple of integers"""
99100
new_len = len(release)
100101
while new_len > 1 and release[new_len - 1] == 0:
@@ -271,7 +272,7 @@ def add_percentages(rows: Rows, include_sign: bool = True) -> Rows:
271272
return rows
272273

273274

274-
def get_download_total(rows: Rows) -> Tuple[int, int]:
275+
def get_download_total(rows: Rows) -> tuple[int, int]:
275276
"""Return the total downloads, and the downloads column"""
276277
headers = rows.pop(0)
277278
index = headers.index('download_count')
@@ -341,13 +342,13 @@ def tabulate(rows: Rows, markdown: bool = False) -> str:
341342
return tabulated
342343

343344

344-
def format_json(rows: Rows, query_info: Dict[str, Any], indent: Optional[int]) -> str:
345+
def format_json(rows: Rows, query_info: dict[str, Any], indent: Optional[int]) -> str:
345346
headers, *_data = rows
346-
data: List[Any] = _data
347-
items: List[Dict[str, Any]] = []
347+
data: list[Any] = _data
348+
items: list[dict[str, Any]] = []
348349

349350
for d in data:
350-
item: Dict[str, Any] = {}
351+
item: dict[str, Any] = {}
351352
for i in range(len(headers)):
352353
if d[i].isdigit():
353354
d[i] = int(d[i])

pypinfo/db.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import contextlib
22
import os
3-
from typing import Iterator, Optional
3+
from typing import Optional
4+
from collections.abc import Iterator
45

56
from platformdirs import user_data_dir
67
from tinydb import TinyDB, Query, where

pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ name = "pypinfo"
77
description = "View PyPI download statistics with ease."
88
readme = "README.md"
99
license = "MIT"
10-
requires-python = ">=3.8"
10+
requires-python = ">=3.9"
1111
keywords = [
1212
"bigquery",
1313
"downloads",
@@ -27,11 +27,11 @@ classifiers = [
2727
"Programming Language :: Python",
2828
"Programming Language :: Python :: 3",
2929
"Programming Language :: Python :: 3 :: Only",
30-
"Programming Language :: Python :: 3.8",
3130
"Programming Language :: Python :: 3.9",
3231
"Programming Language :: Python :: 3.10",
3332
"Programming Language :: Python :: 3.11",
3433
"Programming Language :: Python :: 3.12",
34+
"Programming Language :: Python :: 3.13",
3535
"Programming Language :: Python :: Implementation :: CPython",
3636
"Programming Language :: Python :: Implementation :: PyPy",
3737
]

tests/test_core.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from freezegun import freeze_time
2-
from typing import Any, Iterator, List, Tuple
2+
from typing import Any
3+
from collections.abc import Iterator
34
import copy
45
import pytest
56
import re
@@ -172,7 +173,7 @@ def test_build_query() -> None:
172173
def test_build_query_specifier() -> None:
173174
# pypinfo -sd -2 -ed -1 -l 20 --test 'foo==1'
174175
project = "foo==1"
175-
all_fields: List[Field] = []
176+
all_fields: list[Field] = []
176177
start_date = "-2"
177178
end_date = "-1"
178179
days = None
@@ -273,7 +274,7 @@ def test_build_query_where() -> None:
273274
def test_build_query_no_project() -> None:
274275
# pypinfo -sd -2 -ed -1 -l 20 --all --test ''
275276
project = ""
276-
all_fields: List[Field] = []
277+
all_fields: list[Field] = []
277278
start_date = "-2"
278279
end_date = "-1"
279280
days = None
@@ -508,7 +509,7 @@ def test_format_json() -> None:
508509

509510

510511
def test_parse_query_result() -> None:
511-
data: List[Tuple[Any, ...]] = [
512+
data: list[tuple[Any, ...]] = [
512513
("name", "other"),
513514
("name1", 1),
514515
("name2", 2),
@@ -523,7 +524,7 @@ class MockRowIterator(RowIterator): # type: ignore[misc]
523524
def __init__(self) -> None:
524525
super().__init__(None, None, None, schema)
525526

526-
def __iter__(self) -> Iterator[Tuple[Any, ...]]:
527+
def __iter__(self) -> Iterator[tuple[Any, ...]]:
527528
return iter(data[1:])
528529

529530
actual = core.parse_query_result(MockRowIterator())

tox.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
[tox]
22
minversion = 1.9
33
envlist =
4-
py38,
54
py39,
65
py310,
76
py311,
87
py312,
8+
py313,
99

1010
[testenv]
1111
usedevelop = true

0 commit comments

Comments
 (0)