Skip to content

Commit c7396c1

Browse files
committed
Add tox configuration and remove pre_push.py
1 parent f721335 commit c7396c1

File tree

8 files changed

+726
-157
lines changed

8 files changed

+726
-157
lines changed

.github/workflows/ci.yml

+35-8
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,37 @@
1+
concurrency:
2+
group: check-${{ github.ref }}
3+
cancel-in-progress: true
14
jobs:
2-
ci:
3-
name: CI
4-
secrets: inherit
5-
uses: praw-dev/.github/.github/workflows/ci.yml@main
6-
with:
7-
package: prawcore
5+
test:
6+
name: test with ${{ matrix.env }} on ${{ matrix.os }}
7+
runs-on: ${{ matrix.os }}
8+
strategy:
9+
fail-fast: false
10+
matrix:
11+
env:
12+
- "3.9"
13+
- "3.10"
14+
- "3.11"
15+
- "3.12"
16+
- "3.13"
17+
os:
18+
- macos-latest
19+
- ubuntu-latest
20+
- windows-latest
21+
steps:
22+
- uses: actions/checkout@v4
23+
- name: Install the latest version of uv
24+
uses: astral-sh/setup-uv@v5
25+
- name: Install tox
26+
run: uv tool install --python-preference only-managed --python ${{ matrix.env }} tox --with tox-uv
27+
- name: Run test suite
28+
run: |
29+
tox run --skip-pkg-install -e ${{ fromJson('{ "3.9": "py39", "3.10": "py310", "3.11": "py311", "3.12": "py312", "3.13": "py313", }')[matrix.os] }}
30+
env:
31+
TOX_GH_MAJOR_MINOR: ${{ matrix.env }}
832
name: CI
9-
on: [ pull_request, push ]
10-
permissions: read-all
33+
on:
34+
workflow_dispatch:
35+
push:
36+
branches: ["main"]
37+
pull_request:

pre_push.py

-100
This file was deleted.

pyproject.toml

+64-18
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,25 @@
22
build-backend = "flit_core.buildapi"
33
requires = ["flit_core >=3.4,<4"]
44

5+
[dependency-groups]
6+
dev = [
7+
"tox-uv>=1.22.1"
8+
]
9+
lint = [
10+
"pre-commit",
11+
"ruff>=0.9.5"
12+
]
13+
test = [
14+
"betamax >=0.8, <0.9",
15+
"coverage>=7.6.10",
16+
"pytest>=8.3.4",
17+
"urllib3 ==1.*"
18+
]
19+
type = [
20+
"pyright>=1.1.393",
21+
"pytest>=8.3.4"
22+
]
23+
524
[project]
625
authors = [{name = "Bryce Boe", email = "[email protected]"}]
726
classifiers = [
@@ -31,23 +50,6 @@ name = "prawcore"
3150
readme = "README.rst"
3251
requires-python = "~=3.9"
3352

34-
[project.optional-dependencies]
35-
dev = [
36-
"prawcore[lint]",
37-
"prawcore[test]"
38-
]
39-
lint = [
40-
"pre-commit",
41-
"ruff ==0.9.*"
42-
]
43-
test = [
44-
"betamax >=0.8, <0.9",
45-
"pyright",
46-
"pytest ==7.*",
47-
"types-requests",
48-
"urllib3 ==1.*"
49-
]
50-
5153
[project.urls]
5254
"Issue Tracker" = "https://github.com/praw-dev/prawcore/issues"
5355
"Source Code" = "https://github.com/praw-dev/prawcore"
@@ -117,6 +119,50 @@ suppress-dummy-args = true
117119

118120
[tool.ruff.lint.per-file-ignores]
119121
"__init__.py" = ["F401"]
120-
"pre_push.py" = ["T201"]
121122
"examples/*.py" = ["ANN", "PLR2004", "T201"]
122123
"tests/**.py" = ["ANN", "D", "PLR2004", "S101", "S105", "S106", "S301"]
124+
125+
[tool.tox]
126+
envlist = ["py39", "py310", "py311", "py312", "py313", "pre-commit", "style", "type"]
127+
minversion = "4.22"
128+
129+
[tool.tox.env.pre-commit]
130+
commands = [
131+
["pre-commit", "run", "--all-files"]
132+
]
133+
description = "run pre-commit on code base"
134+
dependency_groups = ["lint"]
135+
runner = "uv-venv-lock-runner"
136+
137+
[tool.tox.env.style]
138+
commands = [
139+
["ruff", "check"],
140+
["ruff", "format", "--diff", "--target-version", "py39"]
141+
]
142+
description = "run lint check on code base"
143+
dependency_groups = ["lint"]
144+
runner = "uv-venv-lock-runner"
145+
146+
[tool.tox.env.stylefix]
147+
commands = [
148+
["ruff", "check", "--fix"],
149+
["ruff", "format", "--target-version", "py39"]
150+
]
151+
description = "run lint check on code base"
152+
dependency_groups = ["lint"]
153+
runner = "uv-venv-lock-runner"
154+
155+
[tool.tox.env.type]
156+
commands = [["pyright", "prawcore"]]
157+
dependency_groups = ["type"]
158+
description = "run type check on code base"
159+
runner = "uv-venv-lock-runner"
160+
161+
[tool.tox.env_run_base]
162+
commands = [
163+
["coverage", "run", "-m", "pytest", "{posargs}"],
164+
["coverage", "report", "-m", "--fail-under=100"]
165+
]
166+
description = "Run test under {base_python}"
167+
dependency_groups = ["test"]
168+
runner = "uv-venv-lock-runner"

tests/conftest.py

+4-20
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
import socket
55
import time
66
from base64 import b64encode
7-
from pathlib import Path
87
from sys import platform
98

109
import pytest
@@ -22,17 +21,6 @@ def _sleep(*_, **__):
2221
monkeypatch.setattr(time, "sleep", value=_sleep)
2322

2423

25-
@pytest.fixture
26-
def image_path():
27-
"""Return path to image."""
28-
29-
def _get_path(name):
30-
"""Return path to image."""
31-
return Path(__file__).parent / "integration" / "files" / name
32-
33-
return _get_path
34-
35-
3624
@pytest.fixture
3725
def requestor():
3826
"""Return path to image."""
@@ -65,16 +53,10 @@ def env_default(key):
6553

6654
def pytest_configure(config):
6755
pytest.placeholders = Placeholders(placeholders)
68-
config.addinivalue_line("markers", "add_placeholder: Define an additional placeholder for the cassette.")
6956
config.addinivalue_line("markers", "cassette_name: Name of cassette to use for test.")
7057
config.addinivalue_line("markers", "recorder_kwargs: Arguments to pass to the recorder.")
7158

7259

73-
def two_factor_callback():
74-
"""Return an OTP code."""
75-
return
76-
77-
7860
class Placeholders:
7961
def __init__(self, _dict):
8062
self.__dict__ = _dict
@@ -88,13 +70,15 @@ def __init__(self, _dict):
8870
).split()
8971
}
9072

