Skip to content

Commit e35b7a0

Browse files
authored
update the python test-server-sdk (#44)
1 parent d26939a commit e35b7a0

7 files changed

Lines changed: 73 additions & 42 deletions

File tree

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ sdks/typescript/sample/dist/
3434
# Python SDK specific
3535
sdks/python/src/test_server_sdk/__pycache__
3636
sdks/python/__pycache__
37-
sdks/python/test_server_sdk.egg-info/
37+
sdks/python/src/test_server_sdk.egg-info
3838

3939
# Python SDK Sample specific
4040
sdks/python/sample/__pycache__

sdks/python/MANIFEST.in

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
include LICENSE
22
include README.md
3-
include install.py
4-
include checksums.json
53

64
prune sample

sdks/python/README.md

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ pip3 install -r requirements.txt
1515

1616
```sh
1717
# Ensure a clean build
18-
rm -rf build/ dist/ *.egg-info/ src/test_server_sdk/bin/ && find . -depth -name "__pycache__" -type d -exec rm -rf {} \;
18+
rm -rf build/ dist/ src/*.egg-info/ *.egg-info && find . -depth -name "__pycache__" -type d -exec rm -rf {} \;
1919
# Build the python wheel
2020
python3 -m build
2121
```
@@ -25,13 +25,17 @@ python3 -m build
2525
## Installation of the Python Test Server sdk
2626

2727
```sh
28+
# Ensure a clean installation
29+
pip3 uninstall test-server-sdk -y
2830
# Install from the dist, use --force-reinstall to alwasy install fresh
29-
pip install --force-reinstall dist/test_server_sdk-0.1.0-py3-none-any.whl
31+
pip3 install --force-reinstall dist/test_server_sdk-0.1.0-py3-none-any.whl
32+
# This is the command to download and verify the underlying golang executabel.
33+
download_golang_executable
3034

3135
# Check on the files
3236
pip show -f test_server_sdk
3337
```
34-
You should see something very similar to this output, note tehat the `test_server_sdk/bin/` folder exist and contains the golang test-server:
38+
You should see something very similar to this output, note tehat the `../../../bin/download_golang_executable` entry exist.
3539
```
3640
Name: test-server-sdk
3741
Version: 0.1.0
@@ -44,25 +48,22 @@ Location: /usr/local/google/home/wanlindu/env/lib/python3.13/site-packages
4448
Requires: PyYAML, requests
4549
Required-by:
4650
Files:
47-
src/test_server_sdk/__init__.py
48-
src/test_server_sdk/__pycache__/__init__.cpython-313.pyc
49-
src/test_server_sdk/__pycache__/test_server_wrapper.cpython-313.pyc
50-
src/test_server_sdk/test_server_wrapper.py
51+
../../../bin/download_golang_executable
5152
test_server_sdk-0.1.0.dist-info/INSTALLER
5253
test_server_sdk-0.1.0.dist-info/METADATA
5354
test_server_sdk-0.1.0.dist-info/RECORD
5455
test_server_sdk-0.1.0.dist-info/REQUESTED
5556
test_server_sdk-0.1.0.dist-info/WHEEL
5657
test_server_sdk-0.1.0.dist-info/direct_url.json
58+
test_server_sdk-0.1.0.dist-info/entry_points.txt
5759
test_server_sdk-0.1.0.dist-info/licenses/LICENSE
5860
test_server_sdk-0.1.0.dist-info/top_level.txt
5961
test_server_sdk/__init__.py
6062
test_server_sdk/__pycache__/__init__.cpython-313.pyc
63+
test_server_sdk/__pycache__/install.cpython-313.pyc
6164
test_server_sdk/__pycache__/test_server_wrapper.cpython-313.pyc
62-
test_server_sdk/bin/CHANGELOG.md
63-
test_server_sdk/bin/LICENSE
64-
test_server_sdk/bin/README.md
65-
test_server_sdk/bin/test-server
65+
test_server_sdk/checksums.json
66+
test_server_sdk/install.py
6667
test_server_sdk/test_server_wrapper.py
6768
```
6869

sdks/python/pyproject.toml

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,8 @@ dependencies = [
2828
Homepage = "https://github.com/google/test-server/sdks/python"
2929
Issues = "https://github.com/google/test-server/issues"
3030

31-
[tool.setuptools]
32-
cmdclass = { bdist_wheel = "install.CustomBuild" }
31+
[tool.setuptools.package-data]
32+
"*" = ["*.*"]
3333

34-
[tool.setuptools.packages.find]
35-
where = ["src", "."]
36-
exclude = ["sample*"]
34+
[project.scripts]
35+
download_golang_executable = "test_server_sdk.install:main_downloader_function"

sdks/python/sample/test-data/recordings/396bab503f4b90ad88858bb4467d59b9e827dcd82e33f41c230e1b8fb43bdc8c.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,18 +28,18 @@
2828
"Cache-Control": "max-age=0, private, must-revalidate",
2929
"Content-Encoding": "gzip",
3030
"Content-Language": "en-US",
31-
"Content-Security-Policy": "default-src 'none'; base-uri 'self'; child-src github.githubassets.com github.com/assets-cdn/worker/ github.com/assets/ gist.github.com/assets-cdn/worker/; connect-src 'self' uploads.github.com www.githubstatus.com collector.github.com raw.githubusercontent.com api.github.com github-cloud.s3.amazonaws.com github-production-repository-file-5c1aeb.s3.amazonaws.com github-production-upload-manifest-file-7fdce7.s3.amazonaws.com github-production-user-asset-6210df.s3.amazonaws.com *.rel.tunnels.api.visualstudio.com wss://*.rel.tunnels.api.visualstudio.com objects-origin.githubusercontent.com copilot-proxy.githubusercontent.com proxy.individual.githubcopilot.com proxy.business.githubcopilot.com proxy.enterprise.githubcopilot.com *.actions.githubusercontent.com wss://*.actions.githubusercontent.com productionresultssa0.blob.core.windows.net/ productionresultssa1.blob.core.windows.net/ productionresultssa2.blob.core.windows.net/ productionresultssa3.blob.core.windows.net/ productionresultssa4.blob.core.windows.net/ productionresultssa5.blob.core.windows.net/ productionresultssa6.blob.core.windows.net/ productionresultssa7.blob.core.windows.net/ productionresultssa8.blob.core.windows.net/ productionresultssa9.blob.core.windows.net/ productionresultssa10.blob.core.windows.net/ productionresultssa11.blob.core.windows.net/ productionresultssa12.blob.core.windows.net/ productionresultssa13.blob.core.windows.net/ productionresultssa14.blob.core.windows.net/ productionresultssa15.blob.core.windows.net/ productionresultssa16.blob.core.windows.net/ productionresultssa17.blob.core.windows.net/ productionresultssa18.blob.core.windows.net/ productionresultssa19.blob.core.windows.net/ github-production-repository-image-32fea6.s3.amazonaws.com github-production-release-asset-2e65be.s3.amazonaws.com insights.github.com wss://alive.github.com wss://alive-staging.github.com api.githubcopilot.com api.individual.githubcopilot.com api.business.githubcopilot.com api.enterprise.githubcopilot.com github.githubassets.com; font-src github.githubassets.com; form-action 'self' github.com gist.github.com copilot-workspace.githubnext.com objects-origin.githubusercontent.com; frame-ancestors 'none'; frame-src viewscreen.githubusercontent.com notebooks.githubusercontent.com www.youtube-nocookie.com; img-src 'self' data: blob: github.githubassets.com media.githubusercontent.com camo.githubusercontent.com identicons.github.com avatars.githubusercontent.com private-avatars.githubusercontent.com github-cloud.s3.amazonaws.com objects.githubusercontent.com release-assets.githubusercontent.com secured-user-images.githubusercontent.com/ user-images.githubusercontent.com/ private-user-images.githubusercontent.com opengraph.githubassets.com copilotprodattachments.blob.core.windows.net/github-production-copilot-attachments/ github-production-user-asset-6210df.s3.amazonaws.com customer-stories-feed.github.com spotlights-feed.github.com objects-origin.githubusercontent.com *.githubusercontent.com images.ctfassets.net/8aevphvgewt8/; manifest-src 'self'; media-src github.com user-images.githubusercontent.com/ secured-user-images.githubusercontent.com/ private-user-images.githubusercontent.com github-production-user-asset-6210df.s3.amazonaws.com gist.github.com github.githubassets.com assets.ctfassets.net/8aevphvgewt8/ videos.ctfassets.net/8aevphvgewt8/; script-src github.githubassets.com; style-src 'unsafe-inline' github.githubassets.com; upgrade-insecure-requests; worker-src github.githubassets.com github.com/assets-cdn/worker/ github.com/assets/ gist.github.com/assets-cdn/worker/",
31+
"Content-Security-Policy": "default-src 'none'; base-uri 'self'; child-src github.githubassets.com github.com/assets-cdn/worker/ github.com/assets/ gist.github.com/assets-cdn/worker/; connect-src 'self' uploads.github.com www.githubstatus.com collector.github.com raw.githubusercontent.com api.github.com github-cloud.s3.amazonaws.com github-production-repository-file-5c1aeb.s3.amazonaws.com github-production-upload-manifest-file-7fdce7.s3.amazonaws.com github-production-user-asset-6210df.s3.amazonaws.com *.rel.tunnels.api.visualstudio.com wss://*.rel.tunnels.api.visualstudio.com objects-origin.githubusercontent.com copilot-proxy.githubusercontent.com proxy.individual.githubcopilot.com proxy.business.githubcopilot.com proxy.enterprise.githubcopilot.com *.actions.githubusercontent.com wss://*.actions.githubusercontent.com productionresultssa0.blob.core.windows.net/ productionresultssa1.blob.core.windows.net/ productionresultssa2.blob.core.windows.net/ productionresultssa3.blob.core.windows.net/ productionresultssa4.blob.core.windows.net/ productionresultssa5.blob.core.windows.net/ productionresultssa6.blob.core.windows.net/ productionresultssa7.blob.core.windows.net/ productionresultssa8.blob.core.windows.net/ productionresultssa9.blob.core.windows.net/ productionresultssa10.blob.core.windows.net/ productionresultssa11.blob.core.windows.net/ productionresultssa12.blob.core.windows.net/ productionresultssa13.blob.core.windows.net/ productionresultssa14.blob.core.windows.net/ productionresultssa15.blob.core.windows.net/ productionresultssa16.blob.core.windows.net/ productionresultssa17.blob.core.windows.net/ productionresultssa18.blob.core.windows.net/ productionresultssa19.blob.core.windows.net/ github-production-repository-image-32fea6.s3.amazonaws.com github-production-release-asset-2e65be.s3.amazonaws.com insights.github.com wss://alive.github.com wss://alive-staging.github.com api.githubcopilot.com api.individual.githubcopilot.com api.business.githubcopilot.com api.enterprise.githubcopilot.com github.githubassets.com edge.fullstory.com rs.fullstory.com; font-src github.githubassets.com; form-action 'self' github.com gist.github.com copilot-workspace.githubnext.com objects-origin.githubusercontent.com; frame-ancestors 'none'; frame-src viewscreen.githubusercontent.com notebooks.githubusercontent.com www.youtube-nocookie.com; img-src 'self' data: blob: github.githubassets.com media.githubusercontent.com camo.githubusercontent.com identicons.github.com avatars.githubusercontent.com private-avatars.githubusercontent.com github-cloud.s3.amazonaws.com objects.githubusercontent.com release-assets.githubusercontent.com secured-user-images.githubusercontent.com/ user-images.githubusercontent.com/ private-user-images.githubusercontent.com opengraph.githubassets.com marketplace-screenshots.githubusercontent.com/ copilotprodattachments.blob.core.windows.net/github-production-copilot-attachments/ github-production-user-asset-6210df.s3.amazonaws.com customer-stories-feed.github.com spotlights-feed.github.com objects-origin.githubusercontent.com *.githubusercontent.com images.ctfassets.net/8aevphvgewt8/; manifest-src 'self'; media-src github.com user-images.githubusercontent.com/ secured-user-images.githubusercontent.com/ private-user-images.githubusercontent.com github-production-user-asset-6210df.s3.amazonaws.com gist.github.com github.githubassets.com assets.ctfassets.net/8aevphvgewt8/ videos.ctfassets.net/8aevphvgewt8/; script-src github.githubassets.com; style-src 'unsafe-inline' github.githubassets.com; upgrade-insecure-requests; worker-src github.githubassets.com github.com/assets-cdn/worker/ github.com/assets/ gist.github.com/assets-cdn/worker/",
3232
"Content-Type": "text/html; charset=utf-8",
33-
"Date": "Thu, 28 Aug 2025 16:27:20 GMT",
34-
"Etag": "W/\"386abcfaf4ff44a2cbfe6a90d3b1d6bf\"",
33+
"Date": "Tue, 09 Sep 2025 15:53:45 GMT",
34+
"Etag": "W/\"8bab6ba1a0068ba77443041a70a012fc\"",
3535
"Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin",
3636
"Server": "github.com",
37-
"Set-Cookie": "_gh_sess=LU54Wf8u3%2B7e1lbnM9LXqhwCyguiOMnGz%2FNGGANwWRg6UkobMXf3bqzDnwD64hIz5SAYSEM3L7IW%2FnzMF6AocWUE6uTxfE93SbuD8kvB1sbsBJlG3DKsg9eZicTdzOZihy3aCv1Y7syr0ZSlp3eKncPgpTAYlwoQGkTDoL1ly84KK2%2F9uGLbKTT2Q1dzWO7KAuP8znAQ98y%2FifLijPjexup%2BWvn95A4SCywsc3XcDgHYP%2BFh6na7uM1pO5toR9li4h2DpBlF5vne2m%2B0jDC0Mg%3D%3D--mDFUX5IeIv53eGZl--dmN4h2k8jrFI5%2Be%2FFUNaYw%3D%3D; Path=/; HttpOnly; Secure; SameSite=Lax, _octo=GH1.1.778961946.1756398441; Path=/; Domain=github.com; Expires=Fri, 28 Aug 2026 16:27:21 GMT; Secure; SameSite=Lax, logged_in=no; Path=/; Domain=github.com; Expires=Fri, 28 Aug 2026 16:27:21 GMT; HttpOnly; Secure; SameSite=Lax",
37+
"Set-Cookie": "_gh_sess=jjLJMJHJa3yHLlB%2FstksHC7tyxHlTIGMZnISFDY5YvN2pZ40k9erSjDcL6N4fwiK3tI4gqB3ZMiFacRZPexRYU%2Fa4QKkFSyDN1oRGfv19gkqDJWH0UygUOc9239ontofFzh8rPEEnLdtPR3Jxq1Mb2sqs8e9MTvgTueqp1XRNElJvU3h0%2BocyQ%2Fr8XI4pIdLm64jp34ysCaisN%2FFXBa9SHzEIpGfQlrvihtWYcWP%2Bmzl0S5MAwox3%2BVFOiUPdf2AnD86OMXJekNHcxgzc41SPA%3D%3D--bex5KbZP2AtUtYXh--rcQmgTr4hiau78tUK896nQ%3D%3D; Path=/; HttpOnly; Secure; SameSite=Lax, _octo=GH1.1.1430909772.1757433231; Path=/; Domain=github.com; Expires=Wed, 09 Sep 2026 15:53:51 GMT; Secure; SameSite=Lax, logged_in=no; Path=/; Domain=github.com; Expires=Wed, 09 Sep 2026 15:53:51 GMT; HttpOnly; Secure; SameSite=Lax",
3838
"Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload",
3939
"Vary": "X-PJAX, X-PJAX-Container, Turbo-Visit, Turbo-Frame, X-Requested-With, Accept-Language,Accept-Encoding, Accept, X-Requested-With",
4040
"X-Content-Type-Options": "nosniff",
4141
"X-Frame-Options": "deny",
42-
"X-Github-Request-Id": "C832:288B0E:2DB350:2E5DA4:68B08369",
42+
"X-Github-Request-Id": "D811:22D066:299B1F:2A4602:68C04D8F",
4343
"X-Xss-Protection": "0"
4444
}
4545
}
File renamed without changes.

