Skip to content
This repository was archived by the owner on Jan 23, 2026. It is now read-only.

[WIP] Corellium serial driver#413

Merged
NickCao merged 1 commit intojumpstarter-dev:mainfrom
odra:corellium-serial-driver
Apr 21, 2025
Merged

[WIP] Corellium serial driver#413
NickCao merged 1 commit intojumpstarter-dev:mainfrom
odra:corellium-serial-driver

Conversation

@odra
Copy link
Copy Markdown
Contributor

@odra odra commented Apr 17, 2025

Changes

  • Adds a new Websocket network driver
  • corellium driver changes to handle console serial connections over websockets

Testing

Create a file like this (set proper values for project_id and instance name):

metadata:
  namespace: default
  name: corellium-demo
endpoint: ""
token: ""
export:
  rd1ae:
    type: jumpstarter_driver_corellium.driver.Corellium
    config:
      project_id: "12245"
      device_name: "name"
      device_flavor: "kronos"
      # optional
      device_os: "1.1.1"
      device_build: "Critical Application Monitor (Baremetal)"
      console_name: "Primary Compute Non-Secure"

Start the jmp shell:

jmp shell --exporter-config sample.yml

Power it on and start the shell:

$ j rd1ae power on
...
$ j rd1ae serial start-console

It should start to stream the remote instance into your local console.

Summary by CodeRabbit

Summary by CodeRabbit

  • New Features

    • Introduced support for WebSocket-based network connections, enabling new types of connectivity within the driver.
    • Added a serial console feature for Corellium instances, allowing users to access instance consoles via WebSocket.
    • Enhanced configuration options for Corellium instances with a new console name field.
  • Bug Fixes

    • Corrected a test fixture path in the Corellium driver test suite.
  • Tests

    • Added comprehensive tests for new console-related API methods and error handling.
    • Added tests for WebSocket network connections and Corellium console URL retrieval.
  • Chores

    • Updated dependencies to include required packages for WebSocket and serial communication.
    • Added new fixture files for testing API responses and error scenarios.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 17, 2025

Walkthrough

This update introduces websocket console support for the Corellium driver. It adds a WebsocketNetwork class to the network driver, a corresponding WebsocketClientStream for client-side websocket communication, and a CorelliumConsole driver that exposes a serial console over websockets. The Corellium API client is extended with methods to retrieve console IDs and URLs. New test fixtures and tests validate the new API methods and error handling. Configuration and dependency files are updated to reflect new requirements and options, including the addition of websocket and pyserial dependencies.

Changes

File(s) Change Summary
jumpstarter-driver-network/jumpstarter_driver_network/driver.py
jumpstarter-driver-network/pyproject.toml
Added WebsocketNetwork class for websocket connectivity; updated dependencies to include websockets>=15.0.1.
jumpstarter-driver-network/jumpstarter_driver_network/streams/websocket.py Added WebsocketClientStream class implementing client-side websocket streaming interface.
jumpstarter-driver-network/jumpstarter_driver_network/driver_test.py Added test for WebsocketNetwork.connect method using mocked websocket client.
jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py Added methods to retrieve console ID and URL from the Corellium API; refined error handling and request data handling.
jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py Added tests for new API methods, including error handling and fixture path correction.
jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py Introduced CorelliumConsole (subclass of WebsocketNetwork) as a child driver for serial console; added console_name field and logic to dynamically fetch console URLs from the API.
jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver_test.py Added tests for CorelliumConsole.url property, covering success and multiple error scenarios with mocked API calls.
jumpstarter-driver-corellium/pyproject.toml Updated dependencies: replaced direct pyserial with jumpstarter-driver-network and jumpstarter-driver-pyserial; added pytest-asyncio for development.
jumpstarter-driver-corellium/examples/exporter.yml Added optional console_name configuration field under the rd1ae export entry.
jumpstarter-driver-corellium/fixtures/http/get-instance-200.json
get-instance-console-url-200.json
get-instance-console-url-400.json
Added new JSON fixture files for instance and console URL retrieval, including success and error cases for API testing.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant CorelliumDriver
    participant CorelliumConsole
    participant ApiClient
    participant CorelliumAPI

    User->>CorelliumDriver: Request serial console connection
    CorelliumDriver->>CorelliumConsole: Initialize serial driver
    CorelliumConsole->>ApiClient: get_instance_console_id(instance, console_name)
    ApiClient->>CorelliumAPI: GET /instances/{id}
    CorelliumAPI-->>ApiClient: Instance details (with consoles)
    ApiClient-->>CorelliumConsole: Console ID
    CorelliumConsole->>ApiClient: get_instance_console_url(instance, console_id)
    ApiClient->>CorelliumAPI: GET /instances/{id}/console?type={console_id}
    CorelliumAPI-->>ApiClient: { "url": "wss://..." }
    ApiClient-->>CorelliumConsole: Console URL
    CorelliumConsole->>WebsocketNetwork: Connect to websocket URL
    WebsocketNetwork->>User: Established stream
Loading

Possibly related PRs

Suggested reviewers

  • mangelajo

Poem

In the warren of code, a new tunnel appears,
Websockets now whisper in Corellium’s ears!
Console connections, so nimble and fleet,
Hop through the network, a technical treat.
With fixtures and tests, the garden grows wide—
A rabbit’s delight, with new streams to ride!
🐇✨


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c30f850 and e8061d7.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (13)
  • packages/jumpstarter-driver-corellium/examples/exporter.yml (1 hunks)
  • packages/jumpstarter-driver-corellium/fixtures/http/get-instance-200.json (1 hunks)
  • packages/jumpstarter-driver-corellium/fixtures/http/get-instance-console-url-200.json (1 hunks)
  • packages/jumpstarter-driver-corellium/fixtures/http/get-instance-console-url-400.json (1 hunks)
  • packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (8 hunks)
  • packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py (3 hunks)
  • packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (4 hunks)
  • packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver_test.py (2 hunks)
  • packages/jumpstarter-driver-corellium/pyproject.toml (1 hunks)
  • packages/jumpstarter-driver-network/jumpstarter_driver_network/driver.py (3 hunks)
  • packages/jumpstarter-driver-network/jumpstarter_driver_network/driver_test.py (2 hunks)
  • packages/jumpstarter-driver-network/jumpstarter_driver_network/streams/websocket.py (2 hunks)
  • packages/jumpstarter-driver-network/pyproject.toml (2 hunks)
✅ Files skipped from review due to trivial changes (1)
  • packages/jumpstarter-driver-corellium/fixtures/http/get-instance-200.json
🚧 Files skipped from review as they are similar to previous changes (12)
  • packages/jumpstarter-driver-corellium/examples/exporter.yml
  • packages/jumpstarter-driver-corellium/fixtures/http/get-instance-console-url-200.json
  • packages/jumpstarter-driver-corellium/pyproject.toml
  • packages/jumpstarter-driver-network/pyproject.toml
  • packages/jumpstarter-driver-network/jumpstarter_driver_network/driver_test.py
  • packages/jumpstarter-driver-corellium/fixtures/http/get-instance-console-url-400.json
  • packages/jumpstarter-driver-network/jumpstarter_driver_network/streams/websocket.py
  • packages/jumpstarter-driver-network/jumpstarter_driver_network/driver.py
  • packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver_test.py
  • packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py
  • packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py
  • packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py
⏰ Context from checks skipped due to timeout of 90000ms (4)
  • GitHub Check: e2e
  • GitHub Check: pytest-matrix (3.13)
  • GitHub Check: pytest-matrix (3.11)
  • GitHub Check: pytest-matrix (3.12)

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@netlify
Copy link
Copy Markdown

netlify Bot commented Apr 17, 2025

Deploy Preview for jumpstarter-docs ready!

Name Link
🔨 Latest commit e8061d7
🔍 Latest deploy log https://app.netlify.com/sites/jumpstarter-docs/deploys/680648193b6d5400083e2d5f
😎 Deploy Preview https://deploy-preview-413--jumpstarter-docs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

Comment thread packages/jumpstarter-driver-pyserial/jumpstarter_driver_pyserial/driver.py Outdated
Copy link
Copy Markdown
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: 5

🧹 Nitpick comments (16)
packages/jumpstarter-driver-corellium/examples/exporter.yml (1)

19-19: Document the Optional console_name Configuration Field
Since console_name is optional and impacts which Corellium console is selected, consider enhancing the documentation or example README to explain its purpose, valid values, and default behavior when omitted.

packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (3)

211-212: Fix trailing whitespace

There's trailing whitespace in this class docstring line.

-    A PySerial subclass to handle 
+    A PySerial subclass to handle
🧰 Tools
🪛 Ruff (0.8.2)

211-211: Trailing whitespace

Remove trailing whitespace

(W291)


213-213: Fix trailing whitespace

There's trailing whitespace at the end of this line.

-    parent: Corellium 
+    parent: Corellium
🧰 Tools
🪛 Ruff (0.8.2)

213-213: Trailing whitespace

Remove trailing whitespace

(W291)


208-243: Document the purpose of the CorelliumSerial class more clearly

The class docstring is incomplete and doesn't fully explain what this class does. Consider expanding the docstring to clarify that this class handles serial communication over websockets for Corellium devices.

-    A PySerial subclass to handle 
+    A PySerial subclass to handle Corellium serial communication over websockets.
+    
+    This class dynamically retrieves the websocket URL for the console from
+    the Corellium API and uses it to establish a serial connection.
🧰 Tools
🪛 Ruff (0.8.2)

211-211: Trailing whitespace

Remove trailing whitespace

(W291)


213-213: Trailing whitespace

Remove trailing whitespace

(W291)

packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py (5)

2-3: Remove unused imports

The asyncio, AsyncMock, and patch imports are not used in this test file.

 import os
-import asyncio
-from unittest.mock import AsyncMock, patch
+
 
 import pytest
🧰 Tools
🪛 Ruff (0.8.2)

2-2: asyncio imported but unused

Remove unused import: asyncio

(F401)


3-3: unittest.mock.AsyncMock imported but unused

Remove unused import

(F401)


3-3: unittest.mock.patch imported but unused

Remove unused import

(F401)


6-8: Remove commented and unused imports

The # import websockets line appears to be a leftover comment, and the imported websockets from .api is not used.

 import pytest
-# import websockets
 
-from .api import ApiClient, websockets
+from .api import ApiClient
 from .exceptions import CorelliumApiException
 from .types import Device, Instance, Project, Session
🧰 Tools
🪛 Ruff (0.8.2)

8-8: .api.websockets imported but unused

Remove unused import: .api.websockets

(F401)


196-196: Fix trailing whitespace

There's trailing whitespace at the end of this line.

-    data = fixture('http/get-instance-200.json') 
+    data = fixture('http/get-instance-200.json')
🧰 Tools
🪛 Ruff (0.8.2)

196-196: Trailing whitespace

Remove trailing whitespace

(W291)


228-228: Fix trailing whitespace

There's trailing whitespace at the end of this line.

-    data = fixture('http/get-instance-console-url-200.json') 
+    data = fixture('http/get-instance-console-url-200.json')
🧰 Tools
🪛 Ruff (0.8.2)

228-228: Trailing whitespace

Remove trailing whitespace

(W291)


188-204: Improve test case verification for console ID

The test for get_instance_console_id_ok could be improved by asserting that the API client method was called with the correct parameters. This would ensure that the test is validating the right behavior.

Consider using a mock to verify the actual API call was made with expected parameters:

from unittest.mock import patch

@pytest.mark.parametrize(
    'console_name,console_id',
    [
        ('Console 1', 'port-1-cons',),
        ('Console 10', None,),
        ('Console 2', 'port-2-cons',),
    ])
def test_get_instance_console_id_ok(requests_mock, console_name, console_id):
    data = fixture('http/get-instance-200.json')
    instance = Instance(id='d59db33d-27bd-4b22-878d-49e4758a648e')
    requests_mock.get(f'https://api-host/api/v1/instances/{instance.id}', status_code=200, text=data)
    api = ApiClient('api-host', 'api-token')
    api.session = Session('session-token', '2022-03-20T01:50:10.000Z')

    current = api.get_instance_console_id(instance, console_name)

    assert console_id == current
