ggcode 1.0.9__tar.gz → 1.1.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.
ggcode-1.1.0/PKG-INFO ADDED
@@ -0,0 +1,69 @@
1
+ Metadata-Version: 2.4
2
+ Name: ggcode
3
+ Version: 1.1.0
4
+ Summary: Thin Python wrapper that installs the ggcode GitHub Release binary
5
+ Author: topcheer
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/topcheer/ggcode
8
+ Project-URL: Repository, https://github.com/topcheer/ggcode.git
9
+ Project-URL: Issues, https://github.com/topcheer/ggcode/issues
10
+ Requires-Python: >=3.9
11
+ Description-Content-Type: text/markdown
12
+
13
+ # ggcode Python wrapper
14
+
15
+ `ggcode` on PyPI is a thin Python wrapper for the `ggcode` terminal agent.
16
+
17
+ It does not ship the platform binary inside the wheel. Instead, the wrapper downloads the latest
18
+ matching `ggcode` GitHub Release on first run, caches it locally, and then launches it.
19
+
20
+ ## Install
21
+
22
+ ```bash
23
+ pip install ggcode
24
+ ```
25
+
26
+ Then run:
27
+
28
+ ```bash
29
+ ggcode
30
+ ```
31
+
32
+ ## What it does
33
+
34
+ - Detects your operating system and CPU architecture
35
+ - Downloads the latest matching `ggcode` archive from GitHub Releases
36
+ - Verifies the archive against `checksums.txt`
37
+ - Extracts and caches the binary for future runs
38
+
39
+ ## Pin a specific ggcode release
40
+
41
+ By default, the wrapper always resolves the latest `ggcode` release.
42
+
43
+ To force a specific release, set `GGCODE_INSTALL_VERSION`:
44
+
45
+ ```bash
46
+ GGCODE_INSTALL_VERSION=vX.Y.Z ggcode
47
+ ```
48
+
49
+ or:
50
+
51
+ ```bash
52
+ GGCODE_INSTALL_VERSION=X.Y.Z ggcode
53
+ ```
54
+
55
+ ## Supported platforms
56
+
57
+ - macOS
58
+ - Linux
59
+ - Windows
60
+
61
+ Supported architectures:
62
+
63
+ - x86_64 / amd64
64
+ - arm64
65
+
66
+ ## Project links
67
+
68
+ - Repository: https://github.com/topcheer/ggcode
69
+ - Issues: https://github.com/topcheer/ggcode/issues
ggcode-1.1.0/README.md ADDED
@@ -0,0 +1,57 @@
1
+ # ggcode Python wrapper
2
+
3
+ `ggcode` on PyPI is a thin Python wrapper for the `ggcode` terminal agent.
4
+
5
+ It does not ship the platform binary inside the wheel. Instead, the wrapper downloads the latest
6
+ matching `ggcode` GitHub Release on first run, caches it locally, and then launches it.
7
+
8
+ ## Install
9
+
10
+ ```bash
11
+ pip install ggcode
12
+ ```
13
+
14
+ Then run:
15
+
16
+ ```bash
17
+ ggcode
18
+ ```
19
+
20
+ ## What it does
21
+
22
+ - Detects your operating system and CPU architecture
23
+ - Downloads the latest matching `ggcode` archive from GitHub Releases
24
+ - Verifies the archive against `checksums.txt`
25
+ - Extracts and caches the binary for future runs
26
+
27
+ ## Pin a specific ggcode release
28
+
29
+ By default, the wrapper always resolves the latest `ggcode` release.
30
+
31
+ To force a specific release, set `GGCODE_INSTALL_VERSION`:
32
+
33
+ ```bash
34
+ GGCODE_INSTALL_VERSION=vX.Y.Z ggcode
35
+ ```
36
+
37
+ or:
38
+
39
+ ```bash
40
+ GGCODE_INSTALL_VERSION=X.Y.Z ggcode
41
+ ```
42
+
43
+ ## Supported platforms
44
+
45
+ - macOS
46
+ - Linux
47
+ - Windows
48
+
49
+ Supported architectures:
50
+
51
+ - x86_64 / amd64
52
+ - arm64
53
+
54
+ ## Project links
55
+
56
+ - Repository: https://github.com/topcheer/ggcode
57
+ - Issues: https://github.com/topcheer/ggcode/issues
@@ -0,0 +1,69 @@
1
+ Metadata-Version: 2.4
2
+ Name: ggcode
3
+ Version: 1.1.0
4
+ Summary: Thin Python wrapper that installs the ggcode GitHub Release binary
5
+ Author: topcheer
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/topcheer/ggcode
8
+ Project-URL: Repository, https://github.com/topcheer/ggcode.git
9
+ Project-URL: Issues, https://github.com/topcheer/ggcode/issues
10
+ Requires-Python: >=3.9
11
+ Description-Content-Type: text/markdown
12
+
13
+ # ggcode Python wrapper
14
+
15
+ `ggcode` on PyPI is a thin Python wrapper for the `ggcode` terminal agent.
16
+
17
+ It does not ship the platform binary inside the wheel. Instead, the wrapper downloads the latest
18
+ matching `ggcode` GitHub Release on first run, caches it locally, and then launches it.
19
+
20
+ ## Install
21
+
22
+ ```bash
23
+ pip install ggcode
24
+ ```
25
+
26
+ Then run:
27
+
28
+ ```bash
29
+ ggcode
30
+ ```
31
+
32
+ ## What it does
33
+
34
+ - Detects your operating system and CPU architecture
35
+ - Downloads the latest matching `ggcode` archive from GitHub Releases
36
+ - Verifies the archive against `checksums.txt`
37
+ - Extracts and caches the binary for future runs
38
+
39
+ ## Pin a specific ggcode release
40
+
41
+ By default, the wrapper always resolves the latest `ggcode` release.
42
+
43
+ To force a specific release, set `GGCODE_INSTALL_VERSION`:
44
+
45
+ ```bash
46
+ GGCODE_INSTALL_VERSION=vX.Y.Z ggcode
47
+ ```
48
+
49
+ or:
50
+
51
+ ```bash
52
+ GGCODE_INSTALL_VERSION=X.Y.Z ggcode
53
+ ```
54
+
55
+ ## Supported platforms
56
+
57
+ - macOS
58
+ - Linux
59
+ - Windows
60
+
61
+ Supported architectures:
62
+
63
+ - x86_64 / amd64
64
+ - arm64
65
+
66
+ ## Project links
67
+
68
+ - Repository: https://github.com/topcheer/ggcode
69
+ - Issues: https://github.com/topcheer/ggcode/issues
@@ -6,4 +6,5 @@ ggcode.egg-info/dependency_links.txt
6
6
  ggcode.egg-info/entry_points.txt
