github-rest-api 0.39.1__tar.gz → 0.40.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.
Files changed (46) hide show
  1. github_rest_api-0.40.0/.devcontainer/devcontainer.json +30 -0
  2. {github_rest_api-0.39.1 → github_rest_api-0.40.0}/PKG-INFO +1 -1
  3. {github_rest_api-0.39.1 → github_rest_api-0.40.0}/github_rest_api/scripts/github/add_github_repo.py +87 -64
  4. {github_rest_api-0.39.1 → github_rest_api-0.40.0}/github_rest_api/scripts/github/create_pull_request.py +30 -3
  5. {github_rest_api-0.39.1 → github_rest_api-0.40.0}/github_rest_api/utils.py +23 -0
  6. {github_rest_api-0.39.1 → github_rest_api-0.40.0}/pyproject.toml +1 -1
  7. {github_rest_api-0.39.1 → github_rest_api-0.40.0}/uv.lock +1 -1
  8. github_rest_api-0.39.1/.gemini/system.md +0 -10
  9. github_rest_api-0.39.1/.gitpod.yml +0 -9
  10. {github_rest_api-0.39.1 → github_rest_api-0.40.0}/.claude/settings.json +0 -0
  11. /github_rest_api-0.39.1/.github/workflows/create_pr_to_main.yml → /github_rest_api-0.40.0/.github/workflows/create_pr_to_main.yaml +0 -0
  12. /github_rest_api-0.39.1/.github/workflows/lint.yml → /github_rest_api-0.40.0/.github/workflows/lint.yaml +0 -0
  13. /github_rest_api-0.39.1/.github/workflows/release.yml → /github_rest_api-0.40.0/.github/workflows/release.yaml +0 -0
  14. /github_rest_api-0.39.1/.github/workflows/remove_branch.yml → /github_rest_api-0.40.0/.github/workflows/remove_branch.yaml +0 -0
  15. /github_rest_api-0.39.1/.github/workflows/test.yml → /github_rest_api-0.40.0/.github/workflows/test.yaml +0 -0
  16. {github_rest_api-0.39.1 → github_rest_api-0.40.0}/.gitignore +0 -0
  17. {github_rest_api-0.39.1 → github_rest_api-0.40.0}/GEMINI.md +0 -0
  18. {github_rest_api-0.39.1 → github_rest_api-0.40.0}/README.md +0 -0
  19. {github_rest_api-0.39.1 → github_rest_api-0.40.0}/github_rest_api/__init__.py +0 -0
  20. {github_rest_api-0.39.1 → github_rest_api-0.40.0}/github_rest_api/github.py +0 -0
  21. {github_rest_api-0.39.1 → github_rest_api-0.40.0}/github_rest_api/scripts/__init__.py +0 -0
  22. {github_rest_api-0.39.1 → github_rest_api-0.40.0}/github_rest_api/scripts/cargo/__init__.py +0 -0
  23. {github_rest_api-0.39.1 → github_rest_api-0.40.0}/github_rest_api/scripts/cargo/benchmark.py +0 -0
  24. {github_rest_api-0.39.1 → github_rest_api-0.40.0}/github_rest_api/scripts/cargo/profiling.py +0 -0
  25. {github_rest_api-0.39.1 → github_rest_api-0.40.0}/github_rest_api/scripts/cargo/utils.py +0 -0
  26. {github_rest_api-0.39.1 → github_rest_api-0.40.0}/github_rest_api/scripts/container/__init__.py +0 -0
  27. {github_rest_api-0.39.1 → github_rest_api-0.40.0}/github_rest_api/scripts/container/build_container_images.py +0 -0
  28. {github_rest_api-0.39.1 → github_rest_api-0.40.0}/github_rest_api/scripts/container/config_container.py +0 -0
  29. {github_rest_api-0.39.1 → github_rest_api-0.40.0}/github_rest_api/scripts/container/update_version_containerfile.py +0 -0
  30. {github_rest_api-0.39.1 → github_rest_api-0.40.0}/github_rest_api/scripts/github/__init__.py +0 -0
  31. {github_rest_api-0.39.1 → github_rest_api-0.40.0}/github_rest_api/scripts/github/release_on_github.py +0 -0
  32. {github_rest_api-0.39.1 → github_rest_api-0.40.0}/github_rest_api/scripts/github/remove_branch.py +0 -0
  33. /github_rest_api-0.39.1/github_rest_api/scripts/github/workflows/create_pr_dev_to_main.yml → /github_rest_api-0.40.0/github_rest_api/scripts/github/workflows/create_pr_dev_to_main.yaml +0 -0
  34. /github_rest_api-0.39.1/github_rest_api/scripts/github/workflows/create_pr_to_dev.yml → /github_rest_api-0.40.0/github_rest_api/scripts/github/workflows/create_pr_to_dev.yaml +0 -0
  35. /github_rest_api-0.39.1/github_rest_api/scripts/github/workflows/create_pr_to_main.yml → /github_rest_api-0.40.0/github_rest_api/scripts/github/workflows/create_pr_to_main.yaml +0 -0
  36. /github_rest_api-0.39.1/github_rest_api/scripts/github/workflows/python/lint.yml → /github_rest_api-0.40.0/github_rest_api/scripts/github/workflows/python/lint.yaml +0 -0
  37. /github_rest_api-0.39.1/github_rest_api/scripts/github/workflows/python/test.yml → /github_rest_api-0.40.0/github_rest_api/scripts/github/workflows/python/test.yaml +0 -0
  38. /github_rest_api-0.39.1/github_rest_api/scripts/github/workflows/remove_branch.yml → /github_rest_api-0.40.0/github_rest_api/scripts/github/workflows/remove_branch.yaml +0 -0
  39. {github_rest_api-0.39.1 → github_rest_api-0.40.0}/github_rest_api/scripts/utils.py +0 -0
  40. {github_rest_api-0.39.1 → github_rest_api-0.40.0}/memory/MEMORY.md +0 -0
  41. {github_rest_api-0.39.1 → github_rest_api-0.40.0}/memory/feedback_test_runner.md +0 -0
  42. {github_rest_api-0.39.1 → github_rest_api-0.40.0}/tests/__init__.py +0 -0
  43. {github_rest_api-0.39.1 → github_rest_api-0.40.0}/tests/test_build_container_images.py +0 -0
  44. {github_rest_api-0.39.1 → github_rest_api-0.40.0}/tests/test_github.py +0 -0
  45. {github_rest_api-0.39.1 → github_rest_api-0.40.0}/tests/test_release_on_github.py +0 -0
  46. {github_rest_api-0.39.1 → github_rest_api-0.40.0}/tests/test_utils.py +0 -0
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "Fedora Codespace",
3
+ "image": "quay.io/legendu/codespaces:next",
4
+ "remoteUser": "vscode",
5
+ "customizations": {
6
+ "vscode": {
7
+ "settings": {
8
+ "terminal.integrated.defaultProfile.linux": "fish"
9
+ },
10
+ "extensions": [
11
+ "Google.geminicodeassist",
12
+ "anthropic.claude-code",
13
+ "asvetliakov.vscode-neovim",
14
+ "mechatroner.rainbow-csv",
15
+ "usernamehw.errorlens",
16
+ "ms-python.python",
17
+ "charliermarsh.ruff",
18
+ "astral-sh.ty",
19
+ "golang.Go",
20
+ "njpwerner.autodocstring",
21
+ "rust-lang.rust-analyzer",
22
+ "fill-labs.dependi",
23
+ "vadimcn.vscode-lldb",
24
+ "fwcd.kotlin",
25
+ "karsten7.mojo-vscode",
26
+ "ReneSaarsoo.sql-formatter-vsc"
27
+ ]
28
+ }
29
+ }
30
+ }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: github-rest-api
3
- Version: 0.39.1
3
+ Version: 0.40.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
@@ -12,68 +12,6 @@ from dulwich import porcelain
12
12
  from github_rest_api import User, Organization
