github-rest-api 0.49.0__tar.gz → 0.50.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {github_rest_api-0.49.0 → github_rest_api-0.50.0}/.github/workflows/test.yaml +6 -2
- github_rest_api-0.49.0/GEMINI.md → github_rest_api-0.50.0/AGENTS.md +1 -1
- github_rest_api-0.50.0/CLAUDE.md +1 -0
- {github_rest_api-0.49.0 → github_rest_api-0.50.0}/PKG-INFO +2 -2
- {github_rest_api-0.49.0 → github_rest_api-0.50.0}/github_rest_api/github.py +26 -0
- {github_rest_api-0.49.0 → github_rest_api-0.50.0}/github_rest_api/scripts/github/create_github_repo.py +3 -16
- {github_rest_api-0.49.0 → github_rest_api-0.50.0}/github_rest_api/scripts/github/release_on_github.py +16 -12
- github_rest_api-0.50.0/github_rest_api/scripts/github/upload_image_to_issue.py +536 -0
- {github_rest_api-0.49.0 → github_rest_api-0.50.0}/github_rest_api/scripts/utils.py +77 -1
- {github_rest_api-0.49.0 → github_rest_api-0.50.0}/pyproject.toml +7 -2
- {github_rest_api-0.49.0 → github_rest_api-0.50.0}/tests/test_github.py +68 -0
- github_rest_api-0.50.0/tests/test_release_on_github.py +121 -0
- github_rest_api-0.50.0/tests/test_upload_image_to_issue.py +700 -0
- {github_rest_api-0.49.0 → github_rest_api-0.50.0}/tests/test_utils.py +36 -0
- {github_rest_api-0.49.0 → github_rest_api-0.50.0}/uv.lock +2 -2
- github_rest_api-0.49.0/tests/test_release_on_github.py +0 -64
- {github_rest_api-0.49.0 → github_rest_api-0.50.0}/.devcontainer/devcontainer.json +0 -0
- {github_rest_api-0.49.0 → github_rest_api-0.50.0}/.github/workflows/auto_merge_pull_request.yaml +0 -0
- {github_rest_api-0.49.0 → github_rest_api-0.50.0}/.github/workflows/claude-code-review.yml +0 -0
- {github_rest_api-0.49.0 → github_rest_api-0.50.0}/.github/workflows/claude.yml +0 -0
- {github_rest_api-0.49.0 → github_rest_api-0.50.0}/.github/workflows/create_pr_to_main.yaml +0 -0
- {github_rest_api-0.49.0 → github_rest_api-0.50.0}/.github/workflows/lint.yaml +0 -0
- {github_rest_api-0.49.0 → github_rest_api-0.50.0}/.github/workflows/release.yaml +0 -0
- {github_rest_api-0.49.0 → github_rest_api-0.50.0}/.github/workflows/remove_branch.yaml +0 -0
- {github_rest_api-0.49.0 → github_rest_api-0.50.0}/.gitignore +0 -0
- {github_rest_api-0.49.0 → github_rest_api-0.50.0}/README.md +0 -0
- {github_rest_api-0.49.0 → github_rest_api-0.50.0}/github_rest_api/__init__.py +0 -0
- {github_rest_api-0.49.0 → github_rest_api-0.50.0}/github_rest_api/pr_content.py +0 -0
- {github_rest_api-0.49.0 → github_rest_api-0.50.0}/github_rest_api/scripts/__init__.py +0 -0
- {github_rest_api-0.49.0 → github_rest_api-0.50.0}/github_rest_api/scripts/cargo/__init__.py +0 -0
- {github_rest_api-0.49.0 → github_rest_api-0.50.0}/github_rest_api/scripts/cargo/benchmark.py +0 -0
- {github_rest_api-0.49.0 → github_rest_api-0.50.0}/github_rest_api/scripts/cargo/profiling.py +0 -0
- {github_rest_api-0.49.0 → github_rest_api-0.50.0}/github_rest_api/scripts/cargo/utils.py +0 -0
- {github_rest_api-0.49.0 → github_rest_api-0.50.0}/github_rest_api/scripts/container/__init__.py +0 -0
- {github_rest_api-0.49.0 → github_rest_api-0.50.0}/github_rest_api/scripts/container/build_container_images.py +0 -0
- {github_rest_api-0.49.0 → github_rest_api-0.50.0}/github_rest_api/scripts/container/config_container.py +0 -0
- {github_rest_api-0.49.0 → github_rest_api-0.50.0}/github_rest_api/scripts/container/update_version_containerfile.py +0 -0
- {github_rest_api-0.49.0 → github_rest_api-0.50.0}/github_rest_api/scripts/github/__init__.py +0 -0
- {github_rest_api-0.49.0 → github_rest_api-0.50.0}/github_rest_api/scripts/github/auto_merge_pull_request.py +0 -0
- {github_rest_api-0.49.0 → github_rest_api-0.50.0}/github_rest_api/scripts/github/create_pull_request.py +0 -0
- {github_rest_api-0.49.0 → github_rest_api-0.50.0}/github_rest_api/scripts/github/remove_branch.py +0 -0
- {github_rest_api-0.49.0 → github_rest_api-0.50.0}/github_rest_api/scripts/github/workflows/auto_merge_pull_request.yaml +0 -0
- {github_rest_api-0.49.0 → github_rest_api-0.50.0}/github_rest_api/scripts/github/workflows/create_pr_dev_to_main.yaml +0 -0
- {github_rest_api-0.49.0 → github_rest_api-0.50.0}/github_rest_api/scripts/github/workflows/create_pr_to_dev.yaml +0 -0
- {github_rest_api-0.49.0 → github_rest_api-0.50.0}/github_rest_api/scripts/github/workflows/create_pr_to_main.yaml +0 -0
- {github_rest_api-0.49.0 → github_rest_api-0.50.0}/github_rest_api/scripts/github/workflows/python/lint.yaml +0 -0
- {github_rest_api-0.49.0 → github_rest_api-0.50.0}/github_rest_api/scripts/github/workflows/python/test.yaml +0 -0
- {github_rest_api-0.49.0 → github_rest_api-0.50.0}/github_rest_api/scripts/github/workflows/remove_branch.yaml +0 -0
- {github_rest_api-0.49.0 → github_rest_api-0.50.0}/github_rest_api/utils.py +0 -0
- {github_rest_api-0.49.0 → github_rest_api-0.50.0}/memory/MEMORY.md +0 -0
- {github_rest_api-0.49.0 → github_rest_api-0.50.0}/memory/feedback_test_runner.md +0 -0
- {github_rest_api-0.49.0 → github_rest_api-0.50.0}/tests/__init__.py +0 -0
- {github_rest_api-0.49.0 → github_rest_api-0.50.0}/tests/test_auto_merge_pull_request.py +0 -0
- {github_rest_api-0.49.0 → github_rest_api-0.50.0}/tests/test_build_container_images.py +0 -0
- {github_rest_api-0.49.0 → github_rest_api-0.50.0}/tests/test_create_github_repo.py +0 -0
- {github_rest_api-0.49.0 → github_rest_api-0.50.0}/tests/test_create_pull_request.py +0 -0
- {github_rest_api-0.49.0 → github_rest_api-0.50.0}/tests/test_pr_content.py +0 -0
|
@@ -11,8 +11,12 @@ jobs:
|
|
|
11
11
|
os:
|
|
12
12
|
- macOS-latest
|
|
13
13
|
- ubuntu-latest
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
# The oldest supported patch release, spelled out rather than "3.12":
|
|
15
|
+
# a bare "3.12" resolves to the runner's system interpreter, which is
|
|
16
|
+
# below `requires-python` on ubuntu-latest, and uv then fails outright
|
|
17
|
+
# instead of looking for a compatible interpreter to download.
|
|
18
|
+
python-version:
|
|
19
|
+
- "3.12.7"
|
|
16
20
|
- "3.13"
|
|
17
21
|
- "3.14"
|
|
18
22
|
steps:
|
|
@@ -7,7 +7,7 @@ A simple Python wrapper for GitHub REST APIs, optimized for use in GitHub Action
|
|
|
7
7
|
- **Purpose:** Provide a streamlined interface for interacting with GitHub's REST API
|
|
8
8
|
and performing Git operations within automation scripts.
|
|
9
9
|
- **Main Technologies:**
|
|
10
|
-
- **Python 3.12+**: Core language.
|
|
10
|
+
- **Python 3.12.7+**: Core language.
|
|
11
11
|
- **requests**: For HTTP interactions with the GitHub API.
|
|
12
12
|
- **dulwich**: A pure-Python implementation of Git for repository operations.
|
|
13
13
|
- **tenacity**: For retry logic on API requests.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
AGENTS.md
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: github-rest-api
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.50.0
|
|
4
4
|
Summary: Simple wrapper of GitHub REST APIs.
|
|
5
5
|
Author-email: Ben Du <longendu@yahoo.com>
|
|
6
6
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
7
7
|
Classifier: Programming Language :: Python :: 3.12
|
|
8
8
|
Classifier: Programming Language :: Python :: 3.13
|
|
9
9
|
Classifier: Programming Language :: Python :: 3.14
|
|
10
|
-
Requires-Python: <4,>=3.12
|
|
10
|
+
Requires-Python: <4,>=3.12.7
|
|
11
11
|
Requires-Dist: dulwich>=0.25.1
|
|
12
12
|
Requires-Dist: psutil>=5.9.4
|
|
13
13
|
Requires-Dist: pynacl>=1.5
|
|
@@ -1465,6 +1465,32 @@ class Repository(GitHub):
|
|
|
1465
1465
|
json={"body": body},
|
|
1466
1466
|
).json()
|
|
1467
1467
|
|
|
1468
|
+
def create_issue_comment_image(
|
|
1469
|
+
self, issue_number: int, url: str, alt: str = "", body: str = ""
|
|
1470
|
+
) -> dict[str, Any]:
|
|
1471
|
+
"""Add a comment containing an image to an issue.
|
|
1472
|
+
|
|
1473
|
+
GitHub has no public API for the attachment upload that its web UI
|
|
1474
|
+
performs on drag and drop, so the image must already be hosted
|
|
1475
|
+
somewhere reachable; this method only references it.
|
|
1476
|
+
|
|
1477
|
+
:param issue_number: The number of the issue.
|
|
1478
|
+
:param url: The URL of an already uploaded image.
|
|
1479
|
+
:param alt: Alt text of the image.
|
|
1480
|
+
:param body: Optional text placed above the image.
|
|
1481
|
+
"""
|
|
1482
|
+
# A bracket in the alt text would close the markdown label early and
|
|
1483
|
+
# degrade the whole image to literal text, so escape both brackets
|
|
1484
|
+
# (and the escape character itself, which must come first).
|
|
1485
|
+
alt = alt.replace("\\", "\\\\").replace("[", "\\[").replace("]", "\\]")
|
|
1486
|
+
# The URL is wrapped in angle brackets so that spaces and unbalanced
|
|
1487
|
+
# parentheses, which are common in URLs derived from file names, do
|
|
1488
|
+
# not terminate the markdown link early.
|
|
1489
|
+
image = f""
|
|
1490
|
+
return self.create_issue_comment(
|
|
1491
|
+
issue_number, f"{body}\n\n{image}" if body else image
|
|
1492
|
+
)
|
|
1493
|
+
|
|
1468
1494
|
def archive(self) -> requests.Response:
|
|
1469
1495
|
return self._patch(
|
|
1470
1496
|
url=self._url_repo,
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
"""Add a GitHub repository and initialize a local Git repository with workflows."""
|
|
2
2
|
|
|
3
3
|
import argparse
|
|
4
|
-
import getpass
|
|
5
4
|
import logging
|
|
6
|
-
import os
|
|
7
5
|
import shutil
|
|
8
6
|
import sys
|
|
9
7
|
from collections.abc import Sequence
|
|
@@ -13,17 +11,12 @@ from dulwich import porcelain
|
|
|
13
11
|
from dulwich.refs import HEADREF, LOCAL_BRANCH_PREFIX, Ref
|
|
14
12
|
|
|
15
13
|
from github_rest_api import Organization, User
|
|
14
|
+
from github_rest_api.scripts.utils import resolve_github_token, validate_repo
|
|
16
15
|
from github_rest_api.utils import as_str_sequence
|
|
17
16
|
|
|
18
17
|
logger = logging.getLogger(__name__)
|
|
19
18
|
|
|
20
19
|
|
|
21
|
-
def _validate_repo(repo: str) -> None:
|
|
22
|
-
parts = repo.split("/")
|
|
23
|
-
if len(parts) != 2 or not parts[0] or not parts[1]:
|
|
24
|
-
raise ValueError(f"Invalid repo format '{repo}'. Expected 'owner/repo'.")
|
|
25
|
-
|
|
26
|
-
|
|
27
20
|
def _create_remote_repo(
|
|
28
21
|
repo: str, private: bool, token: str, is_owner_user: bool
|
|
29
22
|
) -> None:
|
|
@@ -169,15 +162,9 @@ def create_github_repo(
|
|
|
169
162
|
branches: Sequence[str] = ("main",),
|
|
170
163
|
) -> None:
|
|
171
164
|
branches = as_str_sequence(branches)
|
|
172
|
-
token = token
|
|
173
|
-
if not token:
|
|
174
|
-
token = getpass.getpass("Please enter your GitHub token: ")
|
|
175
|
-
if not token:
|
|
176
|
-
raise ValueError(
|
|
177
|
-
"No GitHub token is provided (via $GITHUB_TOKEN, --token or at prompt)."
|
|
178
|
-
)
|
|
165
|
+
token = resolve_github_token(token)
|
|
179
166
|
repo = repo.strip()
|
|
180
|
-
|
|
167
|
+
validate_repo(repo)
|
|
181
168
|
_create_remote_repo(
|
|
182
169
|
repo=repo, private=private, token=token, is_owner_user=is_owner_user
|
|
183
170
|
)
|
|
@@ -1,19 +1,20 @@
|
|
|
1
|
-
import argparse
|
|
2
|
-
import getpass
|
|
3
|
-
import os
|
|
4
1
|
import re
|
|
5
2
|
import sys
|
|
6
3
|
from pathlib import Path
|
|
7
4
|
|
|
8
5
|
from github_rest_api import Repository
|
|
9
6
|
from github_rest_api.scripts.utils import (
|
|
7
|
+
RedactingArgumentParser,
|
|
10
8
|
find_project_root,
|
|
11
9
|
get_project_version,
|
|
12
10
|
get_repo,
|
|
11
|
+
reject_github_token,
|
|
12
|
+
resolve_github_token,
|
|
13
13
|
)
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
def _get_release_tag(tag: str, root: Path, validate: bool = True) -> str:
|
|
17
|
+
reject_github_token("--tag", tag)
|
|
17
18
|
tag = tag.strip()
|
|
18
19
|
if not tag:
|
|
19
20
|
tag = get_project_version(root).strip()
|
|
@@ -54,7 +55,14 @@ def release_on_github(
|
|
|
54
55
|
:param token: GitHub token.
|
|
55
56
|
If not specified, the GITHUB_TOKEN environment variable is used.
|
|
56
57
|
:param validate: If True, validate the tag against semantic versioning format before creating the release.
|
|
58
|
+
:raises ValueError: If a value that looks like a GitHub token is specified
|
|
59
|
+
for anything other than the token itself.
|
|
57
60
|
"""
|
|
61
|
+
# A release is public, so a token mistyped into any of these would be
|
|
62
|
+
# published. -t is the tag on this script rather than the token, which
|
|
63
|
+
# makes that slip easy; --no-validate would otherwise let it through.
|
|
64
|
+
reject_github_token("--branch", branch)
|
|
65
|
+
reject_github_token("--notes", notes)
|
|
58
66
|
root = find_project_root()
|
|
59
67
|
if not root:
|
|
60
68
|
raise FileNotFoundError("Could not find project root (no .git found).")
|
|
@@ -65,13 +73,7 @@ def release_on_github(
|
|
|
65
73
|
if not repo_name:
|
|
66
74
|
raise ValueError("Could not find GitHub repository name.")
|
|
67
75
|
|
|
68
|
-
token = token
|
|
69
|
-
if not token:
|
|
70
|
-
token = getpass.getpass("Please enter your GitHub token: ")
|
|
71
|
-
if not token:
|
|
72
|
-
raise ValueError(
|
|
73
|
-
"No GitHub token is provided (via $GITHUB_TOKEN, --token or at prompt)."
|
|
74
|
-
)
|
|
76
|
+
token = resolve_github_token(token)
|
|
75
77
|
repo = Repository(token=token, repo=repo_name)
|
|
76
78
|
data = {
|
|
77
79
|
"tag_name": tag,
|
|
@@ -87,7 +89,7 @@ def release_on_github(
|
|
|
87
89
|
|
|
88
90
|
|
|
89
91
|
def parse_args(args=None, namespace=None):
|
|
90
|
-
parser =
|
|
92
|
+
parser = RedactingArgumentParser(
|
|
91
93
|
description="Make a release of the project on GitHub."
|
|
92
94
|
)
|
|
93
95
|
parser.add_argument(
|
|
@@ -97,7 +99,9 @@ def parse_args(args=None, namespace=None):
|
|
|
97
99
|
help="The branch (default to main) from which to make the release.",
|
|
98
100
|
)
|
|
99
101
|
parser.add_argument(
|
|
100
|
-
|
|
102
|
+
# No short option on purpose: -t reads as the token to anyone used to
|
|
103
|
+
# the other scripts, and the tag becomes the public name of the
|
|
104
|
+
# release, so that slip would publish the token.
|
|
101
105
|
"--tag",
|
|
102
106
|
default="",
|
|
103
107
|
help="The tag for the release. If not specified, the version from project configuration is used.",
|