Skip to content

Conversation

@mvadari
Copy link
Collaborator

@mvadari mvadari commented Dec 18, 2025

High Level Overview of Change

Title pretty much says it all.

Request.from_xrpl was originally pointing to the from_xrpl of BaseModel, so it was assuming it would be fully PascalCase fields that would need to be camel_case'd. This is incorrect for requests.

Context of Change

Fixes #891

Type of Change

  • Bug fix (non-breaking change which fixes an issue)

Did you update CHANGELOG.md?

  • Yes

Test Plan

CI passes. Added basic test.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 18, 2025

Walkthrough

Adds a new Request.from_xrpl class method as an alias to Request.from_dict (accepting dicts or JSON strings), a unit test validating the alias, and a changelog entry documenting the fix.

Changes

Cohort / File(s) Change Summary
Request method
xrpl/models/requests/request.py
Adds from_xrpl(cls, value: Union[str, Dict[str, Any]]) as a thin alias to from_dict, parsing JSON strings via json.loads. Adds import json.
Tests
tests/unit/models/requests/test_requests.py
Adds test_from_xrpl to verify Request.from_xrpl constructs the correct request type (AccountTx) and includes expected default fields.
Changelog
CHANGELOG.md
Adds Unreleased "Fixed" entry documenting that Request.from_xrpl aliases Request.from_dict.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Suggested reviewers

  • khancode
  • ckeshava
  • pdp2121

Poem

🐰 A tiny alias hops in light and quick,
from_xrpl now follows from_dict’s trick,
dicts and strings both find their way,
tests nod yes, changelog says "Hooray!"
🥕