🧰 Tools
🪛 Ruff (0.8.2)

196-196: Trailing whitespace

Remove trailing whitespace

(W291)

packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (4)

1-4: Remove unused imports

AsyncGenerator and websockets are imported but not used in this file.

-from typing import AsyncGenerator, Optional
+from typing import Optional
 
 import requests
-import websockets
🧰 Tools
🪛 Ruff (0.8.2)

1-1: typing.AsyncGenerator imported but unused

Remove unused import: typing.AsyncGenerator

(F401)


4-4: websockets imported but unused

Remove unused import: websockets

(F401)


166-167: Fix malformed docstring

There's an extra single quote at the end of the docstring for destroy_instance.

-        '"""
+        """

192-193: Remove whitespace from blank line

There's whitespace on this blank line.

             if console['name'] == console_name:
                 return console['id']
-        
+
         return None
🧰 Tools
🪛 Ruff (0.8.2)

192-192: Blank line contains whitespace

Remove whitespace from blank line

(W293)


195-207: Fix typo in docstring and improve error handling

There's a typo in the docstring ("Get a a console URL"), and the method should handle the case where the 'url' key is missing from the response.

     def get_instance_console_url(self, instance: Instance, console_id: str) -> Optional[str]:
         """
-        Get a a console URL (websocket) to stream logs from.
+        Get a console URL (websocket) to stream logs from.
         """
         try:
             res = self.req.get(f'{self.baseurl}/v1/instances/{instance.id}/console',
                                params={'type': console_id.replace('port-', '')})
             data = res.json()
             res.raise_for_status()
         except requests.exceptions.RequestException as e:
             raise CorelliumApiException(data.get('error', str(e))) from e
 
-        return data['url']
+        if 'url' not in data:
+            raise CorelliumApiException("Response did not contain a URL")
+        return data['url']
packages/jumpstarter-driver-pyserial/jumpstarter_driver_pyserial/driver.py (3)

3-3: Remove unused import Any

Any isn’t referenced anywhere in this module, so the import adds to cognitive noise and will be flagged by linters (see Ruff F401).

-from typing import Any
+# from typing import Any   # ← removed – not used
🧰 Tools
🪛 Ruff (0.8.2)

3-3: typing.Any imported but unused

Remove unused import: typing.Any

(F401)


93-94: Doc‑string typo

Use the actual method name (connect_serial) and remove the hyphen:

-        Defaults to `self.connect-serial` in case no valid handler is found.
+        Defaults to `self.connect_serial` if no specialized handler matches.

85-86: Strip trailing / whitespace lines

There’s a blank line with spaces and a trailing space at the log line; these trigger linters (Ruff W293/W291).

🧰 Tools
🪛 Ruff (0.8.2)

85-85: Blank line contains whitespace

Remove whitespace from blank line

(W293)


86-86: Trailing whitespace

Remove trailing whitespace

(W291)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ecc5cb1 and 8e00bec.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (10)
  • packages/jumpstarter-driver-corellium/examples/exporter.yml (1 hunks)
  • packages/jumpstarter-driver-corellium/fixtures/http/get-instance-200.json (1 hunks)
  • packages/jumpstarter-driver-corellium/fixtures/http/get-instance-console-url-200.json (1 hunks)
  • packages/jumpstarter-driver-corellium/fixtures/http/get-instance-console-url-400.json (1 hunks)
  • packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (3 hunks)
  • packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py (3 hunks)
  • packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (4 hunks)
  • packages/jumpstarter-driver-corellium/pyproject.toml (1 hunks)
  • packages/jumpstarter-driver-pyserial/jumpstarter_driver_pyserial/driver.py (4 hunks)
  • packages/jumpstarter-driver-pyserial/pyproject.toml (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py (3)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (3)
  • ApiClient (10-207)
  • get_instance_console_id (176-193)
  • get_instance_console_url (195-207)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/types.py (2)
  • Instance (51-56)
  • Session (9-22)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/exceptions.py (1)
  • CorelliumApiException (7-10)
🪛 Ruff (0.8.2)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py

2-2: asyncio imported but unused

Remove unused import: asyncio

(F401)


3-3: unittest.mock.AsyncMock imported but unused

Remove unused import

(F401)


3-3: unittest.mock.patch imported but unused

Remove unused import

(F401)


8-8: .api.websockets imported but unused

Remove unused import: .api.websockets

(F401)


196-196: Trailing whitespace

Remove trailing whitespace

(W291)


228-228: Trailing whitespace

Remove trailing whitespace

(W291)

packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py

1-1: typing.AsyncGenerator imported but unused

Remove unused import: typing.AsyncGenerator

(F401)


4-4: websockets imported but unused

Remove unused import: websockets

(F401)


192-192: Blank line contains whitespace

Remove whitespace from blank line

(W293)

packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py

211-211: Trailing whitespace

Remove trailing whitespace

(W291)


213-213: Trailing whitespace

Remove trailing whitespace

(W291)

packages/jumpstarter-driver-pyserial/jumpstarter_driver_pyserial/driver.py

3-3: typing.Any imported but unused

Remove unused import: typing.Any

(F401)


85-85: Blank line contains whitespace

Remove whitespace from blank line

(W293)


86-86: Trailing whitespace

Remove trailing whitespace

(W291)

🔇 Additional comments (8)
packages/jumpstarter-driver-pyserial/pyproject.toml (1)

18-18: Include WebSocket Support Dependency
The addition of websockets>=15.0.1 in the runtime dependencies correctly complements the new WebSocket-based serial transport.

packages/jumpstarter-driver-corellium/fixtures/http/get-instance-console-url-200.json (1)

1-3: Approve JSON Fixture for Successful Console URL Retrieval
The get-instance-console-url-200.json fixture accurately models a successful API response containing the WebSocket URL.

packages/jumpstarter-driver-corellium/pyproject.toml (2)

13-17: Add Core WebSocket and PySerial Dependencies
Including jumpstarter-driver-pyserial and websockets>=15.0.1 aligns this package with the enhanced serial‑over‑websocket functionality. Confirm compatibility across dependent driver versions.


23-23:

Details

❓ Verification inconclusive

Enable Asynchronous Test Support
The addition of pytest-asyncio>=0.25.3 is necessary for the new async Corellium API tests. Please verify that tests use the @pytest.mark.asyncio decorator or pytest‑asyncio fixtures accordingly.


🏁 Script executed:

#!/bin/bash
# Verify that async tests reference pytest-asyncio
rg -R "pytest.mark.asyncio" -A2

Length of output: 436


🏁 Script executed:

#!/bin/bash
# Verify that async tests reference pytest-asyncio
# Search for the pytest-asyncio marker decorator in test files
rg "@pytest\.mark\.asyncio" -A2 .

Length of output: 3269


#!/bin/bash
# Verify that Corellium driver tests use pytest-asyncio
echo "Searching for pytest.mark.asyncio in corellium tests..."
rg "@pytest\.mark\.asyncio" -A2 packages/jumpstarter-driver-corellium

echo "Searching for async def test in corellium tests..."
rg "async def test" -A1 packages/jumpstarter-driver-corellium

#!/bin/bash
# Verify that Corellium driver tests reference pytest-asyncio
echo "Searching for pytest.mark.asyncio in corellium tests..."
rg "@pytest\.mark\.asyncio" -A2 packages/jumpstarter-driver-corellium

echo "Searching for async test definitions in corellium tests..."
rg "async def test" -A1 packages/jumpstarter-driver-corellium

Verify pytest‑asyncio decorators in Corellium driver tests
I wasn’t able to locate any @pytest.mark.asyncio usages in the packages/jumpstarter-driver-corellium test files. Please confirm that all async tests for the Corellium API are marked correctly, for example:

  • Add @pytest.mark.asyncio above each async def test_… function.
  • Or leverage the pytest‑asyncio asyncio fixture if preferred.

Locations to inspect:

  • packages/jumpstarter-driver-corellium/test_*.py
  • Any other test modules under packages/jumpstarter-driver-corellium
packages/jumpstarter-driver-corellium/fixtures/http/get-instance-console-url-400.json (2)

1-5: Approve JSON Fixture for Console URL Error Response
The get-instance-console-url-400.json fixture correctly simulates a 400 Invalid Type error from the Corellium API.


1-5:

Details

✅ Verification successful

Verify Error Fixture Usage in Tests
Ensure that the newly added error fixture is referenced in the test suite to cover error‑handling paths.


🏁 Script executed:

#!/bin/bash
# Check for usage of the error fixture in tests
rg -R "get-instance-console-url-400.json"

Length of output: 446


🏁 Script executed:

#!/bin/bash
# Re-run search for the error fixture in the test suite using the correct rg syntax
rg "get-instance-console-url-400.json"

Length of output: 213


Error fixture usage verified
The get-instance-console-url-400.json fixture is already referenced in tests at:

  • packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py
    No further changes needed.
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py (1)

236-237:

Details

❌ Incorrect review comment

Fix incorrect expected URL in test

In test_get_instance_console_url_ok, the expected URL seems to be incorrect. The line below is comparing against 'wss://api-host/port-cons-1' but the fixture likely has a different URL. Double-check this value against the fixture data.


🏁 Script executed:

#!/bin/bash
# Check the URL in the fixture file
cat packages/jumpstarter-driver-corellium/fixtures/http/get-instance-console-url-200.json | grep url

Length of output: 142


Ignore previous suggestion: expected URL is correct

The expected URL in test_get_instance_console_url_ok ('wss://api-host/port-cons-1' at lines 236–237) exactly matches the value in packages/jumpstarter-driver-corellium/fixtures/http/get-instance-console-url-200.json. No change is needed.

Likely an incorrect or invalid review comment.

packages/jumpstarter-driver-corellium/fixtures/http/get-instance-200.json (1)

1-84: LGTM - Good test fixture

The fixture provides a comprehensive representation of a Corellium instance response, including the necessary console information that will be used by the new API methods. The structure matches what would be expected from the Corellium API.

Comment thread packages/jumpstarter-driver-pyserial/jumpstarter_driver_pyserial/driver.py Outdated
Comment thread packages/jumpstarter-driver-pyserial/jumpstarter_driver_pyserial/driver.py Outdated
Comment thread packages/jumpstarter-driver-pyserial/jumpstarter_driver_pyserial/driver.py Outdated
@odra odra force-pushed the corellium-serial-driver branch from 8e00bec to ebaaf01 Compare April 18, 2025 07:39
Copy link
Copy Markdown
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

♻️ Duplicate comments (4)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (1)

224-235: ⚠️ Potential issue

Guard against missing console ‑ same issue previously reported

The call sequence will raise AttributeError when console_id is None because None has no .replace(). The exact concern was raised in an earlier review but is still unresolved.

 console_id = self.parent.api.get_instance_console_id(instance, self.parent.console_name)
+if console_id is None:
+    raise ValueError(
+        f"Console '{self.parent.console_name}' not found on instance "
+        f"'{self.parent.device_name}'"
+    )
 console_url = self.parent.api.get_instance_console_url(instance, console_id)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (1)

176-186: ⚠️ Potential issue

instance parameter should be an Instance, not str (repeat finding)

The method dereferences instance.id, so passing a plain string will explode. This mirrors the unresolved comment in the previous review.

-    def get_instance_console_id(self, instance: str, console_name: str) -> Optional[str]:
+    def get_instance_console_id(self, instance: Instance, console_name: str) -> Optional[str]:

Also update callers (tests & driver) accordingly.

packages/jumpstarter-driver-pyserial/jumpstarter_driver_pyserial/driver.py (2)

54-57: Duplicate close() call

websockets connections are idempotent but calling close() twice is unnecessary.

-        await self.conn.close()
-        await self.conn.close()
+        await self.conn.close()

107-110: ⚠️ Potential issue

Simplify connect_wss to avoid redundant context & fix missing async‑resource handling

WebsocketSerial is already an AsyncResource; wrapping it in another async with is superfluous and may double‑close the websocket.

-        async with websockets.connect(self.url) as websocket:
-            async with WebsocketSerial(conn=websocket) as stream:
-                yield stream
+        async with websockets.connect(self.url) as websocket:
+            yield WebsocketSerial(conn=websocket)
🧹 Nitpick comments (6)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (1)

208-213: Remove trailing whitespace & polish doc‑string

There are two W291 lint hits and the doc‑string is incomplete. Tighten this block and finish the sentence for clarity/readability.

-@dataclass(kw_only=True)
-class CorelliumSerial(PySerial):
-    """
-    A PySerial subclass to handle 
-    """
+@dataclass(kw_only=True)
+class CorelliumSerial(PySerial):
+    """
+    PySerial subclass that transparently connects to a Corellium
+    console (WebSocket) whose URL is discovered via the API.
+    """
🧰 Tools
🪛 Ruff (0.8.2)

211-211: Trailing whitespace

Remove trailing whitespace

(W291)


213-213: Trailing whitespace

Remove trailing whitespace

(W291)

packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py (2)

2-9: Prune unused imports to keep test file clean

asyncio, AsyncMock, patch, and websockets are never referenced. They currently trigger Ruff F401 errors.

-import asyncio
-from unittest.mock import AsyncMock, patch
-# import websockets
-from .api import ApiClient, websockets
+from .api import ApiClient
🧰 Tools
🪛 Ruff (0.8.2)

2-2: asyncio imported but unused

Remove unused import: asyncio

(F401)


3-3: unittest.mock.AsyncMock imported but unused

Remove unused import

(F401)


3-3: unittest.mock.patch imported but unused

Remove unused import

(F401)


8-8: .api.websockets imported but unused

Remove unused import: .api.websockets

(F401)


196-200: Strip trailing whitespace

Ruff flags W291 here. Removing it eliminates noise in CI.

-    data = fixture('http/get-instance-200.json') 
+    data = fixture('http/get-instance-200.json')
🧰 Tools
🪛 Ruff (0.8.2)

196-196: Trailing whitespace

Remove trailing whitespace

(W291)

packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (2)

1-5: Drop unused imports

AsyncGenerator and websockets are never used in this module.

-from typing import AsyncGenerator, Optional
+from typing import Optional
 ...
-import websockets
🧰 Tools
🪛 Ruff (0.8.2)

1-1: typing.AsyncGenerator imported but unused

Remove unused import: typing.AsyncGenerator

(F401)


4-4: websockets imported but unused

Remove unused import: websockets

(F401)


165-168: Doc‑string typo breaks closing quote

The triple‑quoted string for destroy_instance ends with '""", leaving an unmatched single quote.

