From 4d1651d03895cbb22e3defacac439ba13b7111e2 Mon Sep 17 00:00:00 2001 From: Daniel Mach Date: Thu, 4 Jul 2024 14:17:09 +0200 Subject: [PATCH 1/2] Fix colorize() to avoid wrapping empty string into color escape sequences --- osc/output/tty.py | 3 +++ tests/test_output.py | 7 +++++++ 2 files changed, 10 insertions(+) diff --git a/osc/output/tty.py b/osc/output/tty.py index c99a6e35a7..acb104f608 100644 --- a/osc/output/tty.py +++ b/osc/output/tty.py @@ -44,6 +44,9 @@ def colorize(text, color): if not color: return text + if not text: + return text + result = "" for i in color.split(","): result += ESCAPE_CODES[i] diff --git a/tests/test_output.py b/tests/test_output.py index 9800a499e7..cabe296303 100644 --- a/tests/test_output.py +++ b/tests/test_output.py @@ -74,6 +74,13 @@ def test_wide_chars(self): """.strip() self.assertEqual(str(t), expected) + def test_empty_value_no_color(self): + t = KeyValueTable() + t.add("Key", "", color="bold") + + expected = "Key : " + self.assertEqual(str(t), expected) + class TestPrintMsg(unittest.TestCase): def setUp(self): From 52f076636d09c25787c947ed14544ead9b4a113c Mon Sep 17 00:00:00 2001 From: Daniel Mach Date: Thu, 4 Jul 2024 14:21:48 +0200 Subject: [PATCH 2/2] Make most of the fields in KeyinfoPubkey and KeyinfoSslcert models optional The presence of the fields seems to be random and the only truly required field is the actual public key/cert. Other fields are only for the information. --- osc/obs_api/keyinfo_pubkey.py | 16 ++++++++----- osc/obs_api/keyinfo_sslcert.py | 20 +++++++++++----- tests/test_keyinfo.py | 43 ++++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+), 12 deletions(-) create mode 100644 tests/test_keyinfo.py diff --git a/osc/obs_api/keyinfo_pubkey.py b/osc/obs_api/keyinfo_pubkey.py index a3c995153b..6c516de789 100644 --- a/osc/obs_api/keyinfo_pubkey.py +++ b/osc/obs_api/keyinfo_pubkey.py @@ -4,27 +4,27 @@ class KeyinfoPubkey(XmlModel): XML_TAG = "pubkey" - keyid: str = Field( + keyid: Optional[str] = Field( xml_attribute=True, ) - userid: str = Field( + userid: Optional[str] = Field( xml_attribute=True, ) - algo: str = Field( + algo: Optional[str] = Field( xml_attribute=True, ) - keysize: str = Field( + keysize: Optional[str] = Field( xml_attribute=True, ) - expires: int = Field( + expires: Optional[int] = Field( xml_attribute=True, ) - fingerprint: str = Field( + fingerprint: Optional[str] = Field( xml_attribute=True, ) @@ -34,6 +34,10 @@ class KeyinfoPubkey(XmlModel): def get_expires_str(self) -> str: import datetime + + if self.expires is None: + return "" + return datetime.datetime.fromtimestamp(self.expires).strftime("%Y-%m-%d %H:%M:%S") def to_human_readable_string(self) -> str: diff --git a/osc/obs_api/keyinfo_sslcert.py b/osc/obs_api/keyinfo_sslcert.py index cfbf2fbac4..4119001bd0 100644 --- a/osc/obs_api/keyinfo_sslcert.py +++ b/osc/obs_api/keyinfo_sslcert.py @@ -8,7 +8,7 @@ class KeyinfoSslcert(XmlModel): xml_attribute=True, ) - serial: str = Field( + serial: Optional[str] = Field( xml_attribute=True, ) @@ -16,23 +16,23 @@ class KeyinfoSslcert(XmlModel): xml_attribute=True, ) - subject: str = Field( + subject: Optional[str] = Field( xml_attribute=True, ) - algo: str = Field( + algo: Optional[str] = Field( xml_attribute=True, ) - keysize: str = Field( + keysize: Optional[str] = Field( xml_attribute=True, ) - begins: int = Field( + begins: Optional[int] = Field( xml_attribute=True, ) - expires: int = Field( + expires: Optional[int] = Field( xml_attribute=True, ) @@ -46,10 +46,18 @@ class KeyinfoSslcert(XmlModel): def get_begins_str(self) -> str: import datetime + + if self.begins is None: + return "" + return datetime.datetime.fromtimestamp(self.begins).strftime("%Y-%m-%d %H:%M:%S") def get_expires_str(self) -> str: import datetime + + if self.expires is None: + return "" + return datetime.datetime.fromtimestamp(self.expires).strftime("%Y-%m-%d %H:%M:%S") def to_human_readable_string(self) -> str: diff --git a/tests/test_keyinfo.py b/tests/test_keyinfo.py new file mode 100644 index 0000000000..9acff8ddff --- /dev/null +++ b/tests/test_keyinfo.py @@ -0,0 +1,43 @@ +import unittest + +from osc import obs_api + + +class TestKeyinfo(unittest.TestCase): + def test_empty_pubkey(self): + ki = obs_api.Keyinfo() + ki.pubkey_list = [{"value": ""}] + + expected = """ +Type : GPG public key +User ID : +Algorithm : +Key size : +Expires : +Fingerprint : +""".strip() + actual = ki.pubkey_list[0].to_human_readable_string() + self.assertEqual(expected, actual) + + def test_empty_sslcert(self): + ki = obs_api.Keyinfo() + ki.sslcert_list = [{"value": ""}] + + expected = """ +Type : SSL certificate +Subject : +Key ID : +Serial : +Issuer : +Algorithm : +Key size : +Begins : +Expires : +Fingerprint : +""".strip() + actual = ki.sslcert_list[0].to_human_readable_string() + self.assertEqual(expected, actual) + + +if __name__ == "__main__": + unittest.main()