13
13
 
14
14
 
15
- def parse_args(args=None, namespace=None):
16
- parser = argparse.ArgumentParser(description="Add a GitHub repository.")
17
- parser.add_argument(
18
- "repo",
19
- help="The GitHub repo (in the format of owner/repo) to be created.",
20
- )
21
- group = parser.add_mutually_exclusive_group(required=True)
22
- group.add_argument(
23
- "-u",
24
- "--user",
25
- dest="is_owner_user",
26
- action="store_true",
27
- help="The owner of the repo is a user.",
28
- )
29
- group.add_argument(
30
- "-o",
31
- "--org",
32
- "--organization",
33
- dest="is_owner_user",
34
- action="store_false",
35
- help="The owner of the repo is an organization.",
36
- )
37
- parser.add_argument(
38
- "-t",
39
- "--token",
40
- dest="token",
41
- default="",
42
- help="The GitHub token to use.",
43
- )
44
- parser.add_argument(
45
- "-p",
46
- "--public",
47
- dest="private",
48
- action="store_false",
49
- help="Whether to create the repository as public.",
50
- )
51
- parser.add_argument(
52
- "-l",
53
- "--lang",
54
- "--language",
55
- dest="language",
56
- default="",
57
- help="The language of the GitHub repository.",
58
- )
59
- parser.add_argument(
60
- "-d",
61
- "--dir",
62
- dest="dir",
63
- default="",
64
- help="The directory (default to './repo') of the local Git repository.",
65
- )
66
- parser.add_argument(
67
- "--branches",
68
- dest="branches",
69
- nargs="+",
70
- default=["main"],
71
- metavar="BRANCH",
72
- help="Branches to create and push to remote (default: main).",
73
- )
74
- return parser.parse_args(args=args, namespace=namespace)
75
-
76
-
77
15
  def _validate_repo(repo: str) -> None:
78
16
  parts = repo.split("/")
79
17
  if len(parts) != 2 or not parts[0] or not parts[1]:
@@ -93,8 +31,19 @@ def _create_remote_repo(
93
31
  print(f"\nCreated the GitHub repo https://github.com/{repo}.\n")
94
32
 
95
33
 
34
+ def _remote_url(repo: str, protocol: str) -> str:
35
+ if protocol == "git":
36
+ return f"git@github.com:{repo}.git"
37
+ return f"https://github.com/{repo}.git"
38
+
39
+
96
40
  def _init_local_repo(
97
- repo: str, language: str, dir_: str, token: str, branches: Sequence[str]
41
+ repo: str,
42
+ language: str,
43
+ dir_: str,
44
+ token: str,
45
+ protocol: str,
46
+ branches: Sequence[str] = ("main",),
98
47
  ) -> None:
99
48
  repo_name = repo.split("/")[-1]
100
49
  path = Path(dir_) if dir_ else Path(repo_name)
@@ -104,6 +53,7 @@ def _init_local_repo(
104
53
  readme.write_text(f"# {repo_name}\n")
105
54
  if not (path / ".git").exists():
106
55
  porcelain.init(path=path)
56
+ porcelain.remote_add(path, "origin", _remote_url(repo, protocol))
107
57
  initial_branch = (
108
58
  (path / ".git" / "HEAD").read_text().strip().partition("refs/heads/")[-1]
109
59
  )
@@ -116,7 +66,7 @@ def _init_local_repo(
116
66
  porcelain.checkout(repo=path, target=branch)
117
67
  porcelain.push(
118
68
  repo=path,
119
- remote_location=f"https://github.com/{repo}.git",
69
+ remote_location=_remote_url(repo, "https"),
120
70
  username="x-access-token",
121
71
  password=token,
122
72
  )
@@ -136,6 +86,7 @@ def add_github_repo(
136
86
  is_owner_user: bool,
137
87
  dir_: str,
138
88
  token: str,
89
+ protocol: str,
139
90
  branches: Sequence[str] = ("main",),
140
91
  ) -> None:
141
92
  token = token or os.getenv("GITHUB_TOKEN", "")
@@ -156,6 +107,7 @@ def add_github_repo(
156
107
  dir_=dir_,
157
108
  token=token,
158
109
  branches=branches,
110
+ protocol=protocol,
159
111
  )
160
112
 
161
113
 
@@ -177,6 +129,76 @@ def _add_workflow(path: Path, language: str, workflow_dir: Path | None = None) -
177
129
  shutil.copy2(yaml, dir_dest)
178
130
 
179
131
 
132
+ def parse_args(args=None, namespace=None):
133
+ parser = argparse.ArgumentParser(description="Add a GitHub repository.")
134
+ parser.add_argument(
135
+ "repo",
136
+ help="The GitHub repo (in the format of owner/repo) to be created.",
137
+ )
138
+ group = parser.add_mutually_exclusive_group(required=True)
139
+ group.add_argument(
140
+ "-u",
141
+ "--user",
142
+ dest="is_owner_user",
143
+ action="store_true",
144
+ help="The owner of the repo is a user.",
145
+ )
146
+ group.add_argument(
147
+ "-o",
148
+ "--org",
149
+ "--organization",
150
+ dest="is_owner_user",
151
+ action="store_false",
152
+ help="The owner of the repo is an organization.",
153
+ )
154
+ parser.add_argument(
155
+ "-t",
156
+ "--token",
157
+ dest="token",
158
+ default="",
159
+ help="The GitHub token to use.",
160
+ )
161
+ parser.add_argument(
162
+ "-p",
163
+ "--public",
164
+ dest="private",
165
+ action="store_false",
166
+ help="Whether to create the repository as public.",
167
+ )
168
+ parser.add_argument(
169
+ "-l",
170
+ "--lang",
171
+ "--language",
172
+ dest="language",
173
+ default="",
174
+ help="The language of the GitHub repository.",
175
+ )
176
+ parser.add_argument(
177
+ "-d",
178
+ "--dir",
179
+ dest="dir",
180
+ default="",
181
+ help="The directory (default to './repo') of the local Git repository.",
182
+ )
183
+ parser.add_argument(
184
+ "--branches",
185
+ dest="branches",
186
+ nargs="+",
187
+ default=["main"],
188
+ metavar="BRANCH",
189
+ help="Branches to create and push to remote (default: main).",
190
+ )
191
+ parser.add_argument(
192
+ "--https",
193
+ dest="protocol",
194
+ action="store_const",
195
+ const="https",
196
+ default="git",
197
+ help="Use the HTTPS protocol for the remote URL.",
198
+ )
199
+ return parser.parse_args(args=args, namespace=namespace)
200
+
201
+
180
202
  def main() -> int:
181
203
  args = parse_args()
182
204
  try:
@@ -188,6 +210,7 @@ def main() -> int:
188
210
  dir_=args.dir,
189
211
  token=args.token,
190
212
  branches=args.branches,
213
+ protocol=args.protocol,
191
214
  )
192
215
  except Exception as e:
193
216
  print(str(e), file=sys.stderr)
@@ -6,6 +6,7 @@ from argparse import ArgumentParser, Namespace
6
6
  import os
7
7
  import sys
8
8
  from github_rest_api import Repository
9
+ from github_rest_api.utils import compile_patterns
9
10
 
10
11
 
11
12
  def parse_args(args=None, namespace=None) -> Namespace:
@@ -34,6 +35,19 @@ def parse_args(args=None, namespace=None) -> Namespace:
34
35
  required=True,
35
36
  help="The base branch to merge changes into.",
36
37
  )
38
+ parser.add_argument(
39
+ "--ignore-patterns",
40
+ dest="ignore_patterns",
41
+ nargs="*",
42
+ default=["^_"],
43
+ help="A list of regular expression patterns. Branches matching any of these patterns will be ignored.",
44
+ )
45
+ parser.add_argument(
46
+ "--update",
47
+ dest="update",
48
+ action="store_true",
49
+ help="Update the head branch using the base branch before creating the pull request.",
50
+ )
37
51
  return parser.parse_args(args=args, namespace=namespace)
38
52
 
39
53
 
@@ -43,10 +57,23 @@ def main() -> int:
43
57
  The branch is updated (using dev) before creating the PR.
44
58
  """
45
59
  args = parse_args()
46
- # skip branches with the pattern _*
47
- if args.head_branch.startswith("_"):
48
- return 0
60
+ # skip branches matching any of the ignore patterns
61
+ try:
62
+ compiled = compile_patterns(args.ignore_patterns)
63
+ except ValueError as e:
64
+ print(e, file=sys.stderr)
65
+ return 1
66
+ for pattern in compiled:
67
+ if pattern.search(args.head_branch):
68
+ print(
69
+ f"Branch '{args.head_branch}' matches ignore pattern '{
70
+ pattern.pattern
71
+ }', skipping."
72
+ )
73
+ return 0
49
74
  repo = Repository(args.token, os.environ["GITHUB_REPOSITORY"])
75
+ if args.update:
76
+ repo.update_branch(update=args.head_branch, upstream=args.base_branch)
50
77
  repo.create_pull_request(
51
78
  {
52
79
  "base": args.base_branch,
@@ -1,6 +1,8 @@
1
1
  """Some generally useful util functions."""
2
2
 
3
+ from collections.abc import Sequence
3
4
  from itertools import tee, filterfalse
5
+ import re
4
6
 
5
7
 
6
8
  def partition(pred, iterable):
@@ -12,6 +14,27 @@ def partition(pred, iterable):
12
14
  return filter(pred, it1), filterfalse(pred, it2)
13
15
 
14
16
 
17
+ def compile_patterns(patterns: str | Sequence[str] | None) -> list[re.Pattern[str]]:
18
+ """Compile a list of regular expression patterns.
19
+
20
+ :param patterns: A list of regular expression patterns to compile.
21
+ :return: A list of compiled regular expression patterns.
22
+ """
23
+ if not patterns:
24
+ return []
25
+ if isinstance(patterns, str):
26
+ patterns = [patterns]
27
+ compiled = []
28
+ for pattern in patterns:
29
+ try:
30
+ compiled.append(re.compile(pattern))
31
+ except re.error as e:
32
+ raise ValueError(
33
+ f"Invalid regular expression pattern '{pattern}': {e}"
34
+ ) from e
35
+ return compiled
36
+
37
+
15
38
  def strip_patch_version(version: str) -> str:
16
39
  """Strip the patch version.
17
40
 
@@ -4,7 +4,7 @@ requires = [ "hatchling" ]
4
4
 
5
5
  [project]
6
6
  name = "github-rest-api"
7
- version = "0.39.1"
7
+ version = "0.40.0"
8
8
  description = "Simple wrapper of GitHub REST APIs."
9
9
  readme = "README.md"
10
10
  authors = [ { name = "Ben Du", email = "longendu@yahoo.com" } ]
@@ -166,7 +166,7 @@ wheels = [
166
166
 
167
167
  [[package]]
168
168
  name = "github-rest-api"
169
- version = "0.39.1"
169
+ version = "0.40.0"
170
170
  source = { editable = "." }
171
171
  dependencies = [
172
172
  { name = "dulwich" },
@@ -1,10 +0,0 @@
1
- You have my permissions to
2
-
3
- - read any file on the machine if it's readable to the current user
4
- - make changes to files under this project only
5
- - to create and/or remove temporary files under this project only
6
- - to run shell command `uv`, `fish -n` and `fish_indent` to lint or test Python and fish scripts
7
- - to run the shell commands which does NOT change any files
8
-
9
- However,
10
- please do NOT commit changes so that I can review the diff locally.
@@ -1,9 +0,0 @@
1
- image: dclong/gitpod
2
- ports:
3
- - port: 8888
4
- tasks:
5
- - command: . /scripts/gitpod.sh
6
- vscode:
7
- extensions:
8
- - vscodevim.vim@1.23.2
9
- - ms-python.python