91-
if placeholders["client_id"] != "fake_client_id" and placeholders["client_secret"] == "fake_client_secret":
73+
if (
74+
placeholders["client_id"] != "fake_client_id" and placeholders["client_secret"] == "fake_client_secret"
75+
): # pragma: no cover
9276
placeholders["basic_auth"] = b64encode(f"{placeholders['client_id']}:".encode()).decode("utf-8")
9377
else:
9478
placeholders["basic_auth"] = b64encode(
9579
f"{placeholders['client_id']}:{placeholders['client_secret']}".encode()
9680
).decode("utf-8")
9781

9882

99-
if platform == "darwin": # Work around issue with betamax on OS X
83+
if platform == "darwin": # Work around issue with betamax on OS X # pragma: no cover
10084
socket.gethostbyname = lambda _: "127.0.0.1"

tests/integration/__init__.py

+1-6
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ class IntegrationTest:
2222
"""Base class for prawcore integration tests."""
2323

2424
@pytest.fixture(autouse=True, scope="session")
25-
def cassette_tracker(self):
25+
def cassette_tracker(self): # pragma: no cover
2626
"""Track cassettes to ensure unused cassettes are not uploaded."""
2727
for cassette in os.listdir(CASSETTES_PATH):
2828
existing_cassettes.add(cassette[: cassette.rindex(".")])
@@ -36,11 +36,6 @@ def cassette_tracker(self):
3636
def cassette(self, request, recorder, cassette_name):
3737
"""Wrap a test in a Betamax cassette."""
3838
kwargs = {}
39-
for marker in request.node.iter_markers("add_placeholder"):
40-
for key, value in marker.kwargs.items():
41-
recorder.config.default_cassette_options["placeholders"].append(
42-
{"placeholder": f"<{key.upper()}>", "replace": value}
43-
)
4439
for marker in request.node.iter_markers("recorder_kwargs"):
4540
for key, value in marker.kwargs.items():
4641
# Don't overwrite existing values since function markers are provided

tests/unit/test_authorizer.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@
88

99

1010
class InvalidAuthenticator(prawcore.auth.BaseAuthenticator):
11-
def _auth(self):
12-
pass
11+
_auth = None
1312

1413

1514
class TestAuthorizer(UnitTest):

tests/utils.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88

99
def ensure_integration_test(cassette):
10-
if cassette.is_recording():
10+
if cassette.is_recording(): # pragma: no cover
1111
is_integration_test = bool(cassette.interactions)
1212
action = "record"
1313
else:
@@ -17,7 +17,7 @@ def ensure_integration_test(cassette):
1717
assert is_integration_test, message
1818

1919

20-
def filter_access_token(interaction, current_cassette):
20+
def filter_access_token(interaction, current_cassette): # pragma: no cover
2121
"""Add Betamax placeholder to filter access token."""
2222
request_uri = interaction.data["request"]["uri"]
2323
response = interaction.data["response"]
@@ -34,7 +34,7 @@ def filter_access_token(interaction, current_cassette):
3434
)
3535

3636

37-
class PrettyJSONSerializer(JSONSerializer):
37+
class PrettyJSONSerializer(JSONSerializer): # pragma: no cover
3838
name = "prettyjson"
3939

4040
def serialize(self, cassette_data):

0 commit comments

Comments
 (0)