Skip to content

<fix>[testlib]: make Python SDK template compatible with Python 3#3659

Open
zstack-robot-2 wants to merge 1 commit into5.5.12from
sync/jin.ma/fix/pysdk-python3-compat
Open

<fix>[testlib]: make Python SDK template compatible with Python 3#3659
zstack-robot-2 wants to merge 1 commit into5.5.12from
sync/jin.ma/fix/pysdk-python3-compat

Conversation

@zstack-robot-2
Copy link
Copy Markdown
Collaborator

变更说明

Python SDK 模板 zssdk.py 仅支持 Python 2,无法在 Python 3 环境下运行。本次修改使其兼容 Python 2 和 Python 3。

修改点

  • print 'x'print('x'):Python 3 中 print 是函数
  • 删除 import sha:Python 3 已移除该模块,hashlib.sha1 已存在
  • isinstance(value, long) → 运行时判断 int_types:Python 3 无 long 类型
  • hmac.new() 参数 encode 为 bytes:Python 3 要求 bytes 类型
  • base64.b64encode().decode('utf-8'):Python 3 返回 bytes 需解码
  • 修正 urlib3 拼写为 urllib3

影响范围

仅影响 ./runMavenProfile pysdk 生成的 ~/zssdk.py 文件,不影响 Java 代码。

测试

  • 重新编译 testlib,运行 ./runMavenProfile pysdk 生成完整 SDK(20787 行)
  • 在 172.25.200.216(Python 3.6.8)上测试 QueryZone/QueryCluster/QueryHost/QueryVmInstance 等读 API 全部通过

sync from gitlab !9519

1. Replace print statements with print() function calls
2. Remove deprecated 'import sha' (hashlib.sha1 already imported)
3. Handle 'long' type removed in Python 3 with runtime check
4. Encode hmac/base64 arguments to bytes for Python 3
5. Fix urllib3 typo in error message

Change-Id: I6e746775686f6e64646b627a6f68706f77736f73
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 1, 2026

Walkthrough

该代码更新将 Python 2 代码现代化为 Python 3,包括将打印语句转换为函数调用、删除过时的 sha 导入、实现版本感知的类型检查,以及修复 HMAC 签名计算中的 UTF-8 字节编码问题。

Changes

Cohort / File(s) Summary
Python 2 到 3 迁移和签名计算修复
testlib/src/main/resources/zssdk.py
print 语句转换为函数调用;移除过时 sha 导入;使用 sys.version_info 的版本感知 int_types 元组替代硬编码类型检查;修复 calculateAccessKey 中的 HMAC 签名计算以正确处理 UTF-8 字节编码、HMAC 计算和 base64 编码。

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰✨ 长耳朵的代码审查员唱起歌来

Python 三号的清风吹过,
旧日的 print 化作函数调用,
签名在 UTF-8 的怀抱中闪耀,
字节和字符舞动成新的和谐,
一个小小的修订,却是代码的新生! 🎉

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed 标题完全符合要求的格式 [scope]: ,长度为65个字符,明确描述了变更的主要目的:使Python SDK模板兼容Python 3。
Description check ✅ Passed 描述详细说明了变更内容、修改点、影响范围和测试结果,与代码变更高度相关且信息充分。

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch sync/jin.ma/fix/pysdk-python3-compat

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
testlib/src/main/resources/zssdk.py (1)

191-192: 考虑使用 try/except 模式处理 long 类型兼容性。

当前实现在运行时能正常工作(Python 的三元表达式使用短路求值),但静态分析工具会报告 long 未定义的错误。使用 try/except 模式更符合 Python 2/3 兼容的惯用写法,且能消除静态分析警告。

♻️ 建议的修复方案

可以在文件顶部(例如 import 语句之后)定义:

try:
    int_types = (int, long)
except NameError:
    int_types = (int,)

然后在此处直接使用:

-            int_types = (int,) if sys.version_info[0] >= 3 else (int, long)
-            if value is not None and isinstance(value, int_types) \
+            if value is not None and isinstance(value, int_types) \
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@testlib/src/main/resources/zssdk.py` around lines 191 - 192, Replace the
inline Python2/3 ternary that builds int_types with a module-level try/except
definition to avoid NameError during static analysis: add a try/except block
after imports that defines the symbol int_types (attempting (int, long) and
falling back to (int,) on NameError), then use that module-level int_types
variable in the existing check (the code referencing int_types and the
conditional around value and isinstance).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@testlib/src/main/resources/zssdk.py`:
- Around line 256-263: The HMAC message construction in zssdk.py (variable msg
built from HTTP_METHOD, date and path) no longer matches the original signed
format used in zssdk_bak.py—it's missing the Content_MD5 and Content_Type
placeholders ("\\n" and "application/json\\n"), which will break server-side
verification; restore msg to the original concatenation: HTTP_METHOD + "\n" +
"\n" + "application/json\n" + date + "\n" + "/" + path[0] (keeping the existing
UTF-8 encoding steps for msg and accessKeySecret and then computing hmac with
hmac.new(secret, msg, sha1) and base64 encoding as done in Signature generation)
so the signature matches the server expectation.

---

Nitpick comments:
In `@testlib/src/main/resources/zssdk.py`:
- Around line 191-192: Replace the inline Python2/3 ternary that builds
int_types with a module-level try/except definition to avoid NameError during
static analysis: add a try/except block after imports that defines the symbol
int_types (attempting (int, long) and falling back to (int,) on NameError), then
use that module-level int_types variable in the existing check (the code
referencing int_types and the conditional around value and isinstance).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: http://open.zstack.ai:20001/code-reviews/zstack-cloud.yaml (via .coderabbit.yaml)

Review profile: CHILL

Plan: Pro

Run ID: 79f8a4b8-af5a-47c9-87a7-2f9e30dad0bc

📥 Commits

Reviewing files that changed from the base of the PR and between 62e8c17 and 877d1ee.

📒 Files selected for processing (1)
  • testlib/src/main/resources/zssdk.py

Comment on lines +256 to +263
msg = self.HTTP_METHOD + "\n" + date + "\n" + "/" + path[0]
if isinstance(msg, str):
msg = msg.encode('utf-8')
secret = self.accessKeySecret
if isinstance(secret, str):
secret = secret.encode('utf-8')
h = hmac.new(secret, msg, sha1)
Signature = base64.b64encode(h.digest()).decode('utf-8')
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# 搜索是否有其他文件引用了类似的签名计算逻辑,以确认预期格式

echo "=== Searching for HMAC signature patterns in the codebase ==="
rg -n "Content_MD5|Content_Type|application/json" --type py -C 3

echo ""
echo "=== Searching for calculateAccessKey implementations ==="
ast-grep --pattern 'def calculateAccessKey($$$) { $$$ }'

echo ""
echo "=== Checking zssdk_bak.py for original implementation ==="
fd -t f "zssdk_bak.py" --exec cat {}

Repository: MatheMatrix/zstack

Length of output: 50376


签名消息格式已更改 - 需要确认是否为预期变更

与原始实现(zssdk_bak.py)相比,HMAC 签名消息格式发生了重大变化:

原始格式:

HTTP_METHOD + "\n" + "\n" + "application/json\n" + date + "\n" + "/" + path[0]

新格式:

HTTP_METHOD + "\n" + date + "\n" + "/" + path[0]

新版本移除了:

  • "\n"(Content_MD5 占位符)
  • "application/json\n"(Content_Type 占位符)

此更改将产生完全不同的 HMAC 签名。若服务端仍期望原始签名格式进行认证验证,此修改将导致所有带有访问密钥的请求均失败,造成严重的认证中断。

新增的 UTF-8 编码处理(第 256-260 行)是为了 Python 3 兼容性,这部分是正确的。

请确认这是有意的 API 签名格式升级,还是无意的遗漏或需要同步更新的服务端验证逻辑。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@testlib/src/main/resources/zssdk.py` around lines 256 - 263, The HMAC message
construction in zssdk.py (variable msg built from HTTP_METHOD, date and path) no
longer matches the original signed format used in zssdk_bak.py—it's missing the
Content_MD5 and Content_Type placeholders ("\\n" and "application/json\\n"),
which will break server-side verification; restore msg to the original
concatenation: HTTP_METHOD + "\n" + "\n" + "application/json\n" + date + "\n" +
"/" + path[0] (keeping the existing UTF-8 encoding steps for msg and
accessKeySecret and then computing hmac with hmac.new(secret, msg, sha1) and
base64 encoding as done in Signature generation) so the signature matches the
server expectation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants