哪位朋友帮忙用 mac 测试下我的 Python 脚本

gosky 2026-07-10 16:51 1

把输出贴给我

如果有异常,如果能附带帮忙 fix 更好


import signal
import subprocess
from typing import OrderedDict

APP_NAME = "Hello"


class CalledProcessError(subprocess.CalledProcessError):
"""
`subprocess.CalledProcessError` does not print `stderr` and `output`.
"""

def __str__(self):
if self.returncode and self.returncode < 0:
try:
return "Command '%s' died with %r." % (
self.cmd,
signal.Signals(-self.returncode),
)
except ValueError:
return "Command '%s' died with unknown signal %d." % (
self.cmd,
-self.returncode,
)
else:
return (
"Command '%s' returned non-zero exit status %d. stderr: '%s'. output: '%s'"
% (self.cmd, self.returncode, self.stderr.strip(), self.output.strip())
)


class DecryptError(Exception): ...


class DarwinCryptex:
scheme = "security"

def encrypt(self, attrs: OrderedDict[str, str], plaintext: str) -> str:
account = "-".join([f"{k}:{v}" for k, v in attrs.items()])
cmd = [
"security",
"add-generic-password",
"-a",
account,
"-s",
APP_NAME,
"-w",
plaintext,
"-U",
]
r = subprocess.run(
cmd,
capture_output=True,
encoding="utf-8",
text=True,
timeout=5,
)
if r.returncode != 0:
raise CalledProcessError(
r.returncode, cmd, output=r.stdout, stderr=r.stderr
)
return "******"

def decrypt(self, attrs: OrderedDict[str, str], ciphertext: str) -> str:
account = "-".join([f"{k}:{v}" for k, v in attrs.items()])
cmd = [
"security",
"find-generic-password",
"-a",
account,
"-s",
APP_NAME,
"-w",
]
r = subprocess.run(
cmd,
capture_output=True,
encoding="utf-8",
text=True,
timeout=5,
)
if r.returncode == 0:
return r.stdout.strip()
elif r.returncode == 44:
raise DecryptError()
else:
raise CalledProcessError(
r.returncode, cmd, output=r.stdout, stderr=r.stderr
)

def clean(self, attrs: OrderedDict[str, str]):
account = "-".join([f"{k}:{v}" for k, v in attrs.items()])
cmd = ["security", "delete-generic-password", "-a", account, "-s", APP_NAME]
r = subprocess.run(
cmd, capture_output=True, encoding="utf-8", text=True, timeout=5
)
if r.returncode not in (0, 44):
raise CalledProcessError(
r.returncode, cmd, output=r.stdout, stderr=r.stderr
)


cryptex = DarwinCryptex()
attrs: OrderedDict[str, str] = OrderedDict(
[
("app", "test"),
("section", "hello"),
("key", "你好"),
]
)
plaintext = "Hello world! 你好,世界!"

try:
ciphertext = cryptex.encrypt(attrs, plaintext)
decrypted = cryptex.decrypt(attrs, ciphertext)
assert decrypted == plaintext

mismatch_attrs = attrs.copy()
mismatch_attrs["needless"] = "有毒"
try:
cryptex.decrypt(mismatch_attrs, ciphertext)
except DecryptError:
pass
else:
raise AssertionError("Expected DecryptError")
finally:
cryptex.clean(attrs)

最新回复 (12)
  • busln 07-10 17:05
    1
    assert decrypted == plaintext

    不成立报错了

    且 encrypt 是不是没写完全呀
  • gosky 楼主 07-10 17:14
    2
    @busln
    感觉是写完了
    把两个变量都打印瞧瞧?
  • busln 07-10 17:26
    3
    程序有问题, 没写进去
  • gosky 楼主 07-10 17:37
    4
    @busln 我用 claude review 了下,没大问题啊
  • zhhanging 07-10 17:42
    5
    assert 失败,打印两个变量如下
    decrypted: 48656c6c6f20776f726c642120e4bda0e5a5bdefbc8ce4b896e7958cefbc81
    plaintext: Hello world! 你好,世界!
    应该是遇到非 ascii 字符给他转成 hex 了
  • gosky 楼主 07-10 17:48
    6
    @zhhanging
    "Hello world! 你好,世界!".encode('utf-8').hex()
    刚好是
    '48656c6c6f20776f726c642120e4bda0e5a5bdefbc8ce4b896e7958cefbc81'
  • busln 07-10 17:52
    7
    finally 给删了,漏看了
    @gosky
  • busln 07-10 17:53
    8
    bytes.fromhex(hex).decode("utf-8")
    这样就能转换回来了
  • gosky 楼主 07-10 17:56
    9
    @busln
    把下面的中文字符,全换成英文字母,会怎么样?

    attrs: OrderedDict[str, str] = OrderedDict(
    [
    ("app", "test"),
    ("section", "hello"),
    ("key", "你好"),
    ]
    )
    plaintext = "Hello world! 你好,世界!"
  • keakon 07-10 18:17
    10
    你在 github 上建个 ci ,让它用 macos 的容器跑不就行了。。
  • gosky 楼主 07-10 18:23
    11
    @keakon 是的。正这么玩着。感谢
  • wenrouxiaozhu 07-10 18:26
    12
    开虚拟机+黑苹果也行
* 帖子来源V2EX
返回