-        Does not return anything since Corellium's API return a HTTP 204 response.
-        '"""
+        Does not return anything since Corellium's API returns a HTTP‑204 response.
+        """
packages/jumpstarter-driver-pyserial/jumpstarter_driver_pyserial/driver.py (1)

3-4: Remove unused Any import

-from typing import Any
🧰 Tools
🪛 Ruff (0.8.2)

3-3: typing.Any imported but unused

Remove unused import: typing.Any

(F401)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8e00bec and ebaaf01.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (10)
  • packages/jumpstarter-driver-corellium/examples/exporter.yml (1 hunks)
  • packages/jumpstarter-driver-corellium/fixtures/http/get-instance-200.json (1 hunks)
  • packages/jumpstarter-driver-corellium/fixtures/http/get-instance-console-url-200.json (1 hunks)
  • packages/jumpstarter-driver-corellium/fixtures/http/get-instance-console-url-400.json (1 hunks)
  • packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (3 hunks)
  • packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py (3 hunks)
  • packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (4 hunks)
  • packages/jumpstarter-driver-corellium/pyproject.toml (1 hunks)
  • packages/jumpstarter-driver-pyserial/jumpstarter_driver_pyserial/driver.py (4 hunks)
  • packages/jumpstarter-driver-pyserial/pyproject.toml (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (6)
  • packages/jumpstarter-driver-corellium/pyproject.toml
  • packages/jumpstarter-driver-pyserial/pyproject.toml
  • packages/jumpstarter-driver-corellium/fixtures/http/get-instance-console-url-200.json
  • packages/jumpstarter-driver-corellium/examples/exporter.yml
  • packages/jumpstarter-driver-corellium/fixtures/http/get-instance-console-url-400.json
  • packages/jumpstarter-driver-corellium/fixtures/http/get-instance-200.json
🧰 Additional context used
🪛 Ruff (0.8.2)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py

1-1: typing.AsyncGenerator imported but unused

Remove unused import: typing.AsyncGenerator

(F401)


4-4: websockets imported but unused

Remove unused import: websockets

(F401)


192-192: Blank line contains whitespace

Remove whitespace from blank line

(W293)

packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py

2-2: asyncio imported but unused

Remove unused import: asyncio

(F401)


3-3: unittest.mock.AsyncMock imported but unused

Remove unused import

(F401)


3-3: unittest.mock.patch imported but unused

Remove unused import

(F401)


8-8: .api.websockets imported but unused

Remove unused import: .api.websockets

(F401)


196-196: Trailing whitespace

Remove trailing whitespace

(W291)


228-228: Trailing whitespace

Remove trailing whitespace

(W291)

packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py

211-211: Trailing whitespace

Remove trailing whitespace

(W291)


213-213: Trailing whitespace

Remove trailing whitespace

(W291)

packages/jumpstarter-driver-pyserial/jumpstarter_driver_pyserial/driver.py

3-3: typing.Any imported but unused

Remove unused import: typing.Any

(F401)


85-85: Blank line contains whitespace

Remove whitespace from blank line

(W293)


86-86: Trailing whitespace

Remove trailing whitespace

(W291)

@odra odra force-pushed the corellium-serial-driver branch from ebaaf01 to 61459d7 Compare April 18, 2025 07:51
Copy link
Copy Markdown
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: 4

🔭 Outside diff range comments (1)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (1)

208-244: ⚠️ Potential issue

Dataclass field ⇄ property name collision will raise TypeError at import time

PySerial declares a dataclass field named url.
CorelliumSerial (itself a @dataclass) introduces a property with the same name.
During class creation, dataclasses detects the overwrite and raises:

TypeError: Cannot overwrite attribute 'url' in class 'CorelliumSerial'.

Fix suggestion (one of):

-@dataclass(kw_only=True)
-class CorelliumSerial(PySerial):
+@dataclass(kw_only=True)
+class CorelliumSerial(PySerial):
+    # Keep the original field but prevent it from clashing.
+    _dynamic_url: str = field(init=False, repr=False)

-    parent: Corellium 
+    parent: Corellium
+
+    def __post_init__(self):
+        super().__post_init__()
+        # Delay actual connection – do not rely on the bogus URL passed by the parent.
+        self._dynamic_url = ''
 
-    @property
-    def url(self) -> str:
+    @property
+    def url(self) -> str:
         ...
-        return console_url
+        self._dynamic_url = console_url
+        return console_url
+
+    @_dynamic_url.setter
+    def url(self, _value: str) -> None:  # noqa: D401
+        # Disallow external mutation.
+        raise AttributeError("`url` is read‑only for CorelliumSerial")

This eliminates the clash and clearly separates the internal backing field.

🧰 Tools
🪛 Ruff (0.8.2)

211-211: Trailing whitespace

Remove trailing whitespace

(W291)


213-213: Trailing whitespace

Remove trailing whitespace

(W291)

♻️ Duplicate comments (3)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (1)

233-235: Still missing guard for a non‑existent console

Previous review already highlighted that get_instance_console_id can return None.
get_instance_console_url will then raise a TypeError. Please raise a clear, user‑facing exception when console_id is None.

packages/jumpstarter-driver-pyserial/jumpstarter_driver_pyserial/driver.py (2)

54-56: Remove duplicate close() call

The aclose() method calls self.conn.close() twice unnecessarily. While websockets handles closing idempotently, one call is sufficient.

-    async def aclose(self):
-        await self.conn.close()
-        await self.conn.close()
+    async def aclose(self):
+        await self.conn.close()

103-109: Simplify WebSocket context handling

The nested context managers can be simplified since WebsocketSerial just delegates to the websocket connection's close method.

-        async with websockets.connect(self.url) as websocket:
-            async with WebsocketSerial(conn=websocket) as stream:
-                yield stream
+        async with websockets.connect(self.url) as websocket:
+            yield WebsocketSerial(conn=websocket)

This simplifies the code and eliminates the need for WebsocketSerial.aclose() to call close() at all since the outer context will handle it.

🧹 Nitpick comments (8)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (1)

211-213: Trailing whitespace – lines flagged by Ruff (W291).
Please strip to keep the diff clean.

🧰 Tools
🪛 Ruff (0.8.2)

211-211: Trailing whitespace

Remove trailing whitespace

(W291)


213-213: Trailing whitespace

Remove trailing whitespace

(W291)

packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (3)

1-5: Remove unused imports

AsyncGenerator and websockets are imported but never referenced; Ruff (F401) rightfully complains. Drop them to avoid dead code.

-from typing import AsyncGenerator, Optional
+from typing import Optional
 ...
-import websockets
🧰 Tools
🪛 Ruff (0.8.2)

1-1: typing.AsyncGenerator imported but unused

Remove unused import: typing.AsyncGenerator

(F401)


4-4: websockets imported but unused

Remove unused import: websockets

(F401)


195-207: Return type should be str, not Optional[str]

The function either returns data['url'] or raises – it never returns None.
Tighten the signature to improve type‑checking:

-def get_instance_console_url(self, instance: Instance, console_id: str) -> Optional[str]:
+def get_instance_console_url(self, instance: Instance, console_id: str) -> str:

Also update the docstring accordingly.


192-193: Trailing whitespace (W293) – please remove.

🧰 Tools
🪛 Ruff (0.8.2)

192-192: Blank line contains whitespace

Remove whitespace from blank line

(W293)

packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py (2)

2-9: Prune unused test imports

asyncio, AsyncMock, patch, and websockets aren’t used anywhere in this file; Ruff (F401) reports them.
Remove to keep tests lean:

-import asyncio
-from unittest.mock import AsyncMock, patch
 ...
-# import websockets
-from .api import ApiClient, websockets
+from .api import ApiClient
🧰 Tools
🪛 Ruff (0.8.2)

2-2: asyncio imported but unused

Remove unused import: asyncio

(F401)


3-3: unittest.mock.AsyncMock imported but unused

Remove unused import

(F401)


3-3: unittest.mock.patch imported but unused

Remove unused import

(F401)


8-8: .api.websockets imported but unused

Remove unused import: .api.websockets

(F401)


196-199: Trailing whitespace in fixture loading block

Lines 196 and 228 contain extra spaces that trigger Ruff W291.
A quick pre-commit run --all-files will auto‑fix these.

🧰 Tools
🪛 Ruff (0.8.2)

196-196: Trailing whitespace

Remove trailing whitespace

(W291)

packages/jumpstarter-driver-pyserial/jumpstarter_driver_pyserial/driver.py (2)

3-3: Remove unused import

The Any type from typing is imported but not used anywhere in the code.

-from typing import Any
🧰 Tools
🪛 Ruff (0.8.2)

3-3: typing.Any imported but unused

Remove unused import: typing.Any

(F401)


77-86: Clean up whitespace issues

The implementation of the connect method looks good, but there are some whitespace issues that should be fixed.

        async for stream in self.stream_handler():
            yield stream
-        
-        self.logger.info("Disconnected from %s", self.url) 
+
+        self.logger.info("Disconnected from %s", self.url)
🧰 Tools
🪛 Ruff (0.8.2)

85-85: Blank line contains whitespace

Remove whitespace from blank line

(W293)


86-86: Trailing whitespace

Remove trailing whitespace

(W291)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ebaaf01 and 61459d7.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (10)
  • packages/jumpstarter-driver-corellium/examples/exporter.yml (1 hunks)
  • packages/jumpstarter-driver-corellium/fixtures/http/get-instance-200.json (1 hunks)
  • packages/jumpstarter-driver-corellium/fixtures/http/get-instance-console-url-200.json (1 hunks)
  • packages/jumpstarter-driver-corellium/fixtures/http/get-instance-console-url-400.json (1 hunks)
  • packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (3 hunks)
  • packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py (3 hunks)
  • packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (4 hunks)
  • packages/jumpstarter-driver-corellium/pyproject.toml (1 hunks)
  • packages/jumpstarter-driver-pyserial/jumpstarter_driver_pyserial/driver.py (4 hunks)
  • packages/jumpstarter-driver-pyserial/pyproject.toml (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • packages/jumpstarter-driver-corellium/fixtures/http/get-instance-200.json
🚧 Files skipped from review as they are similar to previous changes (5)
  • packages/jumpstarter-driver-corellium/pyproject.toml
  • packages/jumpstarter-driver-corellium/examples/exporter.yml
  • packages/jumpstarter-driver-corellium/fixtures/http/get-instance-console-url-400.json
  • packages/jumpstarter-driver-corellium/fixtures/http/get-instance-console-url-200.json
  • packages/jumpstarter-driver-pyserial/pyproject.toml
🧰 Additional context used
🧬 Code Graph Analysis (2)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (2)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/types.py (1)
  • Instance (51-56)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/exceptions.py (1)
  • CorelliumApiException (7-10)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py (3)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (2)
  • get_instance_console_id (176-193)
  • get_instance_console_url (195-207)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/types.py (2)
  • Instance (51-56)
  • Session (9-22)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/exceptions.py (1)
  • CorelliumApiException (7-10)
🪛 Ruff (0.8.2)
packages/jumpstarter-driver-pyserial/jumpstarter_driver_pyserial/driver.py

3-3: typing.Any imported but unused

Remove unused import: typing.Any

(F401)


85-85: Blank line contains whitespace

Remove whitespace from blank line

(W293)


86-86: Trailing whitespace

Remove trailing whitespace

(W291)

packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py

1-1: typing.AsyncGenerator imported but unused

Remove unused import: typing.AsyncGenerator

(F401)


4-4: websockets imported but unused

Remove unused import: websockets

(F401)


192-192: Blank line contains whitespace

Remove whitespace from blank line

(W293)

packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py

2-2: asyncio imported but unused

Remove unused import: asyncio

(F401)


3-3: unittest.mock.AsyncMock imported but unused

Remove unused import

(F401)


3-3: unittest.mock.patch imported but unused

Remove unused import

(F401)


8-8: .api.websockets imported but unused

Remove unused import: .api.websockets

(F401)


196-196: Trailing whitespace

Remove trailing whitespace

(W291)


228-228: Trailing whitespace

Remove trailing whitespace

(W291)

packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py

211-211: Trailing whitespace

Remove trailing whitespace

(W291)


213-213: Trailing whitespace

Remove trailing whitespace

(W291)

🔇 Additional comments (2)
packages/jumpstarter-driver-pyserial/jumpstarter_driver_pyserial/driver.py (2)

88-101: Well-designed URL scheme handler

The property-based approach for selecting the connection handler based on URL scheme is clean and extensible. This makes adding new connection types straightforward in the future.


111-129: Well-structured connection handlers

The specialized connection handlers for different URL schemes are well-implemented and documented. The consistent pattern makes the code easy to understand and maintain.

Comment thread packages/jumpstarter-driver-pyserial/jumpstarter_driver_pyserial/driver.py Outdated
@odra odra force-pushed the corellium-serial-driver branch from 61459d7 to 5d9e56c Compare April 18, 2025 12:08
Copy link
Copy Markdown
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

♻️ Duplicate comments (6)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (2)

64-64: PySerial child is instantiated with an empty url but still triggers the base-class machinery

Passing an empty URL string could cause issues if PySerial.__post_init__ validates or attempts to use the URL before your override runs.

Consider passing None as a sentinel value, or check the PySerial implementation to ensure it won't prematurely validate the URL.

-        self.children['serial'] = CorelliumSerial(parent=self, url='', check_present=False)
+        self.children['serial'] = CorelliumSerial(parent=self, url=None, check_present=False)

Run the following to verify this issue:

#!/bin/bash
# Look at PySerial.__post_init__ to see if it attempts to validate the URL

cat packages/jumpstarter-driver-pyserial/jumpstarter_driver_pyserial/driver.py | grep -A10 "__post_init__"

233-236: ⚠️ Potential issue

Add error handling for a missing console

If the console specified by console_name doesn't exist, get_instance_console_id will return None. This will lead to a TypeError when passing None to get_instance_console_url.

        console_id = self.parent.api.get_instance_console_id(instance, self.parent.console_name)
+        if console_id is None:
+            raise ValueError(f"Console '{self.parent.console_name}' does not exist on instance '{self.parent.device_name}'")
        console_url = self.parent.api.get_instance_console_url(instance, console_id)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (2)

182-187: ⚠️ Potential issue

Improve error handling in exception handling blocks

If requests.get() raises an exception before res.json() executes (e.g., network error), data is not yet assigned, causing data.get('error', str(e)) to raise an UnboundLocalError that masks the real issue.

        try:
            res = self.req.get(f'{self.baseurl}/v1/instances/{instance.id}')
            data = res.json()
            res.raise_for_status()
        except requests.exceptions.RequestException as e:
-            raise CorelliumApiException(data.get('error', str(e))) from e
+            msg = str(e)
+            if 'data' in locals() and isinstance(data, dict):
+                msg = data.get('error', msg)
+            raise CorelliumApiException(msg) from e

200-205: ⚠️ Potential issue

Improve error handling in exception handling blocks

Apply the same error handling pattern to this method too.

        try:
            res = self.req.get(f'{self.baseurl}/v1/instances/{instance.id}/console',
                               params={'type': console_id.replace('port-', '')})
            data = res.json()
            res.raise_for_status()
        except requests.exceptions.RequestException as e:
-            raise CorelliumApiException(data.get('error', str(e))) from e
+            msg = str(e)
+            if 'data' in locals() and isinstance(data, dict):
+                msg = data.get('error', msg)
+            raise CorelliumApiException(msg) from e
packages/jumpstarter-driver-pyserial/jumpstarter_driver_pyserial/driver.py (2)

54-56: Remove duplicate close call

There are two identical calls to await self.conn.close(). One call is sufficient since websockets handles closing idempotently.

    async def aclose(self):
        await self.conn.close()
-        await self.conn.close()

107-109: Simplify context handling in connect_wss

Nesting the WebsocketSerial context inside the websockets.connect() context is redundant since WebsocketSerial merely delegates to the same conn.close(). You can yield it directly to avoid double-closing.

        async with websockets.connect(self.url) as websocket:
-            async with WebsocketSerial(conn=websocket) as stream:
-                yield stream
+            yield WebsocketSerial(conn=websocket)

This change would also allow simplifying the aclose() method in WebsocketSerial since the outer context will handle closing the connection.

🧹 Nitpick comments (9)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (1)

211-213: Complete the class docstring.

The docstring for CorelliumSerial is incomplete and doesn't explain the purpose of this class. Consider expanding it to describe how it interacts with Corellium's API to provide websocket serial connectivity.

    """