sdks/python/install.py renamed to sdks/python/src/test_server_sdk/install.py

Lines changed: 51 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -22,21 +22,22 @@
2222
import json
2323
from pathlib import Path
2424
import requests
25-
from setuptools.command.bdist_wheel import bdist_wheel
26-
25+
import subprocess
2726

2827
# --- Configuration ---
2928
TEST_SERVER_VERSION = "v0.2.7"
3029
GITHUB_OWNER = "google"
3130
GITHUB_REPO = "test-server"
3231
PROJECT_NAME = "test-server"
32+
PROJECT_ROOT = Path(__file__).parent
33+
34+
CHECKSUMS_PATH = PROJECT_ROOT / "checksums.json"
3335

34-
CHECKSUMS_PATH = Path(__file__).parent / "checksums.json"
3536
try:
3637
with open(CHECKSUMS_PATH, "r") as f:
3738
ALL_EXPECTED_CHECKSUMS = json.load(f)
3839
except (FileNotFoundError, json.JSONDecodeError) as e:
39-
print(f"Error loading checksums.json: {e}")
40+
print(f"Error loading checksums.json: {e}", file=sys.stderr)
4041
sys.exit(1)
4142

4243

@@ -101,7 +102,7 @@ def download_and_verify(download_url, archive_path, version, archive_name):
101102
except Exception as e:
102103
if archive_path.exists():
103104
archive_path.unlink()
104-
print(f"Failed during download or verification: {e}")
105+
print(f"Failed during download or verification: {e}", file=sys.stderr)
105106
raise
106107