🚥 Pre-merge checks | ✅ 3 | ❌ 2
❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Linked Issues check ❓ Inconclusive The PR aliases Request.from_xrpl to Request.from_dict, addressing issue #891's recommendation to fix Request.from_xrpl, but only partially resolves the broader issues around JSON-RPC/WebSocket format handling. The PR handles the narrower fix of making Request.from_xrpl delegate to Request.from_dict, but broader client-level format detection and conversion (enhancement recommendation #1) remain unaddressed.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: aliasing Request.from_xrpl to Request.from_dict to fix a functional bug.
Description check ✅ Passed The description covers the required sections: high-level overview, context (links to issue #891), identifies the change as a bug fix, and confirms CHANGELOG.md was updated.
Out of Scope Changes check ✅ Passed All changes (new from_xrpl method, test, and CHANGELOG entry) are directly scoped to fixing the Request.from_xrpl alias and are consistent with the PR's stated objective.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 84ddad2 and 031f203.

📒 Files selected for processing (1)
  • CHANGELOG.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • CHANGELOG.md
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: Integration test (3.9)
  • GitHub Check: Integration test (3.14)
  • GitHub Check: Integration test (3.13)
  • GitHub Check: Integration test (3.12)
  • GitHub Check: Integration test (3.11)
  • GitHub Check: Integration test (3.10)
  • GitHub Check: Integration test (3.8)

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
xrpl/models/requests/request.py (1)

166-180: Improve docstring clarity and consider JSON error handling.

The implementation correctly delegates to from_dict, but the docstring describes it as an "Alias of from_dict" without mentioning that it additionally accepts JSON strings. Consider updating the docstring to explicitly state this capability.

Additionally, json.loads() will raise JSONDecodeError for invalid JSON strings, which may not provide the clearest error message to users expecting XRPL-specific validation errors.

Note on WebSocket format support:

According to issue #891, from_xrpl should handle both JSON-RPC format (method + params) and WebSocket format (command + params). The current implementation only handles dicts with a method key (since it delegates to from_dict), not the command key used in WebSocket-style requests. The TODO comment at line 139 also mentions this gap.

While GenericRequest.to_dict() converts command to method, the reverse conversion isn't implemented in from_dict. This means WebSocket-style dicts will still fail with "Request does not include method."

Is this partial fix intentional as a first step, with full XRPL format support planned for a follow-up? If so, consider updating the method name or docstring to clarify the current scope.

Apply this diff to improve the docstring:

     @classmethod
     def from_xrpl(cls: Type[Self], value: Union[str, Dict[str, Any]]) -> Self:
         """
-        Construct a new Request from a dictionary of parameters. Alias of `from_dict`.
+        Construct a new Request from a dictionary or JSON string. Alias of `from_dict`
+        with additional support for JSON string parsing.

         Args:
-            value: The value to construct the Request from.
+            value: A dictionary or JSON string to construct the Request from.

         Returns:
             A new Request object, constructed using the given parameters.

         Raises:
             XRPLModelException: If the dictionary provided is invalid.
+            JSONDecodeError: If the string provided is not valid JSON.
         """
         return cls.from_dict(value if isinstance(value, dict) else json.loads(value))

Optional: To improve error handling for invalid JSON, consider wrapping json.loads() in a try-except block:

@classmethod
def from_xrpl(cls: Type[Self], value: Union[str, Dict[str, Any]]) -> Self:
    """
    Construct a new Request from a dictionary or JSON string. Alias of `from_dict`
    with additional support for JSON string parsing.

    Args:
        value: A dictionary or JSON string to construct the Request from.

    Returns:
        A new Request object, constructed using the given parameters.

    Raises:
        XRPLModelException: If the dictionary provided is invalid or if the string
            is not valid JSON.
    """
    if isinstance(value, dict):
        return cls.from_dict(value)
    try:
        parsed = json.loads(value)
    except json.JSONDecodeError as e:
        raise XRPLModelException(f"Invalid JSON string: {e}")
    return cls.from_dict(parsed)
tests/unit/models/requests/test_requests.py (1)

32-42: Consider testing JSON string input.

The test validates that from_xrpl works with dictionary input, which is good. However, from_xrpl adds the capability to accept JSON strings (not just dicts), and this new functionality isn't currently tested.

Consider adding a test for JSON string input:

def test_from_xrpl_json_string(self):
    req_str = '{"method": "account_tx", "account": "rN6zcSynkRnf8zcgTVrRL8K7r4ovE7J4Zj"}'
    obj = Request.from_xrpl(req_str)
    self.assertEqual(obj.__class__.__name__, "AccountTx")
    expected = {
        "method": "account_tx",
        "account": "rN6zcSynkRnf8zcgTVrRL8K7r4ovE7J4Zj",
        "binary": False,
        "forward": False,
        "api_version": _DEFAULT_API_VERSION,
    }
    self.assertDictEqual(obj.to_dict(), expected)

Optionally, you could also add tests for error cases (invalid JSON, unsupported types) to ensure proper error handling.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1464e9e and 84ddad2.

📒 Files selected for processing (3)
  • CHANGELOG.md (1 hunks)
  • tests/unit/models/requests/test_requests.py (1 hunks)
  • xrpl/models/requests/request.py (2 hunks)
🧰 Additional context used
🧠 Learnings (7)
📓 Common learnings
Learnt from: ckeshava
Repo: XRPLF/xrpl-py PR: 814
File: xrpl/models/requests/vault_info.py:16-31
Timestamp: 2025-06-04T22:17:47.822Z
Learning: In the xrpl-py library, Request classes do not perform client-side validation on their contents. The library relies on the rippled node to return appropriate error codes for malformed requests, maintaining a consistent pattern across all Request models.
Learnt from: mvadari
Repo: XRPLF/xrpl-py PR: 726
File: tests/unit/models/requests/test_requests.py:16-18
Timestamp: 2024-11-01T20:40:21.354Z
Learning: In the xrpl-py codebase, the `to_dict` method of classes inheriting from `Request` automatically includes the `api_version` key in the resulting dictionary. When reviewing tests that use `to_dict()`, expect `api_version` to be present in the output.
📚 Learning: 2024-11-01T20:40:21.354Z
Learnt from: mvadari
Repo: XRPLF/xrpl-py PR: 726
File: tests/unit/models/requests/test_requests.py:16-18
Timestamp: 2024-11-01T20:40:21.354Z
Learning: In the xrpl-py codebase, the `to_dict` method of classes inheriting from `Request` automatically includes the `api_version` key in the resulting dictionary. When reviewing tests that use `to_dict()`, expect `api_version` to be present in the output.

Applied to files:

  • CHANGELOG.md
  • tests/unit/models/requests/test_requests.py
  • xrpl/models/requests/request.py
📚 Learning: 2025-06-04T22:17:47.822Z
Learnt from: ckeshava
Repo: XRPLF/xrpl-py PR: 814
File: xrpl/models/requests/vault_info.py:16-31
Timestamp: 2025-06-04T22:17:47.822Z
Learning: In the xrpl-py library, Request classes do not perform client-side validation on their contents. The library relies on the rippled node to return appropriate error codes for malformed requests, maintaining a consistent pattern across all Request models.

Applied to files:

  • CHANGELOG.md
  • tests/unit/models/requests/test_requests.py
  • xrpl/models/requests/request.py
📚 Learning: 2024-11-01T18:53:01.394Z
Learnt from: mvadari
Repo: XRPLF/xrpl-py PR: 759
File: tests/unit/models/requests/test_deposit_authorized.py:7-15
Timestamp: 2024-11-01T18:53:01.394Z
Learning: In `tests/unit/models/requests/test_deposit_authorized.py`, additional tests for invalid credentials are unnecessary because `rippled` handles those checks, and the `xrpl-py` library does not include such checks.

Applied to files:

  • tests/unit/models/requests/test_requests.py
📚 Learning: 2024-10-30T20:34:35.451Z
Learnt from: ckeshava
Repo: XRPLF/xrpl-py PR: 759
File: xrpl/models/transactions/credential_delete.py:57-68
Timestamp: 2024-10-30T20:34:35.451Z
Learning: Consistent implementation patterns are preferred in the `xrpl-py` codebase, especially in transaction models under `xrpl/models/transactions/`. When suggesting refactoring that affects multiple transactions, consider the impact on overall consistency and propose comprehensive changes when appropriate.

Applied to files:

  • tests/unit/models/requests/test_requests.py
📚 Learning: 2024-11-01T16:20:50.192Z
Learnt from: mvadari
Repo: XRPLF/xrpl-py PR: 759
File: tests/integration/transactions/test_credential.py:61-63
Timestamp: 2024-11-01T16:20:50.192Z
Learning: In integration tests for xrpl-py, tests should only be testing the library, not rippled functionalities.

Applied to files:

  • tests/unit/models/requests/test_requests.py
📚 Learning: 2024-11-01T20:41:08.207Z
Learnt from: mvadari
Repo: XRPLF/xrpl-py PR: 759
File: tests/unit/models/transactions/test_credential_create.py:13-22
Timestamp: 2024-11-01T20:41:08.207Z
Learning: In Python test files in the xrpl-py codebase (e.g., `tests/unit/models/transactions/test_credential_create.py`), docstrings are not required for test classes and methods if their names are self-explanatory enough.

Applied to files:

  • tests/unit/models/requests/test_requests.py
🧬 Code graph analysis (1)
tests/unit/models/requests/test_requests.py (2)
xrpl/models/requests/request.py (3)
  • Request (103-213)
  • from_xrpl (167-180)
  • to_dict (204-213)
xrpl/models/requests/generic_request.py (1)
  • to_dict (80-99)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
  • GitHub Check: Integration test (3.8)
  • GitHub Check: Integration test (3.10)
  • GitHub Check: Integration test (3.11)
  • GitHub Check: Integration test (3.14)
  • GitHub Check: Integration test (3.13)
  • GitHub Check: Integration test (3.9)
  • GitHub Check: Integration test (3.12)
  • GitHub Check: semgrep-cloud-platform/scan
🔇 Additional comments (2)
xrpl/models/requests/request.py (1)

8-8: LGTM!

The json import is necessary for parsing JSON strings in the new from_xrpl method.

CHANGELOG.md (1)

10-12: LGTM!

The changelog entry accurately documents the fix and is appropriately categorized under "Fixed" for the Unreleased version.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a bug where Request.from_xrpl was incorrectly using the inherited BaseModel.from_xrpl method, which expected PascalCase fields and converted them to snake_case. Since XRPL request objects already use snake_case for their top-level fields (unlike transactions which use PascalCase), this conversion was incorrect. The fix aliases Request.from_xrpl to Request.from_dict to properly handle snake_case request fields.

  • Creates a new Request.from_xrpl method that delegates to Request.from_dict
  • Adds support for both dictionary and JSON string inputs via type checking
  • Includes a basic test case to verify the functionality

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
xrpl/models/requests/request.py Adds json import and implements from_xrpl method as an alias to from_dict with support for both dict and string inputs
tests/unit/models/requests/test_requests.py Adds test case test_from_xrpl to verify the method works correctly with dictionary input
CHANGELOG.md Documents the bug fix in the Unreleased section

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +32 to +42
def test_from_xrpl(self):
req = {"method": "account_tx", "account": "rN6zcSynkRnf8zcgTVrRL8K7r4ovE7J4Zj"}
obj = Request.from_xrpl(req)
self.assertEqual(obj.__class__.__name__, "AccountTx")
expected = {
**req,
"binary": False,
"forward": False,
"api_version": _DEFAULT_API_VERSION,
}
self.assertDictEqual(obj.to_dict(), expected)
Copy link

Copilot AI Dec 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test only verifies from_xrpl with a dictionary input. According to the method signature and documentation, from_xrpl also accepts a JSON string. Consider adding a test case that passes a JSON string to ensure both input types work correctly. For example: obj = Request.from_xrpl(json.dumps(req)).

Copilot uses AI. Check for mistakes.
Patel-Raj11
Patel-Raj11 previously approved these changes Dec 19, 2025
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Numerous problems using "xrpl" format to submit API request.

3 participants