-    A PySerial subclass to handle 
+    A PySerial subclass to handle websocket console connections to Corellium instances.
+    
+    This class dynamically retrieves console URLs from Corellium's API based on the configured
+    console_name and provides a serial interface over websocket connections.
    """
    parent: Corellium 
🧰 Tools
🪛 Ruff (0.8.2)

211-211: Trailing whitespace

Remove trailing whitespace

(W291)


213-213: Trailing whitespace

Remove trailing whitespace

(W291)

packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py (3)

2-8: Remove unused imports

Several imports are not used in this file and should be removed to improve readability and avoid unnecessary dependencies.

import os
-import asyncio
-from unittest.mock import AsyncMock, patch
+
import pytest
-# import websockets

-from .api import ApiClient, websockets
+from .api import ApiClient
from .exceptions import CorelliumApiException
from .types import Device, Instance, Project, Session
🧰 Tools
🪛 Ruff (0.8.2)

2-2: asyncio imported but unused

Remove unused import: asyncio

(F401)


3-3: unittest.mock.AsyncMock imported but unused

Remove unused import

(F401)


3-3: unittest.mock.patch imported but unused

Remove unused import

(F401)


8-8: .api.websockets imported but unused

Remove unused import: .api.websockets

(F401)


196-196: Remove trailing whitespace.

Remove the trailing whitespace at the end of this line.

-    data = fixture('http/get-instance-200.json') 
+    data = fixture('http/get-instance-200.json')
🧰 Tools
🪛 Ruff (0.8.2)

196-196: Trailing whitespace

Remove trailing whitespace

(W291)


228-228: Remove trailing whitespace.

Remove the trailing whitespace at the end of this line.

-    data = fixture('http/get-instance-console-url-200.json') 
+    data = fixture('http/get-instance-console-url-200.json')
🧰 Tools
🪛 Ruff (0.8.2)

228-228: Trailing whitespace

Remove trailing whitespace

(W291)

packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (3)

1-5: Remove unused imports

Several imports are not used in the file and should be removed.

-from typing import AsyncGenerator, Optional
+from typing import Optional

import requests
-import websockets
+
from .exceptions import CorelliumApiException
🧰 Tools
🪛 Ruff (0.8.2)

1-1: typing.AsyncGenerator imported but unused

Remove unused import: typing.AsyncGenerator

(F401)


4-4: websockets imported but unused

Remove unused import: websockets

(F401)


196-198: Fix typo in docstring

There's a duplicated "a" in the docstring.

    """
