Skip to content

Commit f5737d4

Browse files
authored
Merge pull request #300 from PyO3/xtask
Add xtask Python script to automate recurring development tasks.
2 parents 89c8c74 + 585f389 commit f5737d4

File tree

2 files changed

+139
-3
lines changed

2 files changed

+139
-3
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,7 @@ jobs:
2424
default: true
2525
- uses: Swatinem/rust-cache@v1
2626
continue-on-error: true
27-
- run: |
28-
cargo fmt --all -- --check
29-
cargo clippy --workspace --tests -- --deny warnings
27+
- run: ./x.py check
3028

3129
test:
3230
name: python${{ matrix.python-version }}-${{ matrix.platform.python-architecture }} ${{ matrix.platform.os }}

x.py

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
#!/usr/bin/env python3
2+
3+
import argparse
4+
import os
5+
import subprocess
6+
import sys
7+
from pathlib import Path
8+
9+
10+
def run(*args):
11+
subprocess.run([*args], check=True)
12+
13+
14+
def can_run(*args):
15+
try:
16+
subprocess.run([*args], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
17+
return True
18+
except OSError:
19+
return False
20+
21+
22+
def nightly():
23+
proc = subprocess.run(["rustc", "--version"], capture_output=True)
24+
return b"-nightly " in proc.stdout
25+
26+
27+
def default(args):
28+
run("cargo", "fmt")
29+
30+
if nightly():
31+
run("cargo", "clippy", "--workspace", "--tests", "--benches")
32+
else:
33+
run("cargo", "clippy", "--workspace", "--tests")
34+
35+
run("cargo", "test", "--lib", "--tests")
36+
37+
38+
def check(args):
39+
run("cargo", "fmt", "--", "--check")
40+
41+
run("cargo", "clippy", "--workspace", "--tests", "--", "--deny", "warnings")
42+
43+
44+
def doc(args):
45+
run("cargo", "doc")
46+
47+
if args.name is None:
48+
run("cargo", "test", "--doc")
49+
else:
50+
run("cargo", "test", "--doc", args.name)
51+
52+
53+
def test(args):
54+
if args.name is None:
55+
run("cargo", "test", "--tests")
56+
else:
57+
run("cargo", "test", "--test", args.name)
58+
59+
60+
def bench(args):
61+
if not nightly():
62+
sys.exit("Benchmarks require a nightly build of the Rust compiler.")
63+
64+
if args.name is None:
65+
run("cargo", "bench", "--benches")
66+
else:
67+
run("cargo", "bench", "--bench", args.name)
68+
69+
70+
def examples(args):
71+
if not can_run("nox", "--version"):
72+
sys.exit("Examples require the Nox tool (https://nox.thea.codes)")
73+
74+
if args.name is None:
75+
dirs = [
76+
dir_.name
77+
for dir_ in Path("examples").iterdir()
78+
if (dir_ / "noxfile.py").exists()
79+
]
80+
else:
81+
dirs = [args.name]
82+
83+
for dir in dirs:
84+
run("nox", "--noxfile", f"examples/{dir}/noxfile.py")
85+
86+
87+
def format_(args):
88+
if not can_run("black", "--version"):
89+
sys.exit(
90+
"Formatting requires the Black formatter (https://github.com/psf/black)"
91+
)
92+
93+
run("cargo", "fmt")
94+
run("black", ".")
95+
96+
97+
if __name__ == "__main__":
98+
parser = argparse.ArgumentParser()
99+
subparsers = parser.add_subparsers(
100+
help="Default action is Rustfmt, Clippy and tests"
101+
)
102+
parser.set_defaults(func=default)
103+
104+
check_parser = subparsers.add_parser(
105+
"check", aliases=["c"], help="Rustfmt and Clippy (as in the CI)"
106+
)
107+
check_parser.set_defaults(func=check)
108+
109+
doc_parser = subparsers.add_parser(
110+
"doc", aliases=["d"], help="Rustdoc and doctests"
111+
)
112+
doc_parser.set_defaults(func=doc)
113+
doc_parser.add_argument("name", nargs="?", help="Test case name")
114+
115+
test_parser = subparsers.add_parser("test", aliases=["t"], help="Integration tests")
116+
test_parser.set_defaults(func=test)
117+
test_parser.add_argument("name", nargs="?", help="Test target name")
118+
119+
bench_parser = subparsers.add_parser(
120+
"bench", aliases=["b"], help="Benchmarks (requires nightly)"
121+
)
122+
bench_parser.set_defaults(func=bench)
123+
bench_parser.add_argument("name", nargs="?", help="Benchmark target name")
124+
125+
examples_parser = subparsers.add_parser(
126+
"examples", aliases=["e"], help="Examples (requires Nox)"
127+
)
128+
examples_parser.set_defaults(func=examples)
129+
examples_parser.add_argument("name", nargs="?", help="Example directory name")
130+
131+
format_parser = subparsers.add_parser(
132+
"format", aliases=["f"], help="Format Rust and Python code (requires Black)"
133+
)
134+
format_parser.set_defaults(func=format_)
135+
136+
args = parser.parse_args()
137+
os.chdir(Path(__file__).parent)
138+
args.func(args)

0 commit comments

Comments
 (0)