github-rest-api 0.35.0__tar.gz → 0.37.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 (43) hide show
  1. {github_rest_api-0.35.0 → github_rest_api-0.37.0}/.github/workflows/test.yml +2 -0
  2. {github_rest_api-0.35.0 → github_rest_api-0.37.0}/PKG-INFO +1 -1
  3. {github_rest_api-0.35.0 → github_rest_api-0.37.0}/github_rest_api/actions/container/build_container_images.py +25 -8
  4. {github_rest_api-0.35.0 → github_rest_api-0.37.0}/github_rest_api/actions/container/update_version_containerfile.py +23 -79
  5. {github_rest_api-0.35.0 → github_rest_api-0.37.0}/pyproject.toml +1 -1
  6. {github_rest_api-0.35.0 → github_rest_api-0.37.0}/tests/test_github.py +6 -9
  7. {github_rest_api-0.35.0 → github_rest_api-0.37.0}/uv.lock +1 -1
  8. {github_rest_api-0.35.0 → github_rest_api-0.37.0}/.gemini/system.md +0 -0
  9. {github_rest_api-0.35.0 → github_rest_api-0.37.0}/.github/workflows/create_pr_to_main.yml +0 -0
  10. {github_rest_api-0.35.0 → github_rest_api-0.37.0}/.github/workflows/lint.yml +0 -0
  11. {github_rest_api-0.35.0 → github_rest_api-0.37.0}/.github/workflows/release.yml +0 -0
  12. {github_rest_api-0.35.0 → github_rest_api-0.37.0}/.github/workflows/remove_branch.yml +0 -0
  13. {github_rest_api-0.35.0 → github_rest_api-0.37.0}/.gitignore +0 -0
  14. {github_rest_api-0.35.0 → github_rest_api-0.37.0}/.gitpod.yml +0 -0
  15. {github_rest_api-0.35.0 → github_rest_api-0.37.0}/GEMINI.md +0 -0
  16. {github_rest_api-0.35.0 → github_rest_api-0.37.0}/README.md +0 -0
  17. {github_rest_api-0.35.0 → github_rest_api-0.37.0}/github_rest_api/__init__.py +0 -0
  18. {github_rest_api-0.35.0 → github_rest_api-0.37.0}/github_rest_api/actions/__init__.py +0 -0
  19. {github_rest_api-0.35.0 → github_rest_api-0.37.0}/github_rest_api/actions/cargo/__init__.py +0 -0
  20. {github_rest_api-0.35.0 → github_rest_api-0.37.0}/github_rest_api/actions/cargo/benchmark.py +0 -0
  21. {github_rest_api-0.35.0 → github_rest_api-0.37.0}/github_rest_api/actions/cargo/profiling.py +0 -0
  22. {github_rest_api-0.35.0 → github_rest_api-0.37.0}/github_rest_api/actions/cargo/utils.py +0 -0
  23. {github_rest_api-0.35.0 → github_rest_api-0.37.0}/github_rest_api/actions/container/__init__.py +0 -0
  24. {github_rest_api-0.35.0 → github_rest_api-0.37.0}/github_rest_api/actions/container/config_container.py +0 -0
  25. {github_rest_api-0.35.0 → github_rest_api-0.37.0}/github_rest_api/actions/github/__init__.py +0 -0
  26. {github_rest_api-0.35.0 → github_rest_api-0.37.0}/github_rest_api/actions/github/add_github_repo.py +0 -0
  27. {github_rest_api-0.35.0 → github_rest_api-0.37.0}/github_rest_api/actions/github/create_pull_request.py +0 -0
  28. {github_rest_api-0.35.0 → github_rest_api-0.37.0}/github_rest_api/actions/github/release_on_github.py +0 -0
  29. {github_rest_api-0.35.0 → github_rest_api-0.37.0}/github_rest_api/actions/github/remove_branch.py +0 -0
  30. {github_rest_api-0.35.0 → github_rest_api-0.37.0}/github_rest_api/actions/github/workflows/create_pr_dev_to_main.yml +0 -0
  31. {github_rest_api-0.35.0 → github_rest_api-0.37.0}/github_rest_api/actions/github/workflows/create_pr_to_dev.yml +0 -0
  32. {github_rest_api-0.35.0 → github_rest_api-0.37.0}/github_rest_api/actions/github/workflows/create_pr_to_main.yml +0 -0
  33. {github_rest_api-0.35.0 → github_rest_api-0.37.0}/github_rest_api/actions/github/workflows/python/lint.yml +0 -0
  34. {github_rest_api-0.35.0 → github_rest_api-0.37.0}/github_rest_api/actions/github/workflows/python/test.yml +0 -0
  35. {github_rest_api-0.35.0 → github_rest_api-0.37.0}/github_rest_api/actions/github/workflows/remove_branch.yml +0 -0
  36. {github_rest_api-0.35.0 → github_rest_api-0.37.0}/github_rest_api/actions/utils.py +0 -0
  37. {github_rest_api-0.35.0 → github_rest_api-0.37.0}/github_rest_api/github.py +0 -0
  38. {github_rest_api-0.35.0 → github_rest_api-0.37.0}/github_rest_api/utils.py +0 -0
  39. {github_rest_api-0.35.0 → github_rest_api-0.37.0}/memory/MEMORY.md +0 -0
  40. {github_rest_api-0.35.0 → github_rest_api-0.37.0}/memory/feedback_test_runner.md +0 -0
  41. {github_rest_api-0.35.0 → github_rest_api-0.37.0}/tests/__init__.py +0 -0
  42. {github_rest_api-0.35.0 → github_rest_api-0.37.0}/tests/test_build_container_images.py +0 -0
  43. {github_rest_api-0.35.0 → github_rest_api-0.37.0}/tests/test_utils.py +0 -0