-    Get a a console URL (websocket) to stream logs from.
+    Get a console URL (websocket) to stream logs from.
    """

192-193: Remove whitespace in blank line

Remove the trailing whitespace on the blank line.

            if console['name'] == console_name:
                return console['id']
-        
+
        return None
🧰 Tools
🪛 Ruff (0.8.2)

192-192: Blank line contains whitespace

Remove whitespace from blank line

(W293)

packages/jumpstarter-driver-pyserial/jumpstarter_driver_pyserial/driver.py (2)

3-6: Remove unused import

The import of typing.Any is not used and should be removed.

-from typing import Any
+

import websockets
from websockets.asyncio.client import ClientConnection as WSSClientConnection
🧰 Tools
🪛 Ruff (0.8.2)

3-3: typing.Any imported but unused

Remove unused import: typing.Any

(F401)


85-86: Remove whitespace in blank line and trailing whitespace

Clean up the whitespace for better code readability.

            yield stream
-        
-        self.logger.info("Disconnected from %s", self.url) 
+
+        self.logger.info("Disconnected from %s", self.url)
🧰 Tools
🪛 Ruff (0.8.2)

85-85: Blank line contains whitespace

Remove whitespace from blank line

(W293)


86-86: Trailing whitespace

Remove trailing whitespace

(W291)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 61459d7 and 5d9e56c.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (10)
  • packages/jumpstarter-driver-corellium/examples/exporter.yml (1 hunks)
  • packages/jumpstarter-driver-corellium/fixtures/http/get-instance-200.json (1 hunks)
  • packages/jumpstarter-driver-corellium/fixtures/http/get-instance-console-url-200.json (1 hunks)
  • packages/jumpstarter-driver-corellium/fixtures/http/get-instance-console-url-400.json (1 hunks)
  • packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (2 hunks)
  • packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py (3 hunks)
  • packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (4 hunks)
  • packages/jumpstarter-driver-corellium/pyproject.toml (1 hunks)
  • packages/jumpstarter-driver-pyserial/jumpstarter_driver_pyserial/driver.py (4 hunks)
  • packages/jumpstarter-driver-pyserial/pyproject.toml (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • packages/jumpstarter-driver-corellium/fixtures/http/get-instance-200.json
🚧 Files skipped from review as they are similar to previous changes (5)
  • packages/jumpstarter-driver-pyserial/pyproject.toml
  • packages/jumpstarter-driver-corellium/examples/exporter.yml
  • packages/jumpstarter-driver-corellium/fixtures/http/get-instance-console-url-200.json
  • packages/jumpstarter-driver-corellium/fixtures/http/get-instance-console-url-400.json
  • packages/jumpstarter-driver-corellium/pyproject.toml
🧰 Additional context used
🧬 Code Graph Analysis (1)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py (3)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (2)
  • get_instance_console_id (176-193)
  • get_instance_console_url (195-207)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/types.py (2)
  • Instance (51-56)
  • Session (9-22)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/exceptions.py (1)
  • CorelliumApiException (7-10)
🪛 Ruff (0.8.2)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py

1-1: typing.AsyncGenerator imported but unused

Remove unused import: typing.AsyncGenerator

(F401)


4-4: websockets imported but unused

Remove unused import: websockets

(F401)


192-192: Blank line contains whitespace

Remove whitespace from blank line

(W293)

packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py

2-2: asyncio imported but unused

Remove unused import: asyncio

(F401)


3-3: unittest.mock.AsyncMock imported but unused

Remove unused import

(F401)


3-3: unittest.mock.patch imported but unused

Remove unused import

(F401)


8-8: .api.websockets imported but unused

Remove unused import: .api.websockets

(F401)


196-196: Trailing whitespace

Remove trailing whitespace

(W291)


228-228: Trailing whitespace

Remove trailing whitespace

(W291)

packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py

211-211: Trailing whitespace

Remove trailing whitespace

(W291)


213-213: Trailing whitespace

Remove trailing whitespace

(W291)

packages/jumpstarter-driver-pyserial/jumpstarter_driver_pyserial/driver.py

3-3: typing.Any imported but unused

Remove unused import: typing.Any

(F401)


85-85: Blank line contains whitespace

Remove whitespace from blank line

(W293)


86-86: Trailing whitespace

Remove trailing whitespace

(W291)

Copy link
Copy Markdown
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: 2

♻️ Duplicate comments (2)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (1)

238-240: ⚠️ Potential issue

Add error handling for missing console

The url property retrieves the console ID and URL, but if the console specified by console_name doesn't exist, get_instance_console_id will return None. This will lead to a potential TypeError when passing None to get_instance_console_url.

        console_id = self.parent.api.get_instance_console_id(instance, self.parent.console_name)
+       if console_id is None:
+           raise ValueError(f"Console '{self.parent.console_name}' does not exist on instance '{self.parent.device_name}'")
        console_url = self.parent.api.get_instance_console_url(instance, console_id)
packages/jumpstarter-driver-pyserial/jumpstarter_driver_pyserial/driver.py (1)

106-108: Simplify WebSocket connection context management

Nesting an async with WebsocketSerial(...) inside the websockets.connect() context is redundant; WebsocketSerial simply delegates to conn.close(). Consider simplifying this to avoid double-closing.

-        async with websockets.connect(self.url) as websocket:
-            async with WebsocketSerial(conn=websocket) as stream:
-                yield stream
+        async with websockets.connect(self.url) as websocket:
+            yield WebsocketSerial(conn=websocket)
🧹 Nitpick comments (7)
packages/jumpstarter-driver-network/jumpstarter_driver_network/driver.py (3)

253-253: Fix typo in docstring

There's a typo in the docstring: "srreams" should be "streams".

-        Create a websocket connection to `self.url` and srreams its output.
+        Create a websocket connection to `self.url` and streams its output.

247-247: Fix whitespace issues

There are trailing whitespaces and whitespace in blank lines that should be removed.

    url: str
-    
+
    @exportstream
    @asynccontextmanager
    async def connect(self):
        '''
        Create a websocket connection to `self.url` and srreams its output.
        '''
        self.logger.info("Connecting to %s, baudrate: %d", self.url, self.baudrate)
-        
+
        async with websockets.connect(self.url) as websocket:
            async with WebsocketClientStream(conn=websocket) as stream:
                yield stream

-        self.logger.info("Disconnected from %s", self.url) 
+        self.logger.info("Disconnected from %s", self.url)

Also applies to: 255-255, 260-260

🧰 Tools
🪛 Ruff (0.8.2)

247-247: Blank line contains whitespace

Remove whitespace from blank line

(W293)


254-259: Consider adding error handling for websocket connection failures

The current implementation doesn't handle potential websocket connection issues. Consider adding error handling to make the driver more robust.

        self.logger.info("Connecting to %s, baudrate: %d", self.url, self.baudrate)
        
-        async with websockets.connect(self.url) as websocket:
-            async with WebsocketClientStream(conn=websocket) as stream:
-                yield stream
+        try:
+            async with websockets.connect(self.url) as websocket:
+                async with WebsocketClientStream(conn=websocket) as stream:
+                    yield stream
+        except websockets.exceptions.WebSocketException as e:
+            self.logger.error("WebSocket connection error: %s", str(e))
+            raise ConnectionError(f"Failed to connect to {self.url}: {str(e)}") from e
🧰 Tools
🪛 Ruff (0.8.2)

255-255: Blank line contains whitespace

Remove whitespace from blank line

(W293)

packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (2)

211-211: Fix incomplete docstring

The class docstring is incomplete and has trailing whitespace.

-    A PySerial subclass to handle 
+    A driver that provides console access to Corellium devices via WebSocket.
🧰 Tools
🪛 Ruff (0.8.2)

211-211: Trailing whitespace

Remove trailing whitespace

(W291)


243-248: Remove or implement commented-out code

The commented-out url.setter seems unnecessary since you're creating a read-only property. Consider removing it completely rather than leaving commented code in the codebase.

-#     @url.setter
-#     def url(self, value: str) -> None:
-#         """
-#         A workaround to not do anything, url is retrieved from Corellium's API.
-#         """
-#         pass
packages/jumpstarter-driver-pyserial/jumpstarter_driver_pyserial/driver.py (2)

84-85: Fix whitespace issues

There are trailing whitespaces and whitespace in blank lines that should be removed.

        async for stream in self.stream_handler():
            yield stream
-    
-        self.logger.info("Disconnected from %s", self.url) 
+
+        self.logger.info("Disconnected from %s", self.url)
🧰 Tools
🪛 Ruff (0.8.2)

84-84: Blank line contains whitespace

Remove whitespace from blank line

(W293)


85-85: Trailing whitespace

Remove trailing whitespace

(W291)


92-92: Fix typo in docstring

There's a small typo in the docstring: self.connect-serial should be self.connect_serial (underscore instead of hyphen).

-    Defaults to `self.connect-serial` in case no valid handler is found.
+    Defaults to `self.connect_serial` in case no valid handler is found.
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5d9e56c and 9757e6c.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (6)
  • packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (4 hunks)
  • packages/jumpstarter-driver-corellium/pyproject.toml (1 hunks)
  • packages/jumpstarter-driver-network/jumpstarter_driver_network/driver.py (3 hunks)
  • packages/jumpstarter-driver-network/jumpstarter_driver_network/streams/websocket.py (2 hunks)
  • packages/jumpstarter-driver-network/pyproject.toml (1 hunks)
  • packages/jumpstarter-driver-pyserial/jumpstarter_driver_pyserial/driver.py (4 hunks)
✅ Files skipped from review due to trivial changes (1)
  • packages/jumpstarter-driver-network/pyproject.toml
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/jumpstarter-driver-corellium/pyproject.toml
🧰 Additional context used
🧬 Code Graph Analysis (2)
packages/jumpstarter-driver-network/jumpstarter_driver_network/streams/websocket.py (1)
packages/jumpstarter-driver-pyserial/jumpstarter_driver_pyserial/driver.py (9)
  • client (71-72)
  • send (27-28)
  • send (45-46)
  • receive (30-31)
  • receive (48-49)
  • send_eof (33-34)
  • send_eof (51-52)
  • aclose (36-38)
  • aclose (54-55)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (3)
packages/jumpstarter-driver-network/jumpstarter_driver_network/driver.py (3)
  • WebsocketNetwork (242-260)
  • client (26-27)
  • client (160-161)
packages/jumpstarter-driver-pyserial/jumpstarter_driver_pyserial/driver.py (1)
  • client (71-72)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (4)
  • get_project (56-71)
  • get_instance (113-130)
  • get_instance_console_id (176-193)
  • get_instance_console_url (195-207)
🪛 Ruff (0.8.2)
packages/jumpstarter-driver-network/jumpstarter_driver_network/driver.py

247-247: Blank line contains whitespace

Remove whitespace from blank line

(W293)


255-255: Blank line contains whitespace

Remove whitespace from blank line

(W293)


260-260: Trailing whitespace

Remove trailing whitespace

(W291)

packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py

211-211: Trailing whitespace

Remove trailing whitespace

(W291)

packages/jumpstarter-driver-pyserial/jumpstarter_driver_pyserial/driver.py

3-3: typing.Any imported but unused

Remove unused import: typing.Any

(F401)


84-84: Blank line contains whitespace

Remove whitespace from blank line

(W293)


85-85: Trailing whitespace

Remove trailing whitespace

(W291)

⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: Redirect rules - jumpstarter-docs
  • GitHub Check: Header rules - jumpstarter-docs
  • GitHub Check: Pages changed - jumpstarter-docs
🔇 Additional comments (3)
packages/jumpstarter-driver-network/jumpstarter_driver_network/streams/websocket.py (1)

73-91: LGTM! WebsocketClientStream implementation looks solid

The WebsocketClientStream class correctly implements the ObjectStream[bytes] interface, mirroring similar patterns in the codebase.

packages/jumpstarter-driver-pyserial/jumpstarter_driver_pyserial/driver.py (2)

41-56: WebsocketSerial implementation looks good

The WebsocketSerial class correctly implements the ObjectStream interface with proper methods for sending and receiving data over WebSocket connections.


76-85: Good design for connection handler selection

The refactoring to use a stream_handler property that selects the appropriate connection handler based on URL scheme is a clean and extensible approach. This makes it easy to add support for additional protocols in the future.

Also applies to: 87-101

🧰 Tools
🪛 Ruff (0.8.2)

84-84: Blank line contains whitespace

Remove whitespace from blank line

(W293)


85-85: Trailing whitespace

Remove trailing whitespace

(W291)

Comment thread packages/jumpstarter-driver-network/jumpstarter_driver_network/driver.py Outdated
Comment thread packages/jumpstarter-driver-pyserial/jumpstarter_driver_pyserial/driver.py Outdated
@odra odra force-pushed the corellium-serial-driver branch from 9757e6c to 0c0efee Compare April 18, 2025 18:16
Copy link
Copy Markdown
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

♻️ Duplicate comments (4)
packages/jumpstarter-driver-network/jumpstarter_driver_network/driver.py (1)

242-260: ⚠️ Potential issue

Missing baudrate attribute will cause runtime error

The WebsocketNetwork class references self.baudrate in the connect method, but this attribute is not defined in the class, which will cause an AttributeError at runtime.

Apply this diff to add the missing attribute:

class WebsocketNetwork(NetworkInterface, Driver):
    '''
    Handles websocket connections from a given url.
    '''
    url: str
+   baudrate: int = field(default=115200)
    
    @exportstream
    @asynccontextmanager
🧰 Tools
🪛 Ruff (0.8.2)

247-247: Blank line contains whitespace

Remove whitespace from blank line

(W293)


255-255: Blank line contains whitespace

Remove whitespace from blank line

(W293)


260-260: Trailing whitespace

Remove trailing whitespace

(W291)

packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (1)

238-239: ⚠️ Potential issue

Add error handling for missing console

The code doesn't handle the case where get_instance_console_id returns None (when the console doesn't exist), which would cause a TypeError when passing None to get_instance_console_url.

Apply this diff to add error handling:

    console_id = self.parent.api.get_instance_console_id(instance, self.parent.console_name)
+   if console_id is None:
+       raise ValueError(f"Console '{self.parent.console_name}' does not exist on instance '{self.parent.device_name}'")
    console_url = self.parent.api.get_instance_console_url(instance, console_id)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (2)

182-187: ⚠️ Potential issue

Fix potential UnboundLocalError in exception handling