107108

@@ -129,6 +130,34 @@ def ensure_binary_is_executable(binary_path, go_os):
129130
os.chmod(binary_path, st.st_mode | stat.S_IEXEC)
130131
print(f"Set executable permission for {binary_path}")
131132

133+
def verify_binary_usability(binary_path: Path) -> None:
134+
"""
135+
Verifies the binary can be executed by running a simple command.
136+
This helps catch corrupted downloads or architecture mismatches.
137+
"""
138+
print(f"Verifying usability of binary at {binary_path}...")
139+
try:
140+
# Running with "--help" is a safe, standard way to check execution
141+
subprocess.run(
142+
[str(binary_path), "--help"],
143+
capture_output=True,
144+
text=True,
145+
check=True, # This will raise CalledProcessError on non-zero exit codes
146+
timeout=10
147+
)
148+
print("Binary is executable and responding correctly.")
149+
except (subprocess.CalledProcessError, FileNotFoundError, PermissionError, subprocess.TimeoutExpired) as e:
150+
print(f"ERROR: The binary at {binary_path} is not usable. Error: {e}", file=sys.stderr)
151+
# Clean up the bad binary
152+
if binary_path.exists():
153+
binary_path.unlink()
154+
raise RuntimeError(
155+
f"The downloaded binary at {binary_path} could not be executed. "
156+
"This can mean a corrupted download or an incorrect binary for your OS/architecture. "
157+
"The invalid binary has been removed. Please try running the installation again. "
158+
"Run: download_golang_executable"
159+
) from e
160+
132161

133162
def install_binary(bin_dir: Path):
134163
"""Main function to orchestrate the installation to a specific directory."""
@@ -150,22 +179,26 @@ def install_binary(bin_dir: Path):
150179
download_and_verify(download_url, archive_path, version, archive_name)
151180
extract_archive(archive_path, archive_extension, bin_dir)
152181
ensure_binary_is_executable(binary_path, go_os)
153-
print(f"{PROJECT_NAME} binary is ready at {binary_path}")
182+
verify_binary_usability(binary_path)
183+
print(f"\n{PROJECT_NAME} binary is ready at {binary_path}")
154184
except Exception as e:
155-
print(f"An error occurred during binary installation: {e}")
156-
sys.exit(1)
185+
print(f"\nAn error occurred during binary installation: {e}", file=sys.stderr)
186+
# Re-raise the exception to be caught by the entry point function
187+
raise
157188

158189

159-
# --- The Setuptools Hook ---
160-
class CustomBuild(bdist_wheel):
161-
"""Custom build command to download the binary into the correct build location."""
162-
def run(self):
163-
print("--- Executing CustomBuild hook to download binary! ---")
164190

165-
build_py = self.get_finalized_command('build_py')
166-
build_dir = Path(build_py.build_lib)
167-
bin_path = build_dir / 'test_server_sdk' / 'bin'
191+
def main_downloader_function():
192+
"""
193+
Entry point that determines the install location and calls the installation logic.
194+
"""
195+
install_location = PROJECT_ROOT / "bin"
196+
197+
try:
198+
install_binary(install_location)
199+
except Exception:
200+
sys.exit(1)
168201

169-
install_binary(bin_path)
170202

171-
super().run()
203+
if __name__ == "__main__":
204+
main_downloader_function()

0 commit comments

Comments
 (0)