diff --git a/CHANGELOG.md b/CHANGELOG.md index 3a3c78672..4590771bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ This changelog is based on [Keep a Changelog](https://keepachangelog.com/en/1.1. ### Added +- Added `__str__` and `__repr__` methods to `AccountInfo` class for improved logging and debugging experience (#1098) - Added Good First Issue (GFI) management and frequency documentation to clarify maintainer expectations and SDK-level GFI governance. - Added SDK-level Good First Issue (GFI) guidelines for maintainers to clarify what qualifies as a good first issue. - Codecov workflow diff --git a/examples/account/account_info.py b/examples/account/account_info.py index b81c1fb46..8432ccde6 100644 --- a/examples/account/account_info.py +++ b/examples/account/account_info.py @@ -53,14 +53,8 @@ def build_mock_account_info() -> AccountInfo: def print_account_info(info: AccountInfo) -> None: """Pretty-print key AccountInfo fields.""" - print("📜 AccountInfo Example (Mock Data)") - print(f"Account ID: {info.account_id}") - print(f"Key: {info.key}") - print(f"Balance: {info.balance}") - print(f"Expiration Time: {info.expiration_time}") - print(f"Auto Renew Period: {info.auto_renew_period}") - print(f"Token Relationships: {info.token_relationships}") - print(f"Memo: {info.account_memo}") + print("📜 AccountInfo String Representation:") + print(info) def main(): """Run the AccountInfo example.""" @@ -68,4 +62,4 @@ def main(): print_account_info(info) if __name__ == "__main__": - main() + main() \ No newline at end of file diff --git a/src/hiero_sdk_python/account/account_info.py b/src/hiero_sdk_python/account/account_info.py index 36cf92fe5..e6844a9f8 100644 --- a/src/hiero_sdk_python/account/account_info.py +++ b/src/hiero_sdk_python/account/account_info.py @@ -153,3 +153,56 @@ def _to_proto(self) -> CryptoGetInfoResponse.AccountInfo: decline_reward=self.decline_staking_reward ), ) + + def __str__(self) -> str: + """Returns a user-friendly string representation of the AccountInfo.""" + # Define simple fields to print if they exist + # Format: (value_to_check, label) + simple_fields = [ + (self.account_id, "Account ID"), + (self.contract_account_id, "Contract Account ID"), + (self.balance, "Balance"), + (self.key, "Key"), + (self.account_memo, "Memo"), + (self.owned_nfts, "Owned NFTs"), + (self.max_automatic_token_associations, "Max Automatic Token Associations"), + (self.staked_account_id, "Staked Account ID"), + (self.staked_node_id, "Staked Node ID"), + (self.proxy_received, "Proxy Received"), + (self.expiration_time, "Expiration Time"), + (self.auto_renew_period, "Auto Renew Period"), + ] + + # Use a list comprehension to process simple fields (reduces complexity score) + lines = [f"{label}: {val}" for val, label in simple_fields if val is not None] + + # 2. Handle booleans and special cases explicitly + if self.is_deleted is not None: + lines.append(f"Deleted: {self.is_deleted}") + + if self.receiver_signature_required is not None: + lines.append(f"Receiver Signature Required: {self.receiver_signature_required}") + + if self.decline_staking_reward is not None: + lines.append(f"Decline Staking Reward: {self.decline_staking_reward}") + + if self.token_relationships: + lines.append(f"Token Relationships: {len(self.token_relationships)}") + + return "\n".join(lines) + + def __repr__(self) -> str: + """Returns a string representation of the AccountInfo object for debugging.""" + return ( + f"AccountInfo(" + f"account_id={self.account_id!r}, " + f"contract_account_id={self.contract_account_id!r}, " + f"is_deleted={self.is_deleted!r}, " + f"balance={self.balance!r}, " + f"receiver_signature_required={self.receiver_signature_required!r}, " + f"owned_nfts={self.owned_nfts!r}, " + f"account_memo={self.account_memo!r}, " + f"staked_node_id={self.staked_node_id!r}, " + f"staked_account_id={self.staked_account_id!r}" + f")" + ) \ No newline at end of file diff --git a/tests/unit/account_info_test.py b/tests/unit/account_info_test.py index b75951de9..e645ffba2 100644 --- a/tests/unit/account_info_test.py +++ b/tests/unit/account_info_test.py @@ -169,3 +169,20 @@ def test_proto_conversion(account_info): assert converted_account_info.token_relationships == account_info.token_relationships assert converted_account_info.account_memo == account_info.account_memo assert converted_account_info.owned_nfts == account_info.owned_nfts + +def test_str_and_repr(account_info): + """Test the __str__ and __repr__ methods""" + info_str = str(account_info) + info_repr = repr(account_info) + + # __str__ checks (User-friendly output) + assert "Account ID: 0.0.100" in info_str + assert "Contract Account ID: 0.0.100" in info_str + assert "Balance: 0.05000000 ℏ" in info_str + assert "Memo: Test account memo" in info_str + + # __repr__ checks (Debug output) + assert info_repr.startswith("AccountInfo(") + assert "account_id=AccountId(shard=0, realm=0, num=100" in info_repr + assert "contract_account_id='0.0.100'" in info_repr + assert "account_memo='Test account memo'" in info_repr \ No newline at end of file