If the request fails before data is assigned, accessing data.get('error', str(e)) in the exception handler would cause an UnboundLocalError.

Apply this diff to fix the issue:

    try:
        res = self.req.get(f'{self.baseurl}/v1/instances/{instance.id}')
        data = res.json()
        res.raise_for_status()
    except requests.exceptions.RequestException as e:
-       raise CorelliumApiException(data.get('error', str(e))) from e
+       msg = str(e)
+       if 'data' in locals() and isinstance(data, dict):
+           msg = data.get('error', msg)
+       raise CorelliumApiException(msg) from e

199-205: ⚠️ Potential issue

Fix potential UnboundLocalError in exception handling

Same issue as above: if the request fails before data is assigned, accessing data.get('error', str(e)) in the exception handler would cause an UnboundLocalError.

Apply this diff to fix the issue:

    try:
        res = self.req.get(f'{self.baseurl}/v1/instances/{instance.id}/console',
                           params={'type': console_id.replace('port-', '')})
        data = res.json()
        res.raise_for_status()
    except requests.exceptions.RequestException as e:
-       raise CorelliumApiException(data.get('error', str(e))) from e
+       msg = str(e)
+       if 'data' in locals() and isinstance(data, dict):
+           msg = data.get('error', msg)
+       raise CorelliumApiException(msg) from e
🧹 Nitpick comments (10)
packages/jumpstarter-driver-network/jumpstarter_driver_network/driver.py (2)

252-252: Fix typo in docstring

There's a typo in the docstring: "srreams" should be "streams".

-        Create a websocket connection to `self.url` and srreams its output.
+        Create a websocket connection to `self.url` and streams its output.

247-260: Clean up whitespace and formatting

There are several whitespace issues in this code segment that should be fixed.

    url: str
-    
+
    @exportstream
    @asynccontextmanager
    async def connect(self):
        '''
        Create a websocket connection to `self.url` and srreams its output.
        '''
        self.logger.info("Connecting to %s, baudrate: %d", self.url, self.baudrate)
-        
+
        async with websockets.connect(self.url) as websocket:
            async with WebsocketClientStream(conn=websocket) as stream:
                yield stream

-        self.logger.info("Disconnected from %s", self.url) 
+        self.logger.info("Disconnected from %s", self.url)
🧰 Tools
🪛 Ruff (0.8.2)

247-247: Blank line contains whitespace

Remove whitespace from blank line

(W293)


255-255: Blank line contains whitespace

Remove whitespace from blank line

(W293)


260-260: Trailing whitespace

Remove trailing whitespace

(W291)

packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py (3)

2-8: Remove unused imports

Several imports are never used in this file and should be removed:

  • asyncio
  • AsyncMock and patch from unittest.mock
  • websockets from .api
import os
-import asyncio
-from unittest.mock import AsyncMock, patch

import pytest
-# import websockets

-from .api import ApiClient, websockets
+from .api import ApiClient
from .exceptions import CorelliumApiException
from .types import Device, Instance, Project, Session
🧰 Tools
🪛 Ruff (0.8.2)

2-2: asyncio imported but unused

Remove unused import: asyncio

(F401)


3-3: unittest.mock.AsyncMock imported but unused

Remove unused import

(F401)


3-3: unittest.mock.patch imported but unused

Remove unused import

(F401)


8-8: .api.websockets imported but unused

Remove unused import: .api.websockets

(F401)


196-196: Remove trailing whitespace

Remove trailing whitespace from this line.

-    data = fixture('http/get-instance-200.json') 
+    data = fixture('http/get-instance-200.json')
🧰 Tools
🪛 Ruff (0.8.2)

196-196: Trailing whitespace

Remove trailing whitespace

(W291)


228-228: Remove trailing whitespace

Remove trailing whitespace from this line.

-    data = fixture('http/get-instance-console-url-200.json') 
+    data = fixture('http/get-instance-console-url-200.json')
🧰 Tools
🪛 Ruff (0.8.2)

228-228: Trailing whitespace

Remove trailing whitespace

(W291)

packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (2)

210-212: Complete the class docstring

The docstring for CorelliumConsole is incomplete and ends abruptly.

    """
-   A PySerial subclass to handle 
+   A PySerial subclass to handle console serial connections over websockets.
+   
+   This class extends WebsocketNetwork and dynamically retrieves the websocket
+   URL from the Corellium API to establish a serial connection.
    """
🧰 Tools
🪛 Ruff (0.8.2)

211-211: Trailing whitespace

Remove trailing whitespace

(W291)


243-248: Remove commented-out code

The commented-out url setter method is unnecessary and should be removed. If you need to prevent setting the URL, consider using the property decorator without implementing a setter.

-#     @url.setter
-#     def url(self, value: str) -> None:
-#         """
-#         A workaround to not do anything, url is retrieved from Corellium's API.
-#         """
-#         pass
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (3)

197-197: Fix typo in docstring

There's a typo in the docstring: "Get a a console URL".

-       Get a a console URL (websocket) to stream logs from.
+       Get a console URL (websocket) to stream logs from.

1-4: Remove unused imports

The imports AsyncGenerator and websockets are never used in this file.

-from typing import AsyncGenerator, Optional
+from typing import Optional

import requests
-import websockets
🧰 Tools
🪛 Ruff (0.8.2)

1-1: typing.AsyncGenerator imported but unused

Remove unused import: typing.AsyncGenerator

(F401)


4-4: websockets imported but unused

Remove unused import: websockets

(F401)


192-192: Remove whitespace from blank line

Remove whitespace from the blank line.

        for console in data.get('consoles', []):
            if console['name'] == console_name:
                return console['id']
-        
+
        return None
🧰 Tools
🪛 Ruff (0.8.2)

192-192: Blank line contains whitespace

Remove whitespace from blank line

