diff options
| author | Dave Lee <davelee.com@gmail.com> | 2025-09-04 08:34:34 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-09-04 08:34:34 -0700 |
| commit | d289ff761b2daab625f057efdee25c6616117640 (patch) | |
| tree | 0aed7ceaed62bcf10d64b17c73523aa00e026270 /lldb/test/API/python_api | |
| parent | 1cb47c19f8eca4badd8fb5e1a1b1cf4aaab607b8 (diff) | |
| download | llvm-d289ff761b2daab625f057efdee25c6616117640.zip llvm-d289ff761b2daab625f057efdee25c6616117640.tar.gz llvm-d289ff761b2daab625f057efdee25c6616117640.tar.bz2 | |
[lldb] Reland: Add Pythonic API to SBStructuredData extension (#156771)
* Adds `dynamic` property to automatically convert `SBStructuredData`
instances to the associated Python type (`str`, `int`, `float`, `bool`,
`NoneType`, etc)
* Implements `__getitem__` for Pythonic array and dictionary
subscripting
* Subscripting return the result of the `dynamic` property
* Updates `__iter__` to support dictionary instances (supporting `for`
loops)
* Adds `__str__`, `__int__`, and `__float__`
With these changes, these two expressions are equal:
```py
data["name"] == data.GetValueForKey("name").GetStringValue(1024)
```
**Note**: Unlike the original commit (#155061), this re-commit removes
the `__bool__` implementation, which broke crashlog. Somewhere in the
crashlog execution, it depends on `__bool__` meaning only `IsValid()`.
Additionally did some cleanup in TestStructuredDataAPI.py.
Diffstat (limited to 'lldb/test/API/python_api')
| -rw-r--r-- | lldb/test/API/python_api/sbstructureddata/TestStructuredDataAPI.py | 105 |
1 files changed, 79 insertions, 26 deletions
diff --git a/lldb/test/API/python_api/sbstructureddata/TestStructuredDataAPI.py b/lldb/test/API/python_api/sbstructureddata/TestStructuredDataAPI.py index 99f88d3..b12f4da 100644 --- a/lldb/test/API/python_api/sbstructureddata/TestStructuredDataAPI.py +++ b/lldb/test/API/python_api/sbstructureddata/TestStructuredDataAPI.py @@ -48,10 +48,11 @@ class TestStructuredDataAPI(TestBase): s.Clear() error = example.GetDescription(s) self.assertSuccess(error, "GetDescription works") + # Ensure str() doesn't raise an exception. + self.assertTrue(str(example)) if not "key_float" in s.GetData(): self.fail("FAILED: could not find key_float in description output") - dict_struct = lldb.SBStructuredData() dict_struct = example.GetValueForKey("key_dict") # Tests for dictionary data type @@ -113,18 +114,22 @@ class TestStructuredDataAPI(TestBase): self.assertSuccess(example.SetFromJSON("1")) self.assertEqual(example.GetType(), lldb.eStructuredDataTypeInteger) self.assertEqual(example.GetIntegerValue(), 1) + self.assertEqual(int(example), 1) self.assertSuccess(example.SetFromJSON("4.19")) self.assertEqual(example.GetType(), lldb.eStructuredDataTypeFloat) self.assertEqual(example.GetFloatValue(), 4.19) + self.assertEqual(float(example), 4.19) self.assertSuccess(example.SetFromJSON('"Bonjour, 123!"')) self.assertEqual(example.GetType(), lldb.eStructuredDataTypeString) self.assertEqual(example.GetStringValue(42), "Bonjour, 123!") + self.assertEqual(str(example), "Bonjour, 123!") self.assertSuccess(example.SetFromJSON("true")) self.assertEqual(example.GetType(), lldb.eStructuredDataTypeBoolean) self.assertTrue(example.GetBooleanValue()) + self.assertTrue(example) self.assertSuccess(example.SetFromJSON("null")) self.assertEqual(example.GetType(), lldb.eStructuredDataTypeNull) @@ -187,38 +192,35 @@ class TestStructuredDataAPI(TestBase): self.assertEqual(sb_data, example_arr) def invalid_struct_test(self, example): - invalid_struct = lldb.SBStructuredData() invalid_struct = example.GetValueForKey("invalid_key") if invalid_struct.IsValid(): self.fail("An invalid object should have been returned") # Check Type API - if not invalid_struct.GetType() == lldb.eStructuredDataTypeInvalid: + if invalid_struct.GetType() != lldb.eStructuredDataTypeInvalid: self.fail("Wrong type returned: " + str(invalid_struct.GetType())) def dictionary_struct_test(self, example): # Check API returning a valid SBStructuredData of 'dictionary' type - dict_struct = lldb.SBStructuredData() dict_struct = example.GetValueForKey("key_dict") if not dict_struct.IsValid(): self.fail("A valid object should have been returned") # Check Type API - if not dict_struct.GetType() == lldb.eStructuredDataTypeDictionary: + if dict_struct.GetType() != lldb.eStructuredDataTypeDictionary: self.fail("Wrong type returned: " + str(dict_struct.GetType())) # Check Size API for 'dictionary' type - if not dict_struct.GetSize() == 6: + if dict_struct.GetSize() != 6: self.fail("Wrong no of elements returned: " + str(dict_struct.GetSize())) def string_struct_test(self, dict_struct): - string_struct = lldb.SBStructuredData() string_struct = dict_struct.GetValueForKey("key_string") if not string_struct.IsValid(): self.fail("A valid object should have been returned") # Check Type API - if not string_struct.GetType() == lldb.eStructuredDataTypeString: + if string_struct.GetType() != lldb.eStructuredDataTypeString: self.fail("Wrong type returned: " + str(string_struct.GetType())) # Check API returning 'string' value @@ -238,18 +240,17 @@ class TestStructuredDataAPI(TestBase): # Check a valid SBStructuredData containing an unsigned integer. # We intentionally make this larger than what an int64_t can hold but # still small enough to fit a uint64_t - uint_struct = lldb.SBStructuredData() uint_struct = dict_struct.GetValueForKey("key_uint") if not uint_struct.IsValid(): self.fail("A valid object should have been returned") # Check Type API - if not uint_struct.GetType() == lldb.eStructuredDataTypeInteger: + if uint_struct.GetType() != lldb.eStructuredDataTypeInteger: self.fail("Wrong type returned: " + str(uint_struct.GetType())) # Check API returning unsigned integer value output = uint_struct.GetUnsignedIntegerValue() - if not output == 0xFFFFFFFF00000000: + if output != 0xFFFFFFFF00000000: self.fail("wrong output: " + str(output)) # Calling wrong API on a SBStructuredData @@ -262,18 +263,17 @@ class TestStructuredDataAPI(TestBase): # Check a valid SBStructuredData containing an signed integer. # We intentionally make this smaller than what an uint64_t can hold but # still small enough to fit a int64_t - sint_struct = lldb.SBStructuredData() sint_struct = dict_struct.GetValueForKey("key_sint") if not sint_struct.IsValid(): self.fail("A valid object should have been returned") # Check Type API - if not sint_struct.GetType() == lldb.eStructuredDataTypeSignedInteger: + if sint_struct.GetType() != lldb.eStructuredDataTypeSignedInteger: self.fail("Wrong type returned: " + str(sint_struct.GetType())) # Check API returning signed integer value output = sint_struct.GetSignedIntegerValue() - if not output == -42: + if output != -42: self.fail("wrong output: " + str(output)) # Calling wrong API on a SBStructuredData @@ -283,28 +283,26 @@ class TestStructuredDataAPI(TestBase): self.fail("Valid string " + output + " returned for an integer object") def double_struct_test(self, dict_struct): - floating_point_struct = lldb.SBStructuredData() floating_point_struct = dict_struct.GetValueForKey("key_float") if not floating_point_struct.IsValid(): self.fail("A valid object should have been returned") # Check Type API - if not floating_point_struct.GetType() == lldb.eStructuredDataTypeFloat: + if floating_point_struct.GetType() != lldb.eStructuredDataTypeFloat: self.fail("Wrong type returned: " + str(floating_point_struct.GetType())) # Check API returning 'double' value output = floating_point_struct.GetFloatValue() - if not output == 2.99: + if output != 2.99: self.fail("wrong output: " + str(output)) def bool_struct_test(self, dict_struct): - bool_struct = lldb.SBStructuredData() bool_struct = dict_struct.GetValueForKey("key_bool") if not bool_struct.IsValid(): self.fail("A valid object should have been returned") # Check Type API - if not bool_struct.GetType() == lldb.eStructuredDataTypeBoolean: + if bool_struct.GetType() != lldb.eStructuredDataTypeBoolean: self.fail("Wrong type returned: " + str(bool_struct.GetType())) # Check API returning 'bool' value @@ -314,17 +312,16 @@ class TestStructuredDataAPI(TestBase): def array_struct_test(self, dict_struct): # Check API returning a valid SBStructuredData of 'array' type - array_struct = lldb.SBStructuredData() array_struct = dict_struct.GetValueForKey("key_array") if not array_struct.IsValid(): self.fail("A valid object should have been returned") # Check Type API - if not array_struct.GetType() == lldb.eStructuredDataTypeArray: + if array_struct.GetType() != lldb.eStructuredDataTypeArray: self.fail("Wrong type returned: " + str(array_struct.GetType())) # Check Size API for 'array' type - if not array_struct.GetSize() == 2: + if array_struct.GetSize() != 2: self.fail("Wrong no of elements returned: " + str(array_struct.GetSize())) # Check API returning a valid SBStructuredData for different 'array' @@ -332,17 +329,73 @@ class TestStructuredDataAPI(TestBase): string_struct = array_struct.GetItemAtIndex(0) if not string_struct.IsValid(): self.fail("A valid object should have been returned") - if not string_struct.GetType() == lldb.eStructuredDataTypeString: + if string_struct.GetType() != lldb.eStructuredDataTypeString: self.fail("Wrong type returned: " + str(string_struct.GetType())) output = string_struct.GetStringValue(5) - if not output == "23": + if output != "23": self.fail("wrong output: " + str(output)) string_struct = array_struct.GetItemAtIndex(1) if not string_struct.IsValid(): self.fail("A valid object should have been returned") - if not string_struct.GetType() == lldb.eStructuredDataTypeString: + if string_struct.GetType() != lldb.eStructuredDataTypeString: self.fail("Wrong type returned: " + str(string_struct.GetType())) output = string_struct.GetStringValue(5) - if not output == "arr": + if output != "arr": self.fail("wrong output: " + str(output)) + + def test_round_trip_scalars(self): + for original in (0, 11, -1, 0.0, 4.5, -0.25): + constructor = type(original) + data = lldb.SBStructuredData() + data.SetFromJSON(json.dumps(original)) + round_tripped = constructor(data) + self.assertEqual(round_tripped, original) + + def test_dynamic(self): + for original in (0, 11, -1, 0.0, 4.5, -0.25, "", "dirk", True, False): + data = lldb.SBStructuredData() + data.SetFromJSON(json.dumps(original)) + self.assertEqual(data.dynamic, original) + + def test_round_trip_int(self): + for original in (0, 11, -1): + data = lldb.SBStructuredData() + data.SetFromJSON(json.dumps(original)) + self.assertEqual(int(data), int(original)) + + def test_round_trip_float(self): + for original in (0, 11, -1, 0.0, 4.5, -0.25): + data = lldb.SBStructuredData() + data.SetFromJSON(json.dumps(original)) + self.assertEqual(float(data), float(original)) + + def test_iterate_array(self): + array = [0, 1, 2] + data = lldb.SBStructuredData() + data.SetFromJSON(json.dumps(array)) + for value in data: + self.assertEqual(value, array.pop(0)) + + def test_iterate_dictionary(self): + dictionary = {"0": 0, "1": 1, "2": 2} + keys = set(dictionary.keys()) + data = lldb.SBStructuredData() + data.SetFromJSON(json.dumps(dictionary)) + for key in data: + self.assertIn(key, keys) + keys.remove(key) + + def test_getitem_array(self): + array = [1, 2, 3] + data = lldb.SBStructuredData() + data.SetFromJSON(json.dumps(array)) + for i in range(len(array)): + self.assertEqual(data[i], array[i]) + + def test_getitem_dictionary(self): + dictionary = {"one": 1, "two": 2, "three": 3} + data = lldb.SBStructuredData() + data.SetFromJSON(json.dumps(dictionary)) + for key in dictionary: + self.assertEqual(data[key], dictionary[key]) |