7
7
  ggcode.egg-info/top_level.txt
8
8
  ggcode_release_installer/__init__.py
9
- ggcode_release_installer/cli.py
9
+ ggcode_release_installer/cli.py
10
+ tests/test_cli.py
@@ -0,0 +1 @@
1
+ __version__ = "1.1.0"
@@ -9,19 +9,18 @@ import subprocess
9
9
  import sys
10
10
  import tarfile
11
11
  import tempfile
12
+ import urllib.parse
12
13
  import urllib.request
13
14
  import zipfile
14
15
  from pathlib import Path
15
16
 
16
- from . import __version__
17
-
18
17
  OWNER = "topcheer"
19
18
  REPO = "ggcode"
20
19
 
21
20
 
22
21
  def normalize_version() -> str:
23
- selected = os.environ.get("GGCODE_INSTALL_VERSION", __version__).strip()
24
- if not selected or selected == "latest" or selected.startswith("0.0.0"):
22
+ selected = os.environ.get("GGCODE_INSTALL_VERSION", "").strip()
23
+ if not selected or selected == "latest":
25
24
  return "latest"
26
25
  if selected.startswith("v"):
27
26
  return selected
@@ -29,15 +28,15 @@ def normalize_version() -> str:
29
28
 
30
29
 
31
30
  def resolve_target() -> tuple[str, str]:
32
- platform = sys.platform
33
- if platform.startswith("linux"):
31
+ system = sys.platform
32
+ if system.startswith("linux"):
34
33
  goos = "linux"
35
- elif platform == "darwin":
34
+ elif system == "darwin":
36
35
  goos = "darwin"
37
- elif platform in ("win32", "cygwin"):
36
+ elif system in ("win32", "cygwin"):
38
37
  goos = "windows"
39
38
  else:
40
- raise RuntimeError(f"Unsupported platform: {platform}")
39
+ raise RuntimeError(f"Unsupported platform: {system}")
41
40
 
42
41
  machine = platform.machine().lower() or os.environ.get("PROCESSOR_ARCHITECTURE", "").lower()
43
42
  if machine in ("x86_64", "amd64"):
@@ -67,6 +66,20 @@ def download(url: str) -> bytes:
67
66
  return response.read()
68
67
 
69
68
 
69
+ def resolve_release_version(version: str) -> str:
70
+ if version != "latest":
71
+ return version
72
+
73
+ with urllib.request.urlopen(f"https://github.com/{OWNER}/{REPO}/releases/latest") as response:
74
+ final_url = response.geturl()
75
+
76
+ parsed = urllib.parse.urlparse(final_url)
77
+ parts = [part for part in parsed.path.split("/") if part]
78
+ if len(parts) < 4 or parts[-2] != "tag":
79
+ raise RuntimeError(f"Could not resolve latest ggcode release from {final_url}")
80
+ return urllib.parse.unquote(parts[-1])
81
+
82
+
70
83
  def parse_checksums(body: str) -> dict[str, str]:
