corellium driver#351
Conversation
WalkthroughThis PR integrates a new Corellium driver into the Jumpstarter framework. It introduces configuration and fixture files to define an Changes
Sequence Diagram(s)sequenceDiagram
participant CP as CorelliumPower
participant API as ApiClient
participant Env as Environment
CP->>Env: Retrieve API_HOST & API_TOKEN
CP->>API: login()
API-->>CP: Session established
CP->>API: get_project() & get_device()
alt Instance exists
CP->>API: set_instance_state("on")
else
CP->>API: create_instance()
end
sequenceDiagram
participant User as CLI User
participant VPC as VirtualPowerClient CLI
participant API as ApiClient
User->>VPC: Invoke "off --destroy"
VPC->>API: (if needed) login & get_instance()
alt Instance exists
VPC->>API: destroy_instance()
else
VPC->>VPC: Handle missing instance error
end
VPC-->>User: Output confirmation
Assessment against linked issues
Possibly related PRs
Suggested reviewers
Poem
✨ Finishing Touches
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
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)
Other keywords and placeholders
CodeRabbit Configuration File (
|
✅ Deploy Preview for jumpstarter-docs ready!
To edit notification comments on pull requests, go to your Netlify site configuration. |
There was a problem hiding this comment.
Actionable comments posted: 5
🔭 Outside diff range comments (1)
packages/jumpstarter-driver-corellium/fixtures/http/json-error.json (1)
1-2:⚠️ Potential issueFix JSON Syntax Error in json-error.json.
The JSON is malformed due to an incomplete string for the "token" value. Please add the missing closing quotation mark and ensure the file is valid JSON.Apply the following diff:
-{"token": "a} +{"token": "a"}🧰 Tools
🪛 Biome (1.9.4)
[error] 1-1: Missing closing quote
The closing quote must be on the same line.
(parse)
[error] 1-1: expected
}but instead the file endsthe file ends here
(parse)
🧹 Nitpick comments (19)
packages/jumpstarter-driver-corellium/pyproject.toml (1)
1-18: Project Metadata and Dependencies:
The project metadata is clearly defined with appropriate fields such as name, authors, readme, license, and Python version requirement. The dependency list is comprehensive and aligns with the project needs. Consider providing a brief description rather than leaving it empty to guide users who view the package metadata.packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/exceptions.py (1)
6-7: Consider following PEP 8 for blank linesPEP 8 recommends one blank line between imports and class definitions, rather than two.
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/client.py (1)
9-20: Commented-out future implementationThe commented-out code suggests the intended functionality but isn't implemented yet. Consider either:
- Implementing this functionality if it's meant to be part of this PR
- Adding a TODO comment explaining when this will be implemented
- Moving this to documentation if it's just for reference
This is fine for a WIP PR, but should be addressed before finalizing.
packages/jumpstarter-driver-corellium/examples/exporter.yml (1)
1-18: YAML configuration is properly structured and documented.The configuration defines a template for using the Corellium driver with appropriate naming and parameters. The intentional empty values for
endpointandtokenare clearly documented, which is good practice for example files.Consideration for authentication security
Since this driver will require API credentials to function properly, ensure that your documentation clearly explains how users should securely provide the
CORELLIUM_API_HOSTandCORELLIUM_API_TOKENenvironment variables in production environments.packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver_test.py (6)
1-12: Clean up unused imports.Several imports are flagged as unused by static analysis tools. Remove or use these imports to keep the codebase clean.
-import os from unittest.mock import patch import pytest -import requests_mock from jumpstarter.common import exceptions as jmp_exceptions from .driver import Corellium, CorelliumPower -from .corellium.types import * -from .corellium.api import ApiClient +from .corellium.types import Session, Project, Device, Instance from .corellium.exceptions import CorelliumApiException🧰 Tools
🪛 Ruff (0.8.2)
1-1:
osimported but unusedRemove unused import:
os(F401)
5-5:
requests_mockimported but unusedRemove unused import:
requests_mock(F401)
9-9:
from .corellium.types import *used; unable to detect undefined names(F403)
10-10:
.corellium.api.ApiClientimported but unusedRemove unused import:
.corellium.api.ApiClient(F401)
14-26: Driver initialization test looks good.The test correctly verifies the initialization of the Corellium driver with environment variables. Consider adding assertions to verify any default values that might be set when optional parameters aren't provided.
def test_driver_corellium_init_ok(monkeypatch): monkeypatch.setenv('CORELLIUM_API_HOST', 'api-host') monkeypatch.setenv('CORELLIUM_API_TOKEN', 'api-token') - + c = Corellium(project_id='1', device_name='jmp', device_flavor='kronos', device_os='1.0') - + assert '1' == c.project_id assert 'jmp' == c.device_name assert 'kronos' == c.device_flavor assert '1.0' == c.device_os assert 'api-host' == c._api.host assert 'api-token' == c._api.token🧰 Tools
🪛 Ruff (0.8.2)
17-17: Blank line contains whitespace
Remove whitespace from blank line
(W293)
19-19: Blank line contains whitespace
Remove whitespace from blank line
(W293)
28-59: Environment variable validation tests are thorough.Good use of parameterized tests to cover various error scenarios. The test properly checks for configuration errors when required environment variables are missing or empty.
@pytest.mark.parametrize( 'env,err', - [ + [ ( - dict(), + {}, jmp_exceptions.ConfigurationError('Missing "CORELLIUM_API_HOST" environment variable') ), ( - dict(CORELLIUM_API_HOST=' '), + {'CORELLIUM_API_HOST': ' '}, jmp_exceptions.ConfigurationError('"CORELLIUM_API_HOST" environment variable is empty') ), ( - dict(CORELLIUM_API_HOST='api-host'), + {'CORELLIUM_API_HOST': 'api-host'}, jmp_exceptions.ConfigurationError('Missing "CORELLIUM_API_TOKEN" environment variable') ), ( - dict(CORELLIUM_API_HOST='api-host', CORELLIUM_API_TOKEN=' '), + {'CORELLIUM_API_HOST': 'api-host', 'CORELLIUM_API_TOKEN': ' '}, jmp_exceptions.ConfigurationError('"CORELLIUM_API_TOKEN" environment variable is empty') ), ]) def test_driver_corellium_init_error(monkeypatch, env, err): monkeypatch.delenv('CORELLIUM_API_HOST', raising=False) monkeypatch.delenv('CORELLIUM_API_TOKEN', raising=False) - + for k, v in env.items(): monkeypatch.setenv(k, v) with pytest.raises(type(err)) as e: Corellium(project_id='1', device_name='jmp', device_flavor='kronos', device_os='1.0') - + assert str(err) == str(e.value)🧰 Tools
🪛 Ruff (0.8.2)
30-30: Trailing whitespace
Remove trailing whitespace
(W291)
32-32: Unnecessary
dict()call (rewrite as a literal)Rewrite as a literal
(C408)
36-36: Unnecessary
dict()call (rewrite as a literal)Rewrite as a literal
(C408)
40-40: Unnecessary
dict()call (rewrite as a literal)Rewrite as a literal
(C408)
44-44: Unnecessary
dict()call (rewrite as a literal)Rewrite as a literal
(C408)
51-51: Blank line contains whitespace
Remove whitespace from blank line
(W293)
57-57: Blank line contains whitespace
Remove whitespace from blank line
(W293)
71-87: Power on test has good mocking approach.The test properly mocks API interactions to test the power on functionality. Consider making the mocked return values more specific to better match real scenarios.
@pytest.mark.asyncio async def test_driver_power_on_ok(): project = Project('1', 'Default Project') device = Device(name='rd1ae', type='automotive', flavor='kronos', description='', model='kronos', peripherals=False, quotas={}) instance = Instance(id='7f4f241c-821f-4219-905f-c3b50b0db5dd', state='on') root = Corellium(project_id='1', device_name='jmp', device_flavor='kronos', device_os='1.0') power = CorelliumPower(parent=root) - + with (patch.object(root._api, 'login', return_value=None), patch.object(root._api, 'get_project', return_value=project), patch.object(root._api, 'get_device', return_value=device), patch.object(root._api, 'get_instance', return_value=None), patch.object(root._api, 'create_instance', return_value=instance), patch.object(root._api, 'read_instance_state', return_value=None)): await power.on()🧰 Tools
🪛 Ruff (0.8.2)
73-73:
Projectmay be undefined, or defined from star imports(F405)
74-74:
Devicemay be undefined, or defined from star imports(F405)
75-75: Unnecessary
dict()call (rewrite as a literal)Rewrite as a literal
(C408)
76-76:
Instancemay be undefined, or defined from star imports(F405)
79-79: Blank line contains whitespace
Remove whitespace from blank line
(W293)
112-124: Power off test has good mocking approach.The test correctly sets up mocking for the power off functionality. The side effect on
get_instanceto return different values on subsequent calls is a good approach.@pytest.mark.asyncio async def test_driver_power_off_ok(): project = Project('1', 'Default Project') instance = Instance(id='7f4f241c-821f-4219-905f-c3b50b0db5dd', state='on') root = Corellium(project_id='1', device_name='jmp', device_flavor='kronos', device_os='1.0') power = CorelliumPower(parent=root) - - with (patch.object(root._api, 'login', return_value=None), + + with (patch.object(root._api, 'login', return_value=None), patch.object(root._api, 'get_project', return_value=project), patch.object(root._api, 'get_instance', side_effect=[instance, None]), patch.object(root._api, 'destroy_instance', return_value=instance)): await power.off()🧰 Tools
🪛 Ruff (0.8.2)
114-114:
Projectmay be undefined, or defined from star imports(F405)
115-115:
Instancemay be undefined, or defined from star imports(F405)
118-118: Blank line contains whitespace
Remove whitespace from blank line
(W293)
119-119: Trailing whitespace
Remove trailing whitespace
(W291)
126-145: Power off error test looks good.The test properly checks error handling for the power off functionality with various scenarios. Consider adding assertions to validate specific error messages for more comprehensive testing.
@pytest.mark.asyncio @pytest.mark.parametrize('mock_data',[ ({'login': {'side_effect': CorelliumApiException('login error')}}), ({'get_project': {'return_value': None}}), ({'get_instance': {'return_value': None}}), ({'destroy_instance': {'side_effect': CorelliumApiException('destroy error')}}), ]) async def test_driver_power_off_error(mock_data): project = Project('1', 'Default Project') instance = Instance(id='7f4f241c-821f-4219-905f-c3b50b0db5dd', state='on') root = Corellium(project_id='1', device_name='jmp', device_flavor='kronos', device_os='1.0') power = CorelliumPower(parent=root) - - with pytest.raises((CorelliumApiException, ValueError)): + + with pytest.raises((CorelliumApiException, ValueError)) as exc_info: with (patch.object(root._api, 'login', **mock_data.get('login', {'return_value': None})), patch.object(root._api, 'get_project', **mock_data.get('get_project', {'return_value': project})), patch.object(root._api, 'get_instance', **mock_data.get('get_instance', {'side_effect': [instance, None]})), patch.object(root._api, 'destroy_instance', **mock_data.get('destroy_instance', {'return_value': instance}))): await power.off() + + # Optionally add assertions on exc_info to validate specific error messages🧰 Tools
🪛 Ruff (0.8.2)
134-134:
Projectmay be undefined, or defined from star imports(F405)
135-135:
Instancemay be undefined, or defined from star imports(F405)
138-138: Blank line contains whitespace
Remove whitespace from blank line
(W293)
142-142: Line too long (122 > 120)
(E501)
143-143: Line too long (124 > 120)
(E501)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (2)
147-152: Consider a timeout for the readiness loop.The loop here sleeps for 5 seconds repeatedly without a maximum wait. If the instance stays in a transitional state, this could block indefinitely. Consider adding a timeout or limiting retries to avoid potentially hanging forever.
while True: self.logger.info('Waiting for instance to be ready...') self.parent.api.read_instance_state(instance) if instance.state == 'on': self.logger.info('Instance is ready') break + # Add a retry counter or a timeout check to avoid an infinite loop. time.sleep(5)🧰 Tools
🪛 Ruff (0.8.2)
147-147: f-string without any placeholders
Remove extraneous
fprefix(F541)
150-150: f-string without any placeholders
Remove extraneous
fprefix(F541)
152-152: Trailing whitespace
Remove trailing whitespace
(W291)
116-116: Remove extraneousfprefixes with no placeholders.Several lines define an f-string without using any placeholders. This can be simplified to a regular string. (Static analysis references: F541)
- self.logger.info(f'Corellium Device:') + self.logger.info('Corellium Device:') - self.logger.info(f'Waiting for instance to be ready...') + self.logger.info('Waiting for instance to be ready...') - self.logger.info(f'Instance is ready') + self.logger.info('Instance is ready')Also applies to: 147-147, 150-150
🧰 Tools
🪛 Ruff (0.8.2)
116-116: f-string without any placeholders
Remove extraneous
fprefix(F541)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (3)
46-46: Use ofrequests.postfor login vs.self.req.postfor subsequent API calls.While the code is functional, consider using the same session (
self.req) for login to maintain consistency, utilize shared settings, and easily manage headers/cookies in a single session.- res = requests.post(f'{self.baseurl}/v1/auth/login', json=data) + res = self.req.post(f'{self.baseurl}/v1/auth/login', json=data)Also applies to: 103-103
52-52: Improve error context by chaining exceptions.When catching an exception and re-raising a
CorelliumApiException, consider usingraise ... from eto preserve the original stack trace. This helps debugging while keeping the custom exception.except Exception as e: - raise CorelliumApiException(str(e)) + raise CorelliumApiException(str(e)) from eAlso applies to: 66-66, 85-85, 111-111, 126-126, 158-158, 182-182, 196-196
🧰 Tools
🪛 Ruff (0.8.2)
52-52: Within an
exceptclause, raise exceptions withraise ... from errorraise ... from Noneto distinguish them from errors in exception handling(B904)
5-5: Wildcard import from.types.
from .types import *can introduce namespace clutter and make it harder to track where specific classes or functions come from. Consider importing specific names instead.- from .types import * + from .types import Session, Project, Device, Instance # for example🧰 Tools
🪛 Ruff (0.8.2)
5-5:
from .types import *used; unable to detect undefined names(F403)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py (4)
4-4: Redefinition of therequests_mockfixture and unused import.Each test function redefines
requests_mockwhile there is also a module-level import. Remove the top-levelimport requests_mockand rely solely on the pytest fixture to avoid overshadowing.- import requests_mockAlso applies to: 22-22, 39-39, 55-55, 78-78, 93-93, 112-112, 123-123, 144-144, 158-158, 177-177, 190-190, 205-205
🧰 Tools
🪛 Ruff (0.8.2)
4-4:
requests_mockimported but unusedRemove unused import:
requests_mock(F401)
131-131: Unnecessarydict()call.Static analysis flags calling
dict()when a literal would suffice. Minor readability improvement:- quotas=dict() + quotas={}Also applies to: 152-152
🧰 Tools
🪛 Ruff (0.8.2)
131-131: Unnecessary
dict()call (rewrite as a literal)Rewrite as a literal
(C408)
6-6: Avoid star imports in test files.Similar to the production code, consider importing only the needed names from
.types, such asSession,Project,Device, andInstancefor clarity.- from .types import * + from .types import Session, Project, Device, Instance🧰 Tools
🪛 Ruff (0.8.2)
6-6:
from .types import *used; unable to detect undefined names(F403)
153-153: Unused variable assignment.Within the
test_create_instance_errortest,instanceis creating a local variable but it’s never used beyond raising an exception. This can be removed or replaced with an underscore if you just need the call for the side effect.- instance = api.create_instance('my-instance', project, device, '1.0') + api.create_instance('my-instance', project, device, '1.0')🧰 Tools
🪛 Ruff (0.8.2)
153-153: Local variable
instanceis assigned to but never usedRemove assignment to unused variable
instance(F841)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (2)
packages/jumpstarter-driver-corellium/poetry.lockis excluded by!**/*.lockuv.lockis excluded by!**/*.lock
📒 Files selected for processing (21)
packages/jumpstarter-driver-corellium/examples/exporter.yml(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/403.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/create-instance-200.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/create-instance-400.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/delete-instance-404.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/get-instance-state-200.txt(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/get-instance-state-404.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/get-models-200.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/get-projects-200.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/get-projects-404.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/json-error.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/login-200.json(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/client.py(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/exceptions.py(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/types.py(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver_test.py(1 hunks)packages/jumpstarter-driver-corellium/pyproject.toml(1 hunks)pyproject.toml(1 hunks)
🧰 Additional context used
🪛 Ruff (0.8.2)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/client.py
1-1: contextlib.contextmanager imported but unused
Remove unused import: contextlib.contextmanager
(F401)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver_test.py
1-1: os imported but unused
Remove unused import: os
(F401)
5-5: requests_mock imported but unused
Remove unused import: requests_mock
(F401)
9-9: from .corellium.types import * used; unable to detect undefined names
(F403)
10-10: .corellium.api.ApiClient imported but unused
Remove unused import: .corellium.api.ApiClient
(F401)
17-17: Blank line contains whitespace
Remove whitespace from blank line
(W293)
19-19: Blank line contains whitespace
Remove whitespace from blank line
(W293)
30-30: Trailing whitespace
Remove trailing whitespace
(W291)
32-32: Unnecessary dict() call (rewrite as a literal)
Rewrite as a literal
(C408)
36-36: Unnecessary dict() call (rewrite as a literal)
Rewrite as a literal
(C408)
40-40: Unnecessary dict() call (rewrite as a literal)
Rewrite as a literal
(C408)
44-44: Unnecessary dict() call (rewrite as a literal)
Rewrite as a literal
(C408)
51-51: Blank line contains whitespace
Remove whitespace from blank line
(W293)
57-57: Blank line contains whitespace
Remove whitespace from blank line
(W293)
61-61: Redefinition of unused requests_mock from line 5
(F811)
62-62: Line too long (129 > 120)
(E501)
68-68: Session may be undefined, or defined from star imports
(F405)
73-73: Project may be undefined, or defined from star imports
(F405)
74-74: Device may be undefined, or defined from star imports
(F405)
75-75: Unnecessary dict() call (rewrite as a literal)
Rewrite as a literal
(C408)
76-76: Instance may be undefined, or defined from star imports
(F405)
79-79: Blank line contains whitespace
Remove whitespace from blank line
(W293)
98-98: Project may be undefined, or defined from star imports
(F405)
99-99: Instance may be undefined, or defined from star imports
(F405)
107-107: Line too long (121 > 120)
(E501)
108-108: Line too long (126 > 120)
(E501)
114-114: Project may be undefined, or defined from star imports
(F405)
115-115: Instance may be undefined, or defined from star imports
(F405)
118-118: Blank line contains whitespace
Remove whitespace from blank line
(W293)
119-119: Trailing whitespace
Remove trailing whitespace
(W291)
134-134: Project may be undefined, or defined from star imports
(F405)
135-135: Instance may be undefined, or defined from star imports
(F405)
138-138: Blank line contains whitespace
Remove whitespace from blank line
(W293)
142-142: Line too long (122 > 120)
(E501)
143-143: Line too long (124 > 120)
(E501)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py
4-4: requests_mock imported but unused
Remove unused import: requests_mock
(F401)
6-6: from .types import * used; unable to detect undefined names
(F403)
22-22: Redefinition of unused requests_mock from line 4
(F811)
35-35: Trailing whitespace
Remove trailing whitespace
(W291)
39-39: Redefinition of unused requests_mock from line 4
(F811)
39-39: Trailing whitespace
Remove trailing whitespace
(W291)
55-55: Redefinition of unused requests_mock from line 4
(F811)
58-58: Session may be undefined, or defined from star imports
(F405)
64-64: Blank line contains whitespace
Remove whitespace from blank line
(W293)
74-74: Trailing whitespace
Remove trailing whitespace
(W291)
78-78: Redefinition of unused requests_mock from line 4
(F811)
78-78: Trailing whitespace
Remove trailing whitespace
(W291)
81-81: Session may be undefined, or defined from star imports
(F405)
93-93: Redefinition of unused requests_mock from line 4
(F811)
96-96: Session may be undefined, or defined from star imports
(F405)
99-99: Blank line contains whitespace
Remove whitespace from blank line
(W293)
109-109: Trailing whitespace
Remove trailing whitespace
(W291)
112-112: Redefinition of unused requests_mock from line 4
(F811)
112-112: Trailing whitespace
Remove trailing whitespace
(W291)
115-115: Session may be undefined, or defined from star imports
(F405)
123-123: Redefinition of unused requests_mock from line 4
(F811)
127-127: Session may be undefined, or defined from star imports
(F405)
129-129: Project may be undefined, or defined from star imports
(F405)
130-130: Device may be undefined, or defined from star imports
(F405)
131-131: Unnecessary dict() call (rewrite as a literal)
Rewrite as a literal
(C408)
140-140: Trailing whitespace
Remove trailing whitespace
(W291)
144-144: Redefinition of unused requests_mock from line 4
(F811)
144-144: Trailing whitespace
Remove trailing whitespace
(W291)
147-147: Session may be undefined, or defined from star imports
(F405)
149-149: Trailing whitespace
Remove trailing whitespace
(W291)
150-150: Project may be undefined, or defined from star imports
(F405)
151-151: Device may be undefined, or defined from star imports
(F405)
152-152: Unnecessary dict() call (rewrite as a literal)
Rewrite as a literal
(C408)
153-153: Local variable instance is assigned to but never used
Remove assignment to unused variable instance
(F841)
158-158: Redefinition of unused requests_mock from line 4
(F811)
159-159: Instance may be undefined, or defined from star imports
(F405)
161-161: Blank line contains whitespace
Remove whitespace from blank line
(W293)
164-164: Session may be undefined, or defined from star imports
(F405)
173-173: Trailing whitespace
Remove trailing whitespace
(W291)
177-177: Redefinition of unused requests_mock from line 4
(F811)
177-177: Trailing whitespace
Remove trailing whitespace
(W291)
178-178: Instance may be undefined, or defined from star imports
(F405)
182-182: Session may be undefined, or defined from star imports
(F405)
190-190: Redefinition of unused requests_mock from line 4
(F811)
191-191: Instance may be undefined, or defined from star imports
(F405)
192-192: Blank line contains whitespace
Remove whitespace from blank line
(W293)
195-195: Session may be undefined, or defined from star imports
(F405)
201-201: Trailing whitespace
Remove trailing whitespace
(W291)
205-205: Redefinition of unused requests_mock from line 4
(F811)
205-205: Trailing whitespace
Remove trailing whitespace
(W291)
206-206: Instance may be undefined, or defined from star imports
(F405)
210-210: Session may be undefined, or defined from star imports
(F405)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py
5-5: from .types import * used; unable to detect undefined names
(F403)
13-13: Session may be undefined, or defined from star imports
(F405)
14-14: field may be undefined, or defined from star imports
(F405)
18-18: Trailing whitespace
Remove trailing whitespace
(W291)
28-28: Trailing whitespace
Remove trailing whitespace
(W291)
31-31: Blank line contains whitespace
Remove whitespace from blank line
(W293)
52-52: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
54-54: Session may be undefined, or defined from star imports
(F405)
57-57: Project may be undefined, or defined from star imports
(F405)
66-66: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
70-70: Project may be undefined, or defined from star imports
(F405)
74-74: Device may be undefined, or defined from star imports
(F405)
85-85: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
89-89: Device may be undefined, or defined from star imports
(F405)
93-93: Project may be undefined, or defined from star imports
(F405)
93-93: Device may be undefined, or defined from star imports
(F405)
94-94: Instance may be undefined, or defined from star imports
(F405)
94-94: Line too long (121 > 120)
(E501)
111-111: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
113-113: Instance may be undefined, or defined from star imports
(F405)
115-115: Instance may be undefined, or defined from star imports
(F405)
126-126: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
130-130: Instance may be undefined, or defined from star imports
(F405)
134-134: Instance may be undefined, or defined from star imports
(F405)
134-134: Trailing whitespace
Remove trailing whitespace
(W291)
158-158: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
160-160: Instance may be undefined, or defined from star imports
(F405)
160-160: Trailing whitespace
Remove trailing whitespace
(W291)
182-182: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
186-186: Instance may be undefined, or defined from star imports
(F405)
196-196: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py
35-35: Trailing whitespace
Remove trailing whitespace
(W291)
47-47: Blank line contains whitespace
Remove whitespace from blank line
(W293)
67-67: Trailing whitespace
Remove trailing whitespace
(W291)
83-83: Trailing whitespace
Remove trailing whitespace
(W291)
89-89: Blank line contains whitespace
Remove whitespace from blank line
(W293)
116-116: f-string without any placeholders
Remove extraneous f prefix
(F541)
121-121: Trailing whitespace
Remove trailing whitespace
(W291)
142-142: Trailing whitespace
Remove trailing whitespace
(W291)
147-147: f-string without any placeholders
Remove extraneous f prefix
(F541)
150-150: f-string without any placeholders
Remove extraneous f prefix
(F541)
152-152: Trailing whitespace
Remove trailing whitespace
(W291)
163-163: Blank line contains whitespace
Remove whitespace from blank line
(W293)
167-167: f-string without any placeholders
Remove extraneous f prefix
(F541)
173-173: Undefined name selg
(F821)
🪛 Biome (1.9.4)
packages/jumpstarter-driver-corellium/fixtures/http/json-error.json
[error] 1-1: Missing closing quote
The closing quote must be on the same line.
(parse)
[error] 1-1: expected } but instead the file ends
the file ends here
(parse)
🔇 Additional comments (20)
packages/jumpstarter-driver-corellium/pyproject.toml (2)
19-30: Entry Points and Development Dependencies:
The entry point for the Corellium driver is correctly configured, mappingCorelliumto the expected module and class. The development dependencies section is also suitably detailed, listing all required testing and asynchronous libraries.
31-42: Versioning and Build System Configuration:
The Hatch-related configuration (VCS hooks, version source, and build backend setup) is properly configured. This ensures that versioning is integrated with VCS and that the build system requirements are met.packages/jumpstarter-driver-corellium/fixtures/http/get-instance-state-200.txt (1)
1-1: Fixture File Content Verification:
The fixture content"on"is concise and appears to represent an active instance state. Ensure that your tests correctly interpret this state value.packages/jumpstarter-driver-corellium/fixtures/http/create-instance-200.json (1)
1-4: Valid JSON Fixture for Instance Creation:
The JSON fixture is well-formed with anidfield containing a UUID. Confirm that the UUID format is consistent with the API contract expected by the Corellium driver.packages/jumpstarter-driver-corellium/fixtures/http/login-200.json (1)
1-5: Login Fixture JSON Validity:
This fixture correctly simulates a successful login response with bothtokenandexpirationfields. Ensure that your test suite validates token use and checks for proper expiration handling.packages/jumpstarter-driver-corellium/fixtures/http/get-projects-404.json (1)
1-6: Error Response Fixture Consistency:
The error response JSON provides a clear structure witherror,errorID, andfieldkeys. This should be effective for standardized error handling in project lookup failures. Verify that your error handlers and tests are structured to interpret these fields accurately.packages/jumpstarter-driver-corellium/fixtures/http/403.json (1)
1-5: Approve JSON fixture for 403 Error Response.
The JSON structure is well-formatted and includes the expected keys ("error", "errorID", "originalError") for reporting authorization issues. It adheres to the standardized error response format used by the driver.packages/jumpstarter-driver-corellium/fixtures/http/create-instance-400.json (1)
1-5: Approve JSON Fixture for "Unsupported Device Model" Error.
The structure is clear and consistent with other error response fixtures. The keys ("error", "errorID", "field") are appropriately utilized to convey the error details.packages/jumpstarter-driver-corellium/fixtures/http/get-instance-state-404.json (1)
1-5: Approve JSON Fixture for Instance State 404 Error.
The fixture is correctly structured, providing a clear error message along with an error identifier and related field. Verify that this format aligns with the error handling expectations in the Corellium client.packages/jumpstarter-driver-corellium/fixtures/http/get-models-200.json (1)
1-14: Approve JSON Fixture for Models Retrieval.
The JSON array containing the device model details is well formatted and complete. The provided properties (such as "type", "name", "flavor", "description", "model", "peripherals", and "quotas") appear to correctly represent the model configuration for an IoT device. Ensure that this configuration matches the expected specifications in the driver implementation.packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/exceptions.py (1)
1-11: Well-structured exception classThe custom exception class is properly implemented, inheriting from the framework's base exception class with a clear docstring explaining its purpose.
pyproject.toml (1)
14-14: Correctly integrated into workspace configurationThe new Corellium driver is properly added to the workspace configuration following the established pattern and maintaining alphabetical order.
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/client.py (1)
7-8: Empty client implementationThe
CorelliumClientclass currently doesn't implement any functionality. This is expected for a WIP PR, but should be completed before merging.Please confirm whether this empty implementation is intentional for the current WIP state, or if it should be completed as part of this PR.
packages/jumpstarter-driver-corellium/fixtures/http/delete-instance-404.json (1)
1-8: Well-structured fixture for 404 error responseThis fixture properly models a 404 error response from the Corellium API when attempting to delete a non-existent instance. The JSON structure includes all necessary fields for effective error handling.
packages/jumpstarter-driver-corellium/fixtures/http/get-projects-200.json (1)
1-40: JSON structure for fixture looks good.The fixture provides a well-structured representation of a Corellium API response for projects. This fixture will be useful for testing API client functionality. The structure includes all necessary fields like project IDs, names, settings, and resource quotas.
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/types.py (4)
8-23: Well-structured Session class with good authorization header support.The Session dataclass properly encapsulates the token and expiration data, and the
as_header()method provides a convenient way to generate authorization headers for API requests.
25-32: Project class definition looks good.The Project dataclass has appropriate fields for ID and name, aligning with the JSON fixture structure.
34-48: Device class has comprehensive attribute set.The Device class captures all necessary attributes for Corellium device representation. The docstring clearly explains its purpose in relation to creating virtual instances.
50-57: Instance class with appropriate state handling.Good use of
field(default=None)for the optional state attribute. The Instance class has the minimum necessary fields to identify and check the status of a Corellium instance.packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (1)
57-57: Children dictionary usage is clear and consistent.Assigning
self.children['power'] = CorelliumPower(parent=self)is a good way to keep the driver hierarchy structured and accessible. No concerns here.
There was a problem hiding this comment.
Actionable comments posted: 2
🔭 Outside diff range comments (1)
packages/jumpstarter-driver-corellium/fixtures/http/json-error.json (1)
1-2:⚠️ Potential issueFix the JSON syntax error
The JSON fixture file contains invalid syntax. It's missing a closing quote for the string value and a closing curly brace for the JSON object.
Here's the corrected JSON:
-{"token": "a} +{"token": "a"}🧰 Tools
🪛 Biome (1.9.4)
[error] 1-1: Missing closing quote
The closing quote must be on the same line.
(parse)
[error] 1-1: expected
}but instead the file endsthe file ends here
(parse)
♻️ Duplicate comments (1)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (1)
172-173:⚠️ Potential issueFix multiple issues with instance destruction loop.
- Passing the entire
instanceobject toget_instanceis incorrect; it requires the instance name or ID.- Using
time.sleepinside an async method can block the event loop.- There's a typo referencing
selg.loggerinstead ofself.logger.
All these points were flagged in previous feedback.- while instance := self.parent.api.get_instance(instance) is not None: - selg.logger.info('Waiting for instance to be destroyed...') - time.sleep(5) + import asyncio + while (fetched := self.parent.api.get_instance(instance.id)) is not None: + self.logger.info('Waiting for instance to be destroyed...') + await asyncio.sleep(5)🧰 Tools
🪛 Ruff (0.8.2)
173-173: Undefined name
selg(F821)
🧹 Nitpick comments (20)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/client.py (2)
7-8: Consider adding implementation details to the CorelliumClient classThe
CorelliumClientclass is currently just a stub with apassstatement. Consider adding at least basic implementation details to make it functional, or add a docstring explaining the intended functionality and timeline for full implementation.
9-20: Document planned functionality for future referenceThe commented-out code suggests planned functionality for the client. Consider adding a TODO comment or docstring explaining what functionality is expected to be implemented here and when, to provide context for future developers.
class CorelliumClient(CompositeClient): + """ + Client for interacting with Corellium virtual devices. + + TODO: Implement hostname property and shell context manager. + """ pass # @property # def hostname(self) -> str:packages/jumpstarter-driver-corellium/pyproject.toml (2)
4-4: Add a project descriptionThe project description is currently empty. Consider adding a concise description that explains the purpose of this driver.
-description = "" +description = "Jumpstarter driver for Corellium virtual devices"
11-17: Consider pinning dependency versionsYou've specified minimum versions for some dependencies (
pyserialandasyncclick), but not for others. Consider specifying version constraints for all dependencies to ensure compatibility.dependencies = [ - "jumpstarter", - "jumpstarter-driver-composite", - "jumpstarter-driver-power", + "jumpstarter>=0.1.0", + "jumpstarter-driver-composite>=0.1.0", + "jumpstarter-driver-power>=0.1.0", "pyserial>=3.5", "asyncclick>=8.1.7.2" ]packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver_test.py (3)
1-5: Remove unused imports.
osandrequests_mockare imported but never used, generating warnings from static analysis tools. Removing them helps keep the codebase clean.- import os - import requests_mock + # removed unused imports🧰 Tools
🪛 Ruff (0.8.2)
1-1:
osimported but unusedRemove unused import:
os(F401)
5-5:
requests_mockimported but unusedRemove unused import:
requests_mock(F401)
10-10: Remove unusedApiClientimport.
ApiClientis imported but not referenced in this test file, so it can be safely removed.- from .corellium.api import ApiClient🧰 Tools
🪛 Ruff (0.8.2)
10-10:
.corellium.api.ApiClientimported but unusedRemove unused import:
.corellium.api.ApiClient(F401)
62-62: Line length exceeds 120 characters.The line is longer than the recommended 120-character limit, flagged by static analysis. Consider breaking it down for better readability.
🧰 Tools
🪛 Ruff (0.8.2)
62-62: Line too long (129 > 120)
(E501)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (2)
45-53: Refactor repeated request-exception handling withraise ... from e.Each
exceptblock re-raises errors without preserving the original traceback. This approach obscures the root cause of exceptions. Consider using “raise … from e” or “raise … from None” for clarity, or implement a common request wrapper to unify and simplify repeated logic.- except Exception as e: - raise CorelliumApiException(str(e)) + except Exception as e: + raise CorelliumApiException(str(e)) from eAlso applies to: 66-67, 85-86, 111-112, 126-127, 158-159, 182-183, 196-197
🧰 Tools
🪛 Ruff (0.8.2)
52-52: Within an
exceptclause, raise exceptions withraise ... from errorraise ... from Noneto distinguish them from errors in exception handling(B904)
93-94: Avoid very long function signatures.The signature for
create_instanceline 94 exceeds 120 characters. Consider splitting parameters or applying a newline for better readability.🧰 Tools
🪛 Ruff (0.8.2)
93-93:
Projectmay be undefined, or defined from star imports(F405)
93-93:
Devicemay be undefined, or defined from star imports(F405)
94-94:
Instancemay be undefined, or defined from star imports(F405)
94-94: Line too long (121 > 120)
(E501)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py (11)
1-9: Consider improving imports and module documentationThe file lacks a module docstring explaining its purpose. Also, while star imports (line 6) provide convenience, they make it harder to track which specific types are being used and can lead to namespace pollution.
import os import pytest import requests_mock - from .types import * + from .types import Session, Project, Device, Instance from .api import ApiClient from .exceptions import CorelliumApiException + """Tests for the Corellium API client functionality."""🧰 Tools
🪛 Ruff (0.8.2)
4-4:
requests_mockimported but unusedRemove unused import:
requests_mock(F401)
6-6:
from .types import *used; unable to detect undefined names(F403)
11-20: Enhance fixture loading function with better error handlingThe fixture function lacks error handling for IO operations and could benefit from a more descriptive docstring.
def fixture(path): """ Load file contents from fixtures/$path. + + Args: + path: Relative path to the fixture file + + Returns: + str: Contents of the fixture file + + Raises: + FileNotFoundError: If the fixture file doesn't exist """ cwd = os.path.dirname(os.path.abspath(__file__)) fixtures_dir = f'{cwd}/../../fixtures' + try: with open(f'{fixtures_dir}/{path}', 'r') as f: return f.read() + except FileNotFoundError: + raise FileNotFoundError(f"Fixture file not found: {fixtures_dir}/{path}")
33-48: Clean up trailing whitespace in parametrized testThe test function effectively covers error scenarios, but there's trailing whitespace on lines 35 and 39.
@pytest.mark.parametrize( 'status_code,data,msg', - [ + [ (403, fixture('http/403.json'), '403 Client Error'), (200, fixture('http/json-error.json'), 'Invalid control character at'), ]) -def test_login_error(requests_mock, status_code, data, msg): +def test_login_error(requests_mock, status_code, data, msg):🧰 Tools
🪛 Ruff (0.8.2)
35-35: Trailing whitespace
Remove trailing whitespace
(W291)
39-39: Redefinition of unused
requests_mockfrom line 4(F811)
39-39: Trailing whitespace
Remove trailing whitespace
(W291)
50-70: Improve whitespace consistency in the test_get_project_ok functionGood parametrized test for the project retrieval functionality. There's excess whitespace on line 64 that should be removed for consistency.
def test_get_project_ok(requests_mock, project_name, data, has_results): requests_mock.get('https://api-host/api/v1/projects', status_code=200, text=data) api = ApiClient('api-host', 'api-token') api.session = Session('session-token', '2022-03-20T01:50:10.000Z') args = [] if project_name: args.append(project_name) project = api.get_project(*args) - + if has_results: assert project is not None assert project.name == project_name if project_name is not None else 'Default Project' else: assert project is None🧰 Tools
🪛 Ruff (0.8.2)
55-55: Redefinition of unused
requests_mockfrom line 4(F811)
58-58:
Sessionmay be undefined, or defined from star imports(F405)
64-64: Blank line contains whitespace
Remove whitespace from blank line
(W293)
72-87: Fix trailing whitespace in test_get_project_errorThe test has trailing whitespace on lines 74 and 78. Also consider adding more specific error message assertions.
@pytest.mark.parametrize( 'status_code,data,msg', - [ + [ (403, fixture('http/403.json'), '403 Client Error'), (404, fixture('http/get-projects-404.json'), ''), ]) -def test_get_project_error(requests_mock, status_code, data, msg): +def test_get_project_error(requests_mock, status_code, data, msg):🧰 Tools
🪛 Ruff (0.8.2)
74-74: Trailing whitespace
Remove trailing whitespace
(W291)
78-78: Redefinition of unused
requests_mockfrom line 4(F811)
78-78: Trailing whitespace
Remove trailing whitespace
(W291)
81-81:
Sessionmay be undefined, or defined from star imports(F405)
89-105: Improve whitespace in test_get_device_okGood test for device retrieval. There's excess whitespace on line 99 that should be removed.
def test_get_device_ok(requests_mock, model, data, has_results): requests_mock.get('https://api-host/api/v1/models', status_code=200, text=data) api = ApiClient('api-host', 'api-token') api.session = Session('session-token', '2022-03-20T01:50:10.000Z') device = api.get_device(model) - + if has_results: assert device is not None assert device.model == model else: assert device is None🧰 Tools
🪛 Ruff (0.8.2)
93-93: Redefinition of unused
requests_mockfrom line 4(F811)
96-96:
Sessionmay be undefined, or defined from star imports(F405)
99-99: Blank line contains whitespace
Remove whitespace from blank line
(W293)
107-121: Add more error scenarios for device retrieval testsThe test currently only covers the 403 error scenario. Consider adding more error scenarios like 404 or 500 to ensure robust error handling.
@pytest.mark.parametrize( 'status_code,data,msg', - [ + [ (403, fixture('http/403.json'), '403 Client Error'), + (404, fixture('http/403.json'), '404 Client Error'), + (500, fixture('http/403.json'), '500 Server Error'), ]) -def test_get_device_error(requests_mock, status_code, data, msg): +def test_get_device_error(requests_mock, status_code, data, msg):🧰 Tools
🪛 Ruff (0.8.2)
109-109: Trailing whitespace
Remove trailing whitespace
(W291)
112-112: Redefinition of unused
requests_mockfrom line 4(F811)
112-112: Trailing whitespace
Remove trailing whitespace
(W291)
115-115:
Sessionmay be undefined, or defined from star imports(F405)
123-136: Use dictionary literal instead of dict()Good test for instance creation. Replace
dict()with{}for better readability.def test_create_instance_ok(requests_mock): data = fixture('http/create-instance-200.json') requests_mock.post('https://api-host/api/v1/instances', status_code=200, text=data) api = ApiClient('api-host', 'api-token') api.session = Session('session-token', '2022-03-20T01:50:10.000Z') project = Project('d59db33d-27bd-4b22-878d-49e4758a648e', 'Default Project') device = Device(name='rd1ae', type='automotive', flavor='kronos', - description='', model='kronos', peripherals=False, quotas=dict()) + description='', model='kronos', peripherals=False, quotas={}) instance = api.create_instance('my-instance', project, device, '1.0') assert instance is not None assert instance.id🧰 Tools
🪛 Ruff (0.8.2)
123-123: Redefinition of unused
requests_mockfrom line 4(F811)
127-127:
Sessionmay be undefined, or defined from star imports(F405)
129-129:
Projectmay be undefined, or defined from star imports(F405)
130-130:
Devicemay be undefined, or defined from star imports(F405)
131-131: Unnecessary
dict()call (rewrite as a literal)Rewrite as a literal
(C408)
158-169: Remove extra whitespace in test_get_instance_state_okGood test for instance state retrieval. There's excess whitespace on line 161 that should be removed.
def test_get_instance_state_ok(requests_mock): instance = Instance(id='d59db33d-27bd-4b22-878d-49e4758a648e') data = fixture('http/get-instance-state-200.txt') - + requests_mock.get(f'https://api-host/api/v1/instances/{instance.id}/state', status_code=200, text=data) api = ApiClient('api-host', 'api-token') api.session = Session('session-token', '2022-03-20T01:50:10.000Z') api.read_instance_state(instance) assert instance.id assert instance.state == 'on'🧰 Tools
🪛 Ruff (0.8.2)
158-158: Redefinition of unused
requests_mockfrom line 4(F811)
159-159:
Instancemay be undefined, or defined from star imports(F405)
161-161: Blank line contains whitespace
Remove whitespace from blank line
(W293)
164-164:
Sessionmay be undefined, or defined from star imports(F405)
171-188: Clean up trailing whitespace in parametrized testThe test for instance state error handling has trailing whitespace that should be removed.
@pytest.mark.parametrize( 'status_code,data,msg', - [ + [ (403, fixture('http/403.json'), '403 Client Error'), (404, fixture('http/get-instance-state-404.json'), '404 Client Error'), ]) -def test_get_instance_state_error(requests_mock, status_code, data, msg): +def test_get_instance_state_error(requests_mock, status_code, data, msg):🧰 Tools
🪛 Ruff (0.8.2)
173-173: Trailing whitespace
Remove trailing whitespace
(W291)
177-177: Redefinition of unused
requests_mockfrom line 4(F811)
177-177: Trailing whitespace
Remove trailing whitespace
(W291)
178-178:
Instancemay be undefined, or defined from star imports(F405)
182-182:
Sessionmay be undefined, or defined from star imports(F405)
199-216: Clean up trailing whitespace in the final testThe test has trailing whitespace that should be removed for consistency.
@pytest.mark.parametrize( 'status_code,data,msg', - [ + [ (403, fixture('http/403.json'), '403 Client Error'), (404, fixture('http/get-instance-state-404.json'), '404 Client Error'), ]) -def test_destroy_instance_error(requests_mock, status_code, data, msg): +def test_destroy_instance_error(requests_mock, status_code, data, msg):🧰 Tools
🪛 Ruff (0.8.2)
201-201: Trailing whitespace
Remove trailing whitespace
(W291)
205-205: Redefinition of unused
requests_mockfrom line 4(F811)
205-205: Trailing whitespace
Remove trailing whitespace
(W291)
206-206:
Instancemay be undefined, or defined from star imports(F405)
210-210:
Sessionmay be undefined, or defined from star imports(F405)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (2)
packages/jumpstarter-driver-corellium/poetry.lockis excluded by!**/*.lockuv.lockis excluded by!**/*.lock
📒 Files selected for processing (21)
packages/jumpstarter-driver-corellium/examples/exporter.yml(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/403.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/create-instance-200.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/create-instance-400.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/delete-instance-404.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/get-instance-state-200.txt(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/get-instance-state-404.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/get-models-200.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/get-projects-200.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/get-projects-404.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/json-error.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/login-200.json(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/client.py(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/exceptions.py(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/types.py(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver_test.py(1 hunks)packages/jumpstarter-driver-corellium/pyproject.toml(1 hunks)pyproject.toml(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (13)
- packages/jumpstarter-driver-corellium/fixtures/http/create-instance-400.json
- packages/jumpstarter-driver-corellium/fixtures/http/login-200.json
- packages/jumpstarter-driver-corellium/fixtures/http/delete-instance-404.json
- packages/jumpstarter-driver-corellium/fixtures/http/get-instance-state-200.txt
- packages/jumpstarter-driver-corellium/fixtures/http/get-instance-state-404.json
- packages/jumpstarter-driver-corellium/fixtures/http/get-projects-200.json
- packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/exceptions.py
- packages/jumpstarter-driver-corellium/fixtures/http/create-instance-200.json
- packages/jumpstarter-driver-corellium/examples/exporter.yml
- packages/jumpstarter-driver-corellium/fixtures/http/403.json
- pyproject.toml
- packages/jumpstarter-driver-corellium/fixtures/http/get-models-200.json
- packages/jumpstarter-driver-corellium/fixtures/http/get-projects-404.json
🧰 Additional context used
🪛 Ruff (0.8.2)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py
35-35: Trailing whitespace
Remove trailing whitespace
(W291)
47-47: Blank line contains whitespace
Remove whitespace from blank line
(W293)
67-67: Trailing whitespace
Remove trailing whitespace
(W291)
83-83: Trailing whitespace
Remove trailing whitespace
(W291)
89-89: Blank line contains whitespace
Remove whitespace from blank line
(W293)
116-116: f-string without any placeholders
Remove extraneous f prefix
(F541)
121-121: Trailing whitespace
Remove trailing whitespace
(W291)
142-142: Trailing whitespace
Remove trailing whitespace
(W291)
147-147: f-string without any placeholders
Remove extraneous f prefix
(F541)
150-150: f-string without any placeholders
Remove extraneous f prefix
(F541)
152-152: Trailing whitespace
Remove trailing whitespace
(W291)
163-163: Blank line contains whitespace
Remove whitespace from blank line
(W293)
167-167: f-string without any placeholders
Remove extraneous f prefix
(F541)
173-173: Undefined name selg
(F821)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py
4-4: requests_mock imported but unused
Remove unused import: requests_mock
(F401)
6-6: from .types import * used; unable to detect undefined names
(F403)
22-22: Redefinition of unused requests_mock from line 4
(F811)
35-35: Trailing whitespace
Remove trailing whitespace
(W291)
39-39: Redefinition of unused requests_mock from line 4
(F811)
39-39: Trailing whitespace
Remove trailing whitespace
(W291)
55-55: Redefinition of unused requests_mock from line 4
(F811)
58-58: Session may be undefined, or defined from star imports
(F405)
64-64: Blank line contains whitespace
Remove whitespace from blank line
(W293)
74-74: Trailing whitespace
Remove trailing whitespace
(W291)
78-78: Redefinition of unused requests_mock from line 4
(F811)
78-78: Trailing whitespace
Remove trailing whitespace
(W291)
81-81: Session may be undefined, or defined from star imports
(F405)
93-93: Redefinition of unused requests_mock from line 4
(F811)
96-96: Session may be undefined, or defined from star imports
(F405)
99-99: Blank line contains whitespace
Remove whitespace from blank line
(W293)
109-109: Trailing whitespace
Remove trailing whitespace
(W291)
112-112: Redefinition of unused requests_mock from line 4
(F811)
112-112: Trailing whitespace
Remove trailing whitespace
(W291)
115-115: Session may be undefined, or defined from star imports
(F405)
123-123: Redefinition of unused requests_mock from line 4
(F811)
127-127: Session may be undefined, or defined from star imports
(F405)
129-129: Project may be undefined, or defined from star imports
(F405)
130-130: Device may be undefined, or defined from star imports
(F405)
131-131: Unnecessary dict() call (rewrite as a literal)
Rewrite as a literal
(C408)
140-140: Trailing whitespace
Remove trailing whitespace
(W291)
144-144: Redefinition of unused requests_mock from line 4
(F811)
144-144: Trailing whitespace
Remove trailing whitespace
(W291)
147-147: Session may be undefined, or defined from star imports
(F405)
149-149: Trailing whitespace
Remove trailing whitespace
(W291)
150-150: Project may be undefined, or defined from star imports
(F405)
151-151: Device may be undefined, or defined from star imports
(F405)
152-152: Unnecessary dict() call (rewrite as a literal)
Rewrite as a literal
(C408)
153-153: Local variable instance is assigned to but never used
Remove assignment to unused variable instance
(F841)
158-158: Redefinition of unused requests_mock from line 4
(F811)
159-159: Instance may be undefined, or defined from star imports
(F405)
161-161: Blank line contains whitespace
Remove whitespace from blank line
(W293)
164-164: Session may be undefined, or defined from star imports
(F405)
173-173: Trailing whitespace
Remove trailing whitespace
(W291)
177-177: Redefinition of unused requests_mock from line 4
(F811)
177-177: Trailing whitespace
Remove trailing whitespace
(W291)
178-178: Instance may be undefined, or defined from star imports
(F405)
182-182: Session may be undefined, or defined from star imports
(F405)
190-190: Redefinition of unused requests_mock from line 4
(F811)
191-191: Instance may be undefined, or defined from star imports
(F405)
192-192: Blank line contains whitespace
Remove whitespace from blank line
(W293)
195-195: Session may be undefined, or defined from star imports
(F405)
201-201: Trailing whitespace
Remove trailing whitespace
(W291)
205-205: Redefinition of unused requests_mock from line 4
(F811)
205-205: Trailing whitespace
Remove trailing whitespace
(W291)
206-206: Instance may be undefined, or defined from star imports
(F405)
210-210: Session may be undefined, or defined from star imports
(F405)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver_test.py
1-1: os imported but unused
Remove unused import: os
(F401)
5-5: requests_mock imported but unused
Remove unused import: requests_mock
(F401)
9-9: from .corellium.types import * used; unable to detect undefined names
(F403)
10-10: .corellium.api.ApiClient imported but unused
Remove unused import: .corellium.api.ApiClient
(F401)
17-17: Blank line contains whitespace
Remove whitespace from blank line
(W293)
19-19: Blank line contains whitespace
Remove whitespace from blank line
(W293)
30-30: Trailing whitespace
Remove trailing whitespace
(W291)
32-32: Unnecessary dict() call (rewrite as a literal)
Rewrite as a literal
(C408)
36-36: Unnecessary dict() call (rewrite as a literal)
Rewrite as a literal
(C408)
40-40: Unnecessary dict() call (rewrite as a literal)
Rewrite as a literal
(C408)
44-44: Unnecessary dict() call (rewrite as a literal)
Rewrite as a literal
(C408)
51-51: Blank line contains whitespace
Remove whitespace from blank line
(W293)
57-57: Blank line contains whitespace
Remove whitespace from blank line
(W293)
61-61: Redefinition of unused requests_mock from line 5
(F811)
62-62: Line too long (129 > 120)
(E501)
68-68: Session may be undefined, or defined from star imports
(F405)
76-76: Project may be undefined, or defined from star imports
(F405)
77-77: Device may be undefined, or defined from star imports
(F405)
78-78: Unnecessary dict() call (rewrite as a literal)
Rewrite as a literal
(C408)
79-79: Instance may be undefined, or defined from star imports
(F405)
104-104: Project may be undefined, or defined from star imports
(F405)
105-105: Instance may be undefined, or defined from star imports
(F405)
113-113: Line too long (121 > 120)
(E501)
114-114: Line too long (126 > 120)
(E501)
123-123: Project may be undefined, or defined from star imports
(F405)
124-124: Instance may be undefined, or defined from star imports
(F405)
127-127: Blank line contains whitespace
Remove whitespace from blank line
(W293)
128-128: Trailing whitespace
Remove trailing whitespace
(W291)
146-146: Project may be undefined, or defined from star imports
(F405)
147-147: Instance may be undefined, or defined from star imports
(F405)
150-150: Blank line contains whitespace
Remove whitespace from blank line
(W293)
154-154: Line too long (122 > 120)
(E501)
155-155: Line too long (124 > 120)
(E501)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py
5-5: from .types import * used; unable to detect undefined names
(F403)
13-13: Session may be undefined, or defined from star imports
(F405)
14-14: field may be undefined, or defined from star imports
(F405)
18-18: Trailing whitespace
Remove trailing whitespace
(W291)
28-28: Trailing whitespace
Remove trailing whitespace
(W291)
31-31: Blank line contains whitespace
Remove whitespace from blank line
(W293)
52-52: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
54-54: Session may be undefined, or defined from star imports
(F405)
57-57: Project may be undefined, or defined from star imports
(F405)
66-66: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
70-70: Project may be undefined, or defined from star imports
(F405)
74-74: Device may be undefined, or defined from star imports
(F405)
85-85: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
89-89: Device may be undefined, or defined from star imports
(F405)
93-93: Project may be undefined, or defined from star imports
(F405)
93-93: Device may be undefined, or defined from star imports
(F405)
94-94: Instance may be undefined, or defined from star imports
(F405)
94-94: Line too long (121 > 120)
(E501)
111-111: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
113-113: Instance may be undefined, or defined from star imports
(F405)
115-115: Instance may be undefined, or defined from star imports
(F405)
126-126: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
130-130: Instance may be undefined, or defined from star imports
(F405)
134-134: Instance may be undefined, or defined from star imports
(F405)
134-134: Trailing whitespace
Remove trailing whitespace
(W291)
158-158: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
160-160: Instance may be undefined, or defined from star imports
(F405)
160-160: Trailing whitespace
Remove trailing whitespace
(W291)
182-182: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
186-186: Instance may be undefined, or defined from star imports
(F405)
196-196: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/client.py
1-1: contextlib.contextmanager imported but unused
Remove unused import: contextlib.contextmanager
(F401)
🪛 Biome (1.9.4)
packages/jumpstarter-driver-corellium/fixtures/http/json-error.json
[error] 1-1: Missing closing quote
The closing quote must be on the same line.
(parse)
[error] 1-1: expected } but instead the file ends
the file ends here
(parse)
🔇 Additional comments (6)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/client.py (1)
1-1: Remove unused importThe
contextmanagerfromcontextlibis imported but not used in the active code. Either implement the commented-out code that uses it or remove/comment out this import.-from contextlib import contextmanager +# from contextlib import contextmanager🧰 Tools
🪛 Ruff (0.8.2)
1-1:
contextlib.contextmanagerimported but unusedRemove unused import:
contextlib.contextmanager(F401)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/types.py (1)
1-57: LGTM! Well-structured data classes with good documentationThe data classes are well-designed with appropriate type hints and docstrings. The
Session.as_header()method provides a clean way to generate authentication headers.packages/jumpstarter-driver-corellium/pyproject.toml (1)
19-20:Details
✅ Verification successful
Verify entry point implementation exists
The entry point
jumpstarter_driver_corellium.driver:Corelliumis defined but not included in the reviewed files. Make sure this class exists and correctly implements the required driver interface.
🏁 Script executed:
#!/bin/bash # Check if the Corellium driver class exists rg -l "class Corellium" --type py packages/jumpstarter-driver-corellium/ # Check if PowerInterface is implemented rg -l "PowerInterface" --type py packages/jumpstarter-driver-corellium/Length of output: 468
Verified Entry Point Implementation
The driver classCorelliumis correctly defined inpackages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.pyand it implementsPowerInterfaceas expected. No further changes are required.packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver_test.py (1)
115-115: Fix incorrect method call for power-on error test.This test named
test_driver_power_on_errorcallspower.off()instead ofpower.on(), which conflicts with its purpose. This issue was previously flagged in a past review.- await power.off() + await power.on()packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (1)
128-128: Fix reference to non-existentdevice_model.The error message references
self.parent.device_modelwhich does not exist in this class. Usedevice_flavorto match the actual property.- raise ValueError('Unable to find a device for this model: {self.parent.device_model}') + raise ValueError(f'Unable to find a device for this model: {self.parent.device_flavor}')packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py (1)
22-31: Test covers the success path wellGood test for validating successful login functionality and session token verification.
🧰 Tools
🪛 Ruff (0.8.2)
22-22: Redefinition of unused
requests_mockfrom line 4(F811)
| self.logger.info(f'Instance: {self.parent.device_name} (ID: {instance.id})') | ||
|
|
||
| # wait for device readiness | ||
| while True: |
There was a problem hiding this comment.
There should be a timeout on this.
There was a problem hiding this comment.
I added a method to handle the timeouts now.
|
|
||
| # destroy a virtual device | ||
| # wait until it's gone | ||
| self.parent.api.destroy_instance(instance) |
There was a problem hiding this comment.
What if we just want to reboot the device?
There was a problem hiding this comment.
My previous implementation had a "--destroy" parameter which would allow you to power it off or destroy, but I wasn't using the power interface.
How should we do it in this case? Modify the PowerInterface?
There was a problem hiding this comment.
I created a "VirtualPowerInterface" class and I am using that one instead. It has a "--destroy" flag.
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (5)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (5)
92-98:⚠️ Potential issueSession refresh logic is incorrect.
The condition to refresh the session is incorrect. You're re-logging in if the session expiration time is greater than 1 second away, but you should only re-login if it's less than a threshold (like 60 seconds).
# check if session is about to expire # currently depends on the magic number of 60 seconds now = datetime.utcnow() diff = datetime.strptime(self._api.session.expiration, '%Y-%m-%dT%H:%M:%S.%fZ') - now - if diff > timedelta(seconds=1): + # Re-login if there's less than 60 seconds left in the session + if diff < timedelta(seconds=60): self._api.login()
128-131:⚠️ Potential issueMismatch between 'device_flavor' usage and error message.
You're checking for a device using
self.parent.device_flavorbut raising an error referencing a nonexistentself.parent.device_model. This inconsistency could lead to confusing error messages.- raise ValueError('Unable to find a device for this model: {self.parent.device_model}') + raise ValueError(f'Unable to find a device for this model: {self.parent.device_flavor}')
173-176:⚠️ Potential issueFix incorrect walrus operator usage and typo in logger call.
There are two issues in this code:
- Incorrect usage of the walrus operator - you're passing the whole instance to
get_instanceinstead of its ID- Typo in the logger call -
selginstead ofself- while instance := self.parent.api.get_instance(instance) is not None: - selg.logger.info('Waiting for instance to be destroyed...') + while (fetched := self.parent.api.get_instance(instance.id)) is not None: + self.logger.info('Waiting for instance to be destroyed...') + time.sleep(5)🧰 Tools
🪛 Ruff (0.8.2)
175-175: Undefined name
selg(F821)
147-155:⚠️ Potential issueAdd timeout to the device readiness check.
The current implementation has an infinite loop without a timeout mechanism. This could potentially lead to the program hanging indefinitely if the instance never becomes ready.
# wait for device readiness + start_time = time.time() + timeout = 300 # 5 minutes timeout while True: self.logger.info('Waiting for instance to be ready...') self.parent.api.read_instance_state(instance) if instance.state == 'on': self.logger.info('Instance is ready') break + if time.time() - start_time > timeout: + raise TimeoutError(f"Instance failed to become ready within {timeout} seconds") time.sleep(5)🧰 Tools
🪛 Ruff (0.8.2)
149-149: f-string without any placeholders
Remove extraneous
fprefix(F541)
152-152: f-string without any placeholders
Remove extraneous
fprefix(F541)
154-154: Trailing whitespace
Remove trailing whitespace
(W291)
157-179: 🛠️ Refactor suggestionConsider adding a timeout to the instance destruction wait loop.
Similar to the readiness check, the destruction wait loop also lacks a timeout mechanism, which could lead to hanging.
self.parent.api.destroy_instance(instance) + start_time = time.time() + timeout = 300 # 5 minutes timeout while (fetched := self.parent.api.get_instance(instance.id)) is not None: self.logger.info('Waiting for instance to be destroyed...') time.sleep(5) + if time.time() - start_time > timeout: + self.logger.warning(f"Instance destruction taking longer than {timeout} seconds") + break🧰 Tools
🪛 Ruff (0.8.2)
165-165: Blank line contains whitespace
Remove whitespace from blank line
(W293)
169-169: f-string without any placeholders
Remove extraneous
fprefix(F541)
175-175: Undefined name
selg(F821)
🧹 Nitpick comments (6)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (6)
1-16: Remove trailing whitespaces for better code style.Remove trailing whitespaces from the imports and class definitions section. These linting issues don't affect functionality but maintaining consistent code style improves readability.
- from jumpstarter.driver import Driver, export + from jumpstarter.driver import Driver, export
35-35: Remove trailing whitespace.The
clientclass method contains trailing whitespace at the end of the return statement.- return 'jumpstarter_driver_corellium.client.CorelliumClient' + return 'jumpstarter_driver_corellium.client.CorelliumClient'🧰 Tools
🪛 Ruff (0.8.2)
35-35: Trailing whitespace
Remove trailing whitespace
(W291)
50-50: Fix typo in docstring.There's a typo in "objects/varibales".
- Additionally, it also sets up some internal objects/varibales such as: + Additionally, it also sets up some internal objects/variables such as:
69-69: Remove trailing whitespace.There's trailing whitespace at the end of this line.
- raise jmp_exceptions.ConfigurationError(f'Missing "{name}" environment variable') + raise jmp_exceptions.ConfigurationError(f'Missing "{name}" environment variable')🧰 Tools
🪛 Ruff (0.8.2)
69-69: Trailing whitespace
Remove trailing whitespace
(W291)
118-122: Remove extraneous f-string prefixes where no placeholders exist.Some of your logging statements use f-strings but don't contain any placeholders, which is unnecessary.
- self.logger.info(f'Corellium Device:') + self.logger.info('Corellium Device:')🧰 Tools
🪛 Ruff (0.8.2)
118-118: f-string without any placeholders
Remove extraneous
fprefix(F541)
180-182: Implement thereadmethod or provide explanation for the empty implementation.The
readmethod is declared but not implemented (contains onlypass). If this is intentional as a placeholder, consider adding a TODO comment explaining what this method will do in the future.@export async def read(self) -> AsyncGenerator[PowerReading, None]: - pass + """ + Read power consumption metrics from the Corellium device. + + TODO: Implement power consumption monitoring if/when Corellium supports this feature. + """ + # Currently not implemented as Corellium doesn't provide power consumption metrics + yield PowerReading(timestamp=datetime.utcnow(), watts=0.0)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py(1 hunks)
🧰 Additional context used
🪛 Ruff (0.8.2)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py
35-35: Trailing whitespace
Remove trailing whitespace
(W291)
49-49: Blank line contains whitespace
Remove whitespace from blank line
(W293)
69-69: Trailing whitespace
Remove trailing whitespace
(W291)
85-85: Trailing whitespace
Remove trailing whitespace
(W291)
91-91: Blank line contains whitespace
Remove whitespace from blank line
(W293)
118-118: f-string without any placeholders
Remove extraneous f prefix
(F541)
123-123: Trailing whitespace
Remove trailing whitespace
(W291)
144-144: Trailing whitespace
Remove trailing whitespace
(W291)
149-149: f-string without any placeholders
Remove extraneous f prefix
(F541)
152-152: f-string without any placeholders
Remove extraneous f prefix
(F541)
154-154: Trailing whitespace
Remove trailing whitespace
(W291)
165-165: Blank line contains whitespace
Remove whitespace from blank line
(W293)
169-169: f-string without any placeholders
Remove extraneous f prefix
(F541)
175-175: Undefined name selg
(F821)
🔇 Additional comments (1)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (1)
173-179:Details
❓ Verification inconclusive
Consider adding an option for power off without destroying the instance.
The current implementation destroys the instance when powering off, but this may not always be the desired behavior. Consider adding an option to just power off the instance without destroying it.
Based on the
set_instance_statemethod you use for powering on, it appears there might be support for simply powering off an instance without destroying it. This would be more consistent with a physical power interface.
🏁 Script executed:
#!/bin/bash # Check if Corellium API supports powering off without destroying rg -A 5 "set_instance_state" --include="*.py"Length of output: 487
API Consistency: Provide a Power-Off Option
The current implementation always destroys the instance upon powering off, but this might be too aggressive. It would be beneficial to add an option that simply powers off the instance, leveraging the potential support in the Corellium API (similar to howset_instance_stateis used for powering on). Given that our initial search usingrgproduced an error due to an incorrect flag, please re-run the search using a corrected command like the one below:Once you verify if the API indeed supports powering off without destroying the instance, you can update the implementation accordingly.
🏁 Script executed:
#!/bin/bash # Re-run the search with the corrected flag to check for powering off support rg -A 5 set_instance_state -g '*.py'Length of output: 1552
Enhance Power-Off Behavior Without Destroying the Instance
It appears that the Corellium API provides a
set_instance_statemethod (currently used with the'on'state) that could potentially be leveraged for a non-destructive power-off (by using an'off'state). Currently, the driver always destroys the instance when powering off. Instead, consider adding an option that usesset_instance_state(instance, 'off')to simply power down the instance when desired. This would better mimic a physical power interface while preserving the instance for later use.
- Verify that passing
'off'toset_instance_stateis supported by the Corellium API.- Update the logic in
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py(around lines 173-179) to conditionally use power-off or destroy based on user preference.🧰 Tools
🪛 Ruff (0.8.2)
175-175: Undefined name
selg(F821)
There was a problem hiding this comment.
Actionable comments posted: 0
♻️ Duplicate comments (4)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver_test.py (1)
98-114:⚠️ Potential issueFix incorrect method call in power on error test.
The test is calling
power.off()instead ofpower.on()which doesn't match the test name and intention.with pytest.raises((CorelliumApiException, ValueError)): with (patch.object(root._api, 'login', **mock_data.get('login', {'return_value': None})), patch.object(root._api, 'get_project', **mock_data.get('get_project', {'return_value': project})), patch.object(root._api, 'get_instance', **mock_data.get('get_instance', {'return_value': instance})), patch.object(root._api, 'create_instance', **mock_data.get('create_instance', {'return_value': instance})), patch.object(root._api, 'read_instance_state', **mock_data.get('read_instance_state', {'return_value': None}))): - power.off() + power.on()🧰 Tools
🪛 Ruff (0.8.2)
102-102:
Projectmay be undefined, or defined from star imports(F405)
103-103:
Instancemay be undefined, or defined from star imports(F405)
111-111: Line too long (121 > 120)
(E501)
112-112: Line too long (126 > 120)
(E501)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (3)
92-98:⚠️ Potential issueFix session refresh logic error.
The current code re-logins if the session expiration time is still more than one second away. This should be inverted - you want to re-login only if the remaining time is less than a certain threshold (e.g., 60 seconds).
# check if session is about to expire # currently depends on the magic number of 60 seconds now = datetime.utcnow() diff = datetime.strptime(self._api.session.expiration, '%Y-%m-%dT%H:%M:%S.%fZ') - now -if diff > timedelta(seconds=1): +# Re-login if there's less than 60 seconds left in the session +if diff < timedelta(seconds=60): self._api.login()
137-140:⚠️ Potential issueMismatch between 'device_flavor' usage and error message.
You're checking for a device using
self.parent.device_flavorbut raising an error referencing a nonexistentself.parent.device_model. This is likely a typographical slip that could lead to confusion or incorrect error logging.device = self.parent.api.get_device(self.parent.device_flavor) if device is None: - raise ValueError('Unable to find a device for this model: {self.parent.device_model}') + raise ValueError(f'Unable to find a device for this model: {self.parent.device_flavor}')
191-197:⚠️ Potential issueFix the walrus operator usage and correct the logger variable typo.
There are two issues in this code:
- The walrus operator is used incorrectly - you're assigning to
instancebut then comparing the result of the entire expression toNone.- There's a typo in the logger reference (
selg.loggerinstead ofself.logger).counter = 0 self.parent.api.destroy_instance(instance) -while instance := self.parent.api.get_instance(instance) is not None: +while (fetched_instance := self.parent.api.get_instance(instance.id)) is not None: if counter >= opts['retries']: raise ValueError('Instance took too long to be powered off') - selg.logger.info('Waiting for instance to be destroyed...') + self.logger.info('Waiting for instance to be destroyed...') counter += 1 time.sleep(opts['interval'])🧰 Tools
🪛 Ruff (0.8.2)
195-195: Undefined name
selg(F821)
197-197: Trailing whitespace
Remove trailing whitespace
(W291)
🧹 Nitpick comments (8)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver_test.py (3)
1-11: Clean up unused imports and use explicit imports instead of star imports.There are several issues with the imports:
- The
osmodule is imported but not usedrequests_mockis imported twice (line 5 and as a function parameter in line 61)ApiClientis imported but not used directly- Star imports (
from .corellium.types import *) should be avoided as they make it difficult to track which names are being used-import os from unittest.mock import patch import pytest -import requests_mock from jumpstarter.common import exceptions as jmp_exceptions from .driver import Corellium, CorelliumPower -from .corellium.types import * -from .corellium.api import ApiClient +from .corellium.types import Project, Device, Instance, Session from .corellium.exceptions import CorelliumApiException🧰 Tools
🪛 Ruff (0.8.2)
1-1:
osimported but unusedRemove unused import:
os(F401)
5-5:
requests_mockimported but unusedRemove unused import:
requests_mock(F401)
9-9:
from .corellium.types import *used; unable to detect undefined names(F403)
10-10:
.corellium.api.ApiClientimported but unusedRemove unused import:
.corellium.api.ApiClient(F401)
32-46: Simplify dictionary literals.Using
dict()is unnecessary when you can use dictionary literals directly. This makes the code more concise and readable.- ( - dict(), - jmp_exceptions.ConfigurationError('Missing "CORELLIUM_API_HOST" environment variable') - ), - ( - dict(CORELLIUM_API_HOST=' '), - jmp_exceptions.ConfigurationError('"CORELLIUM_API_HOST" environment variable is empty') - ), - ( - dict(CORELLIUM_API_HOST='api-host'), - jmp_exceptions.ConfigurationError('Missing "CORELLIUM_API_TOKEN" environment variable') - ), - ( - dict(CORELLIUM_API_HOST='api-host', CORELLIUM_API_TOKEN=' '), - jmp_exceptions.ConfigurationError('"CORELLIUM_API_TOKEN" environment variable is empty') - ), + ( + {}, + jmp_exceptions.ConfigurationError('Missing "CORELLIUM_API_HOST" environment variable') + ), + ( + {'CORELLIUM_API_HOST': ' '}, + jmp_exceptions.ConfigurationError('"CORELLIUM_API_HOST" environment variable is empty') + ), + ( + {'CORELLIUM_API_HOST': 'api-host'}, + jmp_exceptions.ConfigurationError('Missing "CORELLIUM_API_TOKEN" environment variable') + ), + ( + {'CORELLIUM_API_HOST': 'api-host', 'CORELLIUM_API_TOKEN': ' '}, + jmp_exceptions.ConfigurationError('"CORELLIUM_API_TOKEN" environment variable is empty') + ),🧰 Tools
🪛 Ruff (0.8.2)
32-32: Unnecessary
dict()call (rewrite as a literal)Rewrite as a literal
(C408)
36-36: Unnecessary
dict()call (rewrite as a literal)Rewrite as a literal
(C408)
40-40: Unnecessary
dict()call (rewrite as a literal)Rewrite as a literal
(C408)
44-44: Unnecessary
dict()call (rewrite as a literal)Rewrite as a literal
(C408)
76-78: Simplify dictionary literals.Using
dict()is unnecessary when you can use dictionary literals directly.device = Device(name='rd1ae', type='automotive', flavor='kronos', - description='', model='kronos', peripherals=False, quotas=dict()) + description='', model='kronos', peripherals=False, quotas={})🧰 Tools
🪛 Ruff (0.8.2)
76-76:
Devicemay be undefined, or defined from star imports(F405)
77-77: Unnecessary
dict()call (rewrite as a literal)Rewrite as a literal
(C408)
78-78:
Instancemay be undefined, or defined from star imports(F405)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (5)
37-54: Fix docstring placement in__post_init__.The docstring is placed after the first statements in the method instead of at the beginning, which is unconventional and makes the documentation harder to find.
def __post_init__(self) -> None: + """ + Post initialization method. + + It will check for the following environment variables: + + - CORELLIUM_API_HOST + - CORELLIUM_API_TOKEN + + Raises an exception in case these variables are not set or empty. + + Additionally, it also sets up some internal objects/varibales such as: + + - Corellium API client instance + - Children jumpstarter drives + """ if hasattr(super(), "__post_init__"): super().__post_init__() - """ - Post initialization method. - - It will check for the following environment variables: - - - CORELLIUM_API_HOST - - CORELLIUM_API_TOKEN - - Raises an exception in case these variables are not set or empty. - - Additionally, it also sets up some internal objects/varibales such as: - - - Corellium API client instance - - Children jumpstarter drives - """🧰 Tools
🪛 Ruff (0.8.2)
49-49: Blank line contains whitespace
Remove whitespace from blank line
(W293)
159-169: Add timeout to the loop for waiting on instance readiness.The current loop has the potential to run infinitely if the instance never transitions to the 'on' state. It's good that you've implemented a retry counter, but you should also consider adding a timeout parameter to avoid blocking indefinitely.
# wait for device readiness opts = self.get_timeout_opts() counter = 0 +start_time = time.time() +timeout = int(os.environ.get('CORELLIUM_API_TIMEOUT', 300)) # 5 minutes default timeout while True: if counter >= opts['retries']: raise ValueError('Instance took too long to be ready') + + if time.time() - start_time > timeout: + raise ValueError(f'Timed out waiting for instance to be ready after {timeout} seconds') self.logger.info(f'Waiting for instance to be ready...') self.parent.api.read_instance_state(instance) if instance.state == 'on': self.logger.info(f'Instance is ready') break counter += 1 time.sleep(opts['interval'])🧰 Tools
🪛 Ruff (0.8.2)
163-163: f-string without any placeholders
Remove extraneous
fprefix(F541)
166-166: f-string without any placeholders
Remove extraneous
fprefix(F541)
169-169: Trailing whitespace
Remove trailing whitespace
(W291)
201-203: Implement thereadmethod or add a TODO comment.The
readmethod is currently a stub that does nothing, even though it's exported. Consider implementing it or at least adding a TODO comment explaining that it's not implemented yet.@export -def read(self) -> AsyncGenerator[PowerReading, None]: - pass +async def read(self) -> AsyncGenerator[PowerReading, None]: + """ + Read power data from the Corellium device. + + Currently not implemented for Corellium devices. + + Yields: + PowerReading: Not implemented yet. + """ + # TODO: Implement power reading for Corellium devices if the API supports it + yield PowerReading(timestamp=datetime.now(), watts=0.0) # Placeholder
84-85: Fix typo in docstring.There's a typo in the docstring: "accross diferent" should be "across different".
It will also be responsible for creating/refreshing the session token used -accross diferent API methods that require authentication. +across different API methods that require authentication.🧰 Tools
🪛 Ruff (0.8.2)
85-85: Trailing whitespace
Remove trailing whitespace
(W291)
189-194: Consider adding reboot functionality.The current implementation only supports powering on or totally destroying a device instance. You might want to consider adding support for rebooting a device without destroying it.
Consider extending the
PowerInterfaceor implementing a separate method to support reboot functionality, which would allow users to restart a device without completely destroying and recreating it.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
uv.lockis excluded by!**/*.lock
📒 Files selected for processing (3)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver_test.py(1 hunks)packages/jumpstarter-driver-corellium/pyproject.toml(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- packages/jumpstarter-driver-corellium/pyproject.toml
🧰 Additional context used
🧬 Code Definitions (1)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver_test.py (4)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (5) (5)
Corellium(19:99)CorelliumPower(103:203)api(79:99)on(121:169)off(172:199)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (1) (1)
ApiClient(9:196)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/exceptions.py (1) (1)
CorelliumApiException(7:11)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/types.py (4) (4)
Session(9:22)Project(26:31)Device(35:47)Instance(51:56)
🪛 Ruff (0.8.2)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py
35-35: Trailing whitespace
Remove trailing whitespace
(W291)
49-49: Blank line contains whitespace
Remove whitespace from blank line
(W293)
69-69: Trailing whitespace
Remove trailing whitespace
(W291)
85-85: Trailing whitespace
Remove trailing whitespace
(W291)
91-91: Blank line contains whitespace
Remove whitespace from blank line
(W293)
113-113: Trailing whitespace
Remove trailing whitespace
(W291)
127-127: f-string without any placeholders
Remove extraneous f prefix
(F541)
132-132: Trailing whitespace
Remove trailing whitespace
(W291)
153-153: Trailing whitespace
Remove trailing whitespace
(W291)
163-163: f-string without any placeholders
Remove extraneous f prefix
(F541)
166-166: f-string without any placeholders
Remove extraneous f prefix
(F541)
169-169: Trailing whitespace
Remove trailing whitespace
(W291)
180-180: Blank line contains whitespace
Remove whitespace from blank line
(W293)
184-184: f-string without any placeholders
Remove extraneous f prefix
(F541)
195-195: Undefined name selg
(F821)
197-197: Trailing whitespace
Remove trailing whitespace
(W291)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver_test.py
1-1: os imported but unused
Remove unused import: os
(F401)
5-5: requests_mock imported but unused
Remove unused import: requests_mock
(F401)
9-9: from .corellium.types import * used; unable to detect undefined names
(F403)
10-10: .corellium.api.ApiClient imported but unused
Remove unused import: .corellium.api.ApiClient
(F401)
17-17: Blank line contains whitespace
Remove whitespace from blank line
(W293)
19-19: Blank line contains whitespace
Remove whitespace from blank line
(W293)
30-30: Trailing whitespace
Remove trailing whitespace
(W291)
32-32: Unnecessary dict() call (rewrite as a literal)
Rewrite as a literal
(C408)
36-36: Unnecessary dict() call (rewrite as a literal)
Rewrite as a literal
(C408)
40-40: Unnecessary dict() call (rewrite as a literal)
Rewrite as a literal
(C408)
44-44: Unnecessary dict() call (rewrite as a literal)
Rewrite as a literal
(C408)
51-51: Blank line contains whitespace
Remove whitespace from blank line
(W293)
57-57: Blank line contains whitespace
Remove whitespace from blank line
(W293)
61-61: Redefinition of unused requests_mock from line 5
(F811)
62-62: Line too long (129 > 120)
(E501)
68-68: Session may be undefined, or defined from star imports
(F405)
75-75: Project may be undefined, or defined from star imports
(F405)
76-76: Device may be undefined, or defined from star imports
(F405)
77-77: Unnecessary dict() call (rewrite as a literal)
Rewrite as a literal
(C408)
78-78: Instance may be undefined, or defined from star imports
(F405)
102-102: Project may be undefined, or defined from star imports
(F405)
103-103: Instance may be undefined, or defined from star imports
(F405)
111-111: Line too long (121 > 120)
(E501)
112-112: Line too long (126 > 120)
(E501)
120-120: Project may be undefined, or defined from star imports
(F405)
121-121: Instance may be undefined, or defined from star imports
(F405)
124-124: Blank line contains whitespace
Remove whitespace from blank line
(W293)
125-125: Trailing whitespace
Remove trailing whitespace
(W291)
142-142: Project may be undefined, or defined from star imports
(F405)
143-143: Instance may be undefined, or defined from star imports
(F405)
146-146: Blank line contains whitespace
Remove whitespace from blank line
(W293)
150-150: Line too long (122 > 120)
(E501)
151-151: Line too long (124 > 120)
(E501)
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (4)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (4)
97-98:⚠️ Potential issueSession refresh logic error.
Your code refreshes the session if the time difference is greater than 1 second, which is the opposite of the intended behavior. You should refresh when there's less than a certain threshold remaining.
- if diff > timedelta(seconds=1): + # Refresh session if there's less than 60 seconds left + if diff < timedelta(seconds=60): self._api.login()
140-140:⚠️ Potential issueMismatch between attribute reference and error message.
You're checking for a device using
self.parent.device_flavorbut referencingself.parent.device_modelin the error message.- raise ValueError('Unable to find a device for this model: {self.parent.device_model}') + raise ValueError(f'Unable to find a device for this model: {self.parent.device_flavor}')
192-192:⚠️ Potential issueFix incorrect walrus operator usage.
The walrus operator is used incorrectly, which would make this loop behave unexpectedly. Currently, the condition evaluates to a boolean which is then assigned to
instance, not the return value ofget_instance().- while instance := self.parent.api.get_instance(instance) is not None: + while (instance := self.parent.api.get_instance(instance.id)) is not None:
196-196:⚠️ Potential issueFix typo in logger reference.
There's a typo in the logger reference:
selg.loggershould beself.logger.- selg.logger.info('Waiting for instance to be destroyed...') + self.logger.info('Waiting for instance to be destroyed...')🧰 Tools
🪛 Ruff (0.8.2)
196-196: Undefined name
selg(F821)
🧹 Nitpick comments (3)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (3)
48-48: Fix typo in docstring.There's a typo in the docstring: "varibales" should be "variables".
- Additionally, it also sets up some internal objects/varibales such as: + Additionally, it also sets up some internal objects/variables such as:
128-128: Remove unnecessary f-strings.Several strings in the code use f-strings but don't contain any variables.
- self.logger.info(f'Corellium Device:') + self.logger.info('Corellium Device:')This also applies to lines 164, 167.
🧰 Tools
🪛 Ruff (0.8.2)
128-128: f-string without any placeholders
Remove extraneous
fprefix(F541)
35-35: Clean up trailing whitespace throughout the file.Multiple lines in the file have trailing whitespace. While this doesn't affect functionality, it's good practice to remove them for code cleanliness.
Run the following command to identify all trailing whitespace:
#!/bin/bash # Find all trailing whitespace in the file rg '\s+$' packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py🧰 Tools
🪛 Ruff (0.8.2)
35-35: Trailing whitespace
Remove trailing whitespace
(W291)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py(1 hunks)
🧰 Additional context used
🪛 Ruff (0.8.2)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py
35-35: Trailing whitespace
Remove trailing whitespace
(W291)
37-37: Trailing whitespace
Remove trailing whitespace
(W291)
47-47: Blank line contains whitespace
Remove whitespace from blank line
(W293)
70-70: Trailing whitespace
Remove trailing whitespace
(W291)
86-86: Trailing whitespace
Remove trailing whitespace
(W291)
92-92: Blank line contains whitespace
Remove whitespace from blank line
(W293)
114-114: Trailing whitespace
Remove trailing whitespace
(W291)
128-128: f-string without any placeholders
Remove extraneous f prefix
(F541)
133-133: Trailing whitespace
Remove trailing whitespace
(W291)
154-154: Trailing whitespace
Remove trailing whitespace
(W291)
164-164: f-string without any placeholders
Remove extraneous f prefix
(F541)
167-167: f-string without any placeholders
Remove extraneous f prefix
(F541)
170-170: Trailing whitespace
Remove trailing whitespace
(W291)
181-181: Blank line contains whitespace
Remove whitespace from blank line
(W293)
185-185: f-string without any placeholders
Remove extraneous f prefix
(F541)
196-196: Undefined name selg
(F821)
198-198: Trailing whitespace
Remove trailing whitespace
(W291)
🔇 Additional comments (1)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (1)
160-170: Add timeout to infinite waiting loop.The while loop runs indefinitely until the condition is met. Although there's a retries check, there's no timeout mechanism to prevent hanging in unexpected scenarios.
Consider adding a timeout parameter and a more robust mechanism to handle exceptional cases:
# wait for device readiness opts = self.get_timeout_opts() counter = 0 + timeout = time.time() + (opts['retries'] * opts['interval']) while True: - if counter >= opts['retries']: + if counter >= opts['retries'] or time.time() > timeout: raise ValueError('Instance took too long to be ready') self.logger.info(f'Waiting for instance to be ready...') self.parent.api.read_instance_state(instance) if instance.state == 'on': self.logger.info(f'Instance is ready') break counter += 1 time.sleep(opts['interval'])🧰 Tools
🪛 Ruff (0.8.2)
164-164: f-string without any placeholders
Remove extraneous
fprefix(F541)
167-167: f-string without any placeholders
Remove extraneous
fprefix(F541)
170-170: Trailing whitespace
Remove trailing whitespace
(W291)
There was a problem hiding this comment.
Actionable comments posted: 4
♻️ Duplicate comments (4)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver_test.py (1)
90-110:⚠️ Potential issueFix the method call in test_driver_power_on_error
The test name indicates it's testing the
onmethod error handling, but it's callingpower.off()instead. This inconsistency makes the test confusing and potentially invalid.with pytest.raises((CorelliumApiException, ValueError)): with (patch.object(root._api, 'login', **mock_data.get('login', {'return_value': None})), patch.object(root._api, 'get_project', **mock_data.get('get_project', {'return_value': project})), patch.object(root._api, 'get_instance', **mock_data.get('get_instance', {'return_value': instance})), patch.object(root._api, 'create_instance', **mock_data.get('create_instance', {'return_value': instance}))): - power.off() + power.on()🧰 Tools
🪛 Ruff (0.8.2)
100-100:
Projectmay be undefined, or defined from star imports(F405)
101-101:
Instancemay be undefined, or defined from star imports(F405)
109-109: Line too long (122 > 120)
(E501)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (3)
158-160:⚠️ Potential issueFix error message string formatting.
There's a mismatch between the code checking for
device_flavorand the error message referencingdevice_model.- raise ValueError('Unable to find a device for this model: {self.parent.device_model}') + raise ValueError(f'Unable to find a device for this model: {self.parent.device_flavor}')
80-101:⚠️ Potential issueFix session refresh logic error.
The current code attempts to refresh the session if
diff > timedelta(seconds=1), which means it refreshes when the token is still valid. This should be reversed to refresh when the token is close to expiration.- if diff > timedelta(seconds=1): + # Re-login if there's less than 60 seconds left in the session + if diff < timedelta(seconds=60): self._api.login()🧰 Tools
🪛 Ruff (0.8.2)
87-87: Trailing whitespace
Remove trailing whitespace
(W291)
93-93: Blank line contains whitespace
Remove whitespace from blank line
(W293)
202-203:⚠️ Potential issueImplement the
readmethod properly.The
readmethod is exported but not implemented, which can lead to unexpected behavior. It should raiseNotImplementedErrorwith an informative message.@export -def read(self) -> AsyncGenerator[PowerReading, None]: - pass +async def read(self) -> AsyncGenerator[PowerReading, None]: + """ + Read power measurements from the device. + + This method is not implemented for Corellium devices. + """ + raise NotImplementedError("Power readings are not available for Corellium devices") + yield # Prevents syntax error for empty generator🧰 Tools
🪛 Ruff (0.8.2)
203-203: Trailing whitespace
Remove trailing whitespace
(W291)
🧹 Nitpick comments (19)
packages/jumpstarter-driver-power/jumpstarter_driver_power/client.py (2)
56-56: Remove trailing whitespaceThere's trailing whitespace at the end of this line.
-class VirtualPowerClient(PowerClient): +class VirtualPowerClient(PowerClient):🧰 Tools
🪛 Ruff (0.8.2)
56-56: Trailing whitespace
Remove trailing whitespace
(W291)
62-62: Remove whitespace from blank lineThis blank line contains whitespace which should be removed.
- +🧰 Tools
🪛 Ruff (0.8.2)
62-62: Blank line contains whitespace
Remove whitespace from blank line
(W293)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver_test.py (2)
9-11: Avoid star imports and remove unused importsUsing star imports can lead to namespace pollution and makes it harder to track which symbols are being used. Additionally, there are unused imports that should be removed.
-import os +from unittest.mock import patch -from unittest.mock import patch - +import pytest -import pytest -import requests_mock +from jumpstarter.common import exceptions as jmp_exceptions -from jumpstarter.common import exceptions as jmp_exceptions - -from .driver import Corellium, CorelliumPower -from .corellium.types import * -from .corellium.api import ApiClient +from .driver import Corellium, CorelliumPower +from .corellium.types import Project, Device, Instance, Session from .corellium.exceptions import CorelliumApiException🧰 Tools
🪛 Ruff (0.8.2)
9-9:
from .corellium.types import *used; unable to detect undefined names(F403)
10-10:
.corellium.api.ApiClientimported but unusedRemove unused import:
.corellium.api.ApiClient(F401)
30-47: Use dictionary literals instead of dict() constructorReplace
dict()calls with dictionary literals ({}) for better readability and performance.[ ( - dict(), + {}, jmp_exceptions.ConfigurationError('Missing "CORELLIUM_API_HOST" environment variable') ), ( - dict(CORELLIUM_API_HOST=' '), + {'CORELLIUM_API_HOST': ' '}, jmp_exceptions.ConfigurationError('"CORELLIUM_API_HOST" environment variable is empty') ), ( - dict(CORELLIUM_API_HOST='api-host'), + {'CORELLIUM_API_HOST': 'api-host'}, jmp_exceptions.ConfigurationError('Missing "CORELLIUM_API_TOKEN" environment variable') ), ( - dict(CORELLIUM_API_HOST='api-host', CORELLIUM_API_TOKEN=' '), + {'CORELLIUM_API_HOST': 'api-host', 'CORELLIUM_API_TOKEN': ' '}, jmp_exceptions.ConfigurationError('"CORELLIUM_API_TOKEN" environment variable is empty') ),🧰 Tools
🪛 Ruff (0.8.2)
30-30: Trailing whitespace
Remove trailing whitespace
(W291)
32-32: Unnecessary
dict()call (rewrite as a literal)Rewrite as a literal
(C408)
36-36: Unnecessary
dict()call (rewrite as a literal)Rewrite as a literal
(C408)
40-40: Unnecessary
dict()call (rewrite as a literal)Rewrite as a literal
(C408)
44-44: Unnecessary
dict()call (rewrite as a literal)Rewrite as a literal
(C408)
packages/jumpstarter-driver-power/jumpstarter_driver_power/driver.py (1)
37-38: Remove extra blank lineThere's an extra blank line that can be removed for consistency.
async def read(self) -> AsyncGenerator[PowerReading, None]: ... - class MockPower(PowerInterface, Driver):packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (4)
121-140: Add timeout handling to wait_instance method.The method has a retry counter but doesn't enforce an actual timeout. Consider adding a timeout parameter with a default value.
-def wait_instance(self, current: Instance, desired: Optional[Instance]): +def wait_instance(self, current: Instance, desired: Optional[Instance], timeout_seconds: int = 60): """ Wait for `current` instance to reach the same state as the `desired` instance. Desired can also be set to None, which means the instace should not exist. + + Args: + current: The current instance to monitor + desired: The desired state of the instance, or None if it should not exist + timeout_seconds: Maximum time to wait in seconds before raising an error """ opts = self.get_timeout_opts() counter = 0 + start_time = time.time() while True: - if counter >= opts['retries']: + if counter >= opts['retries'] or (time.time() - start_time) > timeout_seconds: raise ValueError(f'Instance took too long to reach the desired state: {current.id}')🧰 Tools
🪛 Ruff (0.8.2)
133-133: Undefined name
instance(F821)
137-137: Blank line contains whitespace
Remove whitespace from blank line
(W293)
49-49: Fix typo in docstring.The word "varibales" is misspelled in the docstring.
- Additionally, it also sets up some internal objects/varibales such as: + Additionally, it also sets up some internal objects/variables such as:
86-87: Fix typo in docstring.The word "accross" is misspelled in the docstring.
- accross diferent API methods that require authentication. + across different API methods that require authentication.🧰 Tools
🪛 Ruff (0.8.2)
87-87: Trailing whitespace
Remove trailing whitespace
(W291)
126-126: Fix typo in docstring.The word "instace" is misspelled in the docstring.
- Desired can also be set to None, which means the instace should not exist. + Desired can also be set to None, which means the instance should not exist.packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (5)
16-19: Complete the docstring in__init__method.The docstring ends abruptly with "containing a". Please complete it with proper description.
def __init__(self, host: str, token: str) -> None: """ - Initializes a new client, containing a + Initializes a new client, containing a session for API communication. + + Args: + host: The Corellium API host address + token: The Corellium API token for authentication """🧰 Tools
🪛 Ruff (0.8.2)
18-18: Trailing whitespace
Remove trailing whitespace
(W291)
5-6: Avoid wildcard imports.Using
from .types import *makes it difficult to track which symbols are actually being used. Consider importing specific types explicitly.-from .types import * +from .types import Session, Project, Device, Instance from .exceptions import CorelliumApiException🧰 Tools
🪛 Ruff (0.8.2)
5-5:
from .types import *used; unable to detect undefined names(F403)
49-52: Improve exception handling.Using a broad
Exceptioncatch and not preserving the exception chain is not ideal. Consider narrowing the exception type and usingraise ... from esyntax.- # except (requests.exceptions.RequestException, requests.exceptions.HTTPError) as e: - # except requests.exceptions.HTTPError as e: - except Exception as e: - raise CorelliumApiException(str(e)) + except (requests.exceptions.RequestException, json.JSONDecodeError) as e: + raise CorelliumApiException(str(e)) from e🧰 Tools
🪛 Ruff (0.8.2)
52-52: Within an
exceptclause, raise exceptions withraise ... from errorraise ... from Noneto distinguish them from errors in exception handling(B904)
65-66: Useraise ... from eto preserve exception chain.This better preserves the original exception context for debugging.
Apply this change to all similar exception handlers in the file:
except requests.exceptions.RequestException as e: - raise CorelliumApiException(str(e)) + raise CorelliumApiException(str(e)) from e🧰 Tools
🪛 Ruff (0.8.2)
66-66: Within an
exceptclause, raise exceptions withraise ... from errorraise ... from Noneto distinguish them from errors in exception handling(B904)
93-94: Line exceeds maximum length.This line is too long (123 > 120 characters). Consider breaking it into multiple lines.
- def create_instance(self, name: str, project: Project, device: Device, - os_version: str = '1.1.1', os_build: str = 'Critical Application Monitor (Baremetal)') -> Instance: + def create_instance( + self, + name: str, + project: Project, + device: Device, + os_version: str = '1.1.1', + os_build: str = 'Critical Application Monitor (Baremetal)' + ) -> Instance:🧰 Tools
🪛 Ruff (0.8.2)
93-93:
Projectmay be undefined, or defined from star imports(F405)
93-93:
Devicemay be undefined, or defined from star imports(F405)
94-94:
Instancemay be undefined, or defined from star imports(F405)
94-94: Line too long (123 > 120)
(E501)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py (5)
153-153: Remove unused assignment.The variable
instanceis assigned but never used.- instance = api.create_instance('my-instance', project, device, '1.0') + api.create_instance('my-instance', project, device, '1.0')🧰 Tools
🪛 Ruff (0.8.2)
153-153: Local variable
instanceis assigned to but never usedRemove assignment to unused variable
instance(F841)
158-165: Add assertions to verify instance destruction.The test doesn't assert anything, making it a weak test. Add assertions to verify the request was made correctly.
def test_destroy_instance_state_ok(requests_mock): instance = Instance(id='d59db33d-27bd-4b22-878d-49e4758a648e') requests_mock.delete(f'https://api-host/api/v1/instances/{instance.id}', status_code=204, text='') api = ApiClient('api-host', 'api-token') api.session = Session('session-token', '2022-03-20T01:50:10.000Z') api.destroy_instance(instance) + + # Verify the request was made correctly + assert requests_mock.called + assert requests_mock.last_request.method == 'DELETE' + assert requests_mock.last_request.url == f'https://api-host/api/v1/instances/{instance.id}'🧰 Tools
🪛 Ruff (0.8.2)
158-158: Redefinition of unused
requests_mockfrom line 4(F811)
159-159:
Instancemay be undefined, or defined from star imports(F405)
160-160: Blank line contains whitespace
Remove whitespace from blank line
(W293)
163-163:
Sessionmay be undefined, or defined from star imports(F405)
130-131: Use dict literal instead ofdict().Use modern dictionary literal syntax
{}instead of the less readabledict()function.device = Device(name='rd1ae', type='automotive', flavor='kronos', - description='', model='kronos', peripherals=False, quotas=dict()) + description='', model='kronos', peripherals=False, quotas={})🧰 Tools
🪛 Ruff (0.8.2)
130-130:
Devicemay be undefined, or defined from star imports(F405)
131-131: Unnecessary
dict()call (rewrite as a literal)Rewrite as a literal
(C408)
35-38: Fix whitespace issues.Remove trailing whitespace to improve code readability and consistency.
'status_code,data,msg', - [ + [ (403, fixture('http/403.json'), '403 Client Error'), (200, fixture('http/json-error.json'), 'Invalid control character at'), ])This applies to multiple areas in the file where there is trailing whitespace or extra whitespace in blank lines.
🧰 Tools
🪛 Ruff (0.8.2)
35-35: Trailing whitespace
Remove trailing whitespace
(W291)
4-4: Fix unused import.The
requests_mocklibrary is imported at the top level but not used directly - it's only used as a test fixture parameter.import pytest -import requests_mock🧰 Tools
🪛 Ruff (0.8.2)
4-4:
requests_mockimported but unusedRemove unused import:
requests_mock(F401)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
packages/jumpstarter-driver-corellium/README.md(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver_test.py(1 hunks)packages/jumpstarter-driver-power/jumpstarter_driver_power/client.py(1 hunks)packages/jumpstarter-driver-power/jumpstarter_driver_power/driver.py(1 hunks)
🧰 Additional context used
🧬 Code Definitions (4)
packages/jumpstarter-driver-power/jumpstarter_driver_power/client.py (7)
packages/jumpstarter-driver-power/jumpstarter_driver_power/driver.py (4) (4)
off(17-17)off(32-32)off(58-59)off(86-87)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (1) (1)
off(180-199)packages/jumpstarter-driver-snmp/jumpstarter_driver_snmp/driver.py (1) (1)
off(201-203)packages/jumpstarter-driver-dutlink/jumpstarter_driver_dutlink/driver.py (2) (2)
off(129-130)off(187-188)packages/jumpstarter-driver-raspberrypi/jumpstarter_driver_raspberrypi/client.py (1) (1)
off(8-9)packages/jumpstarter-driver-yepkit/jumpstarter_driver_yepkit/driver.py (1) (1)
off(117-120)packages/jumpstarter-driver-opendal/jumpstarter_driver_opendal/client.py (6) (6)
off(595-597)off(638-640)cli(399-513)cli(533-553)cli(623-647)cli(695-697)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (2)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/exceptions.py (1) (1)
CorelliumApiException(7-11)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/types.py (5) (5)
Session(9-22)as_header(16-22)Project(26-31)Device(35-47)Instance(51-56)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (3)
packages/jumpstarter-driver-power/jumpstarter_driver_power/driver.py (15) (15)
VirtualPowerInterface(23-35)client(10-11)client(25-26)on(14-14)on(29-29)on(54-55)on(82-83)off(17-17)off(32-32)off(58-59)off(86-87)read(20-20)read(35-35)read(62-64)read(90-92)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (8) (8)
ApiClient(9-170)login(32-55)get_instance(115-132)get_project(57-72)get_device(74-91)set_instance_state(134-158)create_instance(93-113)destroy_instance(160-170)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/types.py (1) (1)
Instance(51-56)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver_test.py (4)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (5) (5)
Corellium(20-101)CorelliumPower(105-203)api(81-101)on(142-177)off(180-199)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (1) (1)
ApiClient(9-170)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/exceptions.py (1) (1)
CorelliumApiException(7-11)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/types.py (4) (4)
Session(9-22)Project(26-31)Device(35-47)Instance(51-56)
🪛 Ruff (0.8.2)
packages/jumpstarter-driver-power/jumpstarter_driver_power/client.py
56-56: Trailing whitespace
Remove trailing whitespace
(W291)
62-62: Blank line contains whitespace
Remove whitespace from blank line
(W293)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py
5-5: from .types import * used; unable to detect undefined names
(F403)
13-13: Session may be undefined, or defined from star imports
(F405)
14-14: field may be undefined, or defined from star imports
(F405)
18-18: Trailing whitespace
Remove trailing whitespace
(W291)
28-28: Trailing whitespace
Remove trailing whitespace
(W291)
31-31: Blank line contains whitespace
Remove whitespace from blank line
(W293)
52-52: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
54-54: Session may be undefined, or defined from star imports
(F405)
57-57: Project may be undefined, or defined from star imports
(F405)
66-66: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
70-70: Project may be undefined, or defined from star imports
(F405)
74-74: Device may be undefined, or defined from star imports
(F405)
85-85: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
89-89: Device may be undefined, or defined from star imports
(F405)
93-93: Project may be undefined, or defined from star imports
(F405)
93-93: Device may be undefined, or defined from star imports
(F405)
94-94: Instance may be undefined, or defined from star imports
(F405)
94-94: Line too long (123 > 120)
(E501)
111-111: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
113-113: Instance may be undefined, or defined from star imports
(F405)
115-115: Instance may be undefined, or defined from star imports
(F405)
126-126: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
130-130: Instance may be undefined, or defined from star imports
(F405)
134-134: Instance may be undefined, or defined from star imports
(F405)
134-134: Trailing whitespace
Remove trailing whitespace
(W291)
158-158: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
160-160: Instance may be undefined, or defined from star imports
(F405)
170-170: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py
4-4: requests_mock imported but unused
Remove unused import: requests_mock
(F401)
6-6: from .types import * used; unable to detect undefined names
(F403)
22-22: Redefinition of unused requests_mock from line 4
(F811)
35-35: Trailing whitespace
Remove trailing whitespace
(W291)
39-39: Redefinition of unused requests_mock from line 4
(F811)
39-39: Trailing whitespace
Remove trailing whitespace
(W291)
55-55: Redefinition of unused requests_mock from line 4
(F811)
58-58: Session may be undefined, or defined from star imports
(F405)
64-64: Blank line contains whitespace
Remove whitespace from blank line
(W293)
74-74: Trailing whitespace
Remove trailing whitespace
(W291)
78-78: Redefinition of unused requests_mock from line 4
(F811)
78-78: Trailing whitespace
Remove trailing whitespace
(W291)
81-81: Session may be undefined, or defined from star imports
(F405)
93-93: Redefinition of unused requests_mock from line 4
(F811)
96-96: Session may be undefined, or defined from star imports
(F405)
99-99: Blank line contains whitespace
Remove whitespace from blank line
(W293)
109-109: Trailing whitespace
Remove trailing whitespace
(W291)
112-112: Redefinition of unused requests_mock from line 4
(F811)
112-112: Trailing whitespace
Remove trailing whitespace
(W291)
115-115: Session may be undefined, or defined from star imports
(F405)
123-123: Redefinition of unused requests_mock from line 4
(F811)
127-127: Session may be undefined, or defined from star imports
(F405)
129-129: Project may be undefined, or defined from star imports
(F405)
130-130: Device may be undefined, or defined from star imports
(F405)
131-131: Unnecessary dict() call (rewrite as a literal)
Rewrite as a literal
(C408)
140-140: Trailing whitespace
Remove trailing whitespace
(W291)
144-144: Redefinition of unused requests_mock from line 4
(F811)
144-144: Trailing whitespace
Remove trailing whitespace
(W291)
147-147: Session may be undefined, or defined from star imports
(F405)
149-149: Trailing whitespace
Remove trailing whitespace
(W291)
150-150: Project may be undefined, or defined from star imports
(F405)
151-151: Device may be undefined, or defined from star imports
(F405)
152-152: Unnecessary dict() call (rewrite as a literal)
Rewrite as a literal
(C408)
153-153: Local variable instance is assigned to but never used
Remove assignment to unused variable instance
(F841)
158-158: Redefinition of unused requests_mock from line 4
(F811)
159-159: Instance may be undefined, or defined from star imports
(F405)
160-160: Blank line contains whitespace
Remove whitespace from blank line
(W293)
163-163: Session may be undefined, or defined from star imports
(F405)
169-169: Trailing whitespace
Remove trailing whitespace
(W291)
173-173: Redefinition of unused requests_mock from line 4
(F811)
173-173: Trailing whitespace
Remove trailing whitespace
(W291)
174-174: Instance may be undefined, or defined from star imports
(F405)
178-178: Session may be undefined, or defined from star imports
(F405)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py
36-36: Trailing whitespace
Remove trailing whitespace
(W291)
38-38: Trailing whitespace
Remove trailing whitespace
(W291)
48-48: Blank line contains whitespace
Remove whitespace from blank line
(W293)
71-71: Trailing whitespace
Remove trailing whitespace
(W291)
87-87: Trailing whitespace
Remove trailing whitespace
(W291)
93-93: Blank line contains whitespace
Remove whitespace from blank line
(W293)
115-115: Trailing whitespace
Remove trailing whitespace
(W291)
133-133: Undefined name instance
(F821)
137-137: Blank line contains whitespace
Remove whitespace from blank line
(W293)
148-148: f-string without any placeholders
Remove extraneous f prefix
(F541)
153-153: Trailing whitespace
Remove trailing whitespace
(W291)
174-174: Trailing whitespace
Remove trailing whitespace
(W291)
178-178: Blank line contains whitespace
Remove whitespace from blank line
(W293)
188-188: Blank line contains whitespace
Remove whitespace from blank line
(W293)
192-192: f-string without any placeholders
Remove extraneous f prefix
(F541)
200-200: Blank line contains whitespace
Remove whitespace from blank line
(W293)
203-203: Trailing whitespace
Remove trailing whitespace
(W291)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver_test.py
1-1: os imported but unused
Remove unused import: os
(F401)
5-5: requests_mock imported but unused
Remove unused import: requests_mock
(F401)
9-9: from .corellium.types import * used; unable to detect undefined names
(F403)
10-10: .corellium.api.ApiClient imported but unused
Remove unused import: .corellium.api.ApiClient
(F401)
17-17: Blank line contains whitespace
Remove whitespace from blank line
(W293)
19-19: Blank line contains whitespace
Remove whitespace from blank line
(W293)
30-30: Trailing whitespace
Remove trailing whitespace
(W291)
32-32: Unnecessary dict() call (rewrite as a literal)
Rewrite as a literal
(C408)
36-36: Unnecessary dict() call (rewrite as a literal)
Rewrite as a literal
(C408)
40-40: Unnecessary dict() call (rewrite as a literal)
Rewrite as a literal
(C408)
44-44: Unnecessary dict() call (rewrite as a literal)
Rewrite as a literal
(C408)
51-51: Blank line contains whitespace
Remove whitespace from blank line
(W293)
57-57: Blank line contains whitespace
Remove whitespace from blank line
(W293)
61-61: Redefinition of unused requests_mock from line 5
(F811)
62-62: Line too long (129 > 120)
(E501)
68-68: Session may be undefined, or defined from star imports
(F405)
75-75: Project may be undefined, or defined from star imports
(F405)
76-76: Device may be undefined, or defined from star imports
(F405)
77-77: Unnecessary dict() call (rewrite as a literal)
Rewrite as a literal
(C408)
78-78: Instance may be undefined, or defined from star imports
(F405)
100-100: Project may be undefined, or defined from star imports
(F405)
101-101: Instance may be undefined, or defined from star imports
(F405)
109-109: Line too long (122 > 120)
(E501)
117-117: Project may be undefined, or defined from star imports
(F405)
118-118: Instance may be undefined, or defined from star imports
(F405)
121-121: Blank line contains whitespace
Remove whitespace from blank line
(W293)
122-122: Trailing whitespace
Remove trailing whitespace
(W291)
125-125: Instance may be undefined, or defined from star imports
(F405)
139-139: Project may be undefined, or defined from star imports
(F405)
140-140: Instance may be undefined, or defined from star imports
(F405)
143-143: Blank line contains whitespace
Remove whitespace from blank line
(W293)
147-147: Line too long (122 > 120)
(E501)
148-148: Line too long (124 > 120)
(E501)
🔇 Additional comments (7)
packages/jumpstarter-driver-corellium/README.md (1)
1-54: Well-structured documentation for the Corellium driverThe README provides clear documentation about the driver's purpose, implemented interfaces, and usage examples. The YAML configuration examples are particularly helpful for understanding how to configure the driver for different scenarios.
packages/jumpstarter-driver-power/jumpstarter_driver_power/client.py (1)
57-59: Implementation for destroy parameter in off methodThe implementation properly extends the PowerClient's off method with the destroy parameter, which aligns with the VirtualPowerInterface's requirements. This is essential for supporting the Corellium driver's capability to optionally destroy instances when powering them off.
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver_test.py (3)
72-88: Comprehensive test for power on functionalityThe test effectively covers the successful case of powering on a device, with proper mocking of API dependencies and verification of the expected behavior.
🧰 Tools
🪛 Ruff (0.8.2)
75-75:
Projectmay be undefined, or defined from star imports(F405)
76-76:
Devicemay be undefined, or defined from star imports(F405)
77-77: Unnecessary
dict()call (rewrite as a literal)Rewrite as a literal
(C408)
78-78:
Instancemay be undefined, or defined from star imports(F405)
113-127: Well-structured test for power off functionalityThis test properly verifies the behavior of the
offmethod under normal conditions, with appropriate mocks for API dependencies.🧰 Tools
🪛 Ruff (0.8.2)
117-117:
Projectmay be undefined, or defined from star imports(F405)
118-118:
Instancemay be undefined, or defined from star imports(F405)
121-121: Blank line contains whitespace
Remove whitespace from blank line
(W293)
122-122: Trailing whitespace
Remove trailing whitespace
(W291)
125-125:
Instancemay be undefined, or defined from star imports(F405)
129-149: Thorough error case testing for power offThe test covers various error scenarios for the
offmethod using parameterized tests, which is a good practice for comprehensive testing.🧰 Tools
🪛 Ruff (0.8.2)
139-139:
Projectmay be undefined, or defined from star imports(F405)
140-140:
Instancemay be undefined, or defined from star imports(F405)
143-143: Blank line contains whitespace
Remove whitespace from blank line
(W293)
147-147: Line too long (122 > 120)
(E501)
148-148: Line too long (124 > 120)
(E501)
packages/jumpstarter-driver-power/jumpstarter_driver_power/driver.py (1)
23-36: Well-designed VirtualPowerInterface for virtual device supportThe new
VirtualPowerInterfaceextends the power management capabilities to support virtual devices, with the important addition of thedestroyparameter in theoffmethod. This interface properly facilitates the requirements of the Corellium driver.packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py (1)
151-152: Use dict literal instead ofdict().Use modern dictionary literal syntax
{}instead of the less readabledict()function.device = Device(name='rd1ae', type='automotive', flavor='kronos', - description='', model='kronos', peripherals=False, quotas=dict()) + description='', model='kronos', peripherals=False, quotas={})🧰 Tools
🪛 Ruff (0.8.2)
151-151:
Devicemay be undefined, or defined from star imports(F405)
152-152: Unnecessary
dict()call (rewrite as a literal)Rewrite as a literal
(C408)
| @parent.command() | ||
| @click.option('--destroy', is_flag=True, help='destroy the instance after powering it off') | ||
| def off(destroy: bool): | ||
| """Power off""" | ||
| self.off(destroy) | ||
|
|
There was a problem hiding this comment.
Command redefinition issue in cli method
The off command is being redefined in the child class with the same name as in the parent class. This will likely cause the parent's command to be overridden, which may lead to unexpected behavior.
Consider using a different command name for the virtual power client's off functionality to avoid this collision:
- @parent.command()
- @click.option('--destroy', is_flag=True, help='destroy the instance after powering it off')
- def off(destroy: bool):
+ @parent.command(name='off-virtual')
+ @click.option('--destroy', is_flag=True, help='destroy the instance after powering it off')
+ def off_virtual(destroy: bool):
"""Power off"""
self.off(destroy)Alternatively, if you want to completely replace the parent's off command, you could use the @parent.command(name='off') syntax to make it explicit.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| @parent.command() | |
| @click.option('--destroy', is_flag=True, help='destroy the instance after powering it off') | |
| def off(destroy: bool): | |
| """Power off""" | |
| self.off(destroy) | |
| @parent.command(name='off-virtual') | |
| @click.option('--destroy', is_flag=True, help='destroy the instance after powering it off') | |
| def off_virtual(destroy: bool): | |
| """Power off""" | |
| self.off(destroy) |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (6)
packages/jumpstarter-driver-power/jumpstarter_driver_power/client.py (3)
56-56: Fix trailing whitespace.There's a trailing whitespace at the end of line 56.
-class VirtualPowerClient(PowerClient): +class VirtualPowerClient(PowerClient):🧰 Tools
🪛 Ruff (0.8.2)
56-56: Trailing whitespace
Remove trailing whitespace
(W291)
57-58: Add docstring to off method.Add a docstring to the
offmethod to explain its purpose and thedestroyparameter for better code documentation.def off(self, destroy: bool = False) -> None: + """Power off the virtual device. + + Args: + destroy: If True, destroy the instance after powering it off. + """ self.call('off', destroy)
62-62: Remove whitespace from blank line.Line 62 contains a blank line with whitespace.
def cli(self): parent = super().cli() - + @parent.command(name='off')🧰 Tools
🪛 Ruff (0.8.2)
62-62: Blank line contains whitespace
Remove whitespace from blank line
(W293)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (3)
18-18: Remove trailing/extra whitespace.Lines 18, 28, 31, and 134 contain trailing/blank space that can cause style warnings or inconsistent formatting.
Below is an example of how to remove extra whitespace:
Also applies to: 28-28, 31-31, 134-134
🧰 Tools
🪛 Ruff (0.8.2)
18-18: Trailing whitespace
Remove trailing whitespace
(W291)
52-52: Raise from original exceptions to provide context.When re-raising exceptions in these lines, consider using
raise CorelliumApiException(...) from eto preserve the original traceback context. This practice helps debugging by clarifying the original cause of the error.For instance:
-except Exception as e: - raise CorelliumApiException(str(e)) +except Exception as e: + raise CorelliumApiException(str(e)) from eAlso applies to: 66-66, 85-85, 111-111, 126-126, 158-158, 170-170
🧰 Tools
🪛 Ruff (0.8.2)
52-52: Within an
exceptclause, raise exceptions withraise ... from errorraise ... from Noneto distinguish them from errors in exception handling(B904)
94-94: Break long method definition across multiple lines.This line exceeds the recommended maximum (120 chars). Splitting the parameter list over multiple lines improves readability.
def create_instance( self, name: str, project: Project, device: Device, os_version: str = '1.1.1', os_build: str = 'Critical Application Monitor (Baremetal)' ) -> Instance:🧰 Tools
🪛 Ruff (0.8.2)
94-94:
Instancemay be undefined, or defined from star imports(F405)
94-94: Line too long (123 > 120)
(E501)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py(1 hunks)packages/jumpstarter-driver-power/jumpstarter_driver_power/client.py(1 hunks)
🧰 Additional context used
🧬 Code Definitions (2)
packages/jumpstarter-driver-power/jumpstarter_driver_power/client.py (7)
packages/jumpstarter-driver-power/jumpstarter_driver_power/driver.py (4) (4)
off(17-17)off(32-32)off(58-59)off(86-87)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (1) (1)
off(180-199)packages/jumpstarter-driver-snmp/jumpstarter_driver_snmp/driver.py (1) (1)
off(201-203)packages/jumpstarter-driver-dutlink/jumpstarter_driver_dutlink/driver.py (2) (2)
off(129-130)off(187-188)packages/jumpstarter-driver-raspberrypi/jumpstarter_driver_raspberrypi/client.py (1) (1)
off(8-9)packages/jumpstarter-driver-yepkit/jumpstarter_driver_yepkit/driver.py (1) (1)
off(117-120)packages/jumpstarter-driver-opendal/jumpstarter_driver_opendal/client.py (6) (6)
off(595-597)off(638-640)cli(399-513)cli(533-553)cli(623-647)cli(695-697)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (2)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/exceptions.py (1) (1)
CorelliumApiException(7-11)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/types.py (5) (5)
Session(9-22)as_header(16-22)Project(26-31)Device(35-47)Instance(51-56)
🪛 Ruff (0.8.2)
packages/jumpstarter-driver-power/jumpstarter_driver_power/client.py
56-56: Trailing whitespace
Remove trailing whitespace
(W291)
62-62: Blank line contains whitespace
Remove whitespace from blank line
(W293)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py
5-5: from .types import * used; unable to detect undefined names
(F403)
13-13: Session may be undefined, or defined from star imports
(F405)
14-14: field may be undefined, or defined from star imports
(F405)
18-18: Trailing whitespace
Remove trailing whitespace
(W291)
28-28: Trailing whitespace
Remove trailing whitespace
(W291)
31-31: Blank line contains whitespace
Remove whitespace from blank line
(W293)
52-52: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
54-54: Session may be undefined, or defined from star imports
(F405)
57-57: Project may be undefined, or defined from star imports
(F405)
66-66: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
70-70: Project may be undefined, or defined from star imports
(F405)
74-74: Device may be undefined, or defined from star imports
(F405)
85-85: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
89-89: Device may be undefined, or defined from star imports
(F405)
93-93: Project may be undefined, or defined from star imports
(F405)
93-93: Device may be undefined, or defined from star imports
(F405)
94-94: Instance may be undefined, or defined from star imports
(F405)
94-94: Line too long (123 > 120)
(E501)
111-111: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
113-113: Instance may be undefined, or defined from star imports
(F405)
115-115: Instance may be undefined, or defined from star imports
(F405)
126-126: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
130-130: Instance may be undefined, or defined from star imports
(F405)
134-134: Instance may be undefined, or defined from star imports
(F405)
134-134: Trailing whitespace
Remove trailing whitespace
(W291)
158-158: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
160-160: Instance may be undefined, or defined from star imports
(F405)
170-170: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
🔇 Additional comments (2)
packages/jumpstarter-driver-power/jumpstarter_driver_power/client.py (2)
63-67: Good use of explicit command redefinition.You've correctly addressed the previous review comment by using
@parent.command(name='off')to explicitly replace the parent's command. This approach makes it clear that you're intentionally overriding the parent command with an enhanced version that includes the destroy option.
57-69:Details
✅ Verification successful
Validate implementation against Corellium driver.
The implementation of
VirtualPowerClientaligns well withCorelliumPower.off()in thejumpstarter-driver-corelliumpackage. Make sure that the parameters are passed correctly between these implementations when integrating the drivers.Run the following script to verify the integration:
🏁 Script executed:
#!/bin/bash # Check if the CorelliumPower class properly uses the VirtualPowerClient rg -A 10 -B 10 "VirtualPowerClient" --glob "packages/jumpstarter-driver-corellium/**/*.py" # Verify how CorelliumPower.off is implemented rg -A 10 "def off" --glob "packages/jumpstarter-driver-corellium/**/*.py"Length of output: 1503
Integration Verified: Parameter Passing is Consistent
The implementation injumpstarter-driver-powerproperly delegates thedestroyparameter viaself.call('off', destroy), which aligns with the method signature injumpstarter-driver-corellium(def off(self, destroy: bool = False) -> None). No discrepancies were found between the two drivers.
- Confirmed that both drivers use the parameter
destroywith the same type and default value.- The integration between
VirtualPowerClient.offandCorelliumPower.offis consistent.🧰 Tools
🪛 Ruff (0.8.2)
62-62: Blank line contains whitespace
Remove whitespace from blank line
(W293)
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (5)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (1)
13-14: 🛠️ Refactor suggestionAdd missing explicit imports for dataclasses.field.
The code uses
field(init=False)but doesn't import it, relying on the star import from.types. This can lead to confusion about where symbols are defined.from typing import Optional import requests from .types import Session, Project, Device, Instance +from dataclasses import field from .exceptions import CorelliumApiException🧰 Tools
🪛 Ruff (0.8.2)
13-13:
Sessionmay be undefined, or defined from star imports(F405)
14-14:
fieldmay be undefined, or defined from star imports(F405)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (4)
141-147:⚠️ Potential issueAdd async keyword to match abstract method declaration.
The
onmethod should beasyncto match theVirtualPowerInterfaceabstract method declaration as shown in the relevant code snippets.@export -def on(self) -> None: +async def on(self) -> None: """ Power a Corellium virtual device on. It will create an instance if one does not exist, it will just power the existing one on otherwise. """
179-183:⚠️ Potential issueAdd async keyword and improve method description for off method.
The
offmethod should beasyncto match the abstract method, and the method description should better explain thedestroyparameter.@export -def off(self, destroy: bool = False) -> None: +async def off(self, destroy: bool = False) -> None: """ - Destroy a Corellium virtual device/instance. + Power off a Corellium virtual device/instance. + + Args: + destroy: If True, destroy the instance after powering it off. + If False, just power it off. """
132-134:⚠️ Potential issueFix undefined variable reference in error message.
The error message references an undefined variable
currentbut does not format it properly, and the error message has a grammar error.if counter >= opts['retries']: - raise ValueError(f'Instance took too long to be reach the desired state: {current}') + raise ValueError(f'Instance took too long to reach the desired state: {current.id}')
201-203:⚠️ Potential issueImplement the read method properly.
The
readmethod is defined but not implemented. It should be implemented to match the abstract method definition, even if it only raisesNotImplementedError.@export -def read(self) -> AsyncGenerator[PowerReading, None]: - pass +async def read(self) -> AsyncGenerator[PowerReading, None]: + """ + Read power measurements from the device. + + This method is not implemented for Corellium devices. + """ + raise NotImplementedError("Power readings are not available for Corellium devices")🧰 Tools
🪛 Ruff (0.8.2)
203-203: Trailing whitespace
Remove trailing whitespace
(W291)
🧹 Nitpick comments (12)
packages/jumpstarter-driver-power/jumpstarter_driver_power/client.py (2)
56-56: Fix whitespace issues.There are two minor style issues flagged by static analysis:
- Line 56: Trailing whitespace at the end of the line
- Line 62: Blank line contains whitespace
-class VirtualPowerClient(PowerClient): +class VirtualPowerClient(PowerClient): def cli(self): parent = super().cli() - + @parent.command(name='off')Also applies to: 62-62
🧰 Tools
🪛 Ruff (0.8.2)
56-56: Trailing whitespace
Remove trailing whitespace
(W291)
57-69: Consider adding an equivalent test for the VirtualPowerClient.To ensure proper functionality, it would be beneficial to add tests for the
VirtualPowerClientclass, particularly verifying that thedestroyparameter is correctly passed through to the underlying call method.🧰 Tools
🪛 Ruff (0.8.2)
62-62: Blank line contains whitespace
Remove whitespace from blank line
(W293)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (8)
18-19: Complete the docstring for the constructor.The docstring for
__init__is incomplete and ends with "containing a".def __init__(self, host: str, token: str) -> None: """ - Initializes a new client, containing a + Initializes a new client, containing a session for API requests. + + Args: + host: The Corellium API host + token: The Corellium API token for authentication """🧰 Tools
🪛 Ruff (0.8.2)
18-18: Trailing whitespace
Remove trailing whitespace
(W291)
61-67: Use consistent exception handling pattern.Similar to the login method, use the
raise ... from epattern to preserve the traceback and catch specific exceptions instead of general ones.try: res = self.req.get(f'{self.baseurl}/v1/projects') res.raise_for_status() projects = res.json() except requests.exceptions.RequestException as e: - raise CorelliumApiException(str(e)) + raise CorelliumApiException(f"Failed to get projects: {str(e)}") from e🧰 Tools
🪛 Ruff (0.8.2)
66-66: Within an
exceptclause, raise exceptions withraise ... from errorraise ... from Noneto distinguish them from errors in exception handling(B904)
80-86: Apply consistent exception handling pattern.Follow the same pattern for exception handling as in previous comments.
try: res = self.req.get(f'{self.baseurl}/v1/models') res.raise_for_status() devices = res.json() except requests.exceptions.RequestException as e: - raise CorelliumApiException(str(e)) + raise CorelliumApiException(f"Failed to get devices: {str(e)}") from e🧰 Tools
🪛 Ruff (0.8.2)
85-85: Within an
exceptclause, raise exceptions withraise ... from errorraise ... from Noneto distinguish them from errors in exception handling(B904)
106-112: Apply consistent exception handling pattern for create_instance.try: res = self.req.post(f'{self.baseurl}/v1/instances', json=data) res.raise_for_status() instance = res.json() except requests.exceptions.RequestException as e: - raise CorelliumApiException(str(e)) + raise CorelliumApiException(f"Failed to create instance: {str(e)}") from e🧰 Tools
🪛 Ruff (0.8.2)
111-111: Within an
exceptclause, raise exceptions withraise ... from errorraise ... from Noneto distinguish them from errors in exception handling(B904)
121-127: Apply consistent exception handling pattern for get_instance.try: res = self.req.get(f'{self.baseurl}/v1/instances') res.raise_for_status() instances = res.json() except requests.exceptions.RequestException as e: - raise CorelliumApiException(str(e)) + raise CorelliumApiException(f"Failed to get instances: {str(e)}") from e🧰 Tools
🪛 Ruff (0.8.2)
126-126: Within an
exceptclause, raise exceptions withraise ... from errorraise ... from Noneto distinguish them from errors in exception handling(B904)
154-159: Apply consistent exception handling pattern for set_instance_state.try: res = self.req.put(f'{self.baseurl}/v1/instances/{instance.id}/state', json=data) res.raise_for_status() except requests.exceptions.RequestException as e: - raise CorelliumApiException(str(e)) + raise CorelliumApiException(f"Failed to set instance state: {str(e)}") from e🧰 Tools
🪛 Ruff (0.8.2)
158-158: Within an
exceptclause, raise exceptions withraise ... from errorraise ... from Noneto distinguish them from errors in exception handling(B904)
166-171: Apply consistent exception handling pattern for destroy_instance.try: res = self.req.delete(f'{self.baseurl}/v1/instances/{instance.id}') res.raise_for_status() except requests.exceptions.RequestException as e: - raise CorelliumApiException(str(e)) + raise CorelliumApiException(f"Failed to destroy instance: {str(e)}") from e🧰 Tools
🪛 Ruff (0.8.2)
170-170: Within an
exceptclause, raise exceptions withraise ... from errorraise ... from Noneto distinguish them from errors in exception handling(B904)
93-94: Fix line length and add input validation.The parameter line for
create_instanceexceeds the 120 character limit. Also, consider adding more robust validation for the input parameters.-def create_instance(self, name: str, project: Project, device: Device, - os_version: str = '1.1.1', os_build: str = 'Critical Application Monitor (Baremetal)') -> Instance: +def create_instance( + self, + name: str, + project: Project, + device: Device, + os_version: str = '1.1.1', + os_build: str = 'Critical Application Monitor (Baremetal)' +) -> Instance:🧰 Tools
🪛 Ruff (0.8.2)
93-93:
Projectmay be undefined, or defined from star imports(F405)
93-93:
Devicemay be undefined, or defined from star imports(F405)
94-94:
Instancemay be undefined, or defined from star imports(F405)
94-94: Line too long (123 > 120)
(E501)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (2)
122-140: Add timeout handling to wait_instance method.The current implementation can potentially wait indefinitely. Add a timeout parameter and consider providing a more informative message about what state transitions are occurring.
def wait_instance(self, current: Instance, desired: Optional[Instance]): """ Wait for `current` instance to reach the same state as the `desired` instance. Desired can also be set to None, which means the instace should not exist. + + Args: + current: The current instance to monitor. + desired: The desired state (or None if instance should not exist). + + Raises: + ValueError: If the instance doesn't reach the desired state within timeout. """ opts = self.get_timeout_opts() counter = 0 while True: if counter >= opts['retries']: - raise ValueError(f'Instance took too long to be reach the desired state: {current}') + current_state = "non-existent" if current is None else current.state + desired_state = "non-existent" if desired is None else desired.state + raise ValueError( + f'Instance {current.id} took too long to transition from {current_state} to {desired_state}. ' + f'Exceeded {opts["retries"]} retries with {opts["interval"]}s interval.' + ) if self.parent.api.get_instance(current.id) == desired: break counter += 1 time.sleep(opts['interval'])🧰 Tools
🪛 Ruff (0.8.2)
137-137: Blank line contains whitespace
Remove whitespace from blank line
(W293)
113-120: Improve parameter validation in get_timeout_opts method.The current implementation doesn't validate that the returned values are positive integers, which could lead to unexpected behavior.
def get_timeout_opts(self) -> Dict[str, int]: """ Return config/opts to be used when waiting for Corellium's API. """ + # Get configuration with defaults + retries = os.environ.get('CORELLIUM_API_RETRIES', '12') + interval = os.environ.get('CORELLIUM_API_INTERVAL', '5') + + # Validate and convert to integers + try: + retries_int = int(retries) + interval_int = int(interval) + if retries_int <= 0 or interval_int <= 0: + self.logger.warning(f"Invalid timeout values. Using defaults instead.") + retries_int = 12 + interval_int = 5 + except ValueError: + self.logger.warning(f"Invalid timeout values. Using defaults instead.") + retries_int = 12 + interval_int = 5 + return { - 'retries': int(os.environ.get('CORELLIUM_API_RETRIES', 12)), - 'interval': os.environ.get('CORELLIUM_API_INTERVAL', 5) + 'retries': retries_int, + 'interval': interval_int }🧰 Tools
🪛 Ruff (0.8.2)
115-115: Trailing whitespace
Remove trailing whitespace
(W291)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py(1 hunks)packages/jumpstarter-driver-power/jumpstarter_driver_power/client.py(1 hunks)
🧰 Additional context used
🧬 Code Definitions (3)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (2)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/exceptions.py (1) (1)
CorelliumApiException(7-11)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/types.py (5) (5)
Session(9-22)as_header(16-22)Project(26-31)Device(35-47)Instance(51-56)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (3)
packages/jumpstarter-driver-power/jumpstarter_driver_power/driver.py (15) (15)
VirtualPowerInterface(23-35)client(10-11)client(25-26)on(14-14)on(29-29)on(54-55)on(82-83)off(17-17)off(32-32)off(58-59)off(86-87)read(20-20)read(35-35)read(62-64)read(90-92)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (8) (8)
ApiClient(9-170)login(32-55)get_instance(115-132)get_project(57-72)get_device(74-91)set_instance_state(134-158)create_instance(93-113)destroy_instance(160-170)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/types.py (1) (1)
Instance(51-56)
packages/jumpstarter-driver-power/jumpstarter_driver_power/client.py (3)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (1) (1)
off(180-199)packages/jumpstarter-driver-power/jumpstarter_driver_power/driver.py (4) (4)
off(17-17)off(32-32)off(58-59)off(86-87)packages/jumpstarter-driver-snmp/jumpstarter_driver_snmp/driver.py (1) (1)
off(201-203)
🪛 Ruff (0.8.2)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py
5-5: from .types import * used; unable to detect undefined names
(F403)
13-13: Session may be undefined, or defined from star imports
(F405)
14-14: field may be undefined, or defined from star imports
(F405)
18-18: Trailing whitespace
Remove trailing whitespace
(W291)
28-28: Trailing whitespace
Remove trailing whitespace
(W291)
31-31: Blank line contains whitespace
Remove whitespace from blank line
(W293)
52-52: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
54-54: Session may be undefined, or defined from star imports
(F405)
57-57: Project may be undefined, or defined from star imports
(F405)
66-66: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
70-70: Project may be undefined, or defined from star imports
(F405)
74-74: Device may be undefined, or defined from star imports
(F405)
85-85: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
89-89: Device may be undefined, or defined from star imports
(F405)
93-93: Project may be undefined, or defined from star imports
(F405)
93-93: Device may be undefined, or defined from star imports
(F405)
94-94: Instance may be undefined, or defined from star imports
(F405)
94-94: Line too long (123 > 120)
(E501)
111-111: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
113-113: Instance may be undefined, or defined from star imports
(F405)
115-115: Instance may be undefined, or defined from star imports
(F405)
126-126: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
130-130: Instance may be undefined, or defined from star imports
(F405)
134-134: Instance may be undefined, or defined from star imports
(F405)
134-134: Trailing whitespace
Remove trailing whitespace
(W291)
158-158: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
160-160: Instance may be undefined, or defined from star imports
(F405)
170-170: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py
36-36: Trailing whitespace
Remove trailing whitespace
(W291)
38-38: Trailing whitespace
Remove trailing whitespace
(W291)
48-48: Blank line contains whitespace
Remove whitespace from blank line
(W293)
71-71: Trailing whitespace
Remove trailing whitespace
(W291)
87-87: Trailing whitespace
Remove trailing whitespace
(W291)
93-93: Blank line contains whitespace
Remove whitespace from blank line
(W293)
115-115: Trailing whitespace
Remove trailing whitespace
(W291)
137-137: Blank line contains whitespace
Remove whitespace from blank line
(W293)
148-148: f-string without any placeholders
Remove extraneous f prefix
(F541)
153-153: Trailing whitespace
Remove trailing whitespace
(W291)
174-174: Trailing whitespace
Remove trailing whitespace
(W291)
178-178: Blank line contains whitespace
Remove whitespace from blank line
(W293)
188-188: Blank line contains whitespace
Remove whitespace from blank line
(W293)
192-192: f-string without any placeholders
Remove extraneous f prefix
(F541)
200-200: Blank line contains whitespace
Remove whitespace from blank line
(W293)
203-203: Trailing whitespace
Remove trailing whitespace
(W291)
packages/jumpstarter-driver-power/jumpstarter_driver_power/client.py
56-56: Trailing whitespace
Remove trailing whitespace
(W291)
62-62: Blank line contains whitespace
Remove whitespace from blank line
(W293)
🔇 Additional comments (5)
packages/jumpstarter-driver-power/jumpstarter_driver_power/client.py (2)
63-67: Command override approach is now explicit but consider alternatives.The code now explicitly overrides the parent's
offcommand withname='off', which addresses part of the previous review concern. However, this still replaces the parent command completely rather than providing a separate command.If the intention is to completely replace the parent's behavior, this approach is fine. If you want to preserve both behaviors, consider using a different command name as suggested in the previous review.
Is completely replacing the parent's
offcommand the intended behavior? Or should both commands be available separately?
57-58: Implementation correctly aligns with other virtual power interfaces.The
offmethod with thedestroyparameter properly aligns with theCorelliumPowerimplementation in the Corellium driver, creating a consistent interface across virtual power implementations.packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (1)
5-5: Avoid star imports for clarity and maintainability.Using
from .types import *can lead to namespace pollution and confusion about undefined references likeSession,Project,Device, andInstance. It's preferable to explicitly import these symbols.-from .types import * +from .types import Session, Project, Device, Instance🧰 Tools
🪛 Ruff (0.8.2)
5-5:
from .types import *used; unable to detect undefined names(F403)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (2)
94-101: Fix session expiration check logic.The current code re-logins if the time difference is greater than 1 second, which means it will login almost every time. The logic should check if the time difference is less than a threshold.
# check if session is about to expire # currently depends on the magic number of 60 seconds now = datetime.utcnow() diff = datetime.strptime(self._api.session.expiration, '%Y-%m-%dT%H:%M:%S.%fZ') - now -if diff > timedelta(seconds=1): +# Re-login if there's less than 60 seconds left in the session +if diff < timedelta(seconds=60): self._api.login()
158-161: Fix error message to reference correct attribute.The error message references a nonexistent
device_modelattribute instead of the correctdevice_flavor.device = self.parent.api.get_device(self.parent.device_flavor) if device is None: - raise ValueError('Unable to find a device for this model: {self.parent.device_model}') + raise ValueError(f'Unable to find a device for this model: {self.parent.device_flavor}')
There was a problem hiding this comment.
Caution
Inline review comments failed to post. This is likely due to GitHub's limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.
Actionable comments posted: 2
♻️ Duplicate comments (3)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (2)
160-160:⚠️ Potential issueFix incorrect reference to
device_model.The error message references
{self.parent.device_model}instead of referencing the actualdevice_flavor. This can cause confusion when diagnosing issues.- raise ValueError('Unable to find a device for this model: {self.parent.device_model}') + raise ValueError(f'Unable to find a device for this model: {self.parent.device_flavor}')
202-203: 🛠️ Refactor suggestionImplement or raise
NotImplementedErrorforreadmethod.
readsimply passes without a proper implementation, which can confuse consumers of the API. If reading power data is not supported, raise an exception to clarify.@export -def read(self) -> AsyncGenerator[PowerReading, None]: - pass +def read(self) -> AsyncGenerator[PowerReading, None]: + """ + Not implemented for Corellium devices. + """ + raise NotImplementedError("Power readings are not available for Corellium devices.")🧰 Tools
🪛 Ruff (0.8.2)
203-203: Trailing whitespace
Remove trailing whitespace
(W291)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py (1)
158-164: 🛠️ Refactor suggestionAdd assertion to verify instance destruction
The test for instance destruction doesn't have an assertion to verify success. Add verification to ensure the request was made correctly.
def test_destroy_instance_state_ok(requests_mock): instance = Instance(id='d59db33d-27bd-4b22-878d-49e4758a648e') - + requests_mock.delete(f'https://api-host/api/v1/instances/{instance.id}', status_code=204, text='') api = ApiClient('api-host', 'api-token') api.session = Session('session-token', '2022-03-20T01:50:10.000Z') api.destroy_instance(instance) + + # Verify the request was made correctly + assert requests_mock.called + assert requests_mock.last_request.method == 'DELETE' + assert requests_mock.last_request.url == f'https://api-host/api/v1/instances/{instance.id}'🧰 Tools
🪛 Ruff (0.8.2)
158-158: Redefinition of unused
requests_mockfrom line 4(F811)
159-159:
Instancemay be undefined, or defined from star imports(F405)
160-160: Blank line contains whitespace
Remove whitespace from blank line
(W293)
163-163:
Sessionmay be undefined, or defined from star imports(F405)
🧹 Nitpick comments (17)
packages/jumpstarter-driver-power/jumpstarter_driver_power/client.py (2)
56-56: Fix trailing whitespaceRemove the trailing whitespace after the class definition.
-class VirtualPowerClient(PowerClient): +class VirtualPowerClient(PowerClient):🧰 Tools
🪛 Ruff (0.8.2)
56-56: Trailing whitespace
Remove trailing whitespace
(W291)
62-62: Remove whitespace from blank lineThe blank line contains whitespace that should be removed.
- +🧰 Tools
🪛 Ruff (0.8.2)
62-62: Blank line contains whitespace
Remove whitespace from blank line
(W293)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver_test.py (2)
1-5: Remove unused imports for cleaner code.Static analysis flags
osandrequests_mockas unused. However,requests_mockappears to be used as a test fixture. If indeed required, it can remain; otherwise, remove it. Theosimport is not used at all.Here’s a suggested diff if you confirm the
requests_mockusage is unnecessary:- import os - import requests_mock + import requests_mock🧰 Tools
🪛 Ruff (0.8.2)
1-1:
osimported but unusedRemove unused import:
os(F401)
5-5:
requests_mockimported but unusedRemove unused import:
requests_mock(F401)
32-44: Replacedict()calls with literal syntax for clarity.According to static analysis (C408), calls like
dict()could be replaced with{}for readability and performance.Example diff:
- dict() + {}🧰 Tools
🪛 Ruff (0.8.2)
32-32: Unnecessary
dict()call (rewrite as a literal)Rewrite as a literal
(C408)
36-36: Unnecessary
dict()call (rewrite as a literal)Rewrite as a literal
(C408)
40-40: Unnecessary
dict()call (rewrite as a literal)Rewrite as a literal
(C408)
44-44: Unnecessary
dict()call (rewrite as a literal)Rewrite as a literal
(C408)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (2)
49-49: Fix minor spelling issue in docstring.The docstring refers to “varibales” instead of “variables.” Correcting typos helps improve maintainability.
- Additionally, it also sets up some internal objects/varibales such as: + Additionally, it also sets up some internal objects/variables such as:
85-87: Minor spelling correction in docstring.“accross diferent” is misspelled. It should be “across different.”
- accross diferent API methods + across different API methods🧰 Tools
🪛 Ruff (0.8.2)
87-87: Trailing whitespace
Remove trailing whitespace
(W291)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (2)
5-5: Avoid star imports for clarity.
from .types import *can lead to namespace confusion. Prefer explicit imports to ensure maintainability and avoid silently overwriting symbols.- from .types import * + from .types import Session, Project, Device, Instance🧰 Tools
🪛 Ruff (0.8.2)
5-5:
from .types import *used; unable to detect undefined names(F403)
50-50: Raise exceptions withfromto preserve tracebacks.Consider using
raise ... from efor better debugging. This approach clarifies that theCorelliumApiExceptionwas caused by an underlying error.except (requests.exceptions.RequestException, requests.exceptions.HTTPError) as e: - raise CorelliumApiException(data.get('error', str(e))) + raise CorelliumApiException(data.get('error', str(e))) from e🧰 Tools
🪛 Ruff (0.8.2)
50-50: Within an
exceptclause, raise exceptions withraise ... from errorraise ... from Noneto distinguish them from errors in exception handling(B904)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py (9)
4-8: Clean up import statementsThe
requests_mockimport at line 4 is redundant since it's being redefined in each test function parameter. Either remove the top-level import or modify the test functions to use the fixture instead of redefining it.Additionally, the wildcard import from
.typesmakes it difficult to track which classes are being used. Consider importing specific classes for better code clarity.- import requests_mock + # Import only needed for type hints if necessary + # import requests_mock - from .types import * + from .types import Session, Project, Device, Instance from .api import ApiClient from .exceptions import CorelliumApiException🧰 Tools
🪛 Ruff (0.8.2)
4-4:
requests_mockimported but unusedRemove unused import:
requests_mock(F401)
6-6:
from .types import *used; unable to detect undefined names(F403)
33-47: Fix formatting issues in the login error testThere's trailing whitespace at several lines. Also, since you're testing a variety of error conditions, consider adding a comment explaining the purpose of each test case.
@pytest.mark.parametrize( 'status_code,data,msg', - [ + [ (403, fixture('http/403.json'), 'Invalid or missing authorization token'), (200, fixture('http/json-error.json'), 'Invalid control character at'), ]) -def test_login_error(requests_mock, status_code, data, msg): +def test_login_error(requests_mock, status_code, data, msg): requests_mock.post('https://api-host/api/v1/auth/login', status_code=status_code, text=data) api = ApiClient('api-host', 'api-token')🧰 Tools
🪛 Ruff (0.8.2)
35-35: Trailing whitespace
Remove trailing whitespace
(W291)
39-39: Redefinition of unused
requests_mockfrom line 4(F811)
39-39: Trailing whitespace
Remove trailing whitespace
(W291)
50-69: Fix whitespace in the get_project testRemove the whitespace in the blank line at line 64. Otherwise, the test logic is good - it properly tests different scenarios with parametrization.
project = api.get_project(*args) - + if has_results: assert project is not None🧰 Tools
🪛 Ruff (0.8.2)
55-55: Redefinition of unused
requests_mockfrom line 4(F811)
58-58:
Sessionmay be undefined, or defined from star imports(F405)
64-64: Blank line contains whitespace
Remove whitespace from blank line
(W293)
72-86: Fix formatting issues in the get_project_error testThere's trailing whitespace on lines 74 and 78. Also, the second test case with a 404 response has an empty message check - is this intentional?
@pytest.mark.parametrize( 'status_code,data,msg', - [ + [ (403, fixture('http/403.json'), 'Invalid or missing authorization token'), (404, fixture('http/get-projects-404.json'), ''), ]) -def test_get_project_error(requests_mock, status_code, data, msg): +def test_get_project_error(requests_mock, status_code, data, msg): requests_mock.get('https://api-host/api/v1/projects', status_code=status_code, text=data)🧰 Tools
🪛 Ruff (0.8.2)
74-74: Trailing whitespace
Remove trailing whitespace
(W291)
78-78: Redefinition of unused
requests_mockfrom line 4(F811)
78-78: Trailing whitespace
Remove trailing whitespace
(W291)
81-81:
Sessionmay be undefined, or defined from star imports(F405)
89-104: Fix whitespace in the get_device testRemove the whitespace in the blank line at line 99. Otherwise, the test logic is good for testing device retrieval.
device = api.get_device(model) - + if has_results: assert device is not None🧰 Tools
🪛 Ruff (0.8.2)
93-93: Redefinition of unused
requests_mockfrom line 4(F811)
96-96:
Sessionmay be undefined, or defined from star imports(F405)
99-99: Blank line contains whitespace
Remove whitespace from blank line
(W293)
107-120: Fix formatting issues in the get_device_error testThere's trailing whitespace on lines 109 and 112.
@pytest.mark.parametrize( 'status_code,data,msg', - [ + [ (403, fixture('http/403.json'), 'Invalid or missing authorization token'), ]) -def test_get_device_error(requests_mock, status_code, data, msg): +def test_get_device_error(requests_mock, status_code, data, msg): requests_mock.get('https://api-host/api/v1/models', status_code=status_code, text=data)🧰 Tools
🪛 Ruff (0.8.2)
109-109: Trailing whitespace
Remove trailing whitespace
(W291)
112-112: Redefinition of unused
requests_mockfrom line 4(F811)
112-112: Trailing whitespace
Remove trailing whitespace
(W291)
115-115:
Sessionmay be undefined, or defined from star imports(F405)
123-136: Replace dict() with {} literalReplace the
dict()call with an empty dictionary literal{}for better readability.project = Project('d59db33d-27bd-4b22-878d-49e4758a648e', 'Default Project') device = Device(name='rd1ae', type='automotive', flavor='kronos', - description='', model='kronos', peripherals=False, quotas=dict()) + description='', model='kronos', peripherals=False, quotas={}) instance = api.create_instance('my-instance', project, device, '1.0')🧰 Tools
🪛 Ruff (0.8.2)
123-123: Redefinition of unused
requests_mockfrom line 4(F811)
127-127:
Sessionmay be undefined, or defined from star imports(F405)
129-129:
Projectmay be undefined, or defined from star imports(F405)
130-130:
Devicemay be undefined, or defined from star imports(F405)
131-131: Unnecessary
dict()call (rewrite as a literal)Rewrite as a literal
(C408)
167-183: Fix formatting issues in the destroy_instance_error testThere's trailing whitespace on lines 169 and 173.
@pytest.mark.parametrize( 'status_code,data,msg', - [ + [ (403, fixture('http/403.json'), 'Invalid or missing authorization token'), (404, fixture('http/get-instance-state-404.json'), 'No instance associated with this value'), ]) -def test_destroy_instance_error(requests_mock, status_code, data, msg): +def test_destroy_instance_error(requests_mock, status_code, data, msg): instance = Instance(id='d59db33d-27bd-4b22-878d-49e4758a648e')🧰 Tools
🪛 Ruff (0.8.2)
169-169: Trailing whitespace
Remove trailing whitespace
(W291)
173-173: Redefinition of unused
requests_mockfrom line 4(F811)
173-173: Trailing whitespace
Remove trailing whitespace
(W291)
174-174:
Instancemay be undefined, or defined from star imports(F405)
178-178:
Sessionmay be undefined, or defined from star imports(F405)
1-184: Overall test structure and improvementsThe test structure is good, covering various API operations, but there are some general improvements that could be made:
- Consider organizing these tests into a class to group them logically and potentially share setup fixtures
- Add assertions for request headers in most of the tests to verify the authentication headers are set correctly
- Add docstrings to the test functions to clearly describe the test purpose
- Consider using pytest's
monkeypatchfor setting environment variables if they're used in the API client🧰 Tools
🪛 Ruff (0.8.2)
4-4:
requests_mockimported but unusedRemove unused import:
requests_mock(F401)
6-6:
from .types import *used; unable to detect undefined names(F403)
22-22: Redefinition of unused
requests_mockfrom line 4(F811)
35-35: Trailing whitespace
Remove trailing whitespace
(W291)
39-39: Redefinition of unused
requests_mockfrom line 4(F811)
39-39: Trailing whitespace
Remove trailing whitespace
(W291)
55-55: Redefinition of unused
requests_mockfrom line 4(F811)
58-58:
Sessionmay be undefined, or defined from star imports(F405)
64-64: Blank line contains whitespace
Remove whitespace from blank line
(W293)
74-74: Trailing whitespace
Remove trailing whitespace
(W291)
78-78: Redefinition of unused
requests_mockfrom line 4(F811)
78-78: Trailing whitespace
Remove trailing whitespace
(W291)
81-81:
Sessionmay be undefined, or defined from star imports(F405)
93-93: Redefinition of unused
requests_mockfrom line 4(F811)
96-96:
Sessionmay be undefined, or defined from star imports(F405)
99-99: Blank line contains whitespace
Remove whitespace from blank line
(W293)
109-109: Trailing whitespace
Remove trailing whitespace
(W291)
112-112: Redefinition of unused
requests_mockfrom line 4(F811)
112-112: Trailing whitespace
Remove trailing whitespace
(W291)
115-115:
Sessionmay be undefined, or defined from star imports(F405)
123-123: Redefinition of unused
requests_mockfrom line 4(F811)
127-127:
Sessionmay be undefined, or defined from star imports(F405)
129-129:
Projectmay be undefined, or defined from star imports(F405)
130-130:
Devicemay be undefined, or defined from star imports(F405)
131-131: Unnecessary
dict()call (rewrite as a literal)Rewrite as a literal
(C408)
140-140: Trailing whitespace
Remove trailing whitespace
(W291)
144-144: Redefinition of unused
requests_mockfrom line 4(F811)
144-144: Trailing whitespace
Remove trailing whitespace
(W291)
147-147:
Sessionmay be undefined, or defined from star imports(F405)
149-149: Trailing whitespace
Remove trailing whitespace
(W291)
150-150:
Projectmay be undefined, or defined from star imports(F405)
151-151:
Devicemay be undefined, or defined from star imports(F405)
152-152: Unnecessary
dict()call (rewrite as a literal)Rewrite as a literal
(C408)
153-153: Local variable
instanceis assigned to but never usedRemove assignment to unused variable
instance(F841)
158-158: Redefinition of unused
requests_mockfrom line 4(F811)
159-159:
Instancemay be undefined, or defined from star imports(F405)
160-160: Blank line contains whitespace
Remove whitespace from blank line
(W293)
163-163:
Sessionmay be undefined, or defined from star imports(F405)
169-169: Trailing whitespace
Remove trailing whitespace
(W291)
173-173: Redefinition of unused
requests_mockfrom line 4(F811)
173-173: Trailing whitespace
Remove trailing whitespace
(W291)
174-174:
Instancemay be undefined, or defined from star imports(F405)
178-178:
Sessionmay be undefined, or defined from star imports(F405)
🛑 Comments failed to post (2)
packages/jumpstarter-driver-corellium/fixtures/http/json-error.json (1)
1-1:
⚠️ Potential issueFix malformed JSON fixture data
The JSON fixture has syntax errors that will cause parsing failures:
- Missing closing quotation mark for the string value
- Missing closing brace for the JSON object
-{"token": "a} +{"token": "a"}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.{"token": "a"}🧰 Tools
🪛 Biome (1.9.4)
[error] 1-1: Missing closing quote
The closing quote must be on the same line.
(parse)
[error] 1-1: expected
}but instead the file endsthe file ends here
(parse)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (1)
126-126:
⚠️ Potential issueFix undefined
instancesvariable.The loop references
instances, which is not defined. Likely you intendedfor instance in data:. This leads to aNameErrorat runtime.-for instance in instances: +for instance in data:📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.for instance in data:🧰 Tools
🪛 Ruff (0.8.2)
126-126:
instancesmay be undefined, or defined from star imports(F405)
There was a problem hiding this comment.
Actionable comments posted: 1
🔭 Outside diff range comments (1)
packages/jumpstarter-driver-corellium/fixtures/http/json-error.json (1)
1-2:⚠️ Potential issueFix invalid JSON syntax
The JSON file contains an invalid syntax. The value for the "token" key is missing a closing quotation mark, making it an invalid JSON.
Apply this diff to fix the syntax:
-{"token": "a} +{"token": "a"}🧰 Tools
🪛 Biome (1.9.4)
[error] 1-1: Missing closing quote
The closing quote must be on the same line.
(parse)
[error] 1-1: expected
}but instead the file endsthe file ends here
(parse)
♻️ Duplicate comments (2)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (1)
202-203:⚠️ Potential issueUnimplemented
readmethod.The method is currently a no-op. If this is part of the interface, please either implement it or raise
NotImplementedErrorso the user is aware that it's intentionally unimplemented.- def read(self) -> AsyncGenerator[PowerReading, None]: - pass + def read(self) -> AsyncGenerator[PowerReading, None]: + """ + Not implemented yet. Raise this error to notify callers. + """ + raise NotImplementedError("Power readings are not available for Corellium devices.")🧰 Tools
🪛 Ruff (0.8.2)
203-203: Trailing whitespace
Remove trailing whitespace
(W291)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (1)
5-5: 🛠️ Refactor suggestionAvoid star imports for clarity and maintenance.
Using
from .types import *can lead to potential namespace collisions and reduce code clarity. Prefer importing symbols explicitly.- from .types import * + from .types import Session, Project, Device, Instance🧰 Tools
🪛 Ruff (0.8.2)
5-5:
from .types import *used; unable to detect undefined names(F403)
🧹 Nitpick comments (10)
packages/jumpstarter-driver-power/jumpstarter_driver_power/client.py (3)
56-56: Fix trailing whitespace.There's trailing whitespace at the end of this line.
-class VirtualPowerClient(PowerClient): +class VirtualPowerClient(PowerClient):🧰 Tools
🪛 Ruff (0.8.2)
56-56: Trailing whitespace
Remove trailing whitespace
(W291)
62-62: Remove whitespace from blank line.This blank line contains whitespace.
- +🧰 Tools
🪛 Ruff (0.8.2)
62-62: Blank line contains whitespace
Remove whitespace from blank line
(W293)
60-69: CLI implementation is functional but consider improving command naming.The CLI implementation correctly extends the parent's CLI and overrides the off command. However, this approach completely replaces the parent command rather than adding a variant.
Consider one of these approaches:
- Keep the current override but enhance the docstring to clarify this replaces the standard off command:
@parent.command(name='off') @click.option('--destroy', is_flag=True, help='destroy the instance after powering it off') def off(destroy: bool): - """Power off""" + """Power off with optional instance destruction (overrides standard off command)""" self.off(destroy)
- Add a separate command specifically for virtual power operations:
- @parent.command(name='off') + @parent.command(name='virtual-off') @click.option('--destroy', is_flag=True, help='destroy the instance after powering it off') - def off(destroy: bool): + def virtual_off(destroy: bool): - """Power off""" + """Power off virtual instance with optional destruction""" self.off(destroy)🧰 Tools
🪛 Ruff (0.8.2)
62-62: Blank line contains whitespace
Remove whitespace from blank line
(W293)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/client.py (2)
7-8: Empty class implementationThe
CorelliumClientclass currently has no implementation. Consider adding docstrings to explain the purpose of this class and what functionality it will eventually provide.class CorelliumClient(CompositeClient): - pass + """ + Client implementation for Corellium devices. + + This class inherits from CompositeClient and will be used to interact with + Corellium virtual devices. + """ + pass
9-20: Commented out codeThere are commented-out sections suggesting future implementations. Consider adding TODO comments with ticket references or removing the code if it's not needed.
- # @property - # def hostname(self) -> str: - # return self.call("get_hostname") + # TODO: Implement hostname property + # @property + # def hostname(self) -> str: + # return self.call("get_hostname") - # @contextmanager - # def shell(self): - # with FabricAdapter( - # client=self.ssh, - # user=self.username, - # connect_kwargs={"password": self.password}, - # ) as conn: - # yield conn + # TODO: Implement shell context manager + # @contextmanager + # def shell(self): + # with FabricAdapter( + # client=self.ssh, + # user=self.username, + # connect_kwargs={"password": self.password}, + # ) as conn: + # yield connpackages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver_test.py (2)
9-11: Avoid wildcard importsWildcard imports make it difficult to determine which symbols are imported and can lead to namespace pollution. Consider importing specific symbols instead.
-from .corellium.types import * +from .corellium.types import Session, Project, Device, Instance🧰 Tools
🪛 Ruff (0.8.2)
9-9:
from .corellium.types import *used; unable to detect undefined names(F403)
10-10:
.corellium.api.ApiClientimported but unusedRemove unused import:
.corellium.api.ApiClient(F401)
146-149: Consider adding destroy=True parameter test for off methodThe
offmethod accepts adestroyparameter, but there's no test case that verifies this functionality works when set toTrue.Consider adding a test case that passes
destroy=Trueto theoffmethod and verifies that thedestroy_instancemethod is called:def test_driver_power_off_with_destroy_ok(monkeypatch): monkeypatch.setenv('CORELLIUM_API_HOST', 'api-host') monkeypatch.setenv('CORELLIUM_API_TOKEN', 'api-token') project = Project('1', 'Default Project') instance = Instance(id='7f4f241c-821f-4219-905f-c3b50b0db5dd', state='on') root = Corellium(project_id='1', device_name='jmp', device_flavor='kronos', device_os='1.0') power = CorelliumPower(parent=root) with (patch.object(root._api, 'login', return_value=None), patch.object(root._api, 'get_project', return_value=project), patch.object(root._api, 'set_instance_state', return_value=None), patch.object(root._api, 'get_instance', side_effect=[instance, Instance(id=instance.id, state='off'), None]), patch.object(root._api, 'destroy_instance', return_value=None)): power.off(destroy=True)🧰 Tools
🪛 Ruff (0.8.2)
147-147: Line too long (122 > 120)
(E501)
148-148: Line too long (124 > 120)
(E501)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (1)
45-50: Improve exception chaining for better tracebacks.When catching exceptions and raising a new one, consider chaining with
raise ... from eto preserve the original traceback context.except (requests.exceptions.RequestException, requests.exceptions.HTTPError) as e: - raise CorelliumApiException(data.get('error', str(e))) + raise CorelliumApiException(data.get('error', str(e))) from e🧰 Tools
🪛 Ruff (0.8.2)
50-50: Within an
exceptclause, raise exceptions withraise ... from errorraise ... from Noneto distinguish them from errors in exception handling(B904)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py (2)
131-131: Use a literal instead ofdict().For clarity and slight performance gains, prefer a dictionary literal (
{}) overdict().- quotas=dict() + quotas={}🧰 Tools
🪛 Ruff (0.8.2)
131-131: Unnecessary
dict()call (rewrite as a literal)Rewrite as a literal
(C408)
153-153: Remove the unusedinstancevariable assignment.You're assigning
instance = api.create_instance(...)but never using it. That’s likely unnecessary if you only want to verify exceptions.- instance = api.create_instance('my-instance', project, device, '1.1.1', 'Critical Application Monitor (Baremetal)') + api.create_instance('my-instance', project, device, '1.1.1', 'Critical Application Monitor (Baremetal)')🧰 Tools
🪛 Ruff (0.8.2)
153-153: Local variable
instanceis assigned to but never usedRemove assignment to unused variable
instance(F841)
153-153: Line too long (123 > 120)
(E501)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (2)
packages/jumpstarter-driver-corellium/poetry.lockis excluded by!**/*.lockuv.lockis excluded by!**/*.lock
📒 Files selected for processing (24)
packages/jumpstarter-driver-corellium/README.md(1 hunks)packages/jumpstarter-driver-corellium/examples/exporter.yml(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/403.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/create-instance-200.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/create-instance-400.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/delete-instance-404.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/get-instance-state-200.txt(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/get-instance-state-404.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/get-models-200.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/get-projects-200.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/get-projects-404.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/json-error.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/login-200.json(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/client.py(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/exceptions.py(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/types.py(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver_test.py(1 hunks)packages/jumpstarter-driver-corellium/pyproject.toml(1 hunks)packages/jumpstarter-driver-power/jumpstarter_driver_power/client.py(1 hunks)packages/jumpstarter-driver-power/jumpstarter_driver_power/driver.py(1 hunks)pyproject.toml(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (16)
- packages/jumpstarter-driver-corellium/fixtures/http/login-200.json
- packages/jumpstarter-driver-corellium/fixtures/http/get-instance-state-200.txt
- packages/jumpstarter-driver-corellium/fixtures/http/create-instance-400.json
- packages/jumpstarter-driver-corellium/fixtures/http/get-projects-404.json
- packages/jumpstarter-driver-corellium/fixtures/http/get-instance-state-404.json
- packages/jumpstarter-driver-corellium/fixtures/http/delete-instance-404.json
- pyproject.toml
- packages/jumpstarter-driver-corellium/examples/exporter.yml
- packages/jumpstarter-driver-corellium/fixtures/http/get-models-200.json
- packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/exceptions.py
- packages/jumpstarter-driver-corellium/fixtures/http/get-projects-200.json
- packages/jumpstarter-driver-corellium/README.md
- packages/jumpstarter-driver-corellium/fixtures/http/403.json
- packages/jumpstarter-driver-corellium/fixtures/http/create-instance-200.json
- packages/jumpstarter-driver-corellium/pyproject.toml
- packages/jumpstarter-driver-power/jumpstarter_driver_power/driver.py
🧰 Additional context used
🧬 Code Definitions (4)
packages/jumpstarter-driver-power/jumpstarter_driver_power/client.py (10)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (1) (1)
off(180-199)packages/jumpstarter-driver-power/jumpstarter_driver_power/driver.py (4) (4)
off(17-17)off(32-32)off(58-59)off(86-87)packages/jumpstarter-driver-snmp/jumpstarter_driver_snmp/driver.py (1) (1)
off(201-203)packages/jumpstarter-driver-dutlink/jumpstarter_driver_dutlink/driver.py (2) (2)
off(131-132)off(189-190)packages/jumpstarter-driver-raspberrypi/jumpstarter_driver_raspberrypi/driver.py (1) (1)
off(29-33)packages/jumpstarter-driver-raspberrypi/jumpstarter_driver_raspberrypi/client.py (1) (1)
off(8-9)packages/jumpstarter-driver-yepkit/jumpstarter_driver_yepkit/driver.py (1) (1)
off(117-120)packages/jumpstarter-driver-sdwire/jumpstarter_driver_sdwire/driver.py (1) (1)
off(102-103)packages/jumpstarter-driver-opendal/jumpstarter_driver_opendal/driver.py (2) (2)
off(247-247)off(275-276)packages/jumpstarter-driver-opendal/jumpstarter_driver_opendal/client.py (5) (5)
off(595-597)cli(399-513)cli(533-553)cli(623-647)cli(695-697)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (2)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/exceptions.py (1) (1)
CorelliumApiException(7-10)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/types.py (5) (5)
Session(9-22)as_header(16-22)Project(26-31)Device(35-47)Instance(51-56)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/client.py (1)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (1) (1)
client(32-36)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver_test.py (4)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (5) (5)
Corellium(20-101)CorelliumPower(105-203)api(81-101)on(142-177)off(180-199)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (1) (1)
ApiClient(9-171)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/exceptions.py (1) (1)
CorelliumApiException(7-10)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/types.py (4) (4)
Session(9-22)Project(26-31)Device(35-47)Instance(51-56)
🪛 Ruff (0.8.2)
packages/jumpstarter-driver-power/jumpstarter_driver_power/client.py
56-56: Trailing whitespace
Remove trailing whitespace
(W291)
62-62: Blank line contains whitespace
Remove whitespace from blank line
(W293)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py
5-5: from .types import * used; unable to detect undefined names
(F403)
13-13: Session may be undefined, or defined from star imports
(F405)
14-14: field may be undefined, or defined from star imports
(F405)
18-18: Trailing whitespace
Remove trailing whitespace
(W291)
28-28: Trailing whitespace
Remove trailing whitespace
(W291)
31-31: Blank line contains whitespace
Remove whitespace from blank line
(W293)
50-50: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
52-52: Session may be undefined, or defined from star imports
(F405)
55-55: Project may be undefined, or defined from star imports
(F405)
64-64: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
68-68: Project may be undefined, or defined from star imports
(F405)
72-72: Device may be undefined, or defined from star imports
(F405)
83-83: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
87-87: Device may be undefined, or defined from star imports
(F405)
91-91: Project may be undefined, or defined from star imports
(F405)
91-91: Device may be undefined, or defined from star imports
(F405)
91-91: Instance may be undefined, or defined from star imports
(F405)
108-108: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
110-110: Instance may be undefined, or defined from star imports
(F405)
112-112: Instance may be undefined, or defined from star imports
(F405)
123-123: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
125-125: instances may be undefined, or defined from star imports
(F405)
127-127: Instance may be undefined, or defined from star imports
(F405)
131-131: Instance may be undefined, or defined from star imports
(F405)
131-131: Trailing whitespace
Remove trailing whitespace
(W291)
157-157: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
159-159: Instance may be undefined, or defined from star imports
(F405)
171-171: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py
4-4: requests_mock imported but unused
Remove unused import: requests_mock
(F401)
6-6: from .types import * used; unable to detect undefined names
(F403)
22-22: Redefinition of unused requests_mock from line 4
(F811)
35-35: Trailing whitespace
Remove trailing whitespace
(W291)
39-39: Redefinition of unused requests_mock from line 4
(F811)
39-39: Trailing whitespace
Remove trailing whitespace
(W291)
55-55: Redefinition of unused requests_mock from line 4
(F811)
58-58: Session may be undefined, or defined from star imports
(F405)
64-64: Blank line contains whitespace
Remove whitespace from blank line
(W293)
74-74: Trailing whitespace
Remove trailing whitespace
(W291)
78-78: Redefinition of unused requests_mock from line 4
(F811)
78-78: Trailing whitespace
Remove trailing whitespace
(W291)
81-81: Session may be undefined, or defined from star imports
(F405)
93-93: Redefinition of unused requests_mock from line 4
(F811)
96-96: Session may be undefined, or defined from star imports
(F405)
99-99: Blank line contains whitespace
Remove whitespace from blank line
(W293)
109-109: Trailing whitespace
Remove trailing whitespace
(W291)
112-112: Redefinition of unused requests_mock from line 4
(F811)
112-112: Trailing whitespace
Remove trailing whitespace
(W291)
115-115: Session may be undefined, or defined from star imports
(F405)
123-123: Redefinition of unused requests_mock from line 4
(F811)
127-127: Session may be undefined, or defined from star imports
(F405)
129-129: Project may be undefined, or defined from star imports
(F405)
130-130: Device may be undefined, or defined from star imports
(F405)
131-131: Unnecessary dict() call (rewrite as a literal)
Rewrite as a literal
(C408)
140-140: Trailing whitespace
Remove trailing whitespace
(W291)
144-144: Redefinition of unused requests_mock from line 4
(F811)
147-147: Session may be undefined, or defined from star imports
(F405)
149-149: Trailing whitespace
Remove trailing whitespace
(W291)
150-150: Project may be undefined, or defined from star imports
(F405)
151-151: Device may be undefined, or defined from star imports
(F405)
152-152: Unnecessary dict() call (rewrite as a literal)
Rewrite as a literal
(C408)
153-153: Local variable instance is assigned to but never used
Remove assignment to unused variable instance
(F841)
153-153: Line too long (123 > 120)
(E501)
158-158: Redefinition of unused requests_mock from line 4
(F811)
159-159: Instance may be undefined, or defined from star imports
(F405)
160-160: Blank line contains whitespace
Remove whitespace from blank line
(W293)
163-163: Session may be undefined, or defined from star imports
(F405)
169-169: Trailing whitespace
Remove trailing whitespace
(W291)
173-173: Redefinition of unused requests_mock from line 4
(F811)
173-173: Trailing whitespace
Remove trailing whitespace
(W291)
174-174: Instance may be undefined, or defined from star imports
(F405)
178-178: Session may be undefined, or defined from star imports
(F405)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py
36-36: Trailing whitespace
Remove trailing whitespace
(W291)
38-38: Trailing whitespace
Remove trailing whitespace
(W291)
48-48: Blank line contains whitespace
Remove whitespace from blank line
(W293)
71-71: Trailing whitespace
Remove trailing whitespace
(W291)
87-87: Trailing whitespace
Remove trailing whitespace
(W291)
93-93: Blank line contains whitespace
Remove whitespace from blank line
(W293)
115-115: Trailing whitespace
Remove trailing whitespace
(W291)
137-137: Blank line contains whitespace
Remove whitespace from blank line
(W293)
148-148: f-string without any placeholders
Remove extraneous f prefix
(F541)
153-153: Trailing whitespace
Remove trailing whitespace
(W291)
174-174: Trailing whitespace
Remove trailing whitespace
(W291)
178-178: Blank line contains whitespace
Remove whitespace from blank line
(W293)
188-188: Blank line contains whitespace
Remove whitespace from blank line
(W293)
192-192: f-string without any placeholders
Remove extraneous f prefix
(F541)
200-200: Blank line contains whitespace
Remove whitespace from blank line
(W293)
203-203: Trailing whitespace
Remove trailing whitespace
(W291)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/client.py
1-1: contextlib.contextmanager imported but unused
Remove unused import: contextlib.contextmanager
(F401)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver_test.py
1-1: os imported but unused
Remove unused import: os
(F401)
5-5: requests_mock imported but unused
Remove unused import: requests_mock
(F401)
9-9: from .corellium.types import * used; unable to detect undefined names
(F403)
10-10: .corellium.api.ApiClient imported but unused
Remove unused import: .corellium.api.ApiClient
(F401)
17-17: Blank line contains whitespace
Remove whitespace from blank line
(W293)
19-19: Blank line contains whitespace
Remove whitespace from blank line
(W293)
30-30: Trailing whitespace
Remove trailing whitespace
(W291)
32-32: Unnecessary dict() call (rewrite as a literal)
Rewrite as a literal
(C408)
36-36: Unnecessary dict() call (rewrite as a literal)
Rewrite as a literal
(C408)
40-40: Unnecessary dict() call (rewrite as a literal)
Rewrite as a literal
(C408)
44-44: Unnecessary dict() call (rewrite as a literal)
Rewrite as a literal
(C408)
51-51: Blank line contains whitespace
Remove whitespace from blank line
(W293)
57-57: Blank line contains whitespace
Remove whitespace from blank line
(W293)
61-61: Redefinition of unused requests_mock from line 5
(F811)
62-62: Line too long (129 > 120)
(E501)
68-68: Session may be undefined, or defined from star imports
(F405)
75-75: Project may be undefined, or defined from star imports
(F405)
76-76: Device may be undefined, or defined from star imports
(F405)
77-77: Unnecessary dict() call (rewrite as a literal)
Rewrite as a literal
(C408)
78-78: Instance may be undefined, or defined from star imports
(F405)
100-100: Project may be undefined, or defined from star imports
(F405)
101-101: Instance may be undefined, or defined from star imports
(F405)
109-109: Line too long (122 > 120)
(E501)
117-117: Project may be undefined, or defined from star imports
(F405)
118-118: Instance may be undefined, or defined from star imports
(F405)
121-121: Blank line contains whitespace
Remove whitespace from blank line
(W293)
122-122: Trailing whitespace
Remove trailing whitespace
(W291)
125-125: Instance may be undefined, or defined from star imports
(F405)
139-139: Project may be undefined, or defined from star imports
(F405)
140-140: Instance may be undefined, or defined from star imports
(F405)
143-143: Blank line contains whitespace
Remove whitespace from blank line
(W293)
147-147: Line too long (122 > 120)
(E501)
148-148: Line too long (124 > 120)
(E501)
🪛 Biome (1.9.4)
packages/jumpstarter-driver-corellium/fixtures/http/json-error.json
[error] 1-1: Missing closing quote
The closing quote must be on the same line.
(parse)
[error] 1-1: expected } but instead the file ends
the file ends here
(parse)
🔇 Additional comments (12)
packages/jumpstarter-driver-power/jumpstarter_driver_power/client.py (2)
63-67: Command redefinition issue in cli method.The
offcommand is being redefined in the child class with the same name as in the parent class. This will completely override the parent's command, which might be intentional but could lead to confusion.If you want to completely replace the parent's
offcommand (which seems to be the case given the explicitname='off'), this implementation is correct. However, consider making it clearer in the docstring that this replaces the parent command and adds the destroy functionality.Alternatively, consider using a different command name as suggested in the previous review:
- @parent.command(name='off') - @click.option('--destroy', is_flag=True, help='destroy the instance after powering it off') - def off(destroy: bool): + @parent.command(name='off-virtual') + @click.option('--destroy', is_flag=True, help='destroy the instance after powering it off') + def off_virtual(destroy: bool): """Power off""" self.off(destroy)
57-58: Method signature enhancement looks good.The
offmethod is correctly extended to include thedestroyparameter, which aligns with the implementation in the Corellium driver. This ensures consistency across virtual power interfaces.packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/client.py (1)
1-1: Remove unused importThe
contextmanagerfromcontextlibis imported but not used in the active code. Either implement the commented-out code that uses it or remove/comment out this import.-from contextlib import contextmanager +# from contextlib import contextmanager🧰 Tools
🪛 Ruff (0.8.2)
1-1:
contextlib.contextmanagerimported but unusedRemove unused import:
contextlib.contextmanager(F401)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/types.py (4)
8-23: LGTM: Well-structured Session classThe Session class is well-designed with clear documentation and a useful as_header method.
25-32: LGTM: Clean Project data classThe Project class is properly implemented as a data class with good documentation.
34-48: LGTM: Comprehensive Device data classThe Device class contains all necessary fields for device representation and is well-documented.
50-57: LGTM: Well-designed Instance classThe Instance class includes an optional state field with proper default value handling.
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver_test.py (1)
90-110: Fix incorrect method call in power on error testThe test is calling
power.off()instead ofpower.on()which doesn't match the test name and intention.@pytest.mark.parametrize('mock_data', [ ({'login': {'side_effect': CorelliumApiException('login error')}}), ({'get_project': {'return_value': None}}), ({'get_instance': {'return_value': None}}), ({'create_instance': {'side_effect': CorelliumApiException('create error')}}), ]) def test_driver_power_on_error(monkeypatch, mock_data): monkeypatch.setenv('CORELLIUM_API_HOST', 'api-host') monkeypatch.setenv('CORELLIUM_API_TOKEN', 'api-token') project = Project('1', 'Default Project') instance = Instance(id='7f4f241c-821f-4219-905f-c3b50b0db5dd', state='on') root = Corellium(project_id='1', device_name='jmp', device_flavor='kronos', device_os='1.0') power = CorelliumPower(parent=root) with pytest.raises((CorelliumApiException, ValueError)): with (patch.object(root._api, 'login', **mock_data.get('login', {'return_value': None})), patch.object(root._api, 'get_project', **mock_data.get('get_project', {'return_value': project})), patch.object(root._api, 'get_instance', **mock_data.get('get_instance', {'return_value': instance})), patch.object(root._api, 'create_instance', **mock_data.get('create_instance', {'return_value': instance}))): - power.off() + power.on()🧰 Tools
🪛 Ruff (0.8.2)
100-100:
Projectmay be undefined, or defined from star imports(F405)
101-101:
Instancemay be undefined, or defined from star imports(F405)
109-109: Line too long (122 > 120)
(E501)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (3)
19-23: Implementation logic forCorelliuminitialization looks robust.The driver correctly checks for required environment variables and sets up the API client. No immediate concerns here.
98-99: Potential session refresh logic error.The check at line 98 re-logins when the session has more than one second left (i.e.,
diff > timedelta(seconds=1)), which might cause unnecessary extra logins. Typically, you'd want to re-login only if the session is about to expire (e.g.,diff < timedelta(seconds=60)).
159-160: Mismatch between 'device_flavor' usage and error message.Line 160 references
self.parent.device_model, but the actual property isself.parent.device_flavor. This likely causes confusion or incorrect error logging.packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py (1)
4-4: Verify necessity of therequests_mockimport.You’re passing
requests_mockas a function parameter in many tests, potentially making the explicit import at line 4 redundant. Double-check whether you need both the import statement and the fixture parameter.🧰 Tools
🪛 Ruff (0.8.2)
4-4:
requests_mockimported but unusedRemove unused import:
requests_mock(F401)
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (8)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (3)
126-126: Typographical fix in docstring.The word "instace" in the docstring is misspelled. Consider correcting it to "instance" for consistency.
- Desired can also be set to None, which means the instace should not exist. + Desired can also be set to None, which means the instance should not exist.
148-148: Remove unnecessary 'f' when no placeholders are used.Here, you are using an f-string without any placeholders. For cleaner code, remove the extraneous 'f' prefix.
- self.logger.info(f'Corellium Device:') + self.logger.info('Corellium Device:')🧰 Tools
🪛 Ruff (0.8.2)
148-148: f-string without any placeholders
Remove extraneous
fprefix(F541)
129-139: Consider using a backoff approach when polling instance state.Relying on a fixed
time.sleepin a loop can be inefficient, especially under network delays. Incorporating an exponential backoff or a similar retry mechanism can improve performance and resilience.Example snippet illustrating exponential backoff:
def wait_instance(self, current: Instance, desired: Optional[Instance]): ... backoff = 1 while True: if counter >= opts['retries']: raise ValueError(...) if self.parent.api.get_instance(current.id) == desired: break time.sleep(backoff) + backoff = min(backoff * 2, 30) # cap at 30 seconds counter += 1🧰 Tools
🪛 Ruff (0.8.2)
137-137: Blank line contains whitespace
Remove whitespace from blank line
(W293)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (2)
49-50: Useraise ... from ewithin exception blocks to preserve traceback.In Python, specifying
raise SomeException(...) from eis a recommended practice that helps maintain a more detailed traceback chain. Consider updating exception raising at these lines for improved debugging and clarity.Example for line 50:
except (requests.exceptions.RequestException, requests.exceptions.HTTPError) as e: - raise CorelliumApiException(data.get('error', str(e))) + raise CorelliumApiException(data.get('error', str(e))) from eAlso applies to: 64-64, 83-83, 108-108, 123-123, 157-157, 170-171
🧰 Tools
🪛 Ruff (0.8.2)
50-50: Within an
exceptclause, raise exceptions withraise ... from errorraise ... from Noneto distinguish them from errors in exception handling(B904)
18-18: Remove trailing whitespace.Several lines contain trailing whitespace, which can introduce clutter in version control diffs. Consider removing trailing spaces on these lines.
Also applies to: 28-28, 31-31
🧰 Tools
🪛 Ruff (0.8.2)
18-18: Trailing whitespace
Remove trailing whitespace
(W291)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py (3)
4-4: Avoid potential naming conflict between module import and fixture.You import
requests_mockat the top and also redefine it as a fixture argument. Consider removing the import statement to prevent overshadowing the fixture name.-import requests_mock🧰 Tools
🪛 Ruff (0.8.2)
4-4:
requests_mockimported but unusedRemove unused import:
requests_mock(F401)
153-153: Address line length exceeding recommended limits.This line exceeds recommended style guide limits (123 characters). Consider splitting it into multiple lines for better readability.
🧰 Tools
🪛 Ruff (0.8.2)
153-153: Local variable
instanceis assigned to but never usedRemove assignment to unused variable
instance(F841)
153-153: Line too long (123 > 120)
(E501)
149-154: Remove unused variable and streamline the test.You assign
instancebut never use it. To keep the test concise, remove unnecessary assignments.device = Device(name='rd1ae', type='automotive', flavor='kronos', description='', model='kronos', peripherals=False, quotas=dict()) - instance = api.create_instance('my-instance', project, device, '1.1.1', 'Critical Application Monitor (Baremetal)') + api.create_instance('my-instance', project, device, '1.1.1', 'Critical Application Monitor (Baremetal)')🧰 Tools
🪛 Ruff (0.8.2)
149-149: Trailing whitespace
Remove trailing whitespace
(W291)
150-150:
Projectmay be undefined, or defined from star imports(F405)
151-151:
Devicemay be undefined, or defined from star imports(F405)
152-152: Unnecessary
dict()call (rewrite as a literal)Rewrite as a literal
(C408)
153-153: Local variable
instanceis assigned to but never usedRemove assignment to unused variable
instance(F841)
153-153: Line too long (123 > 120)
(E501)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py(1 hunks)
🧰 Additional context used
🧬 Code Definitions (1)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (2)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/exceptions.py (1) (1)
CorelliumApiException(7-10)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/types.py (5) (5)
Session(9-22)as_header(16-22)Project(26-31)Device(35-47)Instance(51-56)
🪛 Ruff (0.8.2)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py
4-4: requests_mock imported but unused
Remove unused import: requests_mock
(F401)
6-6: from .types import * used; unable to detect undefined names
(F403)
22-22: Redefinition of unused requests_mock from line 4
(F811)
35-35: Trailing whitespace
Remove trailing whitespace
(W291)
39-39: Redefinition of unused requests_mock from line 4
(F811)
39-39: Trailing whitespace
Remove trailing whitespace
(W291)
55-55: Redefinition of unused requests_mock from line 4
(F811)
58-58: Session may be undefined, or defined from star imports
(F405)
64-64: Blank line contains whitespace
Remove whitespace from blank line
(W293)
74-74: Trailing whitespace
Remove trailing whitespace
(W291)
78-78: Redefinition of unused requests_mock from line 4
(F811)
78-78: Trailing whitespace
Remove trailing whitespace
(W291)
81-81: Session may be undefined, or defined from star imports
(F405)
93-93: Redefinition of unused requests_mock from line 4
(F811)
96-96: Session may be undefined, or defined from star imports
(F405)
99-99: Blank line contains whitespace
Remove whitespace from blank line
(W293)
109-109: Trailing whitespace
Remove trailing whitespace
(W291)
112-112: Redefinition of unused requests_mock from line 4
(F811)
112-112: Trailing whitespace
Remove trailing whitespace
(W291)
115-115: Session may be undefined, or defined from star imports
(F405)
123-123: Redefinition of unused requests_mock from line 4
(F811)
127-127: Session may be undefined, or defined from star imports
(F405)
129-129: Project may be undefined, or defined from star imports
(F405)
130-130: Device may be undefined, or defined from star imports
(F405)
131-131: Unnecessary dict() call (rewrite as a literal)
Rewrite as a literal
(C408)
140-140: Trailing whitespace
Remove trailing whitespace
(W291)
144-144: Redefinition of unused requests_mock from line 4
(F811)
147-147: Session may be undefined, or defined from star imports
(F405)
149-149: Trailing whitespace
Remove trailing whitespace
(W291)
150-150: Project may be undefined, or defined from star imports
(F405)
151-151: Device may be undefined, or defined from star imports
(F405)
152-152: Unnecessary dict() call (rewrite as a literal)
Rewrite as a literal
(C408)
153-153: Local variable instance is assigned to but never used
Remove assignment to unused variable instance
(F841)
153-153: Line too long (123 > 120)
(E501)
158-158: Redefinition of unused requests_mock from line 4
(F811)
159-159: Instance may be undefined, or defined from star imports
(F405)
160-160: Blank line contains whitespace
Remove whitespace from blank line
(W293)
163-163: Session may be undefined, or defined from star imports
(F405)
169-169: Trailing whitespace
Remove trailing whitespace
(W291)
173-173: Redefinition of unused requests_mock from line 4
(F811)
173-173: Trailing whitespace
Remove trailing whitespace
(W291)
174-174: Instance may be undefined, or defined from star imports
(F405)
178-178: Session may be undefined, or defined from star imports
(F405)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py
36-36: Trailing whitespace
Remove trailing whitespace
(W291)
38-38: Trailing whitespace
Remove trailing whitespace
(W291)
48-48: Blank line contains whitespace
Remove whitespace from blank line
(W293)
71-71: Trailing whitespace
Remove trailing whitespace
(W291)
87-87: Trailing whitespace
Remove trailing whitespace
(W291)
93-93: Blank line contains whitespace
Remove whitespace from blank line
(W293)
115-115: Trailing whitespace
Remove trailing whitespace
(W291)
137-137: Blank line contains whitespace
Remove whitespace from blank line
(W293)
148-148: f-string without any placeholders
Remove extraneous f prefix
(F541)
153-153: Trailing whitespace
Remove trailing whitespace
(W291)
174-174: Trailing whitespace
Remove trailing whitespace
(W291)
178-178: Blank line contains whitespace
Remove whitespace from blank line
(W293)
188-188: Blank line contains whitespace
Remove whitespace from blank line
(W293)
192-192: f-string without any placeholders
Remove extraneous f prefix
(F541)
200-200: Blank line contains whitespace
Remove whitespace from blank line
(W293)
203-203: Trailing whitespace
Remove trailing whitespace
(W291)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py
5-5: from .types import * used; unable to detect undefined names
(F403)
13-13: Session may be undefined, or defined from star imports
(F405)
14-14: field may be undefined, or defined from star imports
(F405)
18-18: Trailing whitespace
Remove trailing whitespace
(W291)
28-28: Trailing whitespace
Remove trailing whitespace
(W291)
31-31: Blank line contains whitespace
Remove whitespace from blank line
(W293)
50-50: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
52-52: Session may be undefined, or defined from star imports
(F405)
55-55: Project may be undefined, or defined from star imports
(F405)
64-64: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
68-68: Project may be undefined, or defined from star imports
(F405)
72-72: Device may be undefined, or defined from star imports
(F405)
83-83: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
87-87: Device may be undefined, or defined from star imports
(F405)
91-91: Project may be undefined, or defined from star imports
(F405)
91-91: Device may be undefined, or defined from star imports
(F405)
91-91: Instance may be undefined, or defined from star imports
(F405)
108-108: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
110-110: Instance may be undefined, or defined from star imports
(F405)
112-112: Instance may be undefined, or defined from star imports
(F405)
123-123: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
127-127: Instance may be undefined, or defined from star imports
(F405)
131-131: Instance may be undefined, or defined from star imports
(F405)
131-131: Trailing whitespace
Remove trailing whitespace
(W291)
157-157: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
159-159: Instance may be undefined, or defined from star imports
(F405)
171-171: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
🔇 Additional comments (5)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (3)
98-99: Re-check session refresh logic.
160-160: Mismatch between 'device_flavor' usage and error message.
202-203: Implement or raiseNotImplementedErrorforreadmethod.🧰 Tools
🪛 Ruff (0.8.2)
203-203: Trailing whitespace
Remove trailing whitespace
(W291)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (1)
5-5: Avoid using star imports for clarity and maintainability.🧰 Tools
🪛 Ruff (0.8.2)
5-5:
from .types import *used; unable to detect undefined names(F403)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py (1)
6-6: Avoid star imports for clarity and maintainability.🧰 Tools
🪛 Ruff (0.8.2)
6-6:
from .types import *used; unable to detect undefined names(F403)
There was a problem hiding this comment.
Actionable comments posted: 6
🧹 Nitpick comments (2)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (2)
18-18: Remove trailing whitespace for cleaner code.A few lines contain trailing or extraneous whitespace—this can trigger linter warnings and reduce readability. Consider removing these trailing whitespaces, for example:
- Initializes a new client, containing a + Initializes a new client, containing aSame applies to lines 28, 31, and 131.
Also applies to: 28-28, 31-31, 131-131
🧰 Tools
🪛 Ruff (0.8.2)
18-18: Trailing whitespace
Remove trailing whitespace
(W291)
46-46: Consider using the session-based request for consistency.Currently,
requests.postis used here instead ofself.req.post. If the intent is to leverage the same session (e.g., for connection pooling or consistent configurations), it might be beneficial to switch toself.req.post:- res = requests.post(f'{self.baseurl}/v1/auth/login', json=data) + res = self.req.post(f'{self.baseurl}/v1/auth/login', json=data)If you need a fresh connection for login, add a comment clarifying why.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (12)
packages/jumpstarter-cli-client/jumpstarter_cli_client/client_login.py(2 hunks)packages/jumpstarter-cli-client/jumpstarter_cli_client/client_shell.py(1 hunks)packages/jumpstarter-cli-client/jumpstarter_cli_client/common.py(2 hunks)packages/jumpstarter-cli-client/jumpstarter_cli_client/create.py(2 hunks)packages/jumpstarter-cli-client/jumpstarter_cli_client/update.py(2 hunks)packages/jumpstarter-cli-common/jumpstarter_cli_common/oidc.py(2 hunks)packages/jumpstarter-cli-exporter/jumpstarter_cli_exporter/exporter_login.py(2 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py(1 hunks)packages/jumpstarter/jumpstarter/client/grpc.py(6 hunks)packages/jumpstarter/jumpstarter/client/lease.py(2 hunks)packages/jumpstarter/jumpstarter/config/client.py(5 hunks)pyproject.toml(2 hunks)
🧰 Additional context used
🧬 Code Definitions (3)
packages/jumpstarter/jumpstarter/config/client.py (2)
packages/jumpstarter/jumpstarter/common/grpc.py (1) (1)
aio_secure_channel(38-43)packages/jumpstarter/jumpstarter/client/grpc.py (6) (6)
GetExporter(147-154)ListExporters(156-172)ClientService(139-252)CreateLease(201-220)DeleteLease(246-252)UpdateLease(222-244)
packages/jumpstarter-cli-client/jumpstarter_cli_client/client_login.py (1)
packages/jumpstarter-cli-common/jumpstarter_cli_common/oidc.py (3) (3)
Config(40-116)decode_jwt_issuer(123-124)opt_oidc(25-36)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (2)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/types.py (5) (5)
Session(9-22)Project(26-31)Device(35-47)Instance(51-56)as_header(16-22)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/exceptions.py (1) (1)
CorelliumApiException(7-10)
🪛 Ruff (0.8.2)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py
18-18: Trailing whitespace
Remove trailing whitespace
(W291)
28-28: Trailing whitespace
Remove trailing whitespace
(W291)
31-31: Blank line contains whitespace
Remove whitespace from blank line
(W293)
50-50: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
64-64: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
83-83: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
108-108: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
123-123: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
131-131: Trailing whitespace
Remove trailing whitespace
(W291)
157-157: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
171-171: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
🔇 Additional comments (39)
pyproject.toml (2)
14-14: LGTM: Added Corellium driver to workspace configuration.The addition of
jumpstarter-driver-corellium = { workspace = true }correctly integrates the new Corellium driver into the workspace configuration, following the existing pattern used for other drivers.
75-75: What does "Pn" represent in this context?Adding "Pn" to the typo exceptions list seems reasonable, but it would be helpful to understand what this abbreviation represents in the Corellium context to ensure it's a necessary addition.
packages/jumpstarter-cli-common/jumpstarter_cli_common/oidc.py (1)
4-4: Well-structured OIDC option consolidation.This is a good refactoring that consolidates multiple OIDC-related options into a single reusable decorator. The use of
functools.wrapscorrectly preserves the decorated function's metadata.Although this change improves code organization, I don't see direct handling of the CORELLIUM_API_HOST and CORELLIUM_API_TOKEN environment variables mentioned in the PR description. Make sure those authentication requirements are addressed elsewhere in the implementation.
Also applies to: 25-36
packages/jumpstarter-cli-client/jumpstarter_cli_client/common.py (1)
2-2: Well-implemented duration option abstraction.This is a good refactoring that creates a reusable, standardized option for handling duration parameters. The comprehensive help text clearly documents all supported duration formats, which will improve usability.
The use of
functools.partialis appropriate here and creates a clean, maintainable abstraction that can be consistently applied across different commands.Also applies to: 53-69
packages/jumpstarter-cli-client/jumpstarter_cli_client/update.py (1)
7-7: LGTM: Updated to use the standardized duration option.The change properly implements the new
opt_duration_partialabstraction while maintaining the requirement that the duration parameter is mandatory. This improves consistency with other parts of the codebase without changing the command's behavior.Also applies to: 20-20
packages/jumpstarter-cli-client/jumpstarter_cli_client/client_shell.py (5)
2-2: Added timedelta import for duration handling.This addition supports the new approach of representing lease durations as timedelta objects rather than raw seconds, improving type safety and clarity.
7-7: Updated imports to use the new decorator pattern.The import now includes
opt_duration_partialand usesopt_selectorinstead ofopt_selector_simple, reflecting the standardized approach to handling options across the codebase.
14-15: Improved parameter handling with specialized decorators.The changes replace
@opt_selector_simplewith@opt_selectorand add@opt_duration_partialwith appropriate defaults. This improves consistency in the CLI interface and makes the duration parameter's default more user-friendly with a clear time format display.
17-17: Updated function signature to include typed duration parameter.The function now properly types the duration parameter as a timedelta object, improving type safety and code readability.
22-22: Added duration parameter to lease configuration.The lease method call now includes the duration parameter, ensuring the lease time is configurable through the CLI command.
packages/jumpstarter-cli-client/jumpstarter_cli_client/create.py (2)
12-12: Updated imports to use the new decorator pattern.Similar to changes in client_shell.py, this update ensures consistent handling of selectors and durations across commands.
24-25: Standardized parameter handling with specialized decorators.The changes replace
@opt_selector_simplewith@opt_selectorand replace the direct click duration option with@opt_duration_partial(required=True). This improves consistency across the codebase and simplifies the handling of duration parameters.packages/jumpstarter/jumpstarter/client/lease.py (2)
33-33: Changed timeout attribute to duration with proper typing.The change from
timeout: int = 1800toduration: timedeltaimproves type safety and clarity, making it more explicit that this attribute represents a time duration rather than just a number.
54-54: Updated lease creation logic to use duration directly.The method now uses the
durationattribute directly without conversion, simplifying the code and making it more consistent with the rest of the codebase. The logging statements and service call have been updated to reflect this change.Also applies to: 59-60, 62-62
packages/jumpstarter-cli-exporter/jumpstarter_cli_exporter/exporter_login.py (3)
2-2: Updated imports for OIDC authentication.The new import includes
Config, decode_jwt_issuer, opt_oidcfrom the common OIDC module, enabling the consolidation of OIDC-related options.
12-12: Simplified OIDC option handling with a single decorator.The
@opt_oidcdecorator replaces multiple individual OIDC-related options, consolidating them into a single decorator. This simplifies the code and improves consistency in how OIDC authentication is handled.
13-24: Function signature explicitly includes all OIDC parameters.The function signature now clearly documents all required OIDC parameters. These parameters are populated by the
@opt_oidcdecorator, making the authentication process more transparent and maintainable.packages/jumpstarter/jumpstarter/client/grpc.py (8)
12-13: Consistent Error Handling Import
Introducingtranslate_grpc_exceptionshere is a clean approach to centralized error handling. This ensures that gRPC-related exceptions are consistently wrapped and translated throughout the client service, enhancing maintainability and readability.
148-152: Robust Exception Wrapping forGetExporter
Wrapping the gRPC call intranslate_grpc_exceptionsimproves fault tolerance and centralizes exception translation, making the code more resilient to unhandled gRPC errors.
163-170: Error Translation forListExporters
Good practice adding exception translation here. This reduces repetitive try/except blocks and uniformly handles failures duringListExporterscalls.
175-180: Consistent Use of Context Manager forGetLease
Applying the sametranslate_grpc_exceptionspattern to theGetLeasemethod keeps the error handling approach uniform across client service APIs.
190-197: Uniform Exception Handling inListLeases
Extending the wrapping to theListLeasesmethod is consistent with other calls. Ensures no unhandled gRPC issues slip through.
210-218: Enhanced Resilience forCreateLease
Wrapping theCreateLeaseinvocation withtranslate_grpc_exceptionsoffers a safe fallback for gRPC errors, keeping the client robust.
234-242: Error Handling forUpdateLease
Great job ensuringUpdateLeaseis covered by the same exception handling logic as other calls. This maintains consistency and reduces potential runtime failures.
247-251: Comprehensive Coverage forDeleteLease
Applying the context manager here completes the coverage, ensuring every gRPC call in the client is uniformly wrapped for exception translation.packages/jumpstarter-cli-client/jumpstarter_cli_client/client_login.py (2)
3-3: New OIDC Options Import
Addingopt_oidcto imports aligns with the consolidated OIDC approach for simpler CLI options handling.
39-39: Decorator-Based OIDC Integration
Using@opt_oidchere significantly streamlines authentication parameter gathering, reducing the complexity of individual command-line options.packages/jumpstarter/jumpstarter/config/client.py (11)
18-18: New gRPC Credential Import
Adoptingssl_channel_credentialsfromjumpstarter.common.grpchelps maintain a single authoritative source for TLS setups, preventing duplication of credential logic.
64-69: ExtendedleaseMethod with Default Duration
Addingduration: timedelta = timedelta(minutes=30)provides a sensible default while allowing customization. Ensures the user can manage leases without manually specifying a duration each time.
71-72: Passing Lease Duration to Async Context
Forwardingdurationtoself.lease_async(...)is coherent with the updated signature, guaranteeing consistent lease behavior across sync and async contexts.
112-112: DirectGetExporterReturn
Returning the awaited exporter simplifies flow and keeps the function concise. The approach aligns well with the rest of the client methods.
121-121: StreamlinedListExportersAccess
Likewise, directly returning the awaitedListExportersresult avoids extra layers and remains consistent with the updated pattern.
129-132: Simplified Lease Creation Call
Directly returning theCreateLeaseresult follows the same streamlined approach. This clarity improves readability.
135-137: Refined Delete Logic
Awaiting theDeleteLeasemethod and returning immediately is concise and consistent with the other lease operations.
142-142: Symmetry inListLeases
Returning the awaitedListLeasesaligns with the unified style where each method pass-through is concise.
146-146: Direct Return inUpdateLease
Following the established pattern, returning the updated lease object ensures consistent usage of the gRPC client.
153-153: Async Lease Method Receives Duration
Acceptingdurationin thelease_asyncsignature ensures the new default or custom lease duration is consistently applied.
168-168: Passing Duration in Lease Instantiation
Includingdurationin theLease(...)constructor finalizes the lease creation flow so that durations are mirrored between sync and async calls.packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (1)
49-50: Propagate original traceback by usingraise ... from e.This comment reiterates a prior suggestion: raising exceptions with
raise ... from ehelps keep the original traceback intact. Also, note thatHTTPErroris a subclass ofRequestException, so listing both may be redundant:-except (requests.exceptions.RequestException, requests.exceptions.HTTPError) as e: - raise CorelliumApiException(data.get('error', str(e))) +except requests.exceptions.RequestException as e: + raise CorelliumApiException(data.get('error', str(e))) from e🧰 Tools
🪛 Ruff (0.8.2)
50-50: Within an
exceptclause, raise exceptions withraise ... from errorraise ... from Noneto distinguish them from errors in exception handling(B904)
There was a problem hiding this comment.
Actionable comments posted: 2
🔭 Outside diff range comments (1)
packages/jumpstarter-driver-corellium/fixtures/http/json-error.json (1)
1-2:⚠️ Potential issueFix the malformed JSON error fixture
The JSON fixture is intentionally malformed for testing error handling, but it's not properly formed - it's missing a closing quote for the string value "a" and the closing brace.
Apply this diff to create a more realistic JSON parsing error:
-{"token": "a} +{"token": "a"}Alternatively, for a more realistic scenario with syntax errors:
-{"token": "a} +{"token": "a🧰 Tools
🪛 Biome (1.9.4)
[error] 1-1: Missing closing quote
The closing quote must be on the same line.
(parse)
[error] 1-1: expected
}but instead the file endsthe file ends here
(parse)
♻️ Duplicate comments (2)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver_test.py (1)
90-110:⚠️ Potential issueFix incorrect method call in power on error test
The test is calling
power.off()instead ofpower.on()which doesn't match the test name and intention.@pytest.mark.parametrize('mock_data', [ ({'login': {'side_effect': CorelliumApiException('login error')}}), ({'get_project': {'return_value': None}}), ({'get_instance': {'return_value': None}}), ({'create_instance': {'side_effect': CorelliumApiException('create error')}}), ]) def test_driver_power_on_error(monkeypatch, mock_data): monkeypatch.setenv('CORELLIUM_API_HOST', 'api-host') monkeypatch.setenv('CORELLIUM_API_TOKEN', 'api-token') project = Project('1', 'Default Project') instance = Instance(id='7f4f241c-821f-4219-905f-c3b50b0db5dd', state='on') root = Corellium(project_id='1', device_name='jmp', device_flavor='kronos', device_os='1.0') power = CorelliumPower(parent=root) with pytest.raises((CorelliumApiException, ValueError)): with (patch.object(root._api, 'login', **mock_data.get('login', {'return_value': None})), patch.object(root._api, 'get_project', **mock_data.get('get_project', {'return_value': project})), patch.object(root._api, 'get_instance', **mock_data.get('get_instance', {'return_value': instance})), patch.object(root._api, 'create_instance', **mock_data.get('create_instance', {'return_value': instance}))): - power.off() + power.on()🧰 Tools
🪛 Ruff (0.8.2)
100-100:
Projectmay be undefined, or defined from star imports(F405)
101-101:
Instancemay be undefined, or defined from star imports(F405)
109-109: Line too long (122 > 120)
(E501)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (1)
98-100: 🛠️ Refactor suggestionRevise session refresh logic.
Re-logging if there is still more than one second left before expiration can cause unnecessary logins. Consider inverting the condition or using a threshold (e.g. 60 seconds remaining) to avoid frequent re-authentications.
-if diff > timedelta(seconds=1): +if diff < timedelta(seconds=60): self._api.login()
🧹 Nitpick comments (11)
packages/jumpstarter-driver-corellium/README.md (1)
1-54: Add environment variable information to the READMEThe README is well-structured and informative, but it's missing crucial information about the required environment variables that are mentioned in the PR description.
Add a section about required environment variables:
# Corellium Jumpstarter Driver A Jumpstarter driver that manages virtual devices in [Corellium](https://corellium.com). It implements the following interfaces: * PowerInterface +## Prerequisites + +The driver requires the following environment variables to be set: + +* `CORELLIUM_API_HOST`: Corellium API host (e.g., app.corellium.com) +* `CORELLIUM_API_TOKEN`: Corellium API token for authentication + ## Usage Check the [examples folder](./examples) for example files.packages/jumpstarter-driver-power/jumpstarter_driver_power/client.py (2)
56-56: Remove trailing whitespaceThere's trailing whitespace at the end of this line.
-class VirtualPowerClient(PowerClient): +class VirtualPowerClient(PowerClient):🧰 Tools
🪛 Ruff (0.8.2)
56-56: Trailing whitespace
Remove trailing whitespace
(W291)
62-62: Remove whitespace from blank lineThis blank line contains unnecessary whitespace.
- +🧰 Tools
🪛 Ruff (0.8.2)
62-62: Blank line contains whitespace
Remove whitespace from blank line
(W293)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver_test.py (2)
9-10: Improve imports to avoid using star imports and remove unused importsUsing star imports makes it harder to track which symbols are being used and may introduce unnecessary dependencies. Also, some imports are not used.
-from .corellium.types import * -from .corellium.api import ApiClient +from .corellium.types import Project, Device, Instance, Session🧰 Tools
🪛 Ruff (0.8.2)
9-9:
from .corellium.types import *used; unable to detect undefined names(F403)
10-10:
.corellium.api.ApiClientimported but unusedRemove unused import:
.corellium.api.ApiClient(F401)
1-5: Remove unused importsThe imports for
osandrequests_mock(at line 5) are unused in this file. Therequests_mockis actually only used as a fixture parameter at line 61.-import os from unittest.mock import patch import pytest -import requests_mock from jumpstarter.common import exceptions as jmp_exceptions🧰 Tools
🪛 Ruff (0.8.2)
1-1:
osimported but unusedRemove unused import:
os(F401)
5-5:
requests_mockimported but unusedRemove unused import:
requests_mock(F401)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (3)
36-36: Remove trailing whitespace.Multiple lines in the file have trailing whitespace. Removing these extraneous spaces improves cleanliness and consistency.
-<line with trailing whitespace>·· +<line with trailing whitespace>Also applies to: 38-38, 48-48, 71-71, 87-87, 93-93, 115-115, 137-137, 153-153, 178-178, 188-188, 192-192, 200-200, 203-203
🧰 Tools
🪛 Ruff (0.8.2)
36-36: Trailing whitespace
Remove trailing whitespace
(W291)
180-183: Clarify docstring for theoffmethod.The docstring states it destroys the instance, but the method can also simply power it off if
destroyis False. Update wording to avoid confusion.-""" -Destroy a Corellium virtual device/instance. -""" +""" +Power off a Corellium virtual device/instance. +If `destroy` is True, the instance will also be destroyed. +"""
202-203: Return or raise a placeholder inreadmethod.As part of the
VirtualPowerInterface, this method should either return a properAsyncGenerator[PowerReading, None]or raiseNotImplementedErrorif not supported yet.Would you like me to help you generate a placeholder implementation that raises
NotImplementedError?🧰 Tools
🪛 Ruff (0.8.2)
203-203: Trailing whitespace
Remove trailing whitespace
(W291)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (2)
18-18: Remove trailing whitespace.Trailing whitespace is present on these lines. Removing them improves code consistency.
-<line with trailing whitespace>·· +<line with trailing whitespace>Also applies to: 28-28, 31-31, 131-131
🧰 Tools
🪛 Ruff (0.8.2)
18-18: Trailing whitespace
Remove trailing whitespace
(W291)
49-50: Chain exceptions for better traceback.When re-raising exceptions, use the
from esyntax to preserve the original context. This aids debugging by showing the full error chain.-except requests.exceptions.RequestException as e: - raise CorelliumApiException(data.get('error', str(e))) +except requests.exceptions.RequestException as e: + raise CorelliumApiException(data.get('error', str(e))) from eAlso applies to: 64-64, 83-83, 108-108, 123-123, 157-157, 171-171
🧰 Tools
🪛 Ruff (0.8.2)
50-50: Within an
exceptclause, raise exceptions withraise ... from errorraise ... from Noneto distinguish them from errors in exception handling(B904)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py (1)
131-131: Replacedict()calls with literal{}.Using
{}is more idiomatic, concise, and performant thandict()in Python for creating empty dictionaries.-quotas=dict() +quotas={}Also applies to: 152-152
🧰 Tools
🪛 Ruff (0.8.2)
131-131: Unnecessary
dict()call (rewrite as a literal)Rewrite as a literal
(C408)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (2)
packages/jumpstarter-driver-corellium/poetry.lockis excluded by!**/*.lockuv.lockis excluded by!**/*.lock
📒 Files selected for processing (24)
packages/jumpstarter-driver-corellium/README.md(1 hunks)packages/jumpstarter-driver-corellium/examples/exporter.yml(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/403.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/create-instance-200.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/create-instance-400.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/delete-instance-404.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/get-instance-state-200.txt(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/get-instance-state-404.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/get-models-200.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/get-projects-200.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/get-projects-404.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/json-error.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/login-200.json(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/client.py(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/exceptions.py(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/types.py(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver_test.py(1 hunks)packages/jumpstarter-driver-corellium/pyproject.toml(1 hunks)packages/jumpstarter-driver-power/jumpstarter_driver_power/client.py(1 hunks)packages/jumpstarter-driver-power/jumpstarter_driver_power/driver.py(1 hunks)pyproject.toml(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (17)
- packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/exceptions.py
- packages/jumpstarter-driver-corellium/fixtures/http/get-instance-state-200.txt
- packages/jumpstarter-driver-corellium/fixtures/http/create-instance-400.json
- packages/jumpstarter-driver-corellium/fixtures/http/get-projects-404.json
- packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/client.py
- packages/jumpstarter-driver-corellium/fixtures/http/403.json
- packages/jumpstarter-driver-corellium/fixtures/http/login-200.json
- packages/jumpstarter-driver-corellium/fixtures/http/delete-instance-404.json
- packages/jumpstarter-driver-corellium/fixtures/http/get-models-200.json
- packages/jumpstarter-driver-corellium/fixtures/http/get-projects-200.json
- packages/jumpstarter-driver-corellium/examples/exporter.yml
- packages/jumpstarter-driver-corellium/fixtures/http/create-instance-200.json
- packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/types.py
- packages/jumpstarter-driver-power/jumpstarter_driver_power/driver.py
- packages/jumpstarter-driver-corellium/pyproject.toml
- packages/jumpstarter-driver-corellium/fixtures/http/get-instance-state-404.json
- pyproject.toml
🧰 Additional context used
🧬 Code Definitions (3)
packages/jumpstarter-driver-power/jumpstarter_driver_power/client.py (8)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (1) (1)
off(180-199)packages/jumpstarter-driver-power/jumpstarter_driver_power/driver.py (4) (4)
off(17-17)off(32-32)off(58-59)off(86-87)packages/jumpstarter-driver-snmp/jumpstarter_driver_snmp/driver.py (1) (1)
off(201-203)packages/jumpstarter-driver-dutlink/jumpstarter_driver_dutlink/driver.py (2) (2)
off(131-132)off(189-190)packages/jumpstarter-driver-raspberrypi/jumpstarter_driver_raspberrypi/driver.py (1) (1)
off(29-33)packages/jumpstarter-driver-yepkit/jumpstarter_driver_yepkit/driver.py (1) (1)
off(117-120)packages/jumpstarter-driver-opendal/jumpstarter_driver_opendal/driver.py (2) (2)
off(247-247)off(275-276)packages/jumpstarter-driver-opendal/jumpstarter_driver_opendal/client.py (5) (5)
off(595-597)cli(399-513)cli(533-553)cli(623-647)cli(695-697)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (2)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/types.py (5) (5)
Session(9-22)Project(26-31)Device(35-47)Instance(51-56)as_header(16-22)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/exceptions.py (1) (1)
CorelliumApiException(7-10)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver_test.py (4)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (5) (5)
Corellium(20-101)CorelliumPower(105-203)api(81-101)on(142-177)off(180-199)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (1) (1)
ApiClient(9-171)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/exceptions.py (1) (1)
CorelliumApiException(7-10)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/types.py (4) (4)
Session(9-22)Project(26-31)Device(35-47)Instance(51-56)
🪛 Ruff (0.8.2)
packages/jumpstarter-driver-power/jumpstarter_driver_power/client.py
56-56: Trailing whitespace
Remove trailing whitespace
(W291)
62-62: Blank line contains whitespace
Remove whitespace from blank line
(W293)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py
36-36: Trailing whitespace
Remove trailing whitespace
(W291)
38-38: Trailing whitespace
Remove trailing whitespace
(W291)
48-48: Blank line contains whitespace
Remove whitespace from blank line
(W293)
71-71: Trailing whitespace
Remove trailing whitespace
(W291)
87-87: Trailing whitespace
Remove trailing whitespace
(W291)
93-93: Blank line contains whitespace
Remove whitespace from blank line
(W293)
115-115: Trailing whitespace
Remove trailing whitespace
(W291)
137-137: Blank line contains whitespace
Remove whitespace from blank line
(W293)
148-148: f-string without any placeholders
Remove extraneous f prefix
(F541)
153-153: Trailing whitespace
Remove trailing whitespace
(W291)
174-174: Trailing whitespace
Remove trailing whitespace
(W291)
178-178: Blank line contains whitespace
Remove whitespace from blank line
(W293)
188-188: Blank line contains whitespace
Remove whitespace from blank line
(W293)
192-192: f-string without any placeholders
Remove extraneous f prefix
(F541)
200-200: Blank line contains whitespace
Remove whitespace from blank line
(W293)
203-203: Trailing whitespace
Remove trailing whitespace
(W291)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py
4-4: requests_mock imported but unused
Remove unused import: requests_mock
(F401)
6-6: from .types import * used; unable to detect undefined names
(F403)
22-22: Redefinition of unused requests_mock from line 4
(F811)
35-35: Trailing whitespace
Remove trailing whitespace
(W291)
39-39: Redefinition of unused requests_mock from line 4
(F811)
39-39: Trailing whitespace
Remove trailing whitespace
(W291)
55-55: Redefinition of unused requests_mock from line 4
(F811)
58-58: Session may be undefined, or defined from star imports
(F405)
64-64: Blank line contains whitespace
Remove whitespace from blank line
(W293)
74-74: Trailing whitespace
Remove trailing whitespace
(W291)
78-78: Redefinition of unused requests_mock from line 4
(F811)
78-78: Trailing whitespace
Remove trailing whitespace
(W291)
81-81: Session may be undefined, or defined from star imports
(F405)
93-93: Redefinition of unused requests_mock from line 4
(F811)
96-96: Session may be undefined, or defined from star imports
(F405)
99-99: Blank line contains whitespace
Remove whitespace from blank line
(W293)
109-109: Trailing whitespace
Remove trailing whitespace
(W291)
112-112: Redefinition of unused requests_mock from line 4
(F811)
112-112: Trailing whitespace
Remove trailing whitespace
(W291)
115-115: Session may be undefined, or defined from star imports
(F405)
123-123: Redefinition of unused requests_mock from line 4
(F811)
127-127: Session may be undefined, or defined from star imports
(F405)
129-129: Project may be undefined, or defined from star imports
(F405)
130-130: Device may be undefined, or defined from star imports
(F405)
131-131: Unnecessary dict() call (rewrite as a literal)
Rewrite as a literal
(C408)
140-140: Trailing whitespace
Remove trailing whitespace
(W291)
144-144: Redefinition of unused requests_mock from line 4
(F811)
147-147: Session may be undefined, or defined from star imports
(F405)
149-149: Trailing whitespace
Remove trailing whitespace
(W291)
150-150: Project may be undefined, or defined from star imports
(F405)
151-151: Device may be undefined, or defined from star imports
(F405)
152-152: Unnecessary dict() call (rewrite as a literal)
Rewrite as a literal
(C408)
153-153: Local variable instance is assigned to but never used
Remove assignment to unused variable instance
(F841)
153-153: Line too long (123 > 120)
(E501)
158-158: Redefinition of unused requests_mock from line 4
(F811)
159-159: Instance may be undefined, or defined from star imports
(F405)
160-160: Blank line contains whitespace
Remove whitespace from blank line
(W293)
163-163: Session may be undefined, or defined from star imports
(F405)
169-169: Trailing whitespace
Remove trailing whitespace
(W291)
173-173: Redefinition of unused requests_mock from line 4
(F811)
173-173: Trailing whitespace
Remove trailing whitespace
(W291)
174-174: Instance may be undefined, or defined from star imports
(F405)
178-178: Session may be undefined, or defined from star imports
(F405)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py
18-18: Trailing whitespace
Remove trailing whitespace
(W291)
28-28: Trailing whitespace
Remove trailing whitespace
(W291)
31-31: Blank line contains whitespace
Remove whitespace from blank line
(W293)
50-50: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
64-64: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
83-83: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
108-108: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
123-123: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
131-131: Trailing whitespace
Remove trailing whitespace
(W291)
157-157: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
171-171: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver_test.py
1-1: os imported but unused
Remove unused import: os
(F401)
5-5: requests_mock imported but unused
Remove unused import: requests_mock
(F401)
9-9: from .corellium.types import * used; unable to detect undefined names
(F403)
10-10: .corellium.api.ApiClient imported but unused
Remove unused import: .corellium.api.ApiClient
(F401)
17-17: Blank line contains whitespace
Remove whitespace from blank line
(W293)
19-19: Blank line contains whitespace
Remove whitespace from blank line
(W293)
30-30: Trailing whitespace
Remove trailing whitespace
(W291)
32-32: Unnecessary dict() call (rewrite as a literal)
Rewrite as a literal
(C408)
36-36: Unnecessary dict() call (rewrite as a literal)
Rewrite as a literal
(C408)
40-40: Unnecessary dict() call (rewrite as a literal)
Rewrite as a literal
(C408)
44-44: Unnecessary dict() call (rewrite as a literal)
Rewrite as a literal
(C408)
51-51: Blank line contains whitespace
Remove whitespace from blank line
(W293)
57-57: Blank line contains whitespace
Remove whitespace from blank line
(W293)
61-61: Redefinition of unused requests_mock from line 5
(F811)
62-62: Line too long (129 > 120)
(E501)
68-68: Session may be undefined, or defined from star imports
(F405)
75-75: Project may be undefined, or defined from star imports
(F405)
76-76: Device may be undefined, or defined from star imports
(F405)
77-77: Unnecessary dict() call (rewrite as a literal)
Rewrite as a literal
(C408)
78-78: Instance may be undefined, or defined from star imports
(F405)
100-100: Project may be undefined, or defined from star imports
(F405)
101-101: Instance may be undefined, or defined from star imports
(F405)
109-109: Line too long (122 > 120)
(E501)
117-117: Project may be undefined, or defined from star imports
(F405)
118-118: Instance may be undefined, or defined from star imports
(F405)
121-121: Blank line contains whitespace
Remove whitespace from blank line
(W293)
122-122: Trailing whitespace
Remove trailing whitespace
(W291)
125-125: Instance may be undefined, or defined from star imports
(F405)
139-139: Project may be undefined, or defined from star imports
(F405)
140-140: Instance may be undefined, or defined from star imports
(F405)
143-143: Blank line contains whitespace
Remove whitespace from blank line
(W293)
147-147: Line too long (122 > 120)
(E501)
148-148: Line too long (124 > 120)
(E501)
🪛 Biome (1.9.4)
packages/jumpstarter-driver-corellium/fixtures/http/json-error.json
[error] 1-1: Missing closing quote
The closing quote must be on the same line.
(parse)
[error] 1-1: expected } but instead the file ends
the file ends here
(parse)
🔇 Additional comments (3)
packages/jumpstarter-driver-power/jumpstarter_driver_power/client.py (1)
56-69: The VirtualPowerClient implementation looks goodThis implementation properly extends the PowerClient class with virtual device capabilities. It overrides the
offmethod to add adestroyparameter and enhances the CLI with a--destroyoption. The explicit naming withname='off'clearly indicates that it's intentionally overriding the parent's command.🧰 Tools
🪛 Ruff (0.8.2)
56-56: Trailing whitespace
Remove trailing whitespace
(W291)
62-62: Blank line contains whitespace
Remove whitespace from blank line
(W293)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver_test.py (1)
1-150: Comprehensive test coverage looks goodThe test suite provides excellent coverage for the Corellium driver functionality, including initialization, API client functionality, and both the power on and power off operations. The parametrized tests for error conditions are particularly valuable for ensuring the driver handles various failure scenarios correctly.
🧰 Tools
🪛 Ruff (0.8.2)
1-1:
osimported but unusedRemove unused import:
os(F401)
5-5:
requests_mockimported but unusedRemove unused import:
requests_mock(F401)
9-9:
from .corellium.types import *used; unable to detect undefined names(F403)
10-10:
.corellium.api.ApiClientimported but unusedRemove unused import:
.corellium.api.ApiClient(F401)
17-17: Blank line contains whitespace
Remove whitespace from blank line
(W293)
19-19: Blank line contains whitespace
Remove whitespace from blank line
(W293)
30-30: Trailing whitespace
Remove trailing whitespace
(W291)
32-32: Unnecessary
dict()call (rewrite as a literal)Rewrite as a literal
(C408)
36-36: Unnecessary
dict()call (rewrite as a literal)Rewrite as a literal
(C408)
40-40: Unnecessary
dict()call (rewrite as a literal)Rewrite as a literal
(C408)
44-44: Unnecessary
dict()call (rewrite as a literal)Rewrite as a literal
(C408)
51-51: Blank line contains whitespace
Remove whitespace from blank line
(W293)
57-57: Blank line contains whitespace
Remove whitespace from blank line
(W293)
61-61: Redefinition of unused
requests_mockfrom line 5(F811)
62-62: Line too long (129 > 120)
(E501)
68-68:
Sessionmay be undefined, or defined from star imports(F405)
75-75:
Projectmay be undefined, or defined from star imports(F405)
76-76:
Devicemay be undefined, or defined from star imports(F405)
77-77: Unnecessary
dict()call (rewrite as a literal)Rewrite as a literal
(C408)
78-78:
Instancemay be undefined, or defined from star imports(F405)
100-100:
Projectmay be undefined, or defined from star imports(F405)
101-101:
Instancemay be undefined, or defined from star imports(F405)
109-109: Line too long (122 > 120)
(E501)
117-117:
Projectmay be undefined, or defined from star imports(F405)
118-118:
Instancemay be undefined, or defined from star imports(F405)
121-121: Blank line contains whitespace
Remove whitespace from blank line
(W293)
122-122: Trailing whitespace
Remove trailing whitespace
(W291)
125-125:
Instancemay be undefined, or defined from star imports(F405)
139-139:
Projectmay be undefined, or defined from star imports(F405)
140-140:
Instancemay be undefined, or defined from star imports(F405)
143-143: Blank line contains whitespace
Remove whitespace from blank line
(W293)
147-147: Line too long (122 > 120)
(E501)
148-148: Line too long (124 > 120)
(E501)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (1)
158-160: Mismatch in error message and variable reference.You're referencing
self.parent.device_model, but onlyself.parent.device_flavoris defined. Also, you have curly braces but no f-string prefix, so the variable won't interpolate.- raise ValueError('Unable to find a device for this model: {self.parent.device_model}') + raise ValueError(f'Unable to find a device for this flavor: {self.parent.device_flavor}')
| import os | ||
|
|
||
| import pytest | ||
| import requests_mock |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Avoid shadowing the requests_mock import.
The import here is overshadowed by the fixture parameter of the same name. Consider removing this top-level import or renaming the parameter if needed, to reduce confusion.
-import requests_mock📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| import requests_mock |
🧰 Tools
🪛 Ruff (0.8.2)
4-4: requests_mock imported but unused
Remove unused import: requests_mock
(F401)
|
|
||
| @dataclass(kw_only=True) | ||
| class Corellium(Driver): | ||
| """ |
There was a problem hiding this comment.
How does the exporter driver behave if for example, it had crashed, an instance remains running on the cloud, and the exporter starts again.
Would it stop the instance (I believe it doesn't) or would it keep it running?
Would it make sense that in the reset() (called when the instance of the driver is created on exporter boot) method that you can implement in the driver it ensures a clean state (no leftover instance running, etc...)
You also have close() which is called at the end of a session/lease, in most cases you should do the same thing in both.
There was a problem hiding this comment.
Eventually, @NickCao comments, we may want to make the reset method exposed to clients, i.e. to bring up a driver to the default state. So the reset method can be called multiple times within a session.
There was a problem hiding this comment.
I assumed you could simply invoke power off and on to "reset" it.
I there another interface that implements a "reset" method?
There was a problem hiding this comment.
It's not a "reset" call, is a method that the drivers implement to provide a way to bring them to a clean state, it's used internally by the exporter at the start/end of a lease.
There was a problem hiding this comment.
Actionable comments posted: 0
🔭 Outside diff range comments (1)
packages/jumpstarter-driver-corellium/fixtures/http/json-error.json (1)
1-2:⚠️ Potential issueFix malformed JSON in test fixture
The JSON fixture has syntax errors: missing closing quote for the string value and missing closing brace.
-{"token": "a} +{"token": "a"}🧰 Tools
🪛 Biome (1.9.4)
[error] 1-1: Missing closing quote
The closing quote must be on the same line.
(parse)
[error] 1-1: expected
}but instead the file endsthe file ends here
(parse)
♻️ Duplicate comments (1)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver_test.py (1)
90-110:⚠️ Potential issueFix incorrect method call in power on error test
The test is calling
power.off()instead ofpower.on()which doesn't match the test name and intention.@pytest.mark.parametrize('mock_data', [ ({'login': {'side_effect': CorelliumApiException('login error')}}), ({'get_project': {'return_value': None}}), ({'get_instance': {'return_value': None}}), ({'create_instance': {'side_effect': CorelliumApiException('create error')}}), ]) def test_driver_power_on_error(monkeypatch, mock_data): monkeypatch.setenv('CORELLIUM_API_HOST', 'api-host') monkeypatch.setenv('CORELLIUM_API_TOKEN', 'api-token') project = Project('1', 'Default Project') instance = Instance(id='7f4f241c-821f-4219-905f-c3b50b0db5dd', state='on') root = Corellium(project_id='1', device_name='jmp', device_flavor='kronos', device_os='1.0') power = CorelliumPower(parent=root) with pytest.raises((CorelliumApiException, ValueError)): with (patch.object(root._api, 'login', **mock_data.get('login', {'return_value': None})), patch.object(root._api, 'get_project', **mock_data.get('get_project', {'return_value': project})), patch.object(root._api, 'get_instance', **mock_data.get('get_instance', {'return_value': instance})), patch.object(root._api, 'create_instance', **mock_data.get('create_instance', {'return_value': instance}))): - power.off() + power.on()🧰 Tools
🪛 Ruff (0.8.2)
100-100:
Projectmay be undefined, or defined from star imports(F405)
101-101:
Instancemay be undefined, or defined from star imports(F405)
109-109: Line too long (122 > 120)
(E501)
🧹 Nitpick comments (6)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver_test.py (1)
1-10: Clean up importsThere are several unused imports and star imports that could be improved.
import os from unittest.mock import patch import pytest -import requests_mock from jumpstarter.common import exceptions as jmp_exceptions from .driver import Corellium, CorelliumPower -from .corellium.types import * -from .corellium.api import ApiClient +from .corellium.types import Project, Device, Instance, Session from .corellium.exceptions import CorelliumApiException🧰 Tools
🪛 Ruff (0.8.2)
1-1:
osimported but unusedRemove unused import:
os(F401)
5-5:
requests_mockimported but unusedRemove unused import:
requests_mock(F401)
9-9:
from .corellium.types import *used; unable to detect undefined names(F403)
10-10:
.corellium.api.ApiClientimported but unusedRemove unused import:
.corellium.api.ApiClient(F401)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (2)
148-148: Remove extraneousfprefix in log string.No placeholders are used in the string literal. Removing the
fprefix avoids confusion and addresses the static analysis warning.- self.logger.info(f'Corellium Device:') + self.logger.info('Corellium Device:')🧰 Tools
🪛 Ruff (0.8.2)
148-148: f-string without any placeholders
Remove extraneous
fprefix(F541)
201-203: Implement or provide a placeholder forreadmethod.This method is currently unimplemented and silently passed. Consider raising
NotImplementedErroror returning a helpful message explaining why it's not supported.Would you like me to provide a code snippet that raises
NotImplementedErrorhere?🧰 Tools
🪛 Ruff (0.8.2)
203-203: Trailing whitespace
Remove trailing whitespace
(W291)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (1)
131-131: Resolve trailing whitespace.Remove trailing whitespace to maintain a clean codebase.
🧰 Tools
🪛 Ruff (0.8.2)
131-131: Trailing whitespace
Remove trailing whitespace
(W291)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py (2)
4-4: Remove unusedrequests_mockimport.This import shadows the fixture and is not used at the module level, leading to warnings.
-import requests_mock🧰 Tools
🪛 Ruff (0.8.2)
4-4:
requests_mockimported but unusedRemove unused import:
requests_mock(F401)
131-131: Use literal braces instead ofdict().This minor refactor improves readability and aligns with Python best practices.
- description='', model='kronos', peripherals=False, quotas=dict()) + description='', model='kronos', peripherals=False, quotas={})🧰 Tools
🪛 Ruff (0.8.2)
131-131: Unnecessary
dict()call (rewrite as a literal)Rewrite as a literal
(C408)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (2)
packages/jumpstarter-driver-corellium/poetry.lockis excluded by!**/*.lockuv.lockis excluded by!**/*.lock
📒 Files selected for processing (24)
packages/jumpstarter-driver-corellium/README.md(1 hunks)packages/jumpstarter-driver-corellium/examples/exporter.yml(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/403.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/create-instance-200.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/create-instance-400.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/delete-instance-404.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/get-instance-state-200.txt(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/get-instance-state-404.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/get-models-200.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/get-projects-200.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/get-projects-404.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/json-error.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/login-200.json(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/client.py(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/exceptions.py(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/types.py(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver_test.py(1 hunks)packages/jumpstarter-driver-corellium/pyproject.toml(1 hunks)packages/jumpstarter-driver-power/jumpstarter_driver_power/client.py(1 hunks)packages/jumpstarter-driver-power/jumpstarter_driver_power/driver.py(1 hunks)pyproject.toml(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (17)
- packages/jumpstarter-driver-corellium/fixtures/http/login-200.json
- packages/jumpstarter-driver-corellium/fixtures/http/get-instance-state-200.txt
- pyproject.toml
- packages/jumpstarter-driver-corellium/fixtures/http/get-projects-404.json
- packages/jumpstarter-driver-corellium/fixtures/http/get-models-200.json
- packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/exceptions.py
- packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/client.py
- packages/jumpstarter-driver-corellium/fixtures/http/403.json
- packages/jumpstarter-driver-corellium/README.md
- packages/jumpstarter-driver-corellium/fixtures/http/delete-instance-404.json
- packages/jumpstarter-driver-corellium/fixtures/http/get-projects-200.json
- packages/jumpstarter-driver-corellium/fixtures/http/create-instance-200.json
- packages/jumpstarter-driver-corellium/fixtures/http/create-instance-400.json
- packages/jumpstarter-driver-corellium/examples/exporter.yml
- packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/types.py
- packages/jumpstarter-driver-corellium/fixtures/http/get-instance-state-404.json
- packages/jumpstarter-driver-power/jumpstarter_driver_power/driver.py
🧰 Additional context used
🧬 Code Definitions (4)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (2)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/types.py (5)
Session(9-22)Project(26-31)Device(35-47)Instance(51-56)as_header(16-22)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 (6)
ApiClient(9-171)login(32-53)get_project(55-70)get_device(72-89)create_instance(91-110)destroy_instance(159-171)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/exceptions.py (1)
CorelliumApiException(7-10)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/types.py (5)
as_header(16-22)Session(9-22)Project(26-31)Device(35-47)Instance(51-56)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver_test.py (4)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (5)
Corellium(20-101)CorelliumPower(105-203)api(81-101)on(142-177)off(180-199)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (1)
ApiClient(9-171)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/exceptions.py (1)
CorelliumApiException(7-10)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/types.py (4)
Session(9-22)Project(26-31)Device(35-47)Instance(51-56)
packages/jumpstarter-driver-power/jumpstarter_driver_power/client.py (6)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (1)
off(180-199)packages/jumpstarter-driver-power/jumpstarter_driver_power/driver.py (4)
off(17-17)off(32-32)off(58-59)off(86-87)packages/jumpstarter-driver-snmp/jumpstarter_driver_snmp/driver.py (1)
off(201-203)packages/jumpstarter-driver-dutlink/jumpstarter_driver_dutlink/driver.py (2)
off(131-132)off(189-190)packages/jumpstarter-driver-raspberrypi/jumpstarter_driver_raspberrypi/client.py (1)
off(8-9)packages/jumpstarter-driver-yepkit/jumpstarter_driver_yepkit/driver.py (1)
off(117-120)
🪛 Ruff (0.8.2)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py
18-18: Trailing whitespace
Remove trailing whitespace
(W291)
28-28: Trailing whitespace
Remove trailing whitespace
(W291)
31-31: Blank line contains whitespace
Remove whitespace from blank line
(W293)
50-50: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
64-64: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
83-83: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
108-108: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
123-123: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
131-131: Trailing whitespace
Remove trailing whitespace
(W291)
157-157: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
171-171: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py
36-36: Trailing whitespace
Remove trailing whitespace
(W291)
38-38: Trailing whitespace
Remove trailing whitespace
(W291)
48-48: Blank line contains whitespace
Remove whitespace from blank line
(W293)
71-71: Trailing whitespace
Remove trailing whitespace
(W291)
87-87: Trailing whitespace
Remove trailing whitespace
(W291)
93-93: Blank line contains whitespace
Remove whitespace from blank line
(W293)
115-115: Trailing whitespace
Remove trailing whitespace
(W291)
137-137: Blank line contains whitespace
Remove whitespace from blank line
(W293)
148-148: f-string without any placeholders
Remove extraneous f prefix
(F541)
153-153: Trailing whitespace
Remove trailing whitespace
(W291)
174-174: Trailing whitespace
Remove trailing whitespace
(W291)
178-178: Blank line contains whitespace
Remove whitespace from blank line
(W293)
188-188: Blank line contains whitespace
Remove whitespace from blank line
(W293)
192-192: f-string without any placeholders
Remove extraneous f prefix
(F541)
200-200: Blank line contains whitespace
Remove whitespace from blank line
(W293)
203-203: Trailing whitespace
Remove trailing whitespace
(W291)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py
4-4: requests_mock imported but unused
Remove unused import: requests_mock
(F401)
6-6: from .types import * used; unable to detect undefined names
(F403)
22-22: Redefinition of unused requests_mock from line 4
(F811)
35-35: Trailing whitespace
Remove trailing whitespace
(W291)
39-39: Redefinition of unused requests_mock from line 4
(F811)
39-39: Trailing whitespace
Remove trailing whitespace
(W291)
55-55: Redefinition of unused requests_mock from line 4
(F811)
58-58: Session may be undefined, or defined from star imports
(F405)
64-64: Blank line contains whitespace
Remove whitespace from blank line
(W293)
74-74: Trailing whitespace
Remove trailing whitespace
(W291)
78-78: Redefinition of unused requests_mock from line 4
(F811)
78-78: Trailing whitespace
Remove trailing whitespace
(W291)
81-81: Session may be undefined, or defined from star imports
(F405)
93-93: Redefinition of unused requests_mock from line 4
(F811)
96-96: Session may be undefined, or defined from star imports
(F405)
99-99: Blank line contains whitespace
Remove whitespace from blank line
(W293)
109-109: Trailing whitespace
Remove trailing whitespace
(W291)
112-112: Redefinition of unused requests_mock from line 4
(F811)
112-112: Trailing whitespace
Remove trailing whitespace
(W291)
115-115: Session may be undefined, or defined from star imports
(F405)
123-123: Redefinition of unused requests_mock from line 4
(F811)
127-127: Session may be undefined, or defined from star imports
(F405)
129-129: Project may be undefined, or defined from star imports
(F405)
130-130: Device may be undefined, or defined from star imports
(F405)
131-131: Unnecessary dict() call (rewrite as a literal)
Rewrite as a literal
(C408)
140-140: Trailing whitespace
Remove trailing whitespace
(W291)
144-144: Redefinition of unused requests_mock from line 4
(F811)
147-147: Session may be undefined, or defined from star imports
(F405)
149-149: Trailing whitespace
Remove trailing whitespace
(W291)
150-150: Project may be undefined, or defined from star imports
(F405)
151-151: Device may be undefined, or defined from star imports
(F405)
152-152: Unnecessary dict() call (rewrite as a literal)
Rewrite as a literal
(C408)
153-153: Local variable instance is assigned to but never used
Remove assignment to unused variable instance
(F841)
153-153: Line too long (123 > 120)
(E501)
158-158: Redefinition of unused requests_mock from line 4
(F811)
159-159: Instance may be undefined, or defined from star imports
(F405)
160-160: Blank line contains whitespace
Remove whitespace from blank line
(W293)
163-163: Session may be undefined, or defined from star imports
(F405)
169-169: Trailing whitespace
Remove trailing whitespace
(W291)
173-173: Redefinition of unused requests_mock from line 4
(F811)
173-173: Trailing whitespace
Remove trailing whitespace
(W291)
174-174: Instance may be undefined, or defined from star imports
(F405)
178-178: Session may be undefined, or defined from star imports
(F405)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver_test.py
1-1: os imported but unused
Remove unused import: os
(F401)
5-5: requests_mock imported but unused
Remove unused import: requests_mock
(F401)
9-9: from .corellium.types import * used; unable to detect undefined names
(F403)
10-10: .corellium.api.ApiClient imported but unused
Remove unused import: .corellium.api.ApiClient
(F401)
17-17: Blank line contains whitespace
Remove whitespace from blank line
(W293)
19-19: Blank line contains whitespace
Remove whitespace from blank line
(W293)
30-30: Trailing whitespace
Remove trailing whitespace
(W291)
32-32: Unnecessary dict() call (rewrite as a literal)
Rewrite as a literal
(C408)
36-36: Unnecessary dict() call (rewrite as a literal)
Rewrite as a literal
(C408)
40-40: Unnecessary dict() call (rewrite as a literal)
Rewrite as a literal
(C408)
44-44: Unnecessary dict() call (rewrite as a literal)
Rewrite as a literal
(C408)
51-51: Blank line contains whitespace
Remove whitespace from blank line
(W293)
57-57: Blank line contains whitespace
Remove whitespace from blank line
(W293)
61-61: Redefinition of unused requests_mock from line 5
(F811)
62-62: Line too long (129 > 120)
(E501)
68-68: Session may be undefined, or defined from star imports
(F405)
75-75: Project may be undefined, or defined from star imports
(F405)
76-76: Device may be undefined, or defined from star imports
(F405)
77-77: Unnecessary dict() call (rewrite as a literal)
Rewrite as a literal
(C408)
78-78: Instance may be undefined, or defined from star imports
(F405)
100-100: Project may be undefined, or defined from star imports
(F405)
101-101: Instance may be undefined, or defined from star imports
(F405)
109-109: Line too long (122 > 120)
(E501)
117-117: Project may be undefined, or defined from star imports
(F405)
118-118: Instance may be undefined, or defined from star imports
(F405)
121-121: Blank line contains whitespace
Remove whitespace from blank line
(W293)
122-122: Trailing whitespace
Remove trailing whitespace
(W291)
125-125: Instance may be undefined, or defined from star imports
(F405)
139-139: Project may be undefined, or defined from star imports
(F405)
140-140: Instance may be undefined, or defined from star imports
(F405)
143-143: Blank line contains whitespace
Remove whitespace from blank line
(W293)
147-147: Line too long (122 > 120)
(E501)
148-148: Line too long (124 > 120)
(E501)
packages/jumpstarter-driver-power/jumpstarter_driver_power/client.py
56-56: Trailing whitespace
Remove trailing whitespace
(W291)
62-62: Blank line contains whitespace
Remove whitespace from blank line
(W293)
🪛 Biome (1.9.4)
packages/jumpstarter-driver-corellium/fixtures/http/json-error.json
[error] 1-1: Missing closing quote
The closing quote must be on the same line.
(parse)
[error] 1-1: expected } but instead the file ends
the file ends here
(parse)
🔇 Additional comments (7)
packages/jumpstarter-driver-power/jumpstarter_driver_power/client.py (1)
63-67: Command redefinition issue in cli methodThe
offcommand is being redefined in the child class with the same name as in the parent class. This will override the parent's command, which may lead to unexpected behavior.Consider using a different command name for the virtual power client's off functionality:
- @parent.command(name='off') - @click.option('--destroy', is_flag=True, help='destroy the instance after powering it off') - def off(destroy: bool): + @parent.command(name='off-virtual') + @click.option('--destroy', is_flag=True, help='destroy the instance after powering it off') + def off_virtual(destroy: bool): """Power off""" self.off(destroy)Alternatively, if you want to completely replace the parent's
offcommand, make it explicit in your documentation.packages/jumpstarter-driver-corellium/pyproject.toml (1)
1-40: LGTM - Package configuration looks goodThe pyproject.toml configuration is well-structured with appropriate dependencies and entry points for the new Corellium driver.
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (2)
98-99: Revisit session refresh logic.The current check will re-login if there's more than 1 second left before expiration, which is counterintuitive. Typically, you'd want to re-login only if the remaining time is less than a threshold (e.g., 60 seconds). This might cause unnecessary extra logins.
158-160: Fix mismatched device attribute.This error message references
self.parent.device_modelinstead ofdevice_flavor, which appears to be the actual attribute.packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (1)
50-50: Chain the original exception for full traceback.When re-raising an exception, use
raise ... from eto aid debugging and keep the original traceback.- raise CorelliumApiException(data.get('error', str(e))) + raise CorelliumApiException(data.get('error', str(e))) from e🧰 Tools
🪛 Ruff (0.8.2)
50-50: Within an
exceptclause, raise exceptions withraise ... from errorraise ... from Noneto distinguish them from errors in exception handling(B904)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py (2)
6-6: Avoidfrom .types import *.Using bulk imports can cause namespace pollution and make debugging harder. Import explicit symbols instead.
🧰 Tools
🪛 Ruff (0.8.2)
6-6:
from .types import *used; unable to detect undefined names(F403)
158-165: Add assertions to validate instance destruction.Currently, there's no assertion to confirm that the
destroy_instancecall succeeded. Adding a simple verification (e.g., that the mock was called as expected) would help ensure correctness.🧰 Tools
🪛 Ruff (0.8.2)
158-158: Redefinition of unused
requests_mockfrom line 4(F811)
159-159:
Instancemay be undefined, or defined from star imports(F405)
160-160: Blank line contains whitespace
Remove whitespace from blank line
(W293)
163-163:
Sessionmay be undefined, or defined from star imports(F405)
|
Ok, I think it's a good start, I checked the power on / power off, we need to continue working to provide:
Thanks @odra ! :) |
|
argh, the linter now: https://github.com/jumpstarter-dev/jumpstarter/actions/runs/14264211252/job/39987282736?pr=351#step:3:14 you can fix with uv run ruff check --fix also a couple of typos: https://github.com/jumpstarter-dev/jumpstarter/actions/runs/14264211220/job/39987282761?pr=351 |
There was a problem hiding this comment.
Actionable comments posted: 0
🔭 Outside diff range comments (1)
packages/jumpstarter-driver-corellium/fixtures/http/json-error.json (1)
1-2:⚠️ Potential issueFix malformed JSON in test fixture.
The JSON in this file is malformed. It has an unclosed string value and is missing a closing curly brace. This will cause parsing errors when used.
Apply this fix:
-{"token": "a} +{"token": "a"}🧰 Tools
🪛 Biome (1.9.4)
[error] 1-1: Missing closing quote
The closing quote must be on the same line.
(parse)
[error] 1-1: expected
}but instead the file endsthe file ends here
(parse)
♻️ Duplicate comments (5)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (5)
94-100:⚠️ Potential issueSession refresh logic is inverted.
The current logic refreshes the session when it has more than 1 second left, which is the opposite of what's intended. You should refresh when there's less than a threshold of time remaining (e.g., 60 seconds).
- if diff > timedelta(seconds=1): + # Re-login if there's less than 60 seconds left in the session + if diff < timedelta(seconds=60): self._api.login()
141-147:⚠️ Potential issueAdd async keyword to match abstract method.
The
onmethod should be async to match the VirtualPowerInterface abstract method declaration.- @export - def on(self) -> None: + @export + async def on(self) -> None:
179-183:⚠️ Potential issueAdd async keyword and improve docstring.
The
offmethod should be async to match the VirtualPowerInterface abstract method declaration, and the docstring should better explain thedestroyparameter.- @export - def off(self, destroy: bool = False) -> None: + @export + async def off(self, destroy: bool = False) -> None: """ - Destroy a Corellium virtual device/instance. + Power off a Corellium virtual device/instance. + + Args: + destroy: If True, destroy the instance after powering off. + If False, just power it off. """
201-203:⚠️ Potential issueImplement the read method properly.
The
readmethod is defined but not implemented. Since it's exported and part of the interface, it should be implemented or at least raiseNotImplementedError.- @export - def read(self) -> AsyncGenerator[PowerReading, None]: - pass + @export + async def read(self) -> AsyncGenerator[PowerReading, None]: + """ + Read power measurements from the device. + + This method is not implemented for Corellium devices. + """ + raise NotImplementedError("Power readings are not available for Corellium devices")
160-160:⚠️ Potential issueFix f-string missing f-prefix in error message.
There's a missing f-prefix in the error message that references a variable.
- raise ValueError('Unable to find a device for this model: {self.parent.device_model}') + raise ValueError(f'Unable to find a device for this model: {self.parent.device_flavor}')Additionally, the error message refers to
device_modelbut the actual attribute isdevice_flavor, which is inconsistent.
🧹 Nitpick comments (14)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (5)
49-49: Fix typo in docstring.There's a typo in the word "varibales" which should be "variables".
- Additionally, it also sets up some internal objects/varibales such as: + Additionally, it also sets up some internal objects/variables such as:
70-71: Fix indentation inconsistency.The indentation is inconsistent with the rest of the file (3 spaces instead of 4).
- if value is None: - raise jmp_exceptions.ConfigurationError(f'Missing "{name}" environment variable') + if value is None: + raise jmp_exceptions.ConfigurationError(f'Missing "{name}" environment variable')
86-86: Fix typo in docstring.There's a typo in the word "accross" which should be "across".
- accross diferent API methods that require authentication. + across different API methods that require authentication.
118-120: Ensure consistent type handling for timeout settings.The
retriesvalue is being converted to int, butintervalis left as a string. Both should have consistent type handling.- 'interval': os.environ.get('CORELLIUM_API_INTERVAL', 5) + 'interval': int(os.environ.get('CORELLIUM_API_INTERVAL', 5))
132-133: Fix grammatical error in error message.There's a grammatical error "to be reach" in the error message.
- raise ValueError(f'Instance took too long to be reach the desired state: {current}') + raise ValueError(f'Instance took too long to reach the desired state: {current.id}')packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (5)
16-24: Use a consistent session approach for login requests.Currently, the
loginmethod callsrequests.post(...)directly instead of usingself.req.post(...). This can lead to inconsistencies in session handling (e.g., cookies, headers).- res = requests.post(f'{self.baseurl}/v1/auth/login', json=data) + res = self.req.post(f'{self.baseurl}/v1/auth/login', json=data)
45-50: Handle JSON parsing exceptions separately.If the remote server returns invalid JSON,
res.json()will raise aJSONDecodeError, which is not covered byrequests.exceptions.RequestException. This could result indatabeing undefined in the except block.try: res = self.req.post(f'{self.baseurl}/v1/auth/login', json=data) + # Handle JSON parsing errors distinctly + try: + data = res.json() + except ValueError as parse_err: + raise CorelliumApiException("Invalid JSON response") from parse_err res.raise_for_status() except (requests.exceptions.RequestException, requests.exceptions.HTTPError) as e: ...
59-70: Consider adding defensive checks for project data fields.The code assumes the response objects always have
'name'and'id'. If the API response is malformed or missing keys, this can raise aKeyError.for project in data: - if project['name'] == project_ref or project['id'] == project_ref: + if project.get('name') == project_ref or project.get('id') == project_ref:
78-90: Validate device keys in the response.Similarly, in
get_device, the code assumes'model'is always present. If the API’s response is incomplete, it may raise aKeyError.for device in data: - if device['model'] == model: + if device.get('model') == model:
131-146: Add validation for instance states before making PUT requests.When calling
set_instance_state(...), an invalid state (e.g., a typo) might be sent to the server. Adding a validation step or at least logging a warning could reduce potential errors or confusion.valid_states = {"on", "off", "booting", "deleting", "creating", "restoring", "paused", "rebooting", "error"} if instance_state not in valid_states: raise ValueError(f"Invalid instance state: {instance_state}")packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py (4)
21-30: Add coverage for environment-based credentials.All tests pass explicit host and token. If you plan to support environment variables (
CORELLIUM_API_HOSTandCORELLIUM_API_TOKEN), consider a test scenario for cases where these environment variables are used as fallback.
106-120: Add a negative test for unrecognized device model.There’s already partial coverage, but you could strengthen negative tests by verifying the error message when
get_device('nonexistent-model')receives an unexpected format from the server. Currently, only a 403 scenario is tested.
157-164: Verify the DELETE request invocation in the success scenario.Although the code calls
destroy_instance, adding an assertion to confirm that the correct DELETE request was made (URL, method) makes the test more robust.api.destroy_instance(instance) +assert requests_mock.last_request.method == 'DELETE' +assert requests_mock.last_request.url.endswith(f'/v1/instances/{instance.id}')
1-183: Optional: Add a dedicated test forset_instance_state.It appears
set_instance_stateis untested. Consider adding a test to ensure correct behavior for valid states (e.g., "on") and invalid states (e.g., "foo").
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (2)
packages/jumpstarter-driver-corellium/poetry.lockis excluded by!**/*.lockuv.lockis excluded by!**/*.lock
📒 Files selected for processing (24)
packages/jumpstarter-driver-corellium/README.md(1 hunks)packages/jumpstarter-driver-corellium/examples/exporter.yml(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/403.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/create-instance-200.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/create-instance-400.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/delete-instance-404.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/get-instance-state-200.txt(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/get-instance-state-404.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/get-models-200.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/get-projects-200.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/get-projects-404.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/json-error.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/login-200.json(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/client.py(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/exceptions.py(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/types.py(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver_test.py(1 hunks)packages/jumpstarter-driver-corellium/pyproject.toml(1 hunks)packages/jumpstarter-driver-power/jumpstarter_driver_power/client.py(1 hunks)packages/jumpstarter-driver-power/jumpstarter_driver_power/driver.py(1 hunks)pyproject.toml(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (18)
- packages/jumpstarter-driver-corellium/fixtures/http/get-instance-state-200.txt
- packages/jumpstarter-driver-corellium/fixtures/http/403.json
- packages/jumpstarter-driver-corellium/fixtures/http/create-instance-400.json
- packages/jumpstarter-driver-corellium/fixtures/http/get-projects-404.json
- pyproject.toml
- packages/jumpstarter-driver-corellium/fixtures/http/create-instance-200.json
- packages/jumpstarter-driver-corellium/fixtures/http/get-models-200.json
- packages/jumpstarter-driver-corellium/fixtures/http/get-instance-state-404.json
- packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/client.py
- packages/jumpstarter-driver-corellium/fixtures/http/get-projects-200.json
- packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver_test.py
- packages/jumpstarter-driver-corellium/pyproject.toml
- packages/jumpstarter-driver-corellium/fixtures/http/delete-instance-404.json
- packages/jumpstarter-driver-corellium/examples/exporter.yml
- packages/jumpstarter-driver-power/jumpstarter_driver_power/driver.py
- packages/jumpstarter-driver-corellium/README.md
- packages/jumpstarter-driver-corellium/fixtures/http/login-200.json
- packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/exceptions.py
🧰 Additional context used
🧬 Code Definitions (2)
packages/jumpstarter-driver-power/jumpstarter_driver_power/client.py (2)
packages/jumpstarter-driver-power/jumpstarter_driver_power/driver.py (4)
off(17-17)off(32-32)off(58-59)off(86-87)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (1)
off(180-199)
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 (5)
Device(35-47)Instance(51-56)Project(26-31)Session(9-22)as_header(16-22)
🪛 Biome (1.9.4)
packages/jumpstarter-driver-corellium/fixtures/http/json-error.json
[error] 1-1: Missing closing quote
The closing quote must be on the same line.
(parse)
[error] 1-1: expected } but instead the file ends
the file ends here
(parse)
🔇 Additional comments (7)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/types.py (4)
8-23: LGTM: Session class implementation looks good.The Session dataclass correctly implements a container for authentication data with the token and expiration time, and provides a convenient as_header method for authenticated requests.
25-32: LGTM: Project class implementation is clean and focused.The Project dataclass properly represents a Corellium project with the necessary fields.
34-48: LGTM: Device class correctly models Corellium devices.The Device dataclass contains all the necessary fields to represent a Corellium device, with appropriate documentation explaining its purpose.
50-57: LGTM: Instance class implementation is appropriate.The Instance dataclass correctly models a virtual instance with its ID and optional state.
packages/jumpstarter-driver-power/jumpstarter_driver_power/client.py (2)
56-59: LGTM: VirtualPowerClient off method implementation looks good.The method properly extends functionality by adding a destroy parameter and passing it to the parent class's call method.
60-69: Command redefinition could cause confusion.The
offcommand is being redefined in the child class with the same name as in the parent class. While you're using explicit naming withname='off', this will replace the parent's implementation which could cause maintenance issues.Consider either:
- Using a different command name for clarity:
-@parent.command(name='off') +@parent.command(name='off-virtual')
- Or making it clearer that you're intentionally overriding the parent's command:
@parent.command(name='off') +# Intentionally overrides parent's 'off' command to add destroy functionalitypackages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (1)
19-62: Consider implementing reset() method.Based on previous comments, it appears that drivers should implement a
reset()method to bring them to a clean state, which is used by the exporter at the start/end of a lease.Consider adding a
reset()method to ensure there are no leftover instances running when the driver is initialized:def reset(self) -> None: """ Bring the driver to a clean state. Called by the exporter at the start/end of a lease. Ensures no leftover instances are running. """ # Check if an instance exists instance = self.api.get_instance(self.device_name) if instance: # Power off and destroy the instance self.children['power'].off(destroy=True)
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (9)
packages/jumpstarter-driver-power/jumpstarter_driver_power/client.py (1)
56-69:⚠️ Potential issueCommand redefinition issue in CLI method.
The
offcommand is being redefined with the same name as in the parent class. This will override the parent's command implementation, which may lead to unexpected behavior when the command is invoked.Consider one of these approaches:
- Explicitly declare that you're replacing the parent command:
-@parent.command(name='off') +@parent.command(name='off', help='Power off a virtual device')
- Use a different command name to avoid the collision:
-@parent.command(name='off') +@parent.command(name='off-virtual') -def off(destroy: bool): +def off_virtual(destroy: bool):packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (5)
94-101:⚠️ Potential issueFix session refresh logic.
The current code refreshes the session if there's more than 1 second left (diff > timedelta(seconds=1)), which is the opposite of what you likely intended. This will cause unnecessary re-logins.
Apply this diff to correct the logic:
-if diff > timedelta(seconds=1): +# Re-login if there's less than 60 seconds left in the session +if diff < timedelta(seconds=60): self._api.login()
158-161:⚠️ Potential issueFix incorrect variable reference in error message.
The error message references
self.parent.device_modelwhich doesn't exist in the code; it should refer toself.parent.device_flavor.Apply this fix:
-raise ValueError('Unable to find a device for this model: {self.parent.device_model}') +raise ValueError(f'Unable to find a device for this model: {self.parent.device_flavor}')
141-147:⚠️ Potential issueMake method async to match interface.
The
onmethod should be async to match the VirtualPowerInterface abstract method declaration.Apply this fix:
@export -def on(self) -> None: +async def on(self) -> None: """ Power a Corellium virtual device on.
179-183:⚠️ Potential issueMake method async and improve docstring.
The
offmethod should be async to match the VirtualPowerInterface abstract method declaration, and the docstring should better describe thedestroyparameter.Apply this fix:
@export -def off(self, destroy: bool = False) -> None: +async def off(self, destroy: bool = False) -> None: """ - Destroy a Corellium virtual device/instance. + Power off a Corellium virtual device/instance. + + Args: + destroy: If True, destroy the instance after powering it off. + If False, just power it off. """
201-203:⚠️ Potential issueImplement the read method properly.
The
readmethod is defined but not implemented. Since it's part of the required interface, it should either raise aNotImplementedErroror provide a proper implementation.Apply this fix:
@export -def read(self) -> AsyncGenerator[PowerReading, None]: - pass +async def read(self) -> AsyncGenerator[PowerReading, None]: + """ + Read power measurements from the device. + + This method is not implemented for Corellium devices. + """ + raise NotImplementedError("Power readings are not available for Corellium devices")packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (3)
55-71: 🛠️ Refactor suggestionUndefined
datarisk in exception handling.Similarly to
login, ensuredatais gracefully handled if.json()fails.
72-90: 🛠️ Refactor suggestionSame JSON parsing concern.
Define or handle
datacarefully in theexceptblock to avoidNameError.
112-130: 🛠️ Refactor suggestionMissing JSON decode fail handling.
If
res.json()fails,datawould not be set. The same fix applies here.
🧹 Nitpick comments (11)
packages/jumpstarter-driver-corellium/README.md (2)
1-8: Add environment variable requirements to README.The README doesn't mention the required environment variables (CORELLIUM_API_HOST and CORELLIUM_API_TOKEN) that are essential for authentication, as checked in the driver code.
Consider adding a section about environment variables:
## Environment Variables The driver requires the following environment variables to be set: * `CORELLIUM_API_HOST` - The Corellium API host URL * `CORELLIUM_API_TOKEN` - Your Corellium API token for authentication
7-7: Document additional VirtualPowerInterface capabilities.While the README mentions PowerInterface, it doesn't explain the additional features provided by VirtualPowerInterface, like the ability to destroy instances.
Add more detailed information about the supported interfaces and their capabilities:
* PowerInterface * Basic power management (on/off) * VirtualPowerInterface * Extended power management for virtual devices * Support for destroying instances when powering offpackages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (5)
132-133: Fix grammar error in error message.There's a grammatical error in the error message ("to be reach" should be "to reach").
Apply this fix:
-raise ValueError(f'Instance took too long to be reach the desired state: {current}') +raise ValueError(f'Instance took too long to reach the desired state: {current.id}')
48-53: Fix typo in docstring.There's a typo in the docstring: "varibales" should be "variables".
Apply this fix:
- Additionally, it also sets up some internal objects/varibales such as: + Additionally, it also sets up some internal objects/variables such as:
86-87: Fix typo in docstring.There's a typo in the docstring: "accross" should be "across".
Apply this fix:
- accross diferent API methods that require authentication. + across different API methods that require authentication.
126-127: Fix typo in docstring.There's a typo in the docstring: "instace" should be "instance".
Apply this fix:
- Desired can also be set to None, which means the instace should not exist. + Desired can also be set to None, which means the instance should not exist.
38-62:Details
❓ Verification inconclusive
Consider implementing reset method for clean state management.
The driver should handle cases where it starts with pre-existing instances. Implementing a
resetmethod would ensure a clean state at the beginning of a session.Consider adding a reset method that checks for and handles existing instances:
def reset(self) -> None: """ Reset the driver to a clean state. This method is called at the start of a session to ensure no leftover instances are running. """ # Check if an instance with this name already exists instance = self.api.get_instance(self.device_name) if instance: self.logger.info(f"Found existing instance {self.device_name}, cleaning up...") # Power off and destroy the instance self.children['power'].off(destroy=True)Run this script to check how other drivers implement reset:
🏁 Script executed:
#!/bin/bash # Search for reset method implementations in other drivers rg -A 5 "def reset" --include "*.py" packages/jumpstarter-driver-*/Length of output: 1209
Action Required: Implement a Reset Method for Cleaner State Initialization
The current driver’s post-initialization method assumes a fresh session, which might not be the case if pre-existing instances are present. To ensure a clean state at session start, consider adding a
resetmethod as outlined below. Note that an automated search for similar implementations in other drivers was inconclusive due to command errors. Please manually verify whether any driver already implements a reset routine to ensure consistency across the project.
- Location:
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py(suggested addition after the__post_init__method)- Proposal:
def reset(self) -> None: """ Reset the driver to a clean state. This method should be called at the start of a session to ensure no lingering instances exist. """ instance = self._api.get_instance(self.device_name) if instance: self.logger.info(f"Found existing instance {self.device_name}, cleaning up...") # Assuming the children 'power' drive handles power off and cleanup self.children['power'].off(destroy=True)- Verification: Since our attempt to automatically locate a similar
resetimplementation (usingrgwith appropriate parameters) resulted in errors, please verify manually if any other drivers (e.g., in packages likejumpstarter-driver-can,jumpstarter-driver-network, etc.) include a similar reset routine.packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (2)
16-24: Constructor looks good.The constructor sets up the necessary attributes. One small improvement would be to consistently use
self.reqinstead ofrequestsdirectly to ensure session consistency across all methods (e.g. in theloginmethod).- res = requests.post(f'{self.baseurl}/v1/auth/login', json=data) + res = self.req.post(f'{self.baseurl}/v1/auth/login', json=data)
91-111: Repeateddatausage pattern.Consider a shared helper to standardize request+JSON parsing, error handling, and
datausage. This will reduce boilerplate and prevent potential exceptions.packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py (2)
10-19: Handle missing fixture files gracefully.The fixture loader works well for valid files. Consider catching
FileNotFoundErrororIOErrorto fail early with a descriptive error.
157-165: Add an assertion to verify success.Currently, there's no assertion confirming the DELETE request or the outcome after
destroy_instance. Consider checkingrequests_mock.calledor verifying no exceptions were raised.api.destroy_instance(instance) + +assert requests_mock.called, "Expected DELETE request not triggered" +assert requests_mock.last_request.method == 'DELETE' +assert requests_mock.last_request.url == f'https://api-host/api/v1/instances/{instance.id}'
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (2)
packages/jumpstarter-driver-corellium/poetry.lockis excluded by!**/*.lockuv.lockis excluded by!**/*.lock
📒 Files selected for processing (24)
packages/jumpstarter-driver-corellium/README.md(1 hunks)packages/jumpstarter-driver-corellium/examples/exporter.yml(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/403.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/create-instance-200.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/create-instance-400.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/delete-instance-404.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/get-instance-state-200.txt(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/get-instance-state-404.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/get-models-200.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/get-projects-200.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/get-projects-404.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/json-error.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/login-200.json(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/client.py(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/exceptions.py(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/types.py(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver_test.py(1 hunks)packages/jumpstarter-driver-corellium/pyproject.toml(1 hunks)packages/jumpstarter-driver-power/jumpstarter_driver_power/client.py(1 hunks)packages/jumpstarter-driver-power/jumpstarter_driver_power/driver.py(1 hunks)pyproject.toml(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (18)
- packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/client.py
- packages/jumpstarter-driver-corellium/fixtures/http/get-instance-state-200.txt
- packages/jumpstarter-driver-corellium/fixtures/http/delete-instance-404.json
- packages/jumpstarter-driver-corellium/fixtures/http/get-projects-404.json
- packages/jumpstarter-driver-corellium/fixtures/http/get-instance-state-404.json
- packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/exceptions.py
- pyproject.toml
- packages/jumpstarter-driver-corellium/fixtures/http/get-projects-200.json
- packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver_test.py
- packages/jumpstarter-driver-corellium/fixtures/http/login-200.json
- packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/types.py
- packages/jumpstarter-driver-corellium/fixtures/http/create-instance-200.json
- packages/jumpstarter-driver-corellium/examples/exporter.yml
- packages/jumpstarter-driver-corellium/fixtures/http/get-models-200.json
- packages/jumpstarter-driver-corellium/pyproject.toml
- packages/jumpstarter-driver-corellium/fixtures/http/create-instance-400.json
- packages/jumpstarter-driver-corellium/fixtures/http/403.json
- packages/jumpstarter-driver-power/jumpstarter_driver_power/driver.py
🧰 Additional context used
🧬 Code Definitions (3)
packages/jumpstarter-driver-power/jumpstarter_driver_power/client.py (6)
packages/jumpstarter-driver-snmp/jumpstarter_driver_snmp/driver.py (1)
off(201-203)packages/jumpstarter-driver-power/jumpstarter_driver_power/driver.py (4)
off(17-17)off(32-32)off(58-59)off(86-87)packages/jumpstarter-driver-dutlink/jumpstarter_driver_dutlink/driver.py (2)
off(131-132)off(189-190)packages/jumpstarter-driver-raspberrypi/jumpstarter_driver_raspberrypi/client.py (1)
off(8-9)packages/jumpstarter-driver-yepkit/jumpstarter_driver_yepkit/driver.py (1)
off(117-120)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (1)
off(180-199)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (3)
packages/jumpstarter-driver-power/jumpstarter_driver_power/driver.py (13)
VirtualPowerInterface(23-35)on(14-14)on(29-29)on(54-55)on(82-83)off(17-17)off(32-32)off(58-59)off(86-87)read(20-20)read(35-35)read(62-64)read(90-92)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (4)
ApiClient(9-173)get_instance(112-129)set_instance_state(131-158)create_instance(91-110)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/types.py (1)
Instance(51-56)
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 (5)
Device(35-47)Instance(51-56)Project(26-31)Session(9-22)as_header(16-22)
🪛 Biome (1.9.4)
packages/jumpstarter-driver-corellium/fixtures/http/json-error.json
[error] 1-1: Missing closing quote
The closing quote must be on the same line.
(parse)
[error] 1-1: expected } but instead the file ends
the file ends here
(parse)
🔇 Additional comments (11)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (2)
131-159: Consider robust JSON handling.To avoid referencing
datawhen JSON decoding fails, replicate a safer pattern of parsing and reserving raw data separately.
160-174: Likewise for destroy_instance.All methods use a similar pattern; unify the approach to parsing and exception handling for reliability.
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py (9)
21-30: Test looks good.Verifies the happy path for login with correct session token. No issues found.
32-47: Error scenario test coverage is good.The assertions ensure correct exception handling. No concerns here.
49-69: Project retrieval test logic is thorough.Covers multiple scenarios including missing/None name. Well done.
71-86: Error scenario for get_project is clean.Ensures the
CorelliumApiExceptionis raised properly. No concerns here.
88-104: Device retrieval tests are well-structured.Tests both found and not-found flows. Looks good.
106-120: Device error scenario test is sufficient.Successfully checks for tokens or invalid responses. No issues.
122-136: Happy path for instance creation tested.Asserts the returned instance. Nothing to add here.
137-155: Instance creation error coverage is well done.Verifies exception message for unsupported device. Good job.
166-183: Instance destruction error scenario is covered.The test ensures the exception is raised. Looks good.
| @@ -0,0 +1 @@ | |||
| {"token": "a} | |||
There was a problem hiding this comment.
Fix invalid JSON syntax in test fixture.
The JSON file contains syntax errors: the string value for "token" is missing a closing quotation mark, and the JSON object is missing a closing brace. This will cause parsing errors when used.
Apply this diff to correct the JSON syntax:
-{"token": "a}
+{"token": "a"}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| {"token": "a} | |
| {"token": "a"} |
🧰 Tools
🪛 Biome (1.9.4)
[error] 1-1: Missing closing quote
The closing quote must be on the same line.
(parse)
[error] 1-1: expected } but instead the file ends
the file ends here
(parse)
There was a problem hiding this comment.
Actionable comments posted: 0
♻️ Duplicate comments (4)
packages/jumpstarter-driver-corellium/fixtures/http/json-error.json (1)
1-1: Fix invalid JSON syntax.
This JSON fixture is missing a closing quotation mark and a closing brace, rendering it invalid.-{"token": "a} +{"token": "a"}🧰 Tools
🪛 Biome (1.9.4)
[error] 1-1: Missing closing quote
The closing quote must be on the same line.
(parse)
[error] 1-1: expected
}but instead the file endsthe file ends here
(parse)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (1)
98-98: Confirm session refresh logic.
Re-logging in ifdiff > timedelta(seconds=1)seems reversed. Typically, you only log in again if the session is about to expire (i.e.,diff < something). Please verify.packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (1)
45-50: Prevent potential NameError during JSON parse failures.
Ifres.json()fails, usingdatain theexceptblock can raise a NameError. Consider handling JSON parsing separately, or initializingdatabefore parsing.packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py (1)
157-164: Add assertions to verify instance destruction request.There's no assertion to verify that the delete request was actually made correctly.
def test_destroy_instance_state_ok(requests_mock): instance = Instance(id='d59db33d-27bd-4b22-878d-49e4758a648e') requests_mock.delete(f'https://api-host/api/v1/instances/{instance.id}', status_code=204, text='') api = ApiClient('api-host', 'api-token') api.session = Session('session-token', '2022-03-20T01:50:10.000Z') api.destroy_instance(instance) + + # Verify the request was made correctly + assert requests_mock.called + assert requests_mock.last_request.method == 'DELETE' + assert requests_mock.last_request.url == f'https://api-host/api/v1/instances/{instance.id}'
🧹 Nitpick comments (4)
packages/jumpstarter-driver-power/jumpstarter_driver_power/client.py (1)
56-69: Clarify overriding of parent’soffcommand.
Overriding the parent'soffcommand with the same name can cause confusion for users of this CLI. Consider using a distinct command name if you want to preserve the parent’soffbehavior, or confirm you intend to replace it.packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (2)
49-49: Correct typographical and grammatical errors.
Several typos affect documentation clarity:
• Line 49: “varibales” → “variables”
• Line 96: “accross” → “across”
• Line 126: “instace” → “instance”
• Line 133: “to be reach” → “to reach”- Additionally, it also sets up some internal objects/varibales such as: + Additionally, it also sets up some internal objects/variables such as: - accross diferent API methods that require authentication. + across different API methods that require authentication. - Desired can also be set to None, which means the instace should not exist. + Desired can also be set to None, which means the instance should not exist. - raise ValueError(f'Instance took too long to be reach the desired state: {current}') + raise ValueError(f'Instance took too long to reach the desired state: {current}')Also applies to: 96-96, 126-126, 133-133
202-202: Raise NotImplementedError instead of silently passing.
Thereadmethod is empty and may confuse callers. RaisingNotImplementedErrorclarifies that reading power metrics is not supported.- def read(self) -> AsyncGenerator[PowerReading, None]: - pass + def read(self) -> AsyncGenerator[PowerReading, None]: + raise NotImplementedError("Power readings are not available for Corellium devices.")packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (1)
46-47: Raise errors before parsing the response.
Callingres.raise_for_status()after parsing JSON can mask JSON parse errors if the API returns malformed JSON. Consider raising errors prior to or wrapping the parse in a dedicated try-except block.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (2)
packages/jumpstarter-driver-corellium/poetry.lockis excluded by!**/*.lockuv.lockis excluded by!**/*.lock
📒 Files selected for processing (24)
packages/jumpstarter-driver-corellium/README.md(1 hunks)packages/jumpstarter-driver-corellium/examples/exporter.yml(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/403.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/create-instance-200.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/create-instance-400.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/delete-instance-404.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/get-instance-state-200.txt(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/get-instance-state-404.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/get-models-200.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/get-projects-200.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/get-projects-404.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/json-error.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/login-200.json(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/client.py(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/exceptions.py(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/types.py(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver_test.py(1 hunks)packages/jumpstarter-driver-corellium/pyproject.toml(1 hunks)packages/jumpstarter-driver-power/jumpstarter_driver_power/client.py(1 hunks)packages/jumpstarter-driver-power/jumpstarter_driver_power/driver.py(1 hunks)pyproject.toml(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (19)
- packages/jumpstarter-driver-corellium/fixtures/http/login-200.json
- packages/jumpstarter-driver-corellium/fixtures/http/403.json
- packages/jumpstarter-driver-corellium/fixtures/http/create-instance-200.json
- packages/jumpstarter-driver-corellium/fixtures/http/get-projects-404.json
- packages/jumpstarter-driver-corellium/fixtures/http/get-instance-state-200.txt
- packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/client.py
- packages/jumpstarter-driver-corellium/fixtures/http/create-instance-400.json
- packages/jumpstarter-driver-corellium/fixtures/http/delete-instance-404.json
- packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/exceptions.py
- packages/jumpstarter-driver-corellium/fixtures/http/get-instance-state-404.json
- packages/jumpstarter-driver-corellium/fixtures/http/get-models-200.json
- packages/jumpstarter-driver-corellium/fixtures/http/get-projects-200.json
- packages/jumpstarter-driver-corellium/examples/exporter.yml
- packages/jumpstarter-driver-corellium/README.md
- packages/jumpstarter-driver-corellium/pyproject.toml
- packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/types.py
- packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver_test.py
- pyproject.toml
- packages/jumpstarter-driver-power/jumpstarter_driver_power/driver.py
🧰 Additional context used
🧬 Code Definitions (4)
packages/jumpstarter-driver-power/jumpstarter_driver_power/client.py (4)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (1)
off(180-199)packages/jumpstarter-driver-power/jumpstarter_driver_power/driver.py (4)
off(17-17)off(32-32)off(58-59)off(86-87)packages/jumpstarter-driver-snmp/jumpstarter_driver_snmp/client.py (2)
off(15-17)cli(19-28)packages/jumpstarter-driver-raspberrypi/jumpstarter_driver_raspberrypi/client.py (1)
off(8-9)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py (3)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (6)
ApiClient(9-173)login(32-53)get_project(55-70)get_device(72-89)create_instance(91-110)destroy_instance(160-173)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/exceptions.py (1)
CorelliumApiException(7-10)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/types.py (5)
Device(35-47)Instance(51-56)Project(26-31)Session(9-22)as_header(16-22)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (4)
packages/jumpstarter-driver-power/jumpstarter_driver_power/driver.py (15)
VirtualPowerInterface(23-35)client(10-11)client(25-26)on(14-14)on(29-29)on(54-55)on(82-83)off(17-17)off(32-32)off(58-59)off(86-87)read(20-20)read(35-35)read(62-64)read(90-92)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (8)
ApiClient(9-173)login(32-53)get_instance(112-129)get_project(55-70)get_device(72-89)set_instance_state(131-158)create_instance(91-110)destroy_instance(160-173)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/types.py (1)
Instance(51-56)packages/jumpstarter/jumpstarter/common/exceptions.py (1)
ConfigurationError(35-38)
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 (5)
Device(35-47)Instance(51-56)Project(26-31)Session(9-22)as_header(16-22)
🪛 Biome (1.9.4)
packages/jumpstarter-driver-corellium/fixtures/http/json-error.json
[error] 1-1: Missing closing quote
The closing quote must be on the same line.
(parse)
[error] 1-1: expected } but instead the file ends
the file ends here
(parse)
🔇 Additional comments (11)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py (11)
10-18: Clean, well-structured fixture loading function.The
fixturefunction provides a clear way to load test fixtures from a dedicated directory. This is good practice for organizing test data and keeping it separate from test logic.
21-29: Good validation of login functionality and session properties.The test effectively validates successful login, checking the session token, expiration time, and header construction. This ensures the authentication flow works as expected.
32-46: Well-structured parameterized test for login error scenarios.Good use of parameterization to test multiple error scenarios with minimal code duplication. The test properly verifies both the exception message and that the session remains None when login fails.
49-68: Comprehensive testing of project retrieval with multiple scenarios.The test covers all important project retrieval scenarios: finding a specific project, using default project, and handling cases where projects aren't found. The conditional assertion logic is clear and effective.
71-85: Good coverage of error scenarios for project retrieval.The parameterized test effectively validates the error handling for different API responses when retrieving projects.
88-103: Well-structured device retrieval tests with clear assertions.The test covers both successful device retrieval and handling of models that don't exist. The assertions are clear and validate the expected behavior.
106-119: Appropriate testing of error handling for device retrieval.The test properly verifies that exceptions are raised with the expected error messages when device retrieval fails.
122-135: Clear validation of instance creation success case.The test effectively validates that instance creation works correctly by checking the response object. The setup and assertions are straightforward and effective.
137-154: Good error handling tests for instance creation.The parameterized test effectively covers different error scenarios when creating instances, with appropriate assertions to validate the exception messages.
166-182: Thorough error handling tests for instance destruction.The parameterized test covers important error scenarios when destroying instances, with clear assertions to validate the exception messages.
131-131:Details
✅ Verification successful
Verify API method signature usage.
The
create_instancecall here includes 5 parameters, but from the API code snippet provided, the signature has only 4 parameters. It seems the method has been updated to includeos_buildas a new parameter.
🏁 Script executed:
#!/bin/bash # Description: Check if the API client method signature matches its usage in tests. # Find the method definition in api.py rg -A 5 "def create_instance" packages/jumpstarter-driver-corelliumLength of output: 818
API signature verified: The
create_instancemethod is now defined with five parameters (name,project,device,os_version, andos_build), which matches the usage in the test. No changes are needed in the test code.
Co-authored-by: Nick Cao <nickcao@nichi.co> Signed-off-by: Leonardo Rossetti <lrossett@redhat.com>
There was a problem hiding this comment.
Actionable comments posted: 0
♻️ Duplicate comments (9)
packages/jumpstarter-driver-corellium/fixtures/http/json-error.json (1)
1-1: Fix invalid JSON syntax
A closing quotation mark is missing aftera, causing parse failures.-{"token": "a} +{"token": "a"}🧰 Tools
🪛 Biome (1.9.4)
[error] 1-1: Missing closing quote
The closing quote must be on the same line.
(parse)
[error] 1-1: expected
}but instead the file endsthe file ends here
(parse)
packages/jumpstarter-driver-power/jumpstarter_driver_power/client.py (2)
56-59: Overriding the parent’soffmethod
This introduces a newoffmethod with adestroyparameter, overshadowing the parent class’s version. Confirm if this override is intentional.
60-69: Redefinition of theoffCLI command
Defining anotheroffcommand in the child CLI group potentially overrides the parent's command. If you plan to replace the parent’s command, this is fine; otherwise, consider another command name.packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (4)
98-99: Potential session refresh logic issue
Re-logging in when there is more than one second left until expiration could lead to unnecessary extra logins. Typically, you’d refresh when the remaining time is below a certain threshold.
142-145: Async interface mismatch
VirtualPowerInterfacedeclaresasync def on(...), but here it’s implemented synchronously. Consider making this method async for consistency.
159-160: Mismatch betweendevice_flavorusage and error message
The error referencesself.parent.device_model, but the code usesdevice_flavor. Correct this message to avoid confusion.
201-203: Unimplementedreadmethod
This interface method is empty. If not supported, raiseNotImplementedErrorto clarify that reading power data isn’t provided.packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (1)
45-49: Possibledatausage ifjson()fails
Shouldres.json()raise a parse error,datawould be undefined in theexceptblock. Safeguard against that scenario to avoid aNameError.packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py (1)
157-164: Add assertion to verify instance destructionThe test for instance destruction doesn't have an assertion to verify success. Consider adding a verification or checking that no exception was raised.
def test_destroy_instance_state_ok(requests_mock): instance = Instance(id='d59db33d-27bd-4b22-878d-49e4758a648e') requests_mock.delete(f'https://api-host/api/v1/instances/{instance.id}', status_code=204, text='') api = ApiClient('api-host', 'api-token') api.session = Session('session-token', '2022-03-20T01:50:10.000Z') api.destroy_instance(instance) + + # Verify the request was made correctly + assert requests_mock.called + assert requests_mock.last_request.method == 'DELETE' + assert requests_mock.last_request.url == f'https://api-host/api/v1/instances/{instance.id}'
🧹 Nitpick comments (2)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py (2)
10-18: Add error handling for missing fixture filesThe
fixturefunction should handle cases where a fixture file is missing to provide clearer error messages.def fixture(path): """ Load file contents from fixtures/$path. """ cwd = os.path.dirname(os.path.abspath(__file__)) fixtures_dir = f'{cwd}/../../fixtures' - with open(f'{fixtures_dir}/{path}', 'r') as f: - return f.read() + fixture_path = f'{fixtures_dir}/{path}' + try: + with open(fixture_path, 'r') as f: + return f.read() + except FileNotFoundError: + raise FileNotFoundError(f"Fixture file not found: {fixture_path}")
164-165: Add blank line before new test sectionFor consistent code formatting, add a blank line to maintain separation between test functions.
api.destroy_instance(instance) + @pytest.mark.parametrize(
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (2)
packages/jumpstarter-driver-corellium/poetry.lockis excluded by!**/*.lockuv.lockis excluded by!**/*.lock
📒 Files selected for processing (24)
packages/jumpstarter-driver-corellium/README.md(1 hunks)packages/jumpstarter-driver-corellium/examples/exporter.yml(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/403.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/create-instance-200.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/create-instance-400.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/delete-instance-404.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/get-instance-state-200.txt(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/get-instance-state-404.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/get-models-200.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/get-projects-200.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/get-projects-404.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/json-error.json(1 hunks)packages/jumpstarter-driver-corellium/fixtures/http/login-200.json(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/client.py(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api_test.py(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/exceptions.py(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/types.py(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py(1 hunks)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver_test.py(1 hunks)packages/jumpstarter-driver-corellium/pyproject.toml(1 hunks)packages/jumpstarter-driver-power/jumpstarter_driver_power/client.py(1 hunks)packages/jumpstarter-driver-power/jumpstarter_driver_power/driver.py(1 hunks)pyproject.toml(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (19)
- packages/jumpstarter-driver-corellium/fixtures/http/get-instance-state-200.txt
- packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/client.py
- packages/jumpstarter-driver-corellium/fixtures/http/403.json
- packages/jumpstarter-driver-corellium/fixtures/http/get-instance-state-404.json
- packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/exceptions.py
- packages/jumpstarter-driver-corellium/fixtures/http/create-instance-200.json
- packages/jumpstarter-driver-corellium/fixtures/http/get-projects-404.json
- packages/jumpstarter-driver-corellium/README.md
- packages/jumpstarter-driver-corellium/fixtures/http/delete-instance-404.json
- packages/jumpstarter-driver-corellium/fixtures/http/get-projects-200.json
- pyproject.toml
- packages/jumpstarter-driver-corellium/fixtures/http/login-200.json
- packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/types.py
- packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver_test.py
- packages/jumpstarter-driver-corellium/pyproject.toml
- packages/jumpstarter-driver-power/jumpstarter_driver_power/driver.py
- packages/jumpstarter-driver-corellium/fixtures/http/create-instance-400.json
- packages/jumpstarter-driver-corellium/fixtures/http/get-models-200.json
- packages/jumpstarter-driver-corellium/examples/exporter.yml
🧰 Additional context used
🧬 Code Definitions (3)
packages/jumpstarter-driver-power/jumpstarter_driver_power/client.py (4)
packages/jumpstarter-driver-power/jumpstarter_driver_power/driver.py (4)
off(17-17)off(32-32)off(58-59)off(86-87)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (1)
off(180-199)packages/jumpstarter-driver-snmp/jumpstarter_driver_snmp/client.py (2)
off(15-17)cli(19-28)packages/jumpstarter-driver-raspberrypi/jumpstarter_driver_raspberrypi/client.py (1)
off(8-9)
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 (5)
Device(35-47)Instance(51-56)Project(26-31)Session(9-22)as_header(16-22)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (4)
packages/jumpstarter-driver-power/jumpstarter_driver_power/driver.py (15)
VirtualPowerInterface(23-35)client(10-11)client(25-26)on(14-14)on(29-29)on(54-55)on(82-83)off(17-17)off(32-32)off(58-59)off(86-87)read(20-20)read(35-35)read(62-64)read(90-92)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (8)
ApiClient(9-173)login(32-53)get_instance(112-129)get_project(55-70)get_device(72-89)set_instance_state(131-158)create_instance(91-110)destroy_instance(160-173)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/types.py (1)
Instance(51-56)packages/jumpstarter-driver-power/jumpstarter_driver_power/client.py (7)
on(11-12)on(37-39)off(14-15)off(42-44)off(57-58)off(65-67)read(26-28)
🪛 Biome (1.9.4)
packages/jumpstarter-driver-corellium/fixtures/http/json-error.json
[error] 1-1: Missing closing quote
The closing quote must be on the same line.
(parse)
[error] 1-1: expected } but instead the file ends
the file ends here
(parse)
🔇 Additional comments (1)
packages/jumpstarter-driver-power/jumpstarter_driver_power/client.py (1)
54-55: No content to review
These lines are empty; no actions required.
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (3)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (3)
201-203:⚠️ Potential issueProperly implement the read method.
The
readmethod is defined but not implemented. Since it's part of the required interface, it should at least raise aNotImplementedErrorwith an informative message.@export - def read(self) -> AsyncGenerator[PowerReading, None]: - pass + async def read(self) -> AsyncGenerator[PowerReading, None]: + """ + Read power measurements from the device. + + This method is not implemented for Corellium devices. + + Raises: + NotImplementedError: Power readings are not available for Corellium devices. + """ + raise NotImplementedError("Power readings are not available for Corellium devices")
179-200: 🛠️ Refactor suggestionConsider implementing reboot functionality.
The current implementation allows destroying an instance but doesn't provide a way to reboot it without destroying.
Based on the Corellium API capabilities mentioned in the relevant snippets, consider adding reboot functionality:
@export - def off(self, destroy: bool = False) -> None: + async def off(self, destroy: bool = False, reboot: bool = False) -> None: """ - Destroy a Corellium virtual device/instance. + Power off, reboot, or destroy a Corellium virtual device/instance. + + Args: + destroy: If True, destroy the instance after powering it off. + reboot: If True, reboot the instance instead of just powering it off. + This parameter is ignored if destroy is True. """ # fail if project does not exist project = self.parent.api.get_project(self.parent.project_id) if project is None: raise ValueError(f'Unable to fetch project: {self.parent.project_id}') # get instance and fail if instance does not exist instance = self.parent.api.get_instance(self.parent.device_name) if instance is None: raise ValueError('Instance does not exist') - self.parent.api.set_instance_state(instance, 'off') - self.wait_instance(instance, Instance(id=instance.id, state='off')) + if reboot and not destroy: + self.logger.info(f'Rebooting instance: {instance.id}') + self.parent.api.set_instance_state(instance, 'rebooting') + self.wait_instance(instance, Instance(id=instance.id, state='on')) + else: + self.parent.api.set_instance_state(instance, 'off') + self.wait_instance(instance, Instance(id=instance.id, state='off')) if destroy: self.parent.api.destroy_instance(instance) self.wait_instance(instance, None)This provides more flexibility in managing device lifecycle.
19-103: 🛠️ Refactor suggestionImplement reset functionality for clean state initialization.
Based on the previous comments, the driver should implement a reset method to ensure a clean state when the driver is initialized or at the end of a session.
Consider adding a reset method that checks for any existing instances with the configured name and destroys them to ensure a clean state at initialization:
@dataclass(kw_only=True) class Corellium(Driver): # ... existing code ... def __post_init__(self) -> None: # ... existing code ... self._api = ApiClient(api_host, api_token) + # Reset the driver to a clean state + self.reset() self.children['power'] = CorelliumPower(parent=self) + def reset(self) -> None: + """ + Reset the driver to a clean state. + + This method checks for any existing instances with the configured name + and destroys them to ensure a clean state at initialization. + """ + try: + # Login first to ensure we have a valid session + self.api.login() + + # Check if project exists + project = self.api.get_project(self.project_id) + if project is None: + self.logger.warning(f'Project not found: {self.project_id}') + return + + # Check if instance exists + instance = self.api.get_instance(self.device_name) + if instance is None: + return + + # Destroy instance if it exists + self.logger.info(f'Cleaning up existing instance: {self.device_name}') + self.api.destroy_instance(instance) + + # Wait for instance to be destroyed + power = CorelliumPower(parent=self) + power.wait_instance(instance, None) + except Exception as ex: + self.logger.error(f'Error resetting driver: {ex}')This ensures that no leftover instances remain when starting a new session with the driver.
🧹 Nitpick comments (4)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (4)
49-49: Fix typo in docstring.There's a typo in the docstring: "varibales" should be "variables".
- Additionally, it also sets up some internal objects/varibales such as: + Additionally, it also sets up some internal objects/variables such as:
114-120: Cast interval to integer for consistency.While the retries value is cast to an integer, the interval is not, which could lead to type inconsistency when used.
return { 'retries': int(os.environ.get('CORELLIUM_API_RETRIES', 12)), - 'interval': os.environ.get('CORELLIUM_API_INTERVAL', 5) + 'interval': int(os.environ.get('CORELLIUM_API_INTERVAL', 5)) }
117-120: Add validation for environment variables.The timeout configuration retrieves values from environment variables without validation, which could lead to unexpected behavior if invalid values are provided.
return { - 'retries': int(os.environ.get('CORELLIUM_API_RETRIES', 12)), - 'interval': os.environ.get('CORELLIUM_API_INTERVAL', 5) + 'retries': max(1, int(os.environ.get('CORELLIUM_API_RETRIES', 12))), + 'interval': max(1, int(os.environ.get('CORELLIUM_API_INTERVAL', 5))) }This ensures that retries and interval are always positive integers, preventing potential issues with invalid values.
84-87: Improve property docstring.The docstring for the
apiproperty could be more descriptive about what it returns and when it refreshes the session.@property def api(self): """ - Return the internal Corellium API client instance from `self._api`. - - It will also be responsible for creating/refreshing the session token used - across different API methods that require authentication. + Return the Corellium API client with a valid authentication session. + + This property ensures a valid session is available by: + 1. Creating a new session if none exists + 2. Refreshing the session if it's about to expire + + Returns: + ApiClient: A client with a valid authentication session """
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py(1 hunks)
🧰 Additional context used
🧬 Code Definitions (1)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (4)
packages/jumpstarter-driver-power/jumpstarter_driver_power/driver.py (15)
VirtualPowerInterface(23-35)client(10-11)client(25-26)on(14-14)on(29-29)on(54-55)on(82-83)off(17-17)off(32-32)off(58-59)off(86-87)read(20-20)read(35-35)read(62-64)read(90-92)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/api.py (8)
ApiClient(9-173)login(32-53)get_instance(112-129)get_project(55-70)get_device(72-89)set_instance_state(131-158)create_instance(91-110)destroy_instance(160-173)packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/corellium/types.py (1)
Instance(51-56)packages/jumpstarter-driver-power/jumpstarter_driver_power/client.py (7)
on(11-12)on(37-39)off(14-15)off(42-44)off(57-58)off(65-67)read(26-28)
⏰ Context from checks skipped due to timeout of 90000ms (4)
- GitHub Check: pytest-matrix (3.11)
- GitHub Check: pytest-matrix (3.12)
- GitHub Check: pytest-matrix (3.13)
- GitHub Check: e2e
🔇 Additional comments (3)
packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (3)
64-79: LGTM!The
get_env_varmethod is well-implemented with proper error handling and validation.
31-37: LGTM!The
clientclass method correctly returns the path to the client implementation.
122-140: LGTM!The
wait_instancemethod provides a robust mechanism for waiting for an instance to reach a desired state, with proper timeout handling.
| def __post_init__(self) -> None: | ||
| """ | ||
| Post initialization method. | ||
|
|
||
| It will check for the following environment variables: | ||
|
|
||
| - CORELLIUM_API_HOST | ||
| - CORELLIUM_API_TOKEN | ||
|
|
||
| Raises an exception in case these variables are not set or empty. | ||
|
|
||
| Additionally, it also sets up some internal objects/varibales such as: | ||
|
|
||
| - Corellium API client instance | ||
| - Children jumpstarter drives | ||
| """ | ||
| if hasattr(super(), "__post_init__"): | ||
| super().__post_init__() | ||
|
|
||
| api_host = self.get_env_var('CORELLIUM_API_HOST') | ||
| api_token = self.get_env_var('CORELLIUM_API_TOKEN') | ||
| self._api = ApiClient(api_host, api_token) | ||
|
|
||
| self.children['power'] = CorelliumPower(parent=self) | ||
|
|
There was a problem hiding this comment.
🛠️ Refactor suggestion
Consider adding a close method to ensure proper cleanup.
The driver should implement a close method to ensure proper cleanup at the end of a session, mirroring what's done in the reset method.
def __post_init__(self) -> None:
# ... existing code ...
+ def close(self) -> None:
+ """
+ Perform cleanup at the end of a session.
+
+ This method ensures that any resources created by the driver
+ are properly cleaned up when the driver is no longer needed.
+ """
+ self.reset() # Reuse the reset logic for cleanupThis ensures that resources are properly cleaned up when the driver is no longer needed.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| def __post_init__(self) -> None: | |
| """ | |
| Post initialization method. | |
| It will check for the following environment variables: | |
| - CORELLIUM_API_HOST | |
| - CORELLIUM_API_TOKEN | |
| Raises an exception in case these variables are not set or empty. | |
| Additionally, it also sets up some internal objects/varibales such as: | |
| - Corellium API client instance | |
| - Children jumpstarter drives | |
| """ | |
| if hasattr(super(), "__post_init__"): | |
| super().__post_init__() | |
| api_host = self.get_env_var('CORELLIUM_API_HOST') | |
| api_token = self.get_env_var('CORELLIUM_API_TOKEN') | |
| self._api = ApiClient(api_host, api_token) | |
| self.children['power'] = CorelliumPower(parent=self) | |
| def __post_init__(self) -> None: | |
| """ | |
| Post initialization method. | |
| It will check for the following environment variables: | |
| - CORELLIUM_API_HOST | |
| - CORELLIUM_API_TOKEN | |
| Raises an exception in case these variables are not set or empty. | |
| Additionally, it also sets up some internal objects/varibales such as: | |
| - Corellium API client instance | |
| - Children jumpstarter drives | |
| """ | |
| if hasattr(super(), "__post_init__"): | |
| super().__post_init__() | |
| api_host = self.get_env_var('CORELLIUM_API_HOST') | |
| api_token = self.get_env_var('CORELLIUM_API_TOKEN') | |
| self._api = ApiClient(api_host, api_token) | |
| self.children['power'] = CorelliumPower(parent=self) | |
| def close(self) -> None: | |
| """ | |
| Perform cleanup at the end of a session. | |
| This method ensures that any resources created by the driver | |
| are properly cleaned up when the driver is no longer needed. | |
| """ | |
| self.reset() # Reuse the reset logic for cleanup |
| if diff > timedelta(seconds=1): | ||
| self._api.login() |
There was a problem hiding this comment.
💡 Verification agent
🧩 Analysis chain
Ensure session refresh logic is correct.
The current logic refreshes the session if diff > timedelta(seconds=1), which means it will refresh when there is more than 1 second left. This might lead to unnecessary refreshes.
Please verify the logic works as intended. Typically, you'd want to refresh if there's less than a certain threshold remaining (e.g., diff < timedelta(seconds=60)).
🌐 Web query:
What are best practices for token refresh in authentication systems?
💡 Result:
To ensure secure and user-friendly authentication, token refresh systems should implement the following best practices:
Short-Lived Access Tokens
Access tokens should have brief expiration times (minutes to hours) to minimize risks from token compromise[1][3][5]. This limits the window for attackers to misuse stolen tokens while maintaining API performance.
Refresh Token Rotation
- Automatic invalidation: Issue a new refresh token with each access token refresh, invalidating the previous one[1][2][3][6].
- Reuse detection: Flag simultaneous use of the same refresh token across multiple clients, triggering immediate revocation of all related tokens[2][3][6].
Secure Storage and Transmission
- Store refresh tokens server-side using encryption[5][7]
- Use HTTPS for all token exchanges[7]
- Avoid client-side storage in SPAs/mobile apps without secure enclaves[1][6]
Expiration and Revocation Policies
| Policy Type | Implementation | Benefit |
|---|---|---|
| Absolute expiration | 7-90 days for refresh tokens[4][10] | Limits long-term exposure |
| Idle timeout | Revoke after 24h inactivity (SPAs)[10] | Mitigates abandoned sessions |
| Credential change | Invalidate tokens on password reset[10] | Prevents post-compromise access |
OAuth Flow Selection
Use Authorization Code Flow with PKCE for SPAs[6], and Code Flow for server-side apps[1][4]. Avoid implicit flow and client credentials flow for user-facing applications[4].
Security Enhancements
- Sender-constrained tokens: Bind tokens to client IP/device[2][6]
- Token binding: Link refresh tokens to specific client instances[2]
- Regular audits: Monitor token usage patterns for anomalies[9]
For SPAs and mobile apps:
// Sample secure refresh flow with rotation
async function refreshTokens() {
try {
const response = await fetch('/refresh', {
method: 'POST',
credentials: 'include' // HttpOnly cookie
});
const { access_token, refresh_token } = await response.json();
sessionStorage.setItem('access_token', access_token);
// Server stores new refresh_token
} catch (error) {
forceReauthentication();
}
}Failure Handling
- Implement automatic retry with exponential backoff[7]
- Maintain session continuity during failures using:
- Short-term cookie fallbacks (15-30min)[8]
- Silent iframe reauthentication[3][6]
These practices balance security and usability by reducing token exposure surfaces while maintaining seamless user sessions. Systems should combine rotation with HTTPS enforcement and proper client authentication to mitigate both passive interception and active replay attacks[1][2][6].
Citations:
- 1: https://stateful.com/blog/oauth-refresh-token-best-practices
- 2: https://www.descope.com/blog/post/refresh-token-rotation
- 3: https://auth0.com/blog/refresh-tokens-what-are-they-and-when-to-use-them/
- 4: https://curity.io/resources/learn/oauth-refresh/
- 5: https://www.descope.com/learn/post/refresh-token
- 6: https://developer.okta.com/docs/guides/refresh-tokens/main/
- 7: https://www.permit.io/blog/oauth-tokens-definitive-guide
- 8: https://community.xano.com/ask-the-community/post/best-practices-for-securely-refreshing-auth-tokens-seeking-feedback-on-SyQX6kCArwNVBic
- 9: https://auth0.com/docs/secure/tokens/token-best-practices
- 10: https://learn.microsoft.com/en-us/entra/identity-platform/refresh-tokens
**Session Refresh Condition Needs Adjustment **
The current logic in packages/jumpstarter-driver-corellium/jumpstarter_driver_corellium/driver.py (lines 98-99) triggers a session refresh when there is more than 1 second remaining (if diff > timedelta(seconds=1)). This behavior is likely inverted based on best practices. Typically, you should refresh the session when the remaining validity is lower than a threshold (for example, when diff < timedelta(seconds=60)), ensuring that you avoid unnecessary or premature refreshes while still maintaining smooth session continuity.
- Issue: Refreshing when
diff > timedelta(seconds=1)may lead to unnecessary login calls. - Recommendation: Verify and update the condition to trigger a refresh when the remaining time is below an appropriate threshold (e.g.,
diff < timedelta(seconds=60)). This aligns better with standard token refresh best practices.
Fixes #328
Changes
Summary by CodeRabbit
New Features
CorelliumClientclass for enhanced API interaction capabilities.Documentation
Tests