codeberg-cli 0.4.1__py3-none-any.whl → 0.4.2__py3-none-any.whl

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.
codeberg_cli/client.py CHANGED
@@ -16,6 +16,10 @@ _VERBS = {
16
16
  class ClientError(RuntimeError):
17
17
  """Raised when the API returns a non-2xx status."""
18
18
 
19
+ def __init__(self, message: str, status_code: int | None = None) -> None:
20
+ super().__init__(message)
21
+ self.status_code = status_code
22
+
19
23
 
20
24
  def _response_error_message(response: httpx.Response) -> str:
21
25
  if not response.text:
@@ -52,7 +56,12 @@ class Client:
52
56
  raw = raw.rstrip("/")
53
57
  if not raw.endswith("/api/v1"):
54
58
  raw += "/api/v1"
55
- self._client = httpx.Client(base_url=raw, headers=headers, timeout=30.0)
59
+ self._client = httpx.Client(
60
+ base_url=raw,
61
+ headers=headers,
62
+ timeout=30.0,
63
+ follow_redirects=True,
64
+ )
56
65
 
57
66
  @property
58
67
  def base_url(self) -> str:
@@ -99,7 +108,9 @@ class Client:
99
108
  response = self._client.request(method, path, **kwargs)
100
109
  if not response.is_success:
101
110
  msg = _response_error_message(response)
102
- raise ClientError(f"{response.status_code} {msg}")
111
+ raise ClientError(
112
+ f"{response.status_code} {msg}", status_code=response.status_code
113
+ )
103
114
  if response.status_code == 204:
104
115
  return None
105
116
  return response.json()
@@ -1,4 +1,27 @@
1
- from typing import Any
1
+ from typing import Any, Callable, TypeVar
2
+
3
+ from codeberg_cli.client import ClientError
4
+ from xclif.errors import UsageError
5
+
6
+ T = TypeVar("T")
7
+
8
+
9
+ def actions_request(repo: str, call: Callable[[], T]) -> T:
10
+ """Run an Actions API *call*, turning a 404 into a clear message.
11
+
12
+ Forgejo returns 404 for Actions endpoints when Actions is not enabled on
13
+ the repository (or the repo does not exist), which is otherwise surfaced as
14
+ an opaque ``404 The target couldn't be found.`` traceback.
15
+ """
16
+ try:
17
+ return call()
18
+ except ClientError as exc:
19
+ if exc.status_code == 404:
20
+ raise UsageError(
21
+ f"No Actions found for {repo}.",
22
+ hint="Actions may be disabled for this repository, or the repository may not exist.",
23
+ ) from exc
24
+ raise
2
25
 
3
26
 
4
27
  def _first(run: dict[str, Any], *keys: str, default: str = "") -> Any:
@@ -23,9 +23,20 @@ def _(
23
23
  return 1
24
24
  repo = inferred
25
25
 
26
- client.post(
27
- f"/repos/{repo}/actions/workflows/{workflow}/dispatches",
28
- data={"ref": ref},
29
- action="Dispatching workflow",
30
- )
26
+ from codeberg_cli.client import ClientError
27
+ from xclif.errors import UsageError
28
+
29
+ try:
30
+ client.post(
31
+ f"/repos/{repo}/actions/workflows/{workflow}/dispatches",
32
+ data={"ref": ref},
33
+ action="Dispatching workflow",
34
+ )
35
+ except ClientError as exc:
36
+ if exc.status_code == 404:
37
+ raise UsageError(
38
+ f"No workflow {workflow!r} found in {repo}.",
39
+ hint="List workflows with 'cb actions workflows', or Actions may be disabled for this repository.",
40
+ ) from exc
41
+ raise
31
42
  rich.print(f"[green]Dispatched {workflow} on {ref} in {repo}.[/green]")
@@ -24,7 +24,18 @@ def _(
24
24
  return 1
25
25
  repo = inferred
26
26
 
27
- run = client.get(f"/repos/{repo}/actions/runs/{run_id}")
27
+ from codeberg_cli.client import ClientError
28
+ from xclif.errors import UsageError
29
+
30
+ try:
31
+ run = client.get(f"/repos/{repo}/actions/runs/{run_id}")
32
+ except ClientError as exc:
33
+ if exc.status_code == 404:
34
+ raise UsageError(
35
+ f"No run #{run_id} found in {repo}.",
36
+ hint="Check the run ID with 'cb actions runs', or Actions may be disabled for this repository.",
37
+ ) from exc
38
+ raise
28
39
 
29
40
  if is_json_mode():
30
41
  output(run)
@@ -6,7 +6,7 @@ from codeberg_cli.git import infer_repo
6
6
  from codeberg_cli.helpers import print_table, require_client
7
7
  from xclif import Option, command
8
8
 
9
- from codeberg_cli.routes.actions._format import list_runs, normalize_run
9
+ from codeberg_cli.routes.actions._format import actions_request, list_runs, normalize_run
10
10
 
11
11
 
12
12
  @command("runs")
@@ -24,7 +24,10 @@ def _(
24
24
  return 1
25
25
  repo = inferred
26
26
 
27
- response = client.get(f"/repos/{repo}/actions/runs", params={"limit": limit, "page": 1})
27
+ response = actions_request(
28
+ repo,
29
+ lambda: client.get(f"/repos/{repo}/actions/runs", params={"limit": limit, "page": 1}),
30
+ )
28
31
  runs = list_runs(response)
29
32
 
30
33
  if not runs:
@@ -34,7 +34,7 @@ def _(
34
34
  action="Fetching workflow files",
35
35
  )
36
36
  except ClientError as exc:
37
- if str(exc).startswith("404 "):
37
+ if exc.status_code == 404:
38
38
  rich.print(f"[dim]No workflows in {repo}.[/dim]")
39
39
  return
40
40
  raise
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codeberg-cli
3
- Version: 0.4.1
3
+ Version: 0.4.2
4
4
  Summary: A Forgejo CLI — works with Codeberg and any Forgejo instance
5
5
  Project-URL: Homepage, https://codeberg.org/ThatXliner/codeberg-cli
6
6
  Project-URL: Repository, https://codeberg.org/ThatXliner/codeberg-cli
@@ -1,5 +1,5 @@
1
1
  codeberg_cli/__main__.py,sha256=35xiBzBbgDy9rcHqCJWHdIVsWhGEtPQNd-s9wt3k7yE,141
2
- codeberg_cli/client.py,sha256=M0nBI7UyTtO4Me13stntaYEDR-yFA5GtfF4I6KIQzFY,3367
2
+ codeberg_cli/client.py,sha256=BEew6LN5-zchRzlp9dq-Zr1ZBKaeTldkIEEKzuBu3-k,3665
3
3
  codeberg_cli/config.py,sha256=bjVHHM1sG3xTIU6EC7sakwR0nnP-ZsCtO4Jn2od6X4A,822
4
4
  codeberg_cli/git.py,sha256=DIzHSaezhWQGl63f8pkYDNd-qDfoMe7SZBZ7TWVlCxc,1899
5
5
  codeberg_cli/helpers.py,sha256=DQe6Be9B7eLPEVRJ4guo644UWKivAADniS7uh42_3Mk,3268
@@ -8,11 +8,11 @@ codeberg_cli/routes/api.py,sha256=o8she7_o32DNuYqr1v9D0hEHjujW1xEZEhHuxIzKO_8,72
8
8
  codeberg_cli/routes/notifications.py,sha256=Jqjy287S0YevaHMy_xwDp3HSZILWL7RBSS7YskQd3WA,1350
9
9
  codeberg_cli/routes/user.py,sha256=uPQowX-VoOs2zumFhbultqeOeFmZ-OODEMEnu5WvMQ0,1099
10
10
  codeberg_cli/routes/actions/__init__.py,sha256=KCjUWUN2rh_GollBkNwoLZtpm9gPC5PPLfQOvd4gCrc,153
11
- codeberg_cli/routes/actions/_format.py,sha256=J-FE4GQAo97nLPPABtGVBVAYReEG3yAfUalERDn-FWI,1335
12
- codeberg_cli/routes/actions/dispatch.py,sha256=Lu3FyE7M8DdSHefist1y97Qp2khho0MRPj-QcnoKaAU,1030
13
- codeberg_cli/routes/actions/run.py,sha256=r-yNjiYtdx-PyV-GE5vuQI-AVK43YQARRXaAR64rLqg,1529
14
- codeberg_cli/routes/actions/runs.py,sha256=7Bw77hsUMkLN8xwvn0BDD3lkNHNvGlIcD5DrziVAEs8,1398
15
- codeberg_cli/routes/actions/workflows.py,sha256=cbrcINWbn7n9Cm21BLm16l4guMRyZkT6eLHydMLAD7o,1883
11
+ codeberg_cli/routes/actions/_format.py,sha256=W0nC-6-EaBp9gCEahEp-iDiZUs6jCgspmXhCTFfUAto,2129
12
+ codeberg_cli/routes/actions/dispatch.py,sha256=C9lUTs9TGBFIlZJtKdUMTIKiNRdNW9s9rQXRzd0YNT0,1459
13
+ codeberg_cli/routes/actions/run.py,sha256=ZnU6quATij-Yrmfh_SMvw7djjAt2XcadiSK7_sId0Mk,1931
14
+ codeberg_cli/routes/actions/runs.py,sha256=rjT-OOEu59HCfu2JZVF30r2eVaTJ-ntfkyDQcuci8ls,1469
15
+ codeberg_cli/routes/actions/workflows.py,sha256=XgkPHMVWgflQpRpwVkmoPu-483FYLCRJDZX6EOkN1PE,1878
16
16
  codeberg_cli/routes/auth/__init__.py,sha256=eQHz7mep-kGESlmrv4tTAD3EPTqlNC2Dy9MeJkTxUi0,139
17
17
  codeberg_cli/routes/auth/login.py,sha256=6QxaEz5cvSgJbr-dXpudP2VbGxsLx3xPw0cMwWZm1aU,654
18
18
  codeberg_cli/routes/auth/logout.py,sha256=LfsYchVxrr77R5c2WNGbKNCLbkyQtbobkhcpw1DH8HA,351
@@ -116,8 +116,8 @@ codeberg_cli/routes/repo/tag/list.py,sha256=HI9K00-bf50XcimXKzQR-YD4l_y7m8Rfp72U
116
116
  codeberg_cli/routes/repo/topics/__init__.py,sha256=lHx6_CZgeOqtFPasOg0sfM6De61V3mfd-FW-bDOsCqM,117
117
117
  codeberg_cli/routes/repo/topics/list.py,sha256=oV-3wZVQj1RlLeZjBg-EAtv_roB71eTfnB9lWDBg680,931
118
118
  codeberg_cli/routes/repo/topics/set.py,sha256=hhVOMw-3btCgwlQXd34n6A6jEu0f56GcSyJTsyuUiDI,911
119
- codeberg_cli-0.4.1.dist-info/METADATA,sha256=PElJmoyjTT2ZbJne1chLRJ_WRKgkh7rH0EFhw2DuFr0,8124
120
- codeberg_cli-0.4.1.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
121
- codeberg_cli-0.4.1.dist-info/entry_points.txt,sha256=7Kg1K5av7D5TzPCqX_qyFCj09JTneIEvW0f2Gp4q1v4,49
122
- codeberg_cli-0.4.1.dist-info/licenses/LICENSE,sha256=o71itnX05JiF5qOrKHEmWIvuf03sgYcwsc3r6AAW_h0,1065
123
- codeberg_cli-0.4.1.dist-info/RECORD,,
119
+ codeberg_cli-0.4.2.dist-info/METADATA,sha256=V4Is03t_kHviXIRbDr4zA-7j09xl8m8XrHKqMBlvw6U,8124
120
+ codeberg_cli-0.4.2.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
121
+ codeberg_cli-0.4.2.dist-info/entry_points.txt,sha256=7Kg1K5av7D5TzPCqX_qyFCj09JTneIEvW0f2Gp4q1v4,49
122
+ codeberg_cli-0.4.2.dist-info/licenses/LICENSE,sha256=o71itnX05JiF5qOrKHEmWIvuf03sgYcwsc3r6AAW_h0,1065
123
+ codeberg_cli-0.4.2.dist-info/RECORD,,