71
84
  checksums: dict[str, str] = {}
72
85
  for raw_line in body.splitlines():
@@ -77,7 +90,7 @@ def parse_checksums(body: str) -> dict[str, str]:
77
90
 
78
91
 
79
92
  def ensure_installed() -> Path:
80
- version = normalize_version()
93
+ version = resolve_release_version(normalize_version())
81
94
  goos, arch = resolve_target()
82
95
  archive_ext = ".zip" if goos == "windows" else ".tar.gz"
83
96
  archive_name = f"ggcode_{goos}_{arch}{archive_ext}"
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "ggcode"
7
- version = "1.0.9"
7
+ version = "1.1.0"
8
8
  description = "Thin Python wrapper that installs the ggcode GitHub Release binary"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -0,0 +1,41 @@
1
+ from __future__ import annotations
2
+
3
+ import os
4
+ import unittest
5
+ from unittest.mock import patch
6
+
7
+ from ggcode_release_installer import cli
8
+
9
+
10
+ class ResolveTargetTests(unittest.TestCase):
11
+ def test_normalize_version_defaults_to_latest(self) -> None:
12
+ with patch.dict(os.environ, {}, clear=True):
13
+ self.assertEqual(cli.normalize_version(), "latest")
14
+
15
+ def test_normalize_version_uses_explicit_override(self) -> None:
16
+ with patch.dict(os.environ, {"GGCODE_INSTALL_VERSION": "1.2.3"}, clear=True):
17
+ self.assertEqual(cli.normalize_version(), "v1.2.3")
18
+
19
+ def test_resolve_target_uses_platform_module_for_machine(self) -> None:
20
+ with patch.object(cli.sys, "platform", "darwin"):
21
+ with patch.object(cli.platform, "machine", return_value="arm64"):
22
+ self.assertEqual(cli.resolve_target(), ("darwin", "arm64"))
23
+
24
+ def test_resolve_target_falls_back_to_processor_architecture(self) -> None:
25
+ env = dict(os.environ, PROCESSOR_ARCHITECTURE="AMD64")
26
+ with patch.dict(os.environ, env, clear=True):
27
+ with patch.object(cli.sys, "platform", "win32"):
28
+ with patch.object(cli.platform, "machine", return_value=""):
29
+ self.assertEqual(cli.resolve_target(), ("windows", "x86_64"))
30
+
31
+ def test_resolve_release_version_follows_latest_redirect(self) -> None:
32
+ response = unittest.mock.Mock()
33
+ response.geturl.return_value = "https://github.com/topcheer/ggcode/releases/tag/v9.9.9"
34
+ response.__enter__ = unittest.mock.Mock(return_value=response)
35
+ response.__exit__ = unittest.mock.Mock(return_value=False)
36
+ with patch.object(cli.urllib.request, "urlopen", return_value=response):
37
+ self.assertEqual(cli.resolve_release_version("latest"), "v9.9.9")
38
+
39
+
40
+ if __name__ == "__main__":
41
+ unittest.main()
ggcode-1.0.9/PKG-INFO DELETED
@@ -1,16 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: ggcode
3
- Version: 1.0.9
4
- Summary: Thin Python wrapper that installs the ggcode GitHub Release binary
5
- Author: topcheer
6
- License: MIT
7
- Project-URL: Homepage, https://github.com/topcheer/ggcode
8
- Project-URL: Repository, https://github.com/topcheer/ggcode.git
9
- Project-URL: Issues, https://github.com/topcheer/ggcode/issues
10
- Requires-Python: >=3.9
11
- Description-Content-Type: text/markdown
12
-
13
- # ggcode Python wrapper
14
-
15
- This package installs a small Python launcher that downloads the matching `ggcode`
16
- binary from GitHub Releases on first run and then executes it.
ggcode-1.0.9/README.md DELETED
@@ -1,4 +0,0 @@
1
- # ggcode Python wrapper
2
-
3
- This package installs a small Python launcher that downloads the matching `ggcode`
4
- binary from GitHub Releases on first run and then executes it.
@@ -1,16 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: ggcode
3
- Version: 1.0.9
4
- Summary: Thin Python wrapper that installs the ggcode GitHub Release binary
5
- Author: topcheer
6
- License: MIT
7
- Project-URL: Homepage, https://github.com/topcheer/ggcode
8
- Project-URL: Repository, https://github.com/topcheer/ggcode.git
9
- Project-URL: Issues, https://github.com/topcheer/ggcode/issues
10
- Requires-Python: >=3.9
11
- Description-Content-Type: text/markdown
12
-
13
- # ggcode Python wrapper
14
-
15
- This package installs a small Python launcher that downloads the matching `ggcode`
16
- binary from GitHub Releases on first run and then executes it.
@@ -1 +0,0 @@
1
- __version__ = "1.0.9"
File without changes