@@ -23,3 +23,5 @@ jobs:
23
23
  uv sync --all-extras
24
24
  - name: Test with pytest
25
25
  run: uv run --python ${{ matrix.python-version }} pytest
26
+ env:
27
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: github-rest-api
3
- Version: 0.35.0
3
+ Version: 0.37.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
@@ -1,4 +1,5 @@
1
1
  import argparse
2
+ from collections.abc import Sequence
2
3
  import datetime
3
4
  from pathlib import Path
4
5
  import subprocess as sp
@@ -59,7 +60,8 @@ def changed_files_between(
59
60
  def has_relevant_changes(
60
61
  commit1: str | bytes,
61
62
  commit2: str | bytes,
62
- image_dirs: list[str],
63
+ image_dirs: Sequence[str],
64
+ paths_monitoring: Sequence[str] = (),
63
65
  name1: str = "",
64
66
  name2: str = "",
65
67
  ) -> bool:
@@ -69,20 +71,25 @@ def has_relevant_changes(
69
71
  commit1 = commit1.encode()
70
72
  if isinstance(commit2, str):
71
73
  commit2 = commit2.encode()
72
- dirs = [Path(d).resolve() for d in image_dirs]
74
+ monitored = [Path(m).resolve() for m in (*image_dirs, *paths_monitoring)]
73
75
  for p in changed_files_between(commit1, commit2, name1=name1, name2=name2):
74
- if any(p.resolve().is_relative_to(d) for d in dirs):
76
+ p_resolved = p.resolve()
77
+ if any(p_resolved.is_relative_to(m) for m in monitored):
75
78
  return True
76
79
  return False
77
80
 
78
81
 
79
- def has_relevant_changes_main_dev(image_dirs: list[str]) -> bool:
82
+ def has_relevant_changes_main_dev(
83
+ image_dirs: Sequence[str], paths_monitoring: Sequence[str] = ()
84
+ ) -> bool:
80
85
  try:
81
86
  c_main = _get_commit(b"main")
82
87
  c_dev = _get_commit(b"dev")
83
88
  except (KeyError, NotGitRepository):
84
89
  return True
85
- return has_relevant_changes(c_main, c_dev, image_dirs, name1="main", name2="dev")
90
+ return has_relevant_changes(
91
+ c_main, c_dev, image_dirs, paths_monitoring, name1="main", name2="dev"
92
+ )
86
93
 
87
94
 
88
95
  def _tag_date(tag: str) -> str:
@@ -127,11 +134,12 @@ def _build_image(
127
134
  def build_images(
128
135
  commit1: str,
129
136
  commit2: str,
130
- image_dirs: list[str],
137
+ image_dirs: Sequence[str],
138
+ paths_monitoring: Sequence[str] = (),
131
139
  tool: str = "podman",
132
140
  registry: str = "quay.io/legendu",
133
141
  ):
134
- if not has_relevant_changes(commit1, commit2, image_dirs):
142
+ if not has_relevant_changes(commit1, commit2, image_dirs, paths_monitoring):
135
143
  print(
136
144
  f"Skip building {tool} images as there are no relevant changes between {
137
145
  commit1
@@ -139,7 +147,7 @@ def build_images(
139
147
  )
140
148
  return
141
149
  tags = ["next"]
142
- if not has_relevant_changes_main_dev(image_dirs):
150
+ if not has_relevant_changes_main_dev(image_dirs, paths_monitoring):
143
151
  tags.append("latest")
144
152
  tags.extend([_tag_date(tag) for tag in tags])
145
153
  print(f"Building {tool} images using tags:", ", ".join(tags), "\n", flush=True)
@@ -207,6 +215,14 @@ def parse_args():
207
215
  metavar="FILE",
208
216
  help="Path to a file listing image directories to build, one per line.",
209
217
  )
218
+ parser.add_argument(
219
+ "--paths-monitoring",
220
+ dest="paths_monitoring",
221
+ nargs="*",
222
+ default=(),
223
+ metavar="PATH",
224
+ help="Extra paths to monitor for changes in addition to the image directories.",
225
+ )
210
226
  return parser.parse_args()
211
227
 
212
228
 
@@ -223,6 +239,7 @@ def main():
223
239
  args.commit1,
224
240
  args.commit2,
225
241
  _resolve_image_dirs(args),
242
+ paths_monitoring=args.paths_monitoring,
226
243
  tool=args.tool,
227
244
  registry=args.registry,
228
245
  )
@@ -28,83 +28,15 @@ def parse_latest_version(repo: str) -> str:
28
28
  def update_version(
29
29
  containerfile: str | Path, version: str, pattern: str, replace: str
30
30
  ) -> None:
31
- if containerfile == "":
32
- containerfile = "Dockerfile" if Path("Dockerfile").exists() else "Containerfile"
31
+ if not pattern:
32
+ raise ValueError("The pattern to replace must not be empty.")
33
33
  if isinstance(containerfile, str):
34
- containerfile = Path(containerfile).resolve()
35
- match containerfile.parent.name:
36
- case "docker-base":
37
- return _update_version_docker_base(
38
- containerfile=containerfile, version=version
39
- )
40
- case "docker-jupyterlab":
41
- return _update_version_docker_jupyterlab(
42
- containerfile=containerfile, version=version
43
- )
44
- case "docker-jupyterhub":
45
- return _update_version_docker_jupyterhub(
46
- containerfile=containerfile, version=version
47
- )
48
- case "docker-vscode-server":
49
- return _update_version_docker_vscode_server(
50
- containerfile=containerfile, version=version
51
- )
52
- case _:
53
- if not pattern:
54
- raise ValueError("A version pattern must be specified!")
55
- return _update_version_default(
56
- containerfile=containerfile,
57
- version=version,
58
- pattern=pattern,
59
- replace=replace,
60
- )
61
-
62
-
63
- def _update_version_default(
64
- containerfile: Path, version: str, pattern: str, replace: str
65
- ) -> None:
66
- text = containerfile.read_text()
67
- text = re.sub(pattern, replace.format(version=version), text)
68
- containerfile.write_text(text)
69
-
70
-
71
- def _update_version_docker_base(containerfile: Path, version: str) -> None:
72
- _update_version_default(
73
- containerfile=containerfile,
74
- version=version,
75
- pattern=r"-v v?\d+\.\d+\.\d+",
76
- replace="-v v{version}",
77
- )
78
-
79
-
80
- def _update_version_docker_jupyterlab(containerfile: Path, version: str) -> None:
81
- version = next_minor_or_strip_patch(version, 3)
82
- _update_version_default(
83
- containerfile=containerfile,
84
- version=version,
85
- pattern=r",<\d+\.\d+\.0",
86
- replace=",<{version}",
87
- )
88
-
89
-
90
- def _update_version_docker_jupyterhub(containerfile: Path, version: str) -> None:
91
- version = next_minor_or_strip_patch(version, 3)
92
- _update_version_default(
93
- containerfile=containerfile,
94
- version=version,
95
- pattern=r"jupyterhub<\d+\.\d+\.0",
96
- replace="jupyterhub<{version}",
97
- )
98
-
99
-
100
- def _update_version_docker_vscode_server(containerfile: Path, version: str) -> None:
101
- version = next_minor_or_strip_patch(version, 3)
102
- _update_version_default(
103
- containerfile=containerfile,
104
- version=version,
105
- pattern=r",<\d+\.\d+\.0",
106
- replace=",<{version}",
107
- )
34
+ containerfile = Path(containerfile)
35
+ original = containerfile.read_text(encoding="utf-8")
36
+ repl = replace.replace("{version}", version)
37
+ updated = re.sub(pattern, lambda _: repl, original)
38
+ if updated != original:
39
+ containerfile.write_text(updated, encoding="utf-8")
108
40
 
109
41
 
110
42
  def _branch_prefix(repo: str) -> str:
@@ -134,7 +66,7 @@ def parse_args():
134
66
  parser.add_argument(
135
67
  "--containerfile",
136
68
  dest="containerfile",
137
- default="",
69
+ required=True,
138
70
  help="The Dockerfile or Containerfile to update.",
139
71
  )
140
72
  parser.add_argument(
@@ -152,15 +84,25 @@ def parse_args():
152
84
  parser.add_argument(
153
85
  "--pattern",
154
86
  dest="pattern",
155
- default="",
87
+ required=True,
156
88
  help="The version pattern to replace.",
157
89
  )
158
90
  parser.add_argument(
159
91
  "--replace",
160
92
  dest="replace",
161
- default="",
93
+ required=True,
162
94
  help="The replacement for the matched version pattern.",
163
95
  )
96
+ parser.add_argument(
97
+ "--next-minor-or-strip-patch",
98
+ dest="next_minor_or_strip_patch",
99
+ type=int,
100
+ default=None,
101
+ help=(
102
+ "If provided, transform the version with next_minor_or_strip_patch(version, N): "
103
+ "bump to next minor if patch >= N, otherwise strip patch to 0."
104
+ ),
105
+ )
164
106
  return parser.parse_args()
165
107
 
166
108
 
@@ -188,6 +130,8 @@ def main():
188
130
  return
189
131
  checkout_branch(args.repo)
190
132
  version = parse_latest_version(repo=args.repo)
133
+ if args.next_minor_or_strip_patch is not None:
134
+ version = next_minor_or_strip_patch(version, args.next_minor_or_strip_patch)
191
135
  update_version(
192
136
  containerfile=args.containerfile,
193
137
  version=version,
@@ -4,7 +4,7 @@ requires = [ "hatchling" ]
4
4
 
5
5
  [project]
6
6
  name = "github-rest-api"
7
- version = "0.35.0"
7
+ version = "0.37.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" } ]
@@ -1,25 +1,22 @@
1
+ import os
1
2
  from github_rest_api.github import User, Organization, Repository
2
3
 
4
+ TOKEN = os.environ.get("GITHUB_TOKEN", "")
5
+
3
6
 
4
7
  def test_user_get_repositories():
5
- token = ""
6
- username = "dclong"
7
- user = User(token, username)
8
+ user = User(TOKEN, "dclong")
8
9
  repos = user.get_repositories()
9
10
  assert len(repos) > 0
10
11
 
11
12
 
12
13
  def test_organization_get_repositories():
13
- token = ""
14
- org_name = "legendu-net"
15
- org = Organization(token, org_name)
14
+ org = Organization(TOKEN, "legendu-net")
16
15
  repos = org.get_repositories()
17
16
  assert len(repos) > 0
18
17
 
19
18
 
20
19
  def test_repository_get_branch():
21
- token = ""
22
- repo_name = "legendu-net/github_rest_api"
23
- repo = Repository(token, repo_name)
20
+ repo = Repository(TOKEN, "legendu-net/github_rest_api")
24
21
  branch = repo.get_branch("main")
25
22
  assert branch["name"] == "main"
@@ -166,7 +166,7 @@ wheels = [
166
166
 
167
167
  [[package]]
168
168
  name = "github-rest-api"
169
- version = "0.35.0"
169
+ version = "0.36.0"
170
170
  source = { editable = "." }
171
171
  dependencies = [
172
172
  { name = "dulwich" },