(W293)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9757e6c and 0c0efee.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (11)
  • packages/jumpstarter-driver-corellium/examples/exporter.yml (1 hunks)
  • packages/jumpstarter-driver-corellium/fixtures/http/get-instance-200.json (1 hunks)
  • packages/jumpstarter-driver-corellium/fixtures/http/get-instance-console-url-200.json (1 hunks)
  • packages/jumpstarter-driver-corellium/fixtures/http/get-instance-console-url-400.json (1 hunks)
  • packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (2 hunks)
  • packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py (3 hunks)
  • packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (4 hunks)
  • packages/jumpstarter-driver-corellium/pyproject.toml (1 hunks)
  • packages/jumpstarter-driver-network/jumpstarter_driver_network/driver.py (3 hunks)
  • packages/jumpstarter-driver-network/jumpstarter_driver_network/streams/websocket.py (2 hunks)
  • packages/jumpstarter-driver-network/pyproject.toml (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • packages/jumpstarter-driver-corellium/fixtures/http/get-instance-200.json
🚧 Files skipped from review as they are similar to previous changes (6)
  • packages/jumpstarter-driver-corellium/examples/exporter.yml
  • packages/jumpstarter-driver-network/pyproject.toml
  • packages/jumpstarter-driver-corellium/fixtures/http/get-instance-console-url-200.json
  • packages/jumpstarter-driver-corellium/pyproject.toml
  • packages/jumpstarter-driver-corellium/fixtures/http/get-instance-console-url-400.json
  • packages/jumpstarter-driver-network/jumpstarter_driver_network/streams/websocket.py
🧰 Additional context used
🧬 Code Graph Analysis (2)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py (3)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (2)
  • get_instance_console_id (176-193)
  • get_instance_console_url (195-207)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/types.py (2)
  • Instance (51-56)
  • Session (9-22)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/exceptions.py (1)
  • CorelliumApiException (7-10)
packages/jumpstarter-driver-network/jumpstarter_driver_network/driver.py (4)
packages/jumpstarter-driver-network/jumpstarter_driver_network/streams/websocket.py (1)
  • WebsocketClientStream (74-90)
packages/jumpstarter/jumpstarter/driver/base.py (1)
  • Driver (42-250)
packages/jumpstarter-driver-pyserial/jumpstarter_driver_pyserial/driver.py (1)
  • connect (55-69)
packages/jumpstarter-driver-ustreamer/jumpstarter_driver_ustreamer/driver.py (1)
  • connect (77-80)
🪛 Ruff (0.8.2)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py

1-1: typing.AsyncGenerator imported but unused

Remove unused import: typing.AsyncGenerator

(F401)


4-4: websockets imported but unused

Remove unused import: websockets

(F401)


192-192: Blank line contains whitespace

Remove whitespace from blank line

(W293)

packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py

2-2: asyncio imported but unused

Remove unused import: asyncio

(F401)


3-3: unittest.mock.AsyncMock imported but unused

Remove unused import

(F401)


3-3: unittest.mock.patch imported but unused

Remove unused import

(F401)


8-8: .api.websockets imported but unused

Remove unused import: .api.websockets

(F401)


196-196: Trailing whitespace

Remove trailing whitespace

(W291)


228-228: Trailing whitespace

Remove trailing whitespace

(W291)

packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py

211-211: Trailing whitespace

Remove trailing whitespace

(W291)

packages/jumpstarter-driver-network/jumpstarter_driver_network/driver.py

247-247: Blank line contains whitespace

Remove whitespace from blank line

(W293)


255-255: Blank line contains whitespace

Remove whitespace from blank line

(W293)


260-260: Trailing whitespace

Remove trailing whitespace

(W291)

🔇 Additional comments (9)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py (4)

173-173: Fixture path correction looks good

The fixture path correction from get-instance-state-404.json to get-instance-404.json appears appropriate.


188-204: Good test coverage for console ID retrieval

The parameterized tests for get_instance_console_id properly verify both successful console ID retrieval and handling of non-existent console names.

🧰 Tools
🪛 Ruff (0.8.2)

196-196: Trailing whitespace

Remove trailing whitespace

(W291)


226-238: Good test for console URL retrieval

This test correctly verifies that the URL is properly retrieved and formatted from the API response.

🧰 Tools
🪛 Ruff (0.8.2)

228-228: Trailing whitespace

Remove trailing whitespace

(W291)


241-259: Comprehensive error testing

The parameterized tests for error cases cover all relevant HTTP status codes (400, 403, 404) and error messages. This ensures the API client properly handles and reports errors.

packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (3)

214-214: Baudrate setting looks good

The baudrate attribute with default value 115200 is correctly implemented. This properly addresses the issue in the parent WebsocketNetwork class where this attribute was missing.


31-31: Good default console name

Adding the console_name field with a sensible default value provides good flexibility for configuration.


64-64: Good implementation of the serial driver

Adding the CorelliumConsole as a child driver under the key 'serial' aligns well with the PR objective of supporting console serial connections over websockets.

packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (2)

176-181: Good implementation of console ID retrieval

The method to retrieve a console ID by name is well-implemented and handles the case where the console doesn't exist by returning None.


195-196: Good implementation of console URL retrieval

The method to retrieve a console URL is well-implemented and correctly extracts the console type from the ID.

@odra odra force-pushed the corellium-serial-driver branch from 0c0efee to 91d9f27 Compare April 18, 2025 18:51
Copy link
Copy Markdown
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

♻️ Duplicate comments (3)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (1)

238-240: ⚠️ Potential issue

Add error handling for missing console.

The code doesn't check if console_id is None before passing it to get_instance_console_url(). If the specified console doesn't exist, this will cause a runtime error.

    console_id = self.parent.api.get_instance_console_id(instance, self.parent.console_name)
+   if console_id is None:
+       raise ValueError(f"Console '{self.parent.console_name}' not found for instance '{self.parent.device_name}'")
    console_url = self.parent.api.get_instance_console_url(instance, console_id)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (2)

176-187: Fix potential UnboundLocalError in exception handling

If the request fails before res.json() is executed, data would be undefined in the except block, causing an UnboundLocalError.

Apply the same fix pattern as previously suggested:

try:
    res = self.req.get(f'{self.baseurl}/v1/instances/{instance.id}')
    data = res.json()
    res.raise_for_status()
except requests.exceptions.RequestException as e:
-    raise CorelliumApiException(data.get('error', str(e))) from e
+    msg = str(e)
+    if 'data' in locals() and isinstance(data, dict):
+        msg = data.get('error', msg)
+    raise CorelliumApiException(msg) from e

195-207: Fix potential UnboundLocalError in exception handling

The get_instance_console_url method has the same issue with exception handling as the previous method.

Apply the same fix pattern here:

try:
    res = self.req.get(f'{self.baseurl}/v1/instances/{instance.id}/console',
                       params={'type': console_id.replace('port-', '')})
    data = res.json()
    res.raise_for_status()
except requests.exceptions.RequestException as e:
-    raise CorelliumApiException(data.get('error', str(e))) from e
+    msg = str(e)
+    if 'data' in locals() and isinstance(data, dict):
+        msg = data.get('error', msg)
+    raise CorelliumApiException(msg) from e
🧹 Nitpick comments (12)
packages/jumpstarter-driver-network/jumpstarter_driver_network/driver_test.py (1)

153-161: Fix the unused variable and trailing whitespace.

The test correctly verifies the WebsocketNetwork's connect method, but there are two minor issues:

  1. The variable c is assigned but never used
  2. There's trailing whitespace on lines 156 and 161
@pytest.mark.asyncio
async def test_websocket_network_connect():
    ws = AsyncMock()
-   ws.__aenter__.return_value = ws 
+   ws.__aenter__.return_value = ws
    
    with patch("websockets.connect", return_value=ws) as m:
        client =  WebsocketNetwork(url="ws://localhost/something")
-       async with client.connect() as c:
-           m.assert_called_once_with("ws://localhost/something") 
+       async with client.connect() as _:
+           m.assert_called_once_with("ws://localhost/something")
🧰 Tools
🪛 Ruff (0.8.2)

156-156: Trailing whitespace

Remove trailing whitespace

(W291)


160-160: Local variable c is assigned to but never used

Remove assignment to unused variable c

(F841)


161-161: Trailing whitespace

Remove trailing whitespace

(W291)

packages/jumpstarter-driver-network/jumpstarter_driver_network/driver.py (2)

242-261: Fix typo in docstring and whitespace issues.

The WebsocketNetwork implementation has a few minor issues:

  1. There's a typo in the connect method docstring
  2. There are whitespace issues in blank lines and trailing whitespace
@dataclass(kw_only=True)
class WebsocketNetwork(NetworkInterface, Driver):
    '''
    Handles websocket connections from a given url.
    '''
    url: str
-    
+
    @exportstream
    @asynccontextmanager
    async def connect(self):
        '''
-       Create a websocket connection to `self.url` and srreams its output.
+       Create a websocket connection to `self.url` and streams its output.
        '''
        self.logger.info("Connecting to %s", self.url)
-        
+
        async with websockets.connect(self.url) as websocket:
            async with WebsocketClientStream(conn=websocket) as stream:
                yield stream

-       self.logger.info("Disconnected from %s", self.url) 
+       self.logger.info("Disconnected from %s", self.url)
🧰 Tools
🪛 Ruff (0.8.2)

248-248: Blank line contains whitespace

Remove whitespace from blank line

(W293)


256-256: Blank line contains whitespace

Remove whitespace from blank line

(W293)


261-261: Trailing whitespace

Remove trailing whitespace

(W291)


251-261: Add error handling for websocket connection failures.

The current implementation doesn't handle potential exceptions from the websocket connection. It's important to catch and properly log any connection errors.

@asynccontextmanager
async def connect(self):
    '''
    Create a websocket connection to `self.url` and srreams its output.
    '''
    self.logger.info("Connecting to %s", self.url)
    
-   async with websockets.connect(self.url) as websocket:
-       async with WebsocketClientStream(conn=websocket) as stream:
-           yield stream
+   try:
+       async with websockets.connect(self.url) as websocket:
+           async with WebsocketClientStream(conn=websocket) as stream:
+               yield stream
+   except Exception as e:
+       self.logger.error("Failed to connect to %s: %s", self.url, str(e))
+       raise

    self.logger.info("Disconnected from %s", self.url) 
🧰 Tools
🪛 Ruff (0.8.2)

256-256: Blank line contains whitespace

Remove whitespace from blank line

(W293)


261-261: Trailing whitespace

Remove trailing whitespace

(W291)

packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py (3)

2-8: Remove unused imports.

There are several imports that aren't used in the module:

import os
-import asyncio
-from unittest.mock import AsyncMock, patch
+# No unused imports

import pytest
-# import websockets

-from .api import ApiClient, websockets
+from .api import ApiClient
from .exceptions import CorelliumApiException
from .types import Device, Instance, Project, Session
🧰 Tools
🪛 Ruff (0.8.2)

2-2: asyncio imported but unused

Remove unused import: asyncio

(F401)


3-3: unittest.mock.AsyncMock imported but unused

Remove unused import

(F401)


3-3: unittest.mock.patch imported but unused

Remove unused import

(F401)


8-8: .api.websockets imported but unused

Remove unused import: .api.websockets

(F401)


196-204: Fix trailing whitespace in the test function.

There's trailing whitespace in this line that should be removed.

@pytest.mark.parametrize(
    'console_name,console_id',
    [
        ('Console 1', 'port-1-cons',),
        ('Console 10', None,),
        ('Console 2', 'port-2-cons',),
    ])
def test_get_instance_console_id_ok(requests_mock, console_name, console_id):
-    data = fixture('http/get-instance-200.json') 
+    data = fixture('http/get-instance-200.json')
    instance = Instance(id='d59db33d-27bd-4b22-878d-49e4758a648e')
    requests_mock.get(f'https://api-host/api/v1/instances/{instance.id}', status_code=200, text=data)
🧰 Tools
🪛 Ruff (0.8.2)

196-196: Trailing whitespace

Remove trailing whitespace

(W291)


228-238: Fix trailing whitespace and verify URL in test.

The test contains trailing whitespace and uses a hardcoded expected URL. Consider extracting the URL from the fixture for more maintainable tests.

def test_get_instance_console_url_ok(requests_mock):
    console_id = 'port-1-cons'
-    data = fixture('http/get-instance-console-url-200.json') 
+    data = fixture('http/get-instance-console-url-200.json')
    instance = Instance(id='d59db33d-27bd-4b22-878d-49e4758a648e')
    requests_mock.get(f'https://api-host/api/v1/instances/{instance.id}/console?type=1-cons',
                      status_code=200, text=data)
    api = ApiClient('api-host', 'api-token')
    api.session = Session('session-token', '2022-03-20T01:50:10.000Z')

    current = api.get_instance_console_url(instance, console_id)
-    expected = 'wss://api-host/port-cons-1'
+    # Extract expected URL from fixture instead of hardcoding
+    import json
+    expected = json.loads(data)['url']

    assert expected == current
🧰 Tools
🪛 Ruff (0.8.2)

228-228: Trailing whitespace

Remove trailing whitespace

(W291)

packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (2)

208-214: Complete the class docstring.

The docstring for CorelliumConsole is incomplete.

@dataclass(kw_only=True)
class CorelliumConsole(WebsocketNetwork):
    """
-   A PySerial subclass to handle 
+   A driver to handle Corellium console connections over websockets.
+   
+   This class extends WebsocketNetwork to interface with Corellium's
+   console endpoints via websockets, allowing serial communication
+   through a PySerial client.
    """
    parent: Corellium
    baudrate: int = field(default=115200)
🧰 Tools
🪛 Ruff (0.8.2)

211-211: Trailing whitespace

Remove trailing whitespace

(W291)


243-248: Remove or document commented-out code.

The file contains commented-out code for a URL setter that doesn't do anything. Either remove it entirely or add a comment explaining why it's kept.

-#     @url.setter
-#     def url(self, value: str) -> None:
-#         """
-#         A workaround to not do anything, url is retrieved from Corellium's API.
-#         """
-#         pass
+    # Note: No setter for url is implemented as the URL should always
+    # be dynamically fetched from the Corellium API at runtime
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (4)

1-4: Remove unused imports

The imports AsyncGenerator and websockets are currently not being used in this file. While they're likely needed for the websocket functionality implemented elsewhere in the PR, they should be removed from this file unless they'll be used here.

-from typing import AsyncGenerator, Optional
+from typing import Optional

import requests
-import websockets
🧰 Tools
🪛 Ruff (0.8.2)

1-1: typing.AsyncGenerator imported but unused

Remove unused import: typing.AsyncGenerator

(F401)


4-4: websockets imported but unused

Remove unused import: websockets

(F401)


192-192: Remove whitespace from blank line

Line 192 contains whitespace in a blank line.

        for console in data.get('consoles', []):
            if console['name'] == console_name:
                return console['id']
-        
+
        return None
🧰 Tools
🪛 Ruff (0.8.2)

192-192: Blank line contains whitespace

Remove whitespace from blank line

(W293)


197-198: Fix typo in docstring

There's a small typo in the method docstring.

"""
-Get a a console URL (websocket) to stream logs from.
+Get a console URL (websocket) to stream logs from.
"""

176-193: Enhance error handling for non-existing consoles

The method returns None when a console with the specified name doesn't exist, but this might not be the most informative way to handle this scenario. Consider whether raising a specific exception with a clear message would be more helpful when a requested console doesn't exist.

def get_instance_console_id(self, instance: Instance, console_name: str) -> Optional[str]:
    """
    Retrieve an instance's console id by its name.

    Return None if it does not exist.
    """
    try:
        res = self.req.get(f'{self.baseurl}/v1/instances/{instance.id}')
        data = res.json()
        res.raise_for_status()
    except requests.exceptions.RequestException as e:
        msg = str(e)
        if 'data' in locals() and isinstance(data, dict):
            msg = data.get('error', msg)
        raise CorelliumApiException(msg) from e

    for console in data.get('consoles', []):
        if console['name'] == console_name:
            return console['id']

+    # Optional enhancement: raise specific exception when console doesn't exist
+    # raise CorelliumApiException(f"Console '{console_name}' not found for instance {instance.id}")
    return None
🧰 Tools
🪛 Ruff (0.8.2)

192-192: Blank line contains whitespace

Remove whitespace from blank line

(W293)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0c0efee and 91d9f27.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (12)
  • packages/jumpstarter-driver-corellium/examples/exporter.yml (1 hunks)
  • packages/jumpstarter-driver-corellium/fixtures/http/get-instance-200.json (1 hunks)
  • packages/jumpstarter-driver-corellium/fixtures/http/get-instance-console-url-200.json (1 hunks)
  • packages/jumpstarter-driver-corellium/fixtures/http/get-instance-console-url-400.json (1 hunks)
  • packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (2 hunks)
  • packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py (3 hunks)
  • packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (4 hunks)
  • packages/jumpstarter-driver-corellium/pyproject.toml (1 hunks)
  • packages/jumpstarter-driver-network/jumpstarter_driver_network/driver.py (3 hunks)
  • packages/jumpstarter-driver-network/jumpstarter_driver_network/driver_test.py (2 hunks)
  • packages/jumpstarter-driver-network/jumpstarter_driver_network/streams/websocket.py (2 hunks)
  • packages/jumpstarter-driver-network/pyproject.toml (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (7)
  • packages/jumpstarter-driver-corellium/fixtures/http/get-instance-console-url-200.json
  • packages/jumpstarter-driver-network/pyproject.toml
  • packages/jumpstarter-driver-corellium/fixtures/http/get-instance-console-url-400.json
  • packages/jumpstarter-driver-network/jumpstarter_driver_network/streams/websocket.py
  • packages/jumpstarter-driver-corellium/pyproject.toml
  • packages/jumpstarter-driver-corellium/examples/exporter.yml
  • packages/jumpstarter-driver-corellium/fixtures/http/get-instance-200.json
🧰 Additional context used
🧬 Code Graph Analysis (1)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (2)
packages/jumpstarter-driver-network/jumpstarter_driver_network/driver.py (1)
  • WebsocketNetwork (243-261)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (4)
  • get_project (56-71)
  • get_instance (113-130)
  • get_instance_console_id (176-193)
  • get_instance_console_url (195-207)
🪛 Ruff (0.8.2)
packages/jumpstarter-driver-network/jumpstarter_driver_network/driver_test.py

156-156: Trailing whitespace

Remove trailing whitespace

(W291)


160-160: Local variable c is assigned to but never used

Remove assignment to unused variable c

(F841)


161-161: Trailing whitespace

Remove trailing whitespace

(W291)

packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py

1-1: typing.AsyncGenerator imported but unused

Remove unused import: typing.AsyncGenerator

(F401)


4-4: websockets imported but unused

Remove unused import: websockets

(F401)


192-192: Blank line contains whitespace

Remove whitespace from blank line

(W293)

packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py

2-2: asyncio imported but unused

Remove unused import: asyncio

(F401)


3-3: unittest.mock.AsyncMock imported but unused

Remove unused import

(F401)


3-3: unittest.mock.patch imported but unused

Remove unused import

(F401)


8-8: .api.websockets imported but unused

Remove unused import: .api.websockets

(F401)


196-196: Trailing whitespace

Remove trailing whitespace

(W291)


228-228: Trailing whitespace

Remove trailing whitespace

(W291)

packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py

211-211: Trailing whitespace

Remove trailing whitespace

(W291)

packages/jumpstarter-driver-network/jumpstarter_driver_network/driver.py

248-248: Blank line contains whitespace

Remove whitespace from blank line

(W293)


256-256: Blank line contains whitespace

Remove whitespace from blank line

(W293)


261-261: Trailing whitespace

Remove trailing whitespace

(W291)

@odra odra force-pushed the corellium-serial-driver branch from 91d9f27 to fb26ff9 Compare April 18, 2025 19:59
Copy link
Copy Markdown
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: 1

🔭 Outside diff range comments (1)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver_test.py (1)

176-204: ⚠️ Potential issue

Fix incorrect patch for console URL method.

There's an issue in the test function where you're patching the same method twice. Line 201 is incorrectly patching get_instance_console_id again instead of patching get_instance_console_url.

-              patch.object(root._api, 'get_instance_console_id',
+              patch.object(root._api, 'get_instance_console_url',
                           **mock_data.get('get_instance_console_url', {'return_value': 'ws://mock'}))):

Also, note that the static analysis tool flags line 203 as a "useless expression" but this is a false positive. The expression console.url is intentionally used without assignment because the test is verifying that accessing this property raises an exception, which is captured by the pytest.raises context manager.

🧰 Tools
🪛 Ruff (0.8.2)

203-203: Found useless expression. Either assign it to a variable or remove it.

(B018)

🧹 Nitpick comments (5)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (1)

1-1: Unused imports should be removed

The imported AsyncGenerator from typing and websockets module are not used in this file.

-from typing import AsyncGenerator, Optional
+from typing import Optional

import requests
-import websockets

Also applies to: 4-4

🧰 Tools
🪛 Ruff (0.8.2)

1-1: typing.AsyncGenerator imported but unused

Remove unused import: typing.AsyncGenerator

(F401)

packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py (1)

1-8: Unused imports should be removed

Several imported modules aren't used in the file: asyncio, AsyncMock, patch, and websockets from .api.

import os
-import asyncio
-from unittest.mock import AsyncMock, patch

import pytest
# import websockets

-from .api import ApiClient, websockets
+from .api import ApiClient
from .exceptions import CorelliumApiException
from .types import Device, Instance, Project, Session
🧰 Tools
🪛 Ruff (0.8.2)

2-2: asyncio imported but unused

Remove unused import: asyncio

(F401)


3-3: unittest.mock.AsyncMock imported but unused

Remove unused import

(F401)


3-3: unittest.mock.patch imported but unused

Remove unused import

(F401)


8-8: .api.websockets imported but unused

Remove unused import: .api.websockets

(F401)

packages/jumpstarter-driver-network/jumpstarter_driver_network/driver_test.py (1)

153-161: Unused variable in async test

The local variable c in the context manager is assigned but never used, and there's trailing whitespace in the code.

@pytest.mark.asyncio
async def test_websocket_network_connect():
    ws = AsyncMock()
-    ws.__aenter__.return_value = ws 
+    ws.__aenter__.return_value = ws
    
    with patch("websockets.connect", return_value=ws) as m:
        client =  WebsocketNetwork(url="ws://localhost/something")
-        async with client.connect() as c:
-            m.assert_called_once_with("ws://localhost/something") 
+        async with client.connect():
+            m.assert_called_once_with("ws://localhost/something")
🧰 Tools
🪛 Ruff (0.8.2)

156-156: Trailing whitespace

Remove trailing whitespace

(W291)


160-160: Local variable c is assigned to but never used

Remove assignment to unused variable c

(F841)


161-161: Trailing whitespace

Remove trailing whitespace

(W291)

packages/jumpstarter-driver-network/jumpstarter_driver_network/driver.py (2)

252-254: Fix typo in docstring

There's a typo in the docstring where "srreams" should be "streams".

        '''
-        Create a websocket connection to `self.url` and srreams its output.
+        Create a websocket connection to `self.url` and streams its output.
        '''

255-261: LGTM! Well-implemented connect method with proper logging

The connect method properly establishes the websocket connection and wraps it in a WebsocketClientStream.

Remove trailing whitespace and whitespace in blank lines:

        self.logger.info("Connecting to %s", self.url)
-        
+
        async with websockets.connect(self.url) as websocket:
            async with WebsocketClientStream(conn=websocket) as stream:
                yield stream

-        self.logger.info("Disconnected from %s", self.url) 
+        self.logger.info("Disconnected from %s", self.url)
🧰 Tools
🪛 Ruff (0.8.2)

256-256: Blank line contains whitespace

Remove whitespace from blank line

(W293)


261-261: Trailing whitespace

Remove trailing whitespace

(W291)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 91d9f27 and fb26ff9.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (13)
  • packages/jumpstarter-driver-corellium/examples/exporter.yml (1 hunks)
  • packages/jumpstarter-driver-corellium/fixtures/http/get-instance-200.json (1 hunks)
  • packages/jumpstarter-driver-corellium/fixtures/http/get-instance-console-url-200.json (1 hunks)
  • packages/jumpstarter-driver-corellium/fixtures/http/get-instance-console-url-400.json (1 hunks)
  • packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (9 hunks)
  • packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py (3 hunks)
  • packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (4 hunks)
  • packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver_test.py (2 hunks)
  • packages/jumpstarter-driver-corellium/pyproject.toml (1 hunks)
  • packages/jumpstarter-driver-network/jumpstarter_driver_network/driver.py (3 hunks)
  • packages/jumpstarter-driver-network/jumpstarter_driver_network/driver_test.py (2 hunks)
  • packages/jumpstarter-driver-network/jumpstarter_driver_network/streams/websocket.py (2 hunks)
  • packages/jumpstarter-driver-network/pyproject.toml (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (8)
  • packages/jumpstarter-driver-corellium/examples/exporter.yml
  • packages/jumpstarter-driver-network/pyproject.toml
  • packages/jumpstarter-driver-corellium/pyproject.toml
  • packages/jumpstarter-driver-corellium/fixtures/http/get-instance-console-url-200.json
  • packages/jumpstarter-driver-corellium/fixtures/http/get-instance-console-url-400.json
  • packages/jumpstarter-driver-network/jumpstarter_driver_network/streams/websocket.py
  • packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py
  • packages/jumpstarter-driver-corellium/fixtures/http/get-instance-200.json
🧰 Additional context used
🧬 Code Graph Analysis (1)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (2)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/exceptions.py (1)
  • CorelliumApiException (7-10)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/types.py (1)
  • Instance (51-56)
🪛 Ruff (0.8.2)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver_test.py

203-203: Found useless expression. Either assign it to a variable or remove it.

(B018)

packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py

1-1: typing.AsyncGenerator imported but unused

Remove unused import: typing.AsyncGenerator

(F401)


4-4: websockets imported but unused

Remove unused import: websockets

(F401)


53-53: Blank line contains whitespace

Remove whitespace from blank line

(W293)


71-71: Blank line contains whitespace

Remove whitespace from blank line

(W293)


208-208: Local variable msgerr is assigned to but never used

Remove assignment to unused variable msgerr

(F841)


215-215: Blank line contains whitespace

Remove whitespace from blank line

(W293)

packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py

2-2: asyncio imported but unused

Remove unused import: asyncio

(F401)


3-3: unittest.mock.AsyncMock imported but unused

Remove unused import

(F401)


3-3: unittest.mock.patch imported but unused

Remove unused import

(F401)


8-8: .api.websockets imported but unused

Remove unused import: .api.websockets

(F401)


196-196: Trailing whitespace

Remove trailing whitespace

(W291)


228-228: Trailing whitespace

Remove trailing whitespace

(W291)

packages/jumpstarter-driver-network/jumpstarter_driver_network/driver.py

248-248: Blank line contains whitespace

Remove whitespace from blank line

(W293)


256-256: Blank line contains whitespace

Remove whitespace from blank line

(W293)


261-261: Trailing whitespace

Remove trailing whitespace

(W291)

packages/jumpstarter-driver-network/jumpstarter_driver_network/driver_test.py

156-156: Trailing whitespace

Remove trailing whitespace

(W291)


160-160: Local variable c is assigned to but never used

Remove assignment to unused variable c

(F841)


161-161: Trailing whitespace

Remove trailing whitespace

(W291)

🔇 Additional comments (10)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (2)

42-54: LGTM! Improved error handling with data initialization

The addition of data = None before the API call and the improved error handling pattern prevents potential UnboundLocalError when the request fails before JSON data is obtained.

🧰 Tools
🪛 Ruff (0.8.2)

53-53: Blank line contains whitespace

Remove whitespace from blank line

(W293)


218-234: LGTM! Well-implemented console URL retrieval

The method correctly handles the console ID transformation by removing the "port-" prefix and properly formats the API request.

packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py (5)

173-173: LGTM! Fixed fixture path reference

The test now correctly uses the get-instance-404.json fixture for testing instance deletion error handling.


187-205: LGTM! Comprehensive test coverage for console ID retrieval

The parameterized test cases cover important scenarios like found and not found console IDs.

🧰 Tools
🪛 Ruff (0.8.2)

196-196: Trailing whitespace

Remove trailing whitespace

(W291)


206-224: LGTM! Thorough error handling tests for console ID retrieval

Tests for both authorization errors (403) and not found errors (404) ensure robust error handling.


226-239: LGTM! Validates console URL retrieval functionality

The test correctly verifies that the API method returns the expected websocket URL.

🧰 Tools
🪛 Ruff (0.8.2)

228-228: Trailing whitespace

Remove trailing whitespace

(W291)


241-259: LGTM! Comprehensive error case testing for console URL

Tests cover all important error cases: invalid type (400), authorization (403), and not found (404).

packages/jumpstarter-driver-network/jumpstarter_driver_network/driver.py (1)

242-248: LGTM! New WebsocketNetwork class implementation

The WebsocketNetwork class properly implements the required interfaces for network connectivity.

🧰 Tools
🪛 Ruff (0.8.2)

248-248: Blank line contains whitespace

Remove whitespace from blank line

(W293)

packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver_test.py (2)

7-7: LGTM: Appropriate import added.

The import of CorelliumConsole is necessary for the new test functions being added.


159-174: LGTM: Well-structured test for the URL retrieval feature.

This test properly verifies that the console URL can be retrieved successfully and follows the same pattern as other tests in the file. The test mocks all necessary API calls and validates the expected output.

@odra odra force-pushed the corellium-serial-driver branch 3 times, most recently from a380e97 to c30f850 Compare April 18, 2025 20:34
Signed-off-by: Leonardo Rossetti <lrossett@redhat.com>
@NickCao NickCao force-pushed the corellium-serial-driver branch from c30f850 to e8061d7 Compare April 21, 2025 13:28
@NickCao NickCao merged commit 26115ad into jumpstarter-dev:main Apr 21, 2025
15 checks passed
@mangelajo mangelajo added this to the 0.6.0 milestone May 8, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants