如果有异常,如果能附带帮忙 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 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)

