Skip to content

Commit 4661b7c

Browse files
authored
Merge pull request #47 from legendu-net/dev
Merge dev into main
2 parents de30eeb + 8456ffe commit 4661b7c

9 files changed

Lines changed: 78 additions & 70 deletions

File tree

.github/pr.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ def main():
5353
# skip branches with the pattern _*
5454
if args.head_branch.startswith("_"):
5555
return
56-
repo = Repository(args.token, "legendu-net", "github_rest_api")
56+
repo = Repository(args.token, "legendu-net/github_rest_api")
5757
repo.create_pull_request(
5858
{
5959
"base": args.base_branch,

github_rest_api/actions/cargo/benchmark.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,20 @@
55
from pathlib import Path
66
import datetime
77
import shutil
8+
import subprocess as sp
9+
from dulwich import porcelain
810
from ..utils import (
911
config_git,
10-
create_branch,
1112
switch_branch,
1213
push_branch,
1314
gen_temp_branch,
1415
commit_benchmarks,
1516
)
16-
from ...utils import run_cmd
1717

1818

1919
def _copy_last_dev_bench(bench_dir: Path) -> None:
2020
branch = gen_temp_branch()
21-
create_branch(branch)
21+
porcelain.checkout(repo=".", new_branch=branch)
2222
switch_branch(branch="gh-pages", fetch=True)
2323
src = bench_dir / "dev/criterion"
2424
tmpdir = tempfile.mkdtemp()
@@ -37,7 +37,11 @@ def _cargo_criterion(bench_dir: Path, env: str = "") -> None:
3737
:param branch: The branch to benchmark.
3838
"""
3939
_copy_last_dev_bench(bench_dir=bench_dir)
40-
run_cmd(f"{env} cargo criterion --all-features --message-format=json")
40+
sp.run(
41+
f"{env} cargo criterion --all-features --message-format=json",
42+
shell=True,
43+
check=True,
44+
)
4145

4246

4347
def _copy_bench_results(bench_dir: Path, storage: str) -> None:
@@ -63,7 +67,7 @@ def _git_push_gh_pages(bench_dir: Path, pr_number: str) -> str:
6367
commit_benchmarks(bench_dir=bench_dir)
6468
timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
6569
branch = f"gh-pages_{pr_number}_{timestamp}"
66-
create_branch(branch=branch)
70+
porcelain.checkout(repo=".", new_branch=branch)
6771
push_branch(branch=branch)
6872
return branch
6973

github_rest_api/actions/cargo/profiling.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import psutil
99
from .utils import build_project
1010
from ..utils import config_git, switch_branch, push_branch, commit_profiling
11-
from ...utils import partition, run_cmd
11+
from ...utils import partition
1212

1313

1414
def launch_application(cmd: list[str]) -> int:
@@ -64,13 +64,13 @@ def nperf(pid: int, prof_name: str, prof_dir: str | Path = ".") -> Path:
6464
yymmdd = time.strftime("%Y%m%d")
6565
prof_dir.mkdir(exist_ok=True, parents=True)
6666
data_file = prof_dir / f"{yymmdd}_{prof_name}"
67-
run_cmd(f"nperf record -p {pid} -o '{data_file}'")
67+
sp.run(f"nperf record -p {pid} -o '{data_file}'", shell=True, check=True)
6868
return _gen_flamegraph(data_file)
6969

7070

7171
def _gen_flamegraph(data_file: Path) -> Path:
7272
flamegraph = data_file.with_name(data_file.name + ".svg")
73-
run_cmd(f"nperf flamegraph '{data_file}' > '{flamegraph}'")
73+
sp.run(f"nperf flamegraph '{data_file}' > '{flamegraph}'", shell=True, check=True)
7474
return flamegraph
7575

7676

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
"""Util functions for building GitHub Actions for Rust projects."""
22

3-
from ...utils import run_cmd
3+
import subprocess as sp
44

55

66
def build_project(profile: str = "release") -> None:
77
"""Build the Rust project.
88
:param profile: The profile for building.
99
"""
10-
run_cmd(f"RUSTFLAGS=-Awarnings cargo build --profile {profile}")
10+
sp.run(
11+
f"RUSTFLAGS=-Awarnings cargo build --profile {profile}", shell=True, check=True
12+
)

github_rest_api/actions/utils.py

Lines changed: 17 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,8 @@
33
from typing import Iterable
44
from pathlib import Path
55
import random
6-
from ..utils import run_cmd
7-
8-
9-
class FailToPushToGitHubException(Exception):
10-
"""Exception for failure to push a branch to GitHub."""
11-
12-
def __init__(self, branch: str, branch_alt: str):
13-
msg = f"Failed to push the branch {branch} to GitHub!"
14-
if branch_alt:
15-
msg += f" Pushed to {branch_alt} instead."
16-
super().__init__(msg)
6+
from dulwich import porcelain
7+
from dulwich.repo import Repo
178

189

1910
def config_git(local_repo_dir: str | Path, user_email: str, user_name: str):
@@ -22,18 +13,9 @@ def config_git(local_repo_dir: str | Path, user_email: str, user_name: str):
2213
:param user_email: The email of the user (no need to be a valid one).
2314
:param user_name: The name of the user.
2415
"""
25-
cmd = f"""git config --global --add safe.directory {local_repo_dir} \
26-
&& git config --global user.email "{user_email}" \
27-
&& git config --global user.name "{user_name}"
28-
"""
29-
run_cmd(cmd)
30-
31-
32-
def create_branch(branch: str) -> None:
33-
"""Create a new local branch.
34-
:param branch: The new local branch to create.
35-
"""
36-
run_cmd(f"git checkout -b {branch}")
16+
config = Repo(local_repo_dir).get_config()
17+
config.set(b"user", b"email", user_email.encode())
18+
config.set(b"user", b"name", user_name.encode())
3719

3820

3921
def switch_branch(branch: str, fetch: bool) -> None:
@@ -42,8 +24,8 @@ def switch_branch(branch: str, fetch: bool) -> None:
4224
:param fetch: If true, fetch the branch from remote first.
4325
"""
4426
if fetch:
45-
run_cmd(f"git fetch origin {branch}")
46-
run_cmd(f"git checkout {branch}")
27+
porcelain.fetch(repo=".")
28+
porcelain.checkout(repo=".", target=branch)
4729

4830

4931
def gen_temp_branch(
@@ -67,26 +49,27 @@ def push_branch(branch: str, branch_alt: str = ""):
6749
:param branch_alt: An alternative branch name to push to GitHub.
6850
"""
6951
try:
70-
run_cmd(f"git push origin {branch}")
52+
porcelain.push(repo=".", refspecs=branch)
7153
except Exception as err:
7254
if branch_alt:
73-
cmd = f"""git checkout {branch} \
74-
&& git checkout -b {branch_alt} \
75-
&& git push origin {branch_alt}
76-
"""
77-
run_cmd(cmd)
78-
raise FailToPushToGitHubException(branch, branch_alt) from err
55+
porcelain.checkout(repo=".", target=branch)
56+
porcelain.checkout(repo=".", new_branch=branch_alt)
57+
porcelain.push(repo=".", refspecs=branch_alt)
58+
else:
59+
raise err
7960

8061

8162
def commit_benchmarks(bench_dir: str | Path):
8263
"""Commit changes in the benchmark directory.
8364
:param bench_dir: The benchmark directory.
8465
"""
85-
run_cmd(f"git add {bench_dir} && git commit -m 'add benchmarks'")
66+
porcelain.add(paths=bench_dir)
67+
porcelain.commit(message="Add benchmarks.")
8668

8769

8870
def commit_profiling(prof_dir: str | Path):
8971
"""Commit changes in the profiling directory.
9072
:param prof_dir: The profiling directory.
9173
"""
92-
run_cmd(f"git add {prof_dir} && git commit -m 'update profiling results'")
74+
porcelain.add(paths=prof_dir)
75+
porcelain.commit(message="Updating profiling results.")

github_rest_api/github.py

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -80,20 +80,18 @@ def put(self, url, raise_for_status: bool = True) -> requests.Response:
8080
class Repository(GitHub):
8181
"""Abstraction of a GitHub repository."""
8282

83-
def __init__(self, token: str, owner: str, repo: str):
83+
def __init__(self, token: str, repo: str):
8484
"""Initialize Repository.
8585
:param token: An authorization token for GitHub REST APIs.
86-
:param owner: The owner of the repository.
87-
:param repo: The name of the repository.
86+
:param repo: A GitHub repository (in the format of owner/repo).
8887
"""
8988
super().__init__(token)
90-
self._owner = owner
9189
self._repo = repo
92-
self._url_pull = f"https://api.github.com/repos/{owner}/{repo}/pulls"
93-
self._url_branches = f"https://api.github.com/repos/{owner}/{repo}/branches"
94-
self._url_refs = f"https://api.github.com/repos/{owner}/{repo}/git/refs"
95-
self._url_issues = f"https://api.github.com/repos/{owner}/{repo}/issues"
96-
self._url_releases = f"https://api.github.com/repos/{owner}/{repo}/releases"
90+
self._url_pull = f"https://api.github.com/repos/{repo}/pulls"
91+
self._url_branches = f"https://api.github.com/repos/{repo}/branches"
92+
self._url_refs = f"https://api.github.com/repos/{repo}/git/refs"
93+
self._url_issues = f"https://api.github.com/repos/{repo}/issues"
94+
self._url_releases = f"https://api.github.com/repos/{repo}/releases"
9795

9896
def get_releases(self) -> list[dict[str, Any]]:
9997
"""List releases in this repository."""
@@ -315,4 +313,4 @@ def get_repositories(
315313
return repos
316314

317315
def instantiate_repository(self, repo: str) -> Repository:
318-
return Repository(token=self._token, owner=self._owner, repo=repo)
316+
return Repository(token=self._token, repo=f"{self._owner}/{repo}")

github_rest_api/utils.py

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
"""Some generally useful util functions."""
22

33
from itertools import tee, filterfalse
4-
import logging
5-
import subprocess as sp
64

75

86
def partition(pred, iterable):
@@ -12,15 +10,3 @@ def partition(pred, iterable):
1210
"""
1311
it1, it2 = tee(iterable)
1412
return filter(pred, it1), filterfalse(pred, it2)
15-
16-
17-
def run_cmd(cmd: list | str, capture_output: bool = False) -> None:
18-
"""Run a shell command.
19-
20-
:param cmd: The command to run.
21-
:param capture_output: Whether to capture stdout and stderr of the command.
22-
"""
23-
proc = sp.run(
24-
cmd, shell=isinstance(cmd, str), check=True, capture_output=capture_output
25-
)
26-
logging.debug(proc.args)

pyproject.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
[project]
22
name = "github_rest_api"
3-
version = "0.26.0"
3+
version = "0.27.0"
44
description = "Simple wrapper of GitHub REST APIs."
55
authors = [{ name = "Ben Du", email = "longendu@yahoo.com" }]
66
requires-python = ">=3.11,<4"
77
readme = "README.md"
88
dependencies = [
99
"requests>=2.28.2",
1010
"psutil>=5.9.4",
11+
"dulwich>=0.25.1",
1112
]
1213

1314
[dependency-groups]

uv.lock

Lines